summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/src/renderer/null.rs2
-rw-r--r--core/src/text.rs40
-rw-r--r--core/src/widget/text.rs13
-rw-r--r--examples/checkbox/src/main.rs3
-rw-r--r--examples/todos/src/main.rs3
-rw-r--r--graphics/src/backend.rs2
-rw-r--r--graphics/src/geometry/text.rs8
-rw-r--r--graphics/src/primitive.rs11
-rw-r--r--graphics/src/renderer.rs6
-rw-r--r--renderer/src/backend.rs11
-rw-r--r--tiny_skia/Cargo.toml5
-rw-r--r--tiny_skia/src/backend.rs8
-rw-r--r--tiny_skia/src/geometry.rs1
-rw-r--r--tiny_skia/src/text.rs17
-rw-r--r--wgpu/Cargo.toml2
-rw-r--r--wgpu/fonts/Iced-Icons.ttfbin5108 -> 5108 bytes
-rw-r--r--wgpu/src/backend.rs6
-rw-r--r--wgpu/src/geometry.rs1
-rw-r--r--wgpu/src/layer.rs4
-rw-r--r--wgpu/src/layer/text.rs4
-rw-r--r--wgpu/src/text.rs16
-rw-r--r--widget/src/checkbox.rs17
-rw-r--r--widget/src/overlay/menu.rs12
-rw-r--r--widget/src/pick_list.rs43
-rw-r--r--widget/src/radio.rs21
-rw-r--r--widget/src/text.rs1
-rw-r--r--widget/src/text_input.rs13
-rw-r--r--widget/src/toggler.rs12
28 files changed, 249 insertions, 33 deletions
diff --git a/core/src/renderer/null.rs b/core/src/renderer/null.rs
index 88c58825..22afb058 100644
--- a/core/src/renderer/null.rs
+++ b/core/src/renderer/null.rs
@@ -62,6 +62,7 @@ impl text::Renderer for Null {
_size: f32,
_font: Font,
_bounds: Size,
+ _shaping: text::Shaping,
) -> (f32, f32) {
(0.0, 20.0)
}
@@ -72,6 +73,7 @@ impl text::Renderer for Null {
_size: f32,
_font: Self::Font,
_bounds: Size,
+ _shaping: text::Shaping,
_point: Point,
_nearest_only: bool,
) -> Option<text::Hit> {
diff --git a/core/src/text.rs b/core/src/text.rs
index 4c72abc3..c59d8fce 100644
--- a/core/src/text.rs
+++ b/core/src/text.rs
@@ -27,6 +27,33 @@ pub struct Text<'a, Font> {
/// The vertical alignment of the [`Text`].
pub vertical_alignment: alignment::Vertical,
+
+ /// The [`Shaping`] strategy of the [`Text`].
+ pub shaping: Shaping,
+}
+
+/// The shaping strategy of some text.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
+pub enum Shaping {
+ /// No shaping and no font fallback.
+ ///
+ /// This shaping strategy is very cheap, but it will not display complex
+ /// scripts properly nor try to find missing glyphs in your system fonts.
+ ///
+ /// 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]
+ Basic,
+ /// Advanced text shaping and font fallback.
+ ///
+ /// You will need to enable this flag if the text contains a complex
+ /// script, the font used needs it, and/or multiple fonts in your system
+ /// may be needed to display all of the glyphs.
+ ///
+ /// Advanced shaping is expensive! You should only enable it when necessary.
+ Advanced,
}
/// The result of hit testing on text.
@@ -77,11 +104,19 @@ pub trait Renderer: crate::Renderer {
size: f32,
font: Self::Font,
bounds: Size,
+ shaping: Shaping,
) -> (f32, f32);
/// Measures the width of the text as if it were laid out in a single line.
- fn measure_width(&self, content: &str, size: f32, font: Self::Font) -> f32 {
- let (width, _) = self.measure(content, size, font, Size::INFINITY);
+ fn measure_width(
+ &self,
+ content: &str,
+ size: f32,
+ font: Self::Font,
+ shaping: Shaping,
+ ) -> f32 {
+ let (width, _) =
+ self.measure(content, size, font, Size::INFINITY, shaping);
width
}
@@ -99,6 +134,7 @@ pub trait Renderer: crate::Renderer {
size: f32,
font: Self::Font,
bounds: Size,
+ shaping: Shaping,
point: Point,
nearest_only: bool,
) -> Option<Hit>;
diff --git a/core/src/widget/text.rs b/core/src/widget/text.rs
index 3193ba84..f0392168 100644
--- a/core/src/widget/text.rs
+++ b/core/src/widget/text.rs
@@ -24,6 +24,7 @@ where
horizontal_alignment: alignment::Horizontal,
vertical_alignment: alignment::Vertical,
font: Option<Renderer::Font>,
+ shaping: text::Shaping,
style: <Renderer::Theme as StyleSheet>::Style,
}
@@ -42,6 +43,7 @@ where
height: Length::Shrink,
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
+ shaping: text::Shaping::Basic,
style: Default::default(),
}
}
@@ -98,6 +100,12 @@ where
self.vertical_alignment = alignment;
self
}
+
+ /// Sets the [`text::Shaping`] strategy of the [`Text`].
+ pub fn shaping(mut self, shaping: text::Shaping) -> Self {
+ self.shaping = shaping;
+ self
+ }
}
impl<'a, Message, Renderer> Widget<Message, Renderer> for Text<'a, Renderer>
@@ -129,6 +137,7 @@ where
size,
self.font.unwrap_or_else(|| renderer.default_font()),
bounds,
+ self.shaping,
);
let size = limits.resolve(Size::new(width, height));
@@ -156,6 +165,7 @@ where
theme.appearance(self.style.clone()),
self.horizontal_alignment,
self.vertical_alignment,
+ self.shaping,
);
}
}
@@ -180,6 +190,7 @@ pub fn draw<Renderer>(
appearance: Appearance,
horizontal_alignment: alignment::Horizontal,
vertical_alignment: alignment::Vertical,
+ shaping: text::Shaping,
) where
Renderer: text::Renderer,
{
@@ -205,6 +216,7 @@ pub fn draw<Renderer>(
font: font.unwrap_or_else(|| renderer.default_font()),
horizontal_alignment,
vertical_alignment,
+ shaping,
});
}
@@ -234,6 +246,7 @@ where
vertical_alignment: self.vertical_alignment,
font: self.font,
style: self.style.clone(),
+ shaping: self.shaping,
}
}
}
diff --git a/examples/checkbox/src/main.rs b/examples/checkbox/src/main.rs
index c5f3c134..5852e978 100644
--- a/examples/checkbox/src/main.rs
+++ b/examples/checkbox/src/main.rs
@@ -1,6 +1,6 @@
use iced::executor;
use iced::font::{self, Font};
-use iced::widget::{checkbox, column, container};
+use iced::widget::{checkbox, column, container, text};
use iced::{Application, Command, Element, Length, Settings, Theme};
const ICON_FONT: Font = Font::with_name("icons");
@@ -59,6 +59,7 @@ impl Application for Example {
font: ICON_FONT,
code_point: '\u{e901}',
size: None,
+ shaping: text::Shaping::Basic,
});
let content = column![default_checkbox, custom_checkbox].spacing(22);
diff --git a/examples/todos/src/main.rs b/examples/todos/src/main.rs
index 8bc7be09..6ad7b4fb 100644
--- a/examples/todos/src/main.rs
+++ b/examples/todos/src/main.rs
@@ -364,7 +364,8 @@ impl Task {
self.completed,
TaskMessage::Completed,
)
- .width(Length::Fill);
+ .width(Length::Fill)
+ .text_shaping(text::Shaping::Advanced);
row![
checkbox,
diff --git a/graphics/src/backend.rs b/graphics/src/backend.rs
index dd2888ab..0c2a6d30 100644
--- a/graphics/src/backend.rs
+++ b/graphics/src/backend.rs
@@ -48,6 +48,7 @@ pub trait Text {
size: f32,
font: Font,
bounds: Size,
+ shaping: text::Shaping,
) -> (f32, f32);
/// Tests whether the provided point is within the boundaries of [`Text`]
@@ -63,6 +64,7 @@ pub trait Text {
size: f32,
font: Font,
bounds: Size,
+ shaping: text::Shaping,
point: Point,
nearest_only: bool,
) -> Option<text::Hit>;
diff --git a/graphics/src/geometry/text.rs b/graphics/src/geometry/text.rs
index 0befd635..0f731e74 100644
--- a/graphics/src/geometry/text.rs
+++ b/graphics/src/geometry/text.rs
@@ -1,5 +1,6 @@
-use iced_core::alignment;
-use iced_core::{Color, Font, Point};
+use crate::core::alignment;
+use crate::core::text::Shaping;
+use crate::core::{Color, Font, Point};
/// A bunch of text that can be drawn to a canvas
#[derive(Debug, Clone)]
@@ -25,6 +26,8 @@ pub struct Text {
pub horizontal_alignment: alignment::Horizontal,
/// The vertical alignment of the text
pub vertical_alignment: alignment::Vertical,
+ /// The shaping strategy of the text.
+ pub shaping: Shaping,
}
impl Default for Text {
@@ -37,6 +40,7 @@ impl Default for Text {
font: Font::default(),
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
+ shaping: Shaping::Basic,
}
}
}
diff --git a/graphics/src/primitive.rs b/graphics/src/primitive.rs
index d6a2c4c4..db237035 100644
--- a/graphics/src/primitive.rs
+++ b/graphics/src/primitive.rs
@@ -1,7 +1,8 @@
-use iced_core::alignment;
-use iced_core::image;
-use iced_core::svg;
-use iced_core::{Background, Color, Font, Gradient, Rectangle, Size, Vector};
+use crate::core::alignment;
+use crate::core::image;
+use crate::core::svg;
+use crate::core::text;
+use crate::core::{Background, Color, Font, Gradient, Rectangle, Size, Vector};
use bytemuck::{Pod, Zeroable};
use std::sync::Arc;
@@ -26,6 +27,8 @@ pub enum Primitive {
horizontal_alignment: alignment::Horizontal,
/// The vertical alignment of the text
vertical_alignment: alignment::Vertical,
+ /// The shaping strategy of the text.
+ shaping: text::Shaping,
},
/// A quad primitive
Quad {
diff --git a/graphics/src/renderer.rs b/graphics/src/renderer.rs
index 23e594be..605286d6 100644
--- a/graphics/src/renderer.rs
+++ b/graphics/src/renderer.rs
@@ -138,8 +138,9 @@ where
size: f32,
font: Font,
bounds: Size,
+ shaping: text::Shaping,
) -> (f32, f32) {
- self.backend().measure(content, size, font, bounds)
+ self.backend().measure(content, size, font, bounds, shaping)
}
fn hit_test(
@@ -148,6 +149,7 @@ where
size: f32,
font: Font,
bounds: Size,
+ shaping: text::Shaping,
point: Point,
nearest_only: bool,
) -> Option<text::Hit> {
@@ -156,6 +158,7 @@ where
size,
font,
bounds,
+ shaping,
point,
nearest_only,
)
@@ -174,6 +177,7 @@ where
font: text.font,
horizontal_alignment: text.horizontal_alignment,
vertical_alignment: text.vertical_alignment,
+ shaping: text.shaping,
});
}
}
diff --git a/renderer/src/backend.rs b/renderer/src/backend.rs
index 120dd644..70b146f4 100644
--- a/renderer/src/backend.rs
+++ b/renderer/src/backend.rs
@@ -48,8 +48,13 @@ impl backend::Text for Backend {
size: f32,
font: Font,
bounds: Size,
+ shaping: text::Shaping,
) -> (f32, f32) {
- delegate!(self, backend, backend.measure(contents, size, font, bounds))
+ delegate!(
+ self,
+ backend,
+ backend.measure(contents, size, font, bounds, shaping)
+ )
}
fn hit_test(
@@ -58,6 +63,7 @@ impl backend::Text for Backend {
size: f32,
font: Font,
bounds: Size,
+ shaping: text::Shaping,
position: Point,
nearest_only: bool,
) -> Option<text::Hit> {
@@ -69,8 +75,9 @@ impl backend::Text for Backend {
size,
font,
bounds,
+ shaping,
position,
- nearest_only
+ nearest_only,
)
)
}
diff --git a/tiny_skia/Cargo.toml b/tiny_skia/Cargo.toml
index a3bddc93..400eee6a 100644
--- a/tiny_skia/Cargo.toml
+++ b/tiny_skia/Cargo.toml
@@ -12,7 +12,6 @@ geometry = ["iced_graphics/geometry"]
raw-window-handle = "0.5"
softbuffer = "0.2"
tiny-skia = "0.9"
-cosmic-text = "0.8"
bytemuck = "1"
rustc-hash = "1.1"
kurbo = "0.9"
@@ -23,6 +22,10 @@ version = "0.8"
path = "../graphics"
features = ["tiny-skia"]
+[dependencies.cosmic-text]
+git = "https://github.com/hecrj/cosmic-text.git"
+rev = "b85d6a4f2376f8a8a7dadc0f8bcb89d4db10a1c9"
+
[dependencies.twox-hash]
version = "1.6"
default-features = false
diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs
index 9c69e1d2..3ef7e717 100644
--- a/tiny_skia/src/backend.rs
+++ b/tiny_skia/src/backend.rs
@@ -219,6 +219,7 @@ impl Backend {
font,
horizontal_alignment,
vertical_alignment,
+ shaping,
} => {
let physical_bounds =
(primitive.bounds() + translation) * scale_factor;
@@ -238,6 +239,7 @@ impl Backend {
*font,
*horizontal_alignment,
*vertical_alignment,
+ *shaping,
pixels,
clip_mask,
);
@@ -626,8 +628,10 @@ impl backend::Text for Backend {
size: f32,
font: Font,
bounds: Size,
+ shaping: text::Shaping,
) -> (f32, f32) {
- self.text_pipeline.measure(contents, size, font, bounds)
+ self.text_pipeline
+ .measure(contents, size, font, bounds, shaping)
}
fn hit_test(
@@ -636,6 +640,7 @@ impl backend::Text for Backend {
size: f32,
font: Font,
bounds: Size,
+ shaping: text::Shaping,
point: Point,
nearest_only: bool,
) -> Option<text::Hit> {
@@ -644,6 +649,7 @@ impl backend::Text for Backend {
size,
font,
bounds,
+ shaping,
point,
nearest_only,
)
diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs
index 508965ad..7963fd89 100644
--- a/tiny_skia/src/geometry.rs
+++ b/tiny_skia/src/geometry.rs
@@ -114,6 +114,7 @@ impl Frame {
font: text.font,
horizontal_alignment: text.horizontal_alignment,
vertical_alignment: text.vertical_alignment,
+ shaping: text.shaping,
});
}
diff --git a/tiny_skia/src/text.rs b/tiny_skia/src/text.rs
index 1246bbd5..58079cc0 100644
--- a/tiny_skia/src/text.rs
+++ b/tiny_skia/src/text.rs
@@ -1,6 +1,6 @@
use crate::core::alignment;
use crate::core::font::{self, Font};
-use crate::core::text::Hit;
+use crate::core::text::{Hit, Shaping};
use crate::core::{Color, Point, Rectangle, Size};
use rustc_hash::{FxHashMap, FxHashSet};
@@ -49,6 +49,7 @@ impl Pipeline {
font: Font,
horizontal_alignment: alignment::Horizontal,
vertical_alignment: alignment::Vertical,
+ shaping: Shaping,
pixels: &mut tiny_skia::PixmapMut<'_>,
clip_mask: Option<&tiny_skia::Mask>,
) {
@@ -63,6 +64,7 @@ impl Pipeline {
content,
font,
size,
+ shaping,
};
let (_, buffer) = self.render_cache.allocate(font_system, key);
@@ -130,6 +132,7 @@ impl Pipeline {
size: f32,
font: Font,
bounds: Size,
+ shaping: Shaping,
) -> (f32, f32) {
let mut measurement_cache = self.measurement_cache.borrow_mut();
@@ -140,6 +143,7 @@ impl Pipeline {
size,
font,
bounds,
+ shaping,
},
);
@@ -159,6 +163,7 @@ impl Pipeline {
size: f32,
font: Font,
bounds: Size,
+ shaping: Shaping,
point: Point,
_nearest_only: bool,
) -> Option<Hit> {
@@ -171,6 +176,7 @@ impl Pipeline {
size,
font,
bounds,
+ shaping,
},
);
@@ -223,6 +229,13 @@ fn to_stretch(stretch: font::Stretch) -> cosmic_text::Stretch {
}
}
+fn to_shaping(shaping: Shaping) -> cosmic_text::Shaping {
+ match shaping {
+ Shaping::Basic => cosmic_text::Shaping::Basic,
+ Shaping::Advanced => cosmic_text::Shaping::Advanced,
+ }
+}
+
#[derive(Debug, Clone, Default)]
struct GlyphCache {
entries: FxHashMap<
@@ -390,6 +403,7 @@ impl Cache {
.family(to_family(key.font.family))
.weight(to_weight(key.font.weight))
.stretch(to_stretch(key.font.stretch)),
+ to_shaping(key.shaping),
);
let _ = entry.insert(buffer);
@@ -420,6 +434,7 @@ struct Key<'a> {
size: f32,
font: Font,
bounds: Size,
+ shaping: Shaping,
}
type KeyHash = u64;
diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml
index 9f9bd066..6934ae49 100644
--- a/wgpu/Cargo.toml
+++ b/wgpu/Cargo.toml
@@ -44,7 +44,7 @@ path = "../graphics"
[dependencies.glyphon]
version = "0.2"
git = "https://github.com/hecrj/glyphon.git"
-rev = "1d26d92b19407c5dabe4625944d4a6babbbf0715"
+rev = "504aa8a9a1fb42726f02fa244b70119e7ca25933"
[dependencies.encase]
version = "0.3.0"
diff --git a/wgpu/fonts/Iced-Icons.ttf b/wgpu/fonts/Iced-Icons.ttf
index 7112f086..e3273141 100644
--- a/wgpu/fonts/Iced-Icons.ttf
+++ b/wgpu/fonts/Iced-Icons.ttf
Binary files differ
diff --git a/wgpu/src/backend.rs b/wgpu/src/backend.rs
index 9772781a..6b847aff 100644
--- a/wgpu/src/backend.rs
+++ b/wgpu/src/backend.rs
@@ -354,8 +354,10 @@ impl backend::Text for Backend {
size: f32,
font: Font,
bounds: Size,
+ shaping: core::text::Shaping,
) -> (f32, f32) {
- self.text_pipeline.measure(contents, size, font, bounds)
+ self.text_pipeline
+ .measure(contents, size, font, bounds, shaping)
}
fn hit_test(
@@ -364,6 +366,7 @@ impl backend::Text for Backend {
size: f32,
font: Font,
bounds: Size,
+ shaping: core::text::Shaping,
point: Point,
nearest_only: bool,
) -> Option<core::text::Hit> {
@@ -372,6 +375,7 @@ impl backend::Text for Backend {
size,
font,
bounds,
+ shaping,
point,
nearest_only,
)
diff --git a/wgpu/src/geometry.rs b/wgpu/src/geometry.rs
index 59ec31fe..f6397ab7 100644
--- a/wgpu/src/geometry.rs
+++ b/wgpu/src/geometry.rs
@@ -334,6 +334,7 @@ impl Frame {
font: text.font,
horizontal_alignment: text.horizontal_alignment,
vertical_alignment: text.vertical_alignment,
+ shaping: text.shaping,
});
}
diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs
index c4723397..b9fd044e 100644
--- a/wgpu/src/layer.rs
+++ b/wgpu/src/layer.rs
@@ -10,6 +10,7 @@ pub use mesh::Mesh;
pub use quad::Quad;
pub use text::Text;
+use crate::core;
use crate::core::alignment;
use crate::core::{Background, Color, Font, Point, Rectangle, Size, Vector};
use crate::graphics::{Primitive, Viewport};
@@ -64,6 +65,7 @@ impl<'a> Layer<'a> {
font: Font::MONOSPACE,
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
+ shaping: core::text::Shaping::Basic,
};
overlay.text.push(text);
@@ -116,6 +118,7 @@ impl<'a> Layer<'a> {
font,
horizontal_alignment,
vertical_alignment,
+ shaping,
} => {
let layer = &mut layers[current_layer];
@@ -127,6 +130,7 @@ impl<'a> Layer<'a> {
font: *font,
horizontal_alignment: *horizontal_alignment,
vertical_alignment: *vertical_alignment,
+ shaping: *shaping,
});
}
Primitive::Quad {
diff --git a/wgpu/src/layer/text.rs b/wgpu/src/layer/text.rs
index fdbdaafb..665f7188 100644
--- a/wgpu/src/layer/text.rs
+++ b/wgpu/src/layer/text.rs
@@ -1,4 +1,5 @@
use crate::core::alignment;
+use crate::core::text;
use crate::core::{Color, Font, Rectangle};
/// A paragraph of text.
@@ -24,4 +25,7 @@ pub struct Text<'a> {
/// The vertical alignment of the [`Text`].
pub vertical_alignment: alignment::Vertical,
+
+ /// The shaping strategy of the text.
+ pub shaping: text::Shaping,
}
diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs
index f01e0b42..ad7bdc8d 100644
--- a/wgpu/src/text.rs
+++ b/wgpu/src/text.rs
@@ -1,6 +1,6 @@
use crate::core::alignment;
use crate::core::font::{self, Font};
-use crate::core::text::Hit;
+use crate::core::text::{Hit, Shaping};
use crate::core::{Point, Rectangle, Size};
use crate::layer::Text;
@@ -83,6 +83,7 @@ impl Pipeline {
height: (section.bounds.height * scale_factor)
.ceil(),
},
+ shaping: section.shaping,
},
);
@@ -213,6 +214,7 @@ impl Pipeline {
size: f32,
font: Font,
bounds: Size,
+ shaping: Shaping,
) -> (f32, f32) {
let mut measurement_cache = self.measurement_cache.borrow_mut();
@@ -223,6 +225,7 @@ impl Pipeline {
size,
font,
bounds,
+ shaping,
},
);
@@ -242,6 +245,7 @@ impl Pipeline {
size: f32,
font: Font,
bounds: Size,
+ shaping: Shaping,
point: Point,
_nearest_only: bool,
) -> Option<Hit> {
@@ -254,6 +258,7 @@ impl Pipeline {
size,
font,
bounds,
+ shaping,
},
);
@@ -306,6 +311,13 @@ fn to_stretch(stretch: font::Stretch) -> glyphon::Stretch {
}
}
+fn to_shaping(shaping: Shaping) -> glyphon::Shaping {
+ match shaping {
+ Shaping::Basic => glyphon::Shaping::Basic,
+ Shaping::Advanced => glyphon::Shaping::Advanced,
+ }
+}
+
struct Cache {
entries: FxHashMap<KeyHash, glyphon::Buffer>,
recently_used: FxHashSet<KeyHash>,
@@ -364,6 +376,7 @@ impl Cache {
.family(to_family(key.font.family))
.weight(to_weight(key.font.weight))
.stretch(to_stretch(key.font.stretch)),
+ to_shaping(key.shaping),
);
let _ = entry.insert(buffer);
@@ -388,6 +401,7 @@ struct Key<'a> {
size: f32,
font: Font,
bounds: Size,
+ shaping: Shaping,
}
type KeyHash = u64;
diff --git a/widget/src/checkbox.rs b/widget/src/checkbox.rs
index 6505cfdd..2a09b8fd 100644
--- a/widget/src/checkbox.rs
+++ b/widget/src/checkbox.rs
@@ -46,6 +46,7 @@ where
size: f32,
spacing: f32,
text_size: Option<f32>,
+ text_shaping: text::Shaping,
font: Option<Renderer::Font>,
icon: Icon<Renderer::Font>,
style: <Renderer::Theme as StyleSheet>::Style,
@@ -82,11 +83,13 @@ where
size: Self::DEFAULT_SIZE,
spacing: Self::DEFAULT_SPACING,
text_size: None,
+ text_shaping: text::Shaping::Basic,
font: None,
icon: Icon {
font: Renderer::ICON_FONT,
code_point: Renderer::CHECKMARK_ICON,
size: None,
+ shaping: text::Shaping::Basic,
},
style: Default::default(),
}
@@ -116,6 +119,12 @@ where
self
}
+ /// Sets the [`text::Shaping`] strategy of the [`Checkbox`].
+ pub fn text_shaping(mut self, shaping: text::Shaping) -> Self {
+ self.text_shaping = shaping;
+ self
+ }
+
/// Sets the [`Font`] of the text of the [`Checkbox`].
///
/// [`Font`]: crate::text::Renderer::Font
@@ -171,7 +180,8 @@ where
.size(
self.text_size
.unwrap_or_else(|| renderer.default_size()),
- ),
+ )
+ .shaping(self.text_shaping),
)
.layout(renderer, limits)
}
@@ -257,6 +267,7 @@ where
font,
code_point,
size,
+ shaping,
} = &self.icon;
let size = size.unwrap_or(bounds.height * 0.7);
@@ -273,6 +284,7 @@ where
color: custom_style.icon_color,
horizontal_alignment: alignment::Horizontal::Center,
vertical_alignment: alignment::Vertical::Center,
+ shaping: *shaping,
});
}
}
@@ -292,6 +304,7 @@ where
},
alignment::Horizontal::Left,
alignment::Vertical::Center,
+ self.text_shaping,
);
}
}
@@ -320,4 +333,6 @@ pub struct Icon<Font> {
pub code_point: char,
/// Font size of the content.
pub size: Option<f32>,
+ /// The shaping strategy of the icon.
+ pub shaping: text::Shaping,
}
diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs
index c322c8ba..7de3cbae 100644
--- a/widget/src/overlay/menu.rs
+++ b/widget/src/overlay/menu.rs
@@ -31,6 +31,7 @@ where
width: f32,
padding: Padding,
text_size: Option<f32>,
+ text_shaping: text::Shaping,
font: Option<Renderer::Font>,
style: <Renderer::Theme as StyleSheet>::Style,
}
@@ -58,6 +59,7 @@ where
width: 0.0,
padding: Padding::ZERO,
text_size: None,
+ text_shaping: text::Shaping::Basic,
font: None,
style: Default::default(),
}
@@ -81,6 +83,12 @@ where
self
}
+ /// Sets the [`text::Shaping`] strategy of the [`Menu`].
+ pub fn text_shaping(mut self, shaping: text::Shaping) -> Self {
+ self.text_shaping = shaping;
+ self
+ }
+
/// Sets the font of the [`Menu`].
pub fn font(mut self, font: impl Into<Renderer::Font>) -> Self {
self.font = Some(font.into());
@@ -168,6 +176,7 @@ where
padding,
font,
text_size,
+ text_shaping,
style,
} = menu;
@@ -177,6 +186,7 @@ where
last_selection,
font,
text_size,
+ text_shaping,
padding,
style: style.clone(),
}));
@@ -311,6 +321,7 @@ where
last_selection: &'a mut Option<T>,
padding: Padding,
text_size: Option<f32>,
+ text_shaping: text::Shaping,
font: Option<Renderer::Font>,
style: <Renderer::Theme as StyleSheet>::Style,
}
@@ -500,6 +511,7 @@ where
},
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Center,
+ shaping: self.text_shaping,
});
}
}
diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs
index cd23cdd2..c0cb2946 100644
--- a/widget/src/pick_list.rs
+++ b/widget/src/pick_list.rs
@@ -36,6 +36,7 @@ where
width: Length,
padding: Padding,
text_size: Option<f32>,
+ text_shaping: text::Shaping,
font: Option<Renderer::Font>,
handle: Handle<Renderer::Font>,
style: <Renderer::Theme as StyleSheet>::Style,
@@ -71,6 +72,7 @@ where
width: Length::Shrink,
padding: Self::DEFAULT_PADDING,
text_size: None,
+ text_shaping: text::Shaping::Basic,
font: None,
handle: Default::default(),
style: Default::default(),
@@ -101,6 +103,12 @@ where
self
}
+ /// Sets the [`text::Shaping`] strategy of the [`PickList`].
+ pub fn text_shaping(mut self, shaping: text::Shaping) -> Self {
+ self.text_shaping = shaping;
+ self
+ }
+
/// Sets the font of the [`PickList`].
pub fn font(mut self, font: impl Into<Renderer::Font>) -> Self {
self.font = Some(font.into());
@@ -164,6 +172,7 @@ where
self.width,
self.padding,
self.text_size,
+ self.text_shaping,
self.font,
self.placeholder.as_deref(),
&self.options,
@@ -221,6 +230,7 @@ where
cursor_position,
self.padding,
self.text_size,
+ self.text_shaping,
font,
self.placeholder.as_deref(),
self.selected.as_ref(),
@@ -243,6 +253,7 @@ where
state,
self.padding,
self.text_size,
+ self.text_shaping,
self.font.unwrap_or_else(|| renderer.default_font()),
&self.options,
self.style.clone(),
@@ -336,6 +347,8 @@ pub struct Icon<Font> {
pub code_point: char,
/// Font size of the content.
pub size: Option<f32>,
+ /// The shaping strategy of the icon.
+ pub shaping: text::Shaping,
}
/// Computes the layout of a [`PickList`].
@@ -345,6 +358,7 @@ pub fn layout<Renderer, T>(
width: Length,
padding: Padding,
text_size: Option<f32>,
+ text_shaping: text::Shaping,
font: Option<Renderer::Font>,
placeholder: Option<&str>,
options: &[T],
@@ -366,6 +380,7 @@ where
text_size,
font.unwrap_or_else(|| renderer.default_font()),
Size::new(f32::INFINITY, f32::INFINITY),
+ text_shaping,
);
width.round()
@@ -515,6 +530,7 @@ pub fn overlay<'a, T, Message, Renderer>(
state: &'a mut State<T>,
padding: Padding,
text_size: Option<f32>,
+ text_shaping: text::Shaping,
font: Renderer::Font,
options: &'a [T],
style: <Renderer::Theme as StyleSheet>::Style,
@@ -542,6 +558,7 @@ where
.width(bounds.width)
.padding(padding)
.font(font)
+ .text_shaping(text_shaping)
.style(style);
if let Some(text_size) = text_size {
@@ -562,6 +579,7 @@ pub fn draw<'a, T, Renderer>(
cursor_position: Point,
padding: Padding,
text_size: Option<f32>,
+ text_shaping: text::Shaping,
font: Renderer::Font,
placeholder: Option<&str>,
selected: Option<&T>,
@@ -594,25 +612,34 @@ pub fn draw<'a, T, Renderer>(
);
let handle = match handle {
- Handle::Arrow { size } => {
- Some((Renderer::ICON_FONT, Renderer::ARROW_DOWN_ICON, *size))
- }
+ Handle::Arrow { size } => Some((
+ Renderer::ICON_FONT,
+ Renderer::ARROW_DOWN_ICON,
+ *size,
+ text::Shaping::Basic,
+ )),
Handle::Static(Icon {
font,
code_point,
size,
- }) => Some((*font, *code_point, *size)),
+ shaping,
+ }) => Some((*font, *code_point, *size, *shaping)),
Handle::Dynamic { open, closed } => {
if state().is_open {
- Some((open.font, open.code_point, open.size))
+ Some((open.font, open.code_point, open.size, open.shaping))
} else {
- Some((closed.font, closed.code_point, closed.size))
+ Some((
+ closed.font,
+ closed.code_point,
+ closed.size,
+ closed.shaping,
+ ))
}
}
Handle::None => None,
};
- if let Some((font, code_point, size)) = handle {
+ if let Some((font, code_point, size, shaping)) = handle {
let size = size.unwrap_or_else(|| renderer.default_size());
renderer.fill_text(Text {
@@ -628,6 +655,7 @@ pub fn draw<'a, T, Renderer>(
},
horizontal_alignment: alignment::Horizontal::Right,
vertical_alignment: alignment::Vertical::Center,
+ shaping,
});
}
@@ -653,6 +681,7 @@ pub fn draw<'a, T, Renderer>(
},
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Center,
+ shaping: text_shaping,
});
}
}
diff --git a/widget/src/radio.rs b/widget/src/radio.rs
index c3229aed..f62f4703 100644
--- a/widget/src/radio.rs
+++ b/widget/src/radio.rs
@@ -81,6 +81,7 @@ where
size: f32,
spacing: f32,
text_size: Option<f32>,
+ text_shaping: text::Shaping,
font: Option<Renderer::Font>,
style: <Renderer::Theme as StyleSheet>::Style,
}
@@ -123,6 +124,7 @@ where
size: Self::DEFAULT_SIZE,
spacing: Self::DEFAULT_SPACING, //15
text_size: None,
+ text_shaping: text::Shaping::Basic,
font: None,
style: Default::default(),
}
@@ -152,6 +154,12 @@ where
self
}
+ /// Sets the [`text::Shaping`] strategy of the [`Radio`] button.
+ pub fn text_shaping(mut self, shaping: text::Shaping) -> Self {
+ self.text_shaping = shaping;
+ self
+ }
+
/// Sets the text font of the [`Radio`] button.
pub fn font(mut self, font: impl Into<Renderer::Font>) -> Self {
self.font = Some(font.into());
@@ -192,9 +200,15 @@ where
.spacing(self.spacing)
.align_items(Alignment::Center)
.push(Row::new().width(self.size).height(self.size))
- .push(Text::new(&self.label).width(self.width).size(
- self.text_size.unwrap_or_else(|| renderer.default_size()),
- ))
+ .push(
+ Text::new(&self.label)
+ .width(self.width)
+ .size(
+ self.text_size
+ .unwrap_or_else(|| renderer.default_size()),
+ )
+ .shaping(self.text_shaping),
+ )
.layout(renderer, limits)
}
@@ -309,6 +323,7 @@ where
},
alignment::Horizontal::Left,
alignment::Vertical::Center,
+ self.text_shaping,
);
}
}
diff --git a/widget/src/text.rs b/widget/src/text.rs
index 04c31edc..50aa1370 100644
--- a/widget/src/text.rs
+++ b/widget/src/text.rs
@@ -1,3 +1,4 @@
+pub use crate::core::text::Shaping;
pub use crate::core::widget::text::*;
pub type Text<'a, Renderer = crate::Renderer> =
diff --git a/widget/src/text_input.rs b/widget/src/text_input.rs
index 9db382f7..32d0b1f8 100644
--- a/widget/src/text_input.rs
+++ b/widget/src/text_input.rs
@@ -463,6 +463,7 @@ where
&icon.code_point.to_string(),
icon.size.unwrap_or_else(|| renderer.default_size()),
icon.font,
+ text::Shaping::Advanced,
);
let mut text_node = layout::Node::new(
@@ -975,6 +976,7 @@ pub fn draw<Renderer>(
bounds: icon_layout.bounds(),
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
+ shaping: text::Shaping::Advanced,
});
}
@@ -1079,6 +1081,7 @@ pub fn draw<Renderer>(
if text.is_empty() { placeholder } else { &text },
size,
font,
+ text::Shaping::Advanced,
);
let render = |renderer: &mut Renderer| {
@@ -1106,6 +1109,7 @@ pub fn draw<Renderer>(
size,
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Center,
+ shaping: text::Shaping::Advanced,
});
};
@@ -1310,8 +1314,12 @@ where
{
let text_before_cursor = value.until(cursor_index).to_string();
- let text_value_width =
- renderer.measure_width(&text_before_cursor, size, font);
+ let text_value_width = renderer.measure_width(
+ &text_before_cursor,
+ size,
+ font,
+ text::Shaping::Advanced,
+ );
let offset = ((text_value_width + 5.0) - text_bounds.width).max(0.0);
@@ -1344,6 +1352,7 @@ where
size,
font,
Size::INFINITY,
+ text::Shaping::Advanced,
Point::new(x + offset, text_bounds.height / 2.0),
true,
)
diff --git a/widget/src/toggler.rs b/widget/src/toggler.rs
index 713a9c30..639bbb3b 100644
--- a/widget/src/toggler.rs
+++ b/widget/src/toggler.rs
@@ -43,6 +43,7 @@ where
size: f32,
text_size: Option<f32>,
text_alignment: alignment::Horizontal,
+ text_shaping: text::Shaping,
spacing: f32,
font: Option<Renderer::Font>,
style: <Renderer::Theme as StyleSheet>::Style,
@@ -80,6 +81,7 @@ where
size: Self::DEFAULT_SIZE,
text_size: None,
text_alignment: alignment::Horizontal::Left,
+ text_shaping: text::Shaping::Basic,
spacing: 0.0,
font: None,
style: Default::default(),
@@ -110,6 +112,12 @@ where
self
}
+ /// Sets the [`text::Shaping`] strategy of the [`Toggler`].
+ pub fn text_shaping(mut self, shaping: text::Shaping) -> Self {
+ self.text_shaping = shaping;
+ self
+ }
+
/// Sets the spacing between the [`Toggler`] and the text.
pub fn spacing(mut self, spacing: impl Into<Pixels>) -> Self {
self.spacing = spacing.into().0;
@@ -167,7 +175,8 @@ where
.size(
self.text_size
.unwrap_or_else(|| renderer.default_size()),
- ),
+ )
+ .shaping(self.text_shaping),
);
}
@@ -249,6 +258,7 @@ where
Default::default(),
self.text_alignment,
alignment::Vertical::Center,
+ self.text_shaping,
);
}