diff --git a/Cargo.toml b/Cargo.toml index be4070ac..a3ae52c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,6 +69,10 @@ advanced = ["iced_core/advanced", "iced_widget/advanced"] fira-sans = ["iced_renderer/fira-sans"] # Auto-detects light/dark mode for the built-in 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 strict-assertions = ["iced_renderer/strict-assertions"] # Redraws on every runtime event, and not only when a widget requests it diff --git a/core/Cargo.toml b/core/Cargo.toml index f57aaa4d..cb7ef3ef 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -17,6 +17,8 @@ workspace = true auto-detect-theme = ["dep:dark-light"] advanced = [] crisp = [] +basic-shaping = [] +advanced-shaping = [] [dependencies] bitflags.workspace = true diff --git a/core/src/text.rs b/core/src/text.rs index 0b51f244..e47d9bbd 100644 --- a/core/src/text.rs +++ b/core/src/text.rs @@ -130,8 +130,17 @@ impl From for alignment::Horizontal { } /// The shaping strategy of some text. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 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. /// /// 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 /// and the font you are displaying in your application. /// - /// This is the default. - #[default] + /// This will be the default if the `basic-shaping` feature is enabled and + /// the `advanced-shaping` feature is disabled. Basic, /// Advanced text shaping and font fallback. /// @@ -150,9 +159,23 @@ pub enum Shaping { /// may be needed to display all of the glyphs. /// /// Advanced shaping is expensive! You should only enable it when necessary. + /// + /// This will be the default if the `advanced-shaping` feature is enabled. 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. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] pub enum Wrapping { diff --git a/examples/layout/src/main.rs b/examples/layout/src/main.rs index c15a0bfc..f3765d9d 100644 --- a/examples/layout/src/main.rs +++ b/examples/layout/src/main.rs @@ -94,14 +94,14 @@ impl Layout { let controls = row([ (!self.example.is_first()).then_some( - button(text("← Previous").shaping(text::Shaping::Advanced)) + button(text("← Previous")) .padding([5, 10]) .on_press(Message::Previous) .into(), ), Some(horizontal_space().into()), (!self.example.is_last()).then_some( - button(text("Next →").shaping(text::Shaping::Advanced)) + button(text("Next →")) .padding([5, 10]) .on_press(Message::Next) .into(), @@ -313,7 +313,7 @@ fn quotes<'a>() -> Element<'a, Message> { "This is another reply", ), horizontal_rule(1), - text("A separator ↑").shaping(text::Shaping::Advanced), + text("A separator ↑"), ] .width(Shrink) .spacing(10) diff --git a/examples/styling/snapshots/catppuccin_frappé-tiny-skia.sha256 b/examples/styling/snapshots/catppuccin_frappé-tiny-skia.sha256 index cdc79b78..c7a8077d 100644 --- a/examples/styling/snapshots/catppuccin_frappé-tiny-skia.sha256 +++ b/examples/styling/snapshots/catppuccin_frappé-tiny-skia.sha256 @@ -1 +1 @@ -0650eb2c27c21c5d48e1e00031a52d8471d8a3b4e827ad502c4628914f5c1c13 \ No newline at end of file +129523830df064908cfa911214ba61dadc31d8975425ba3efaae69da9514a3d0 \ No newline at end of file diff --git a/graphics/src/text.rs b/graphics/src/text.rs index e00b3ac7..9f932661 100644 --- a/graphics/src/text.rs +++ b/graphics/src/text.rs @@ -323,8 +323,15 @@ fn to_align(alignment: Alignment) -> Option { } /// 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 { + Shaping::Auto => { + if text.is_ascii() { + cosmic_text::Shaping::Basic + } else { + cosmic_text::Shaping::Advanced + } + } Shaping::Basic => cosmic_text::Shaping::Basic, Shaping::Advanced => cosmic_text::Shaping::Advanced, } diff --git a/graphics/src/text/cache.rs b/graphics/src/text/cache.rs index 9bb66362..a7fc5ddd 100644 --- a/graphics/src/text/cache.rs +++ b/graphics/src/text/cache.rs @@ -55,7 +55,7 @@ impl Cache { font_system, key.content, &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); diff --git a/graphics/src/text/paragraph.rs b/graphics/src/text/paragraph.rs index f2c6f404..ea2b30d2 100644 --- a/graphics/src/text/paragraph.rs +++ b/graphics/src/text/paragraph.rs @@ -88,7 +88,7 @@ impl core::text::Paragraph for Paragraph { font_system.raw(), text.content, &text::to_attributes(text.font), - text::to_shaping(text.shaping), + text::to_shaping(text.shaping, text.content), ); let min_bounds = @@ -158,7 +158,7 @@ impl core::text::Paragraph for Paragraph { (span.text.as_ref(), attrs.metadata(i)) }), &text::to_attributes(text.font), - text::to_shaping(text.shaping), + cosmic_text::Shaping::Advanced, None, );