Introduce text::Shaping enum and replace magic boolean
This commit is contained in:
parent
33b5a90019
commit
4bd290afe7
25 changed files with 203 additions and 132 deletions
|
|
@ -62,7 +62,7 @@ impl text::Renderer for Null {
|
||||||
_size: f32,
|
_size: f32,
|
||||||
_font: Font,
|
_font: Font,
|
||||||
_bounds: Size,
|
_bounds: Size,
|
||||||
_needs_shaping: bool,
|
_shaping: text::Shaping,
|
||||||
) -> (f32, f32) {
|
) -> (f32, f32) {
|
||||||
(0.0, 20.0)
|
(0.0, 20.0)
|
||||||
}
|
}
|
||||||
|
|
@ -73,9 +73,9 @@ impl text::Renderer for Null {
|
||||||
_size: f32,
|
_size: f32,
|
||||||
_font: Self::Font,
|
_font: Self::Font,
|
||||||
_bounds: Size,
|
_bounds: Size,
|
||||||
|
_shaping: text::Shaping,
|
||||||
_point: Point,
|
_point: Point,
|
||||||
_nearest_only: bool,
|
_nearest_only: bool,
|
||||||
_advanced_shape: bool,
|
|
||||||
) -> Option<text::Hit> {
|
) -> Option<text::Hit> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,14 +28,32 @@ pub struct Text<'a, Font> {
|
||||||
/// The vertical alignment of the [`Text`].
|
/// The vertical alignment of the [`Text`].
|
||||||
pub vertical_alignment: alignment::Vertical,
|
pub vertical_alignment: alignment::Vertical,
|
||||||
|
|
||||||
/// Whether the [`Text`] needs advanced shaping and font fallback.
|
/// 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
|
/// 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
|
/// script, the font used needs it, and/or multiple fonts in your system
|
||||||
/// 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.
|
||||||
pub advanced_shape: bool,
|
Advanced,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The result of hit testing on text.
|
/// The result of hit testing on text.
|
||||||
|
|
@ -86,7 +104,7 @@ pub trait Renderer: crate::Renderer {
|
||||||
size: f32,
|
size: f32,
|
||||||
font: Self::Font,
|
font: Self::Font,
|
||||||
bounds: Size,
|
bounds: Size,
|
||||||
advanced_shape: bool,
|
shaping: Shaping,
|
||||||
) -> (f32, f32);
|
) -> (f32, f32);
|
||||||
|
|
||||||
/// Measures the width of the text as if it were laid out in a single line.
|
/// Measures the width of the text as if it were laid out in a single line.
|
||||||
|
|
@ -95,10 +113,10 @@ pub trait Renderer: crate::Renderer {
|
||||||
content: &str,
|
content: &str,
|
||||||
size: f32,
|
size: f32,
|
||||||
font: Self::Font,
|
font: Self::Font,
|
||||||
advanced_shape: bool,
|
shaping: Shaping,
|
||||||
) -> f32 {
|
) -> f32 {
|
||||||
let (width, _) =
|
let (width, _) =
|
||||||
self.measure(content, size, font, Size::INFINITY, advanced_shape);
|
self.measure(content, size, font, Size::INFINITY, shaping);
|
||||||
|
|
||||||
width
|
width
|
||||||
}
|
}
|
||||||
|
|
@ -116,9 +134,9 @@ pub trait Renderer: crate::Renderer {
|
||||||
size: f32,
|
size: f32,
|
||||||
font: Self::Font,
|
font: Self::Font,
|
||||||
bounds: Size,
|
bounds: Size,
|
||||||
|
shaping: Shaping,
|
||||||
point: Point,
|
point: Point,
|
||||||
nearest_only: bool,
|
nearest_only: bool,
|
||||||
advanced_shape: bool,
|
|
||||||
) -> Option<Hit>;
|
) -> Option<Hit>;
|
||||||
|
|
||||||
/// Loads a [`Self::Font`] from its bytes.
|
/// Loads a [`Self::Font`] from its bytes.
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ where
|
||||||
horizontal_alignment: alignment::Horizontal,
|
horizontal_alignment: alignment::Horizontal,
|
||||||
vertical_alignment: alignment::Vertical,
|
vertical_alignment: alignment::Vertical,
|
||||||
font: Option<Renderer::Font>,
|
font: Option<Renderer::Font>,
|
||||||
|
shaping: text::Shaping,
|
||||||
style: <Renderer::Theme as StyleSheet>::Style,
|
style: <Renderer::Theme as StyleSheet>::Style,
|
||||||
advanced_shape: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Renderer> Text<'a, Renderer>
|
impl<'a, Renderer> Text<'a, Renderer>
|
||||||
|
|
@ -43,8 +43,8 @@ where
|
||||||
height: Length::Shrink,
|
height: Length::Shrink,
|
||||||
horizontal_alignment: alignment::Horizontal::Left,
|
horizontal_alignment: alignment::Horizontal::Left,
|
||||||
vertical_alignment: alignment::Vertical::Top,
|
vertical_alignment: alignment::Vertical::Top,
|
||||||
|
shaping: text::Shaping::Basic,
|
||||||
style: Default::default(),
|
style: Default::default(),
|
||||||
advanced_shape: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,17 +101,9 @@ where
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enables advanced text shaping and font fallback for the [`Text`].
|
/// Sets the [`text::Shaping`] strategy of the [`Text`].
|
||||||
///
|
pub fn shaping(mut self, shaping: text::Shaping) -> Self {
|
||||||
/// You will need to enable this if the text contains a complex script, the
|
self.shaping = shaping;
|
||||||
/// font used needs it, and/or multiple fonts in your system may be needed
|
|
||||||
/// to display all of the glyphs.
|
|
||||||
///
|
|
||||||
/// If your text isn't displaying properly, try enabling this!
|
|
||||||
///
|
|
||||||
/// Advanced shaping is expensive! You should only enable it when necessary.
|
|
||||||
pub fn advanced_shape(mut self) -> Self {
|
|
||||||
self.advanced_shape = true;
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -145,7 +137,7 @@ where
|
||||||
size,
|
size,
|
||||||
self.font.unwrap_or_else(|| renderer.default_font()),
|
self.font.unwrap_or_else(|| renderer.default_font()),
|
||||||
bounds,
|
bounds,
|
||||||
self.advanced_shape,
|
self.shaping,
|
||||||
);
|
);
|
||||||
|
|
||||||
let size = limits.resolve(Size::new(width, height));
|
let size = limits.resolve(Size::new(width, height));
|
||||||
|
|
@ -173,7 +165,7 @@ where
|
||||||
theme.appearance(self.style.clone()),
|
theme.appearance(self.style.clone()),
|
||||||
self.horizontal_alignment,
|
self.horizontal_alignment,
|
||||||
self.vertical_alignment,
|
self.vertical_alignment,
|
||||||
self.advanced_shape,
|
self.shaping,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -198,7 +190,7 @@ pub fn draw<Renderer>(
|
||||||
appearance: Appearance,
|
appearance: Appearance,
|
||||||
horizontal_alignment: alignment::Horizontal,
|
horizontal_alignment: alignment::Horizontal,
|
||||||
vertical_alignment: alignment::Vertical,
|
vertical_alignment: alignment::Vertical,
|
||||||
advanced_shape: bool,
|
shaping: text::Shaping,
|
||||||
) where
|
) where
|
||||||
Renderer: text::Renderer,
|
Renderer: text::Renderer,
|
||||||
{
|
{
|
||||||
|
|
@ -224,7 +216,7 @@ pub fn draw<Renderer>(
|
||||||
font: font.unwrap_or_else(|| renderer.default_font()),
|
font: font.unwrap_or_else(|| renderer.default_font()),
|
||||||
horizontal_alignment,
|
horizontal_alignment,
|
||||||
vertical_alignment,
|
vertical_alignment,
|
||||||
advanced_shape,
|
shaping,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -254,7 +246,7 @@ where
|
||||||
vertical_alignment: self.vertical_alignment,
|
vertical_alignment: self.vertical_alignment,
|
||||||
font: self.font,
|
font: self.font,
|
||||||
style: self.style.clone(),
|
style: self.style.clone(),
|
||||||
advanced_shape: self.advanced_shape,
|
shaping: self.shaping,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -364,7 +364,8 @@ impl Task {
|
||||||
self.completed,
|
self.completed,
|
||||||
TaskMessage::Completed,
|
TaskMessage::Completed,
|
||||||
)
|
)
|
||||||
.width(Length::Fill);
|
.width(Length::Fill)
|
||||||
|
.text_shaping(text::Shaping::Advanced);
|
||||||
|
|
||||||
row![
|
row![
|
||||||
checkbox,
|
checkbox,
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ pub trait Text {
|
||||||
size: f32,
|
size: f32,
|
||||||
font: Font,
|
font: Font,
|
||||||
bounds: Size,
|
bounds: Size,
|
||||||
advanced_shape: bool,
|
shaping: text::Shaping,
|
||||||
) -> (f32, f32);
|
) -> (f32, f32);
|
||||||
|
|
||||||
/// Tests whether the provided point is within the boundaries of [`Text`]
|
/// Tests whether the provided point is within the boundaries of [`Text`]
|
||||||
|
|
@ -64,9 +64,9 @@ pub trait Text {
|
||||||
size: f32,
|
size: f32,
|
||||||
font: Font,
|
font: Font,
|
||||||
bounds: Size,
|
bounds: Size,
|
||||||
|
shaping: text::Shaping,
|
||||||
point: Point,
|
point: Point,
|
||||||
nearest_only: bool,
|
nearest_only: bool,
|
||||||
advanced_shape: bool,
|
|
||||||
) -> Option<text::Hit>;
|
) -> Option<text::Hit>;
|
||||||
|
|
||||||
/// Loads a [`Font`] from its bytes.
|
/// Loads a [`Font`] from its bytes.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use iced_core::alignment;
|
use crate::core::alignment;
|
||||||
use iced_core::{Color, Font, Point};
|
use crate::core::text::Shaping;
|
||||||
|
use crate::core::{Color, Font, Point};
|
||||||
|
|
||||||
/// A bunch of text that can be drawn to a canvas
|
/// A bunch of text that can be drawn to a canvas
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
@ -25,15 +26,8 @@ pub struct Text {
|
||||||
pub horizontal_alignment: alignment::Horizontal,
|
pub horizontal_alignment: alignment::Horizontal,
|
||||||
/// The vertical alignment of the text
|
/// The vertical alignment of the text
|
||||||
pub vertical_alignment: alignment::Vertical,
|
pub vertical_alignment: alignment::Vertical,
|
||||||
/// Whether the text needs advanced shaping and font fallback.
|
/// The shaping strategy of the text.
|
||||||
///
|
pub shaping: Shaping,
|
||||||
/// 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.
|
|
||||||
pub advanced_shape: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Text {
|
impl Default for Text {
|
||||||
|
|
@ -46,7 +40,7 @@ impl Default for Text {
|
||||||
font: Font::default(),
|
font: Font::default(),
|
||||||
horizontal_alignment: alignment::Horizontal::Left,
|
horizontal_alignment: alignment::Horizontal::Left,
|
||||||
vertical_alignment: alignment::Vertical::Top,
|
vertical_alignment: alignment::Vertical::Top,
|
||||||
advanced_shape: false,
|
shaping: Shaping::Basic,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
use iced_core::alignment;
|
use crate::core::alignment;
|
||||||
use iced_core::image;
|
use crate::core::image;
|
||||||
use iced_core::svg;
|
use crate::core::svg;
|
||||||
use iced_core::{Background, Color, Font, Gradient, Rectangle, Size, Vector};
|
use crate::core::text;
|
||||||
|
use crate::core::{Background, Color, Font, Gradient, Rectangle, Size, Vector};
|
||||||
|
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
@ -26,15 +27,8 @@ pub enum Primitive {
|
||||||
horizontal_alignment: alignment::Horizontal,
|
horizontal_alignment: alignment::Horizontal,
|
||||||
/// The vertical alignment of the text
|
/// The vertical alignment of the text
|
||||||
vertical_alignment: alignment::Vertical,
|
vertical_alignment: alignment::Vertical,
|
||||||
/// Whether the text needs advanced shaping and font fallback.
|
/// The shaping strategy of the text.
|
||||||
///
|
shaping: text::Shaping,
|
||||||
/// 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_shape: bool,
|
|
||||||
},
|
},
|
||||||
/// A quad primitive
|
/// A quad primitive
|
||||||
Quad {
|
Quad {
|
||||||
|
|
|
||||||
|
|
@ -138,10 +138,9 @@ where
|
||||||
size: f32,
|
size: f32,
|
||||||
font: Font,
|
font: Font,
|
||||||
bounds: Size,
|
bounds: Size,
|
||||||
needs_shaping: bool,
|
shaping: text::Shaping,
|
||||||
) -> (f32, f32) {
|
) -> (f32, f32) {
|
||||||
self.backend()
|
self.backend().measure(content, size, font, bounds, shaping)
|
||||||
.measure(content, size, font, bounds, needs_shaping)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hit_test(
|
fn hit_test(
|
||||||
|
|
@ -150,18 +149,18 @@ where
|
||||||
size: f32,
|
size: f32,
|
||||||
font: Font,
|
font: Font,
|
||||||
bounds: Size,
|
bounds: Size,
|
||||||
|
shaping: text::Shaping,
|
||||||
point: Point,
|
point: Point,
|
||||||
nearest_only: bool,
|
nearest_only: bool,
|
||||||
advanced_shape: bool,
|
|
||||||
) -> Option<text::Hit> {
|
) -> Option<text::Hit> {
|
||||||
self.backend().hit_test(
|
self.backend().hit_test(
|
||||||
content,
|
content,
|
||||||
size,
|
size,
|
||||||
font,
|
font,
|
||||||
bounds,
|
bounds,
|
||||||
|
shaping,
|
||||||
point,
|
point,
|
||||||
nearest_only,
|
nearest_only,
|
||||||
advanced_shape,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -178,7 +177,7 @@ where
|
||||||
font: text.font,
|
font: text.font,
|
||||||
horizontal_alignment: text.horizontal_alignment,
|
horizontal_alignment: text.horizontal_alignment,
|
||||||
vertical_alignment: text.vertical_alignment,
|
vertical_alignment: text.vertical_alignment,
|
||||||
advanced_shape: text.advanced_shape,
|
shaping: text.shaping,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,12 +48,12 @@ impl backend::Text for Backend {
|
||||||
size: f32,
|
size: f32,
|
||||||
font: Font,
|
font: Font,
|
||||||
bounds: Size,
|
bounds: Size,
|
||||||
advanced_shape: bool,
|
shaping: text::Shaping,
|
||||||
) -> (f32, f32) {
|
) -> (f32, f32) {
|
||||||
delegate!(
|
delegate!(
|
||||||
self,
|
self,
|
||||||
backend,
|
backend,
|
||||||
backend.measure(contents, size, font, bounds, advanced_shape)
|
backend.measure(contents, size, font, bounds, shaping)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,9 +63,9 @@ impl backend::Text for Backend {
|
||||||
size: f32,
|
size: f32,
|
||||||
font: Font,
|
font: Font,
|
||||||
bounds: Size,
|
bounds: Size,
|
||||||
|
shaping: text::Shaping,
|
||||||
position: Point,
|
position: Point,
|
||||||
nearest_only: bool,
|
nearest_only: bool,
|
||||||
advanced_shape: bool,
|
|
||||||
) -> Option<text::Hit> {
|
) -> Option<text::Hit> {
|
||||||
delegate!(
|
delegate!(
|
||||||
self,
|
self,
|
||||||
|
|
@ -75,9 +75,9 @@ impl backend::Text for Backend {
|
||||||
size,
|
size,
|
||||||
font,
|
font,
|
||||||
bounds,
|
bounds,
|
||||||
|
shaping,
|
||||||
position,
|
position,
|
||||||
nearest_only,
|
nearest_only,
|
||||||
advanced_shape
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -219,7 +219,7 @@ impl Backend {
|
||||||
font,
|
font,
|
||||||
horizontal_alignment,
|
horizontal_alignment,
|
||||||
vertical_alignment,
|
vertical_alignment,
|
||||||
advanced_shape,
|
shaping,
|
||||||
} => {
|
} => {
|
||||||
let physical_bounds =
|
let physical_bounds =
|
||||||
(primitive.bounds() + translation) * scale_factor;
|
(primitive.bounds() + translation) * scale_factor;
|
||||||
|
|
@ -239,7 +239,7 @@ impl Backend {
|
||||||
*font,
|
*font,
|
||||||
*horizontal_alignment,
|
*horizontal_alignment,
|
||||||
*vertical_alignment,
|
*vertical_alignment,
|
||||||
*advanced_shape,
|
*shaping,
|
||||||
pixels,
|
pixels,
|
||||||
clip_mask,
|
clip_mask,
|
||||||
);
|
);
|
||||||
|
|
@ -628,10 +628,10 @@ impl backend::Text for Backend {
|
||||||
size: f32,
|
size: f32,
|
||||||
font: Font,
|
font: Font,
|
||||||
bounds: Size,
|
bounds: Size,
|
||||||
advanced_shape: bool,
|
shaping: text::Shaping,
|
||||||
) -> (f32, f32) {
|
) -> (f32, f32) {
|
||||||
self.text_pipeline
|
self.text_pipeline
|
||||||
.measure(contents, size, font, bounds, advanced_shape)
|
.measure(contents, size, font, bounds, shaping)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hit_test(
|
fn hit_test(
|
||||||
|
|
@ -640,18 +640,18 @@ impl backend::Text for Backend {
|
||||||
size: f32,
|
size: f32,
|
||||||
font: Font,
|
font: Font,
|
||||||
bounds: Size,
|
bounds: Size,
|
||||||
|
shaping: text::Shaping,
|
||||||
point: Point,
|
point: Point,
|
||||||
nearest_only: bool,
|
nearest_only: bool,
|
||||||
advanced_shape: bool,
|
|
||||||
) -> Option<text::Hit> {
|
) -> Option<text::Hit> {
|
||||||
self.text_pipeline.hit_test(
|
self.text_pipeline.hit_test(
|
||||||
contents,
|
contents,
|
||||||
size,
|
size,
|
||||||
font,
|
font,
|
||||||
bounds,
|
bounds,
|
||||||
|
shaping,
|
||||||
point,
|
point,
|
||||||
nearest_only,
|
nearest_only,
|
||||||
advanced_shape,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ impl Frame {
|
||||||
font: text.font,
|
font: text.font,
|
||||||
horizontal_alignment: text.horizontal_alignment,
|
horizontal_alignment: text.horizontal_alignment,
|
||||||
vertical_alignment: text.vertical_alignment,
|
vertical_alignment: text.vertical_alignment,
|
||||||
advanced_shape: text.advanced_shape,
|
shaping: text.shaping,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::core::alignment;
|
use crate::core::alignment;
|
||||||
use crate::core::font::{self, Font};
|
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 crate::core::{Color, Point, Rectangle, Size};
|
||||||
|
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
|
@ -49,7 +49,7 @@ impl Pipeline {
|
||||||
font: Font,
|
font: Font,
|
||||||
horizontal_alignment: alignment::Horizontal,
|
horizontal_alignment: alignment::Horizontal,
|
||||||
vertical_alignment: alignment::Vertical,
|
vertical_alignment: alignment::Vertical,
|
||||||
advanced_shape: bool,
|
shaping: Shaping,
|
||||||
pixels: &mut tiny_skia::PixmapMut<'_>,
|
pixels: &mut tiny_skia::PixmapMut<'_>,
|
||||||
clip_mask: Option<&tiny_skia::Mask>,
|
clip_mask: Option<&tiny_skia::Mask>,
|
||||||
) {
|
) {
|
||||||
|
|
@ -64,7 +64,7 @@ impl Pipeline {
|
||||||
content,
|
content,
|
||||||
font,
|
font,
|
||||||
size,
|
size,
|
||||||
advanced_shape,
|
shaping,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (_, buffer) = self.render_cache.allocate(font_system, key);
|
let (_, buffer) = self.render_cache.allocate(font_system, key);
|
||||||
|
|
@ -132,7 +132,7 @@ impl Pipeline {
|
||||||
size: f32,
|
size: f32,
|
||||||
font: Font,
|
font: Font,
|
||||||
bounds: Size,
|
bounds: Size,
|
||||||
advanced_shape: bool,
|
shaping: Shaping,
|
||||||
) -> (f32, f32) {
|
) -> (f32, f32) {
|
||||||
let mut measurement_cache = self.measurement_cache.borrow_mut();
|
let mut measurement_cache = self.measurement_cache.borrow_mut();
|
||||||
|
|
||||||
|
|
@ -143,7 +143,7 @@ impl Pipeline {
|
||||||
size,
|
size,
|
||||||
font,
|
font,
|
||||||
bounds,
|
bounds,
|
||||||
advanced_shape,
|
shaping,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -163,9 +163,9 @@ impl Pipeline {
|
||||||
size: f32,
|
size: f32,
|
||||||
font: Font,
|
font: Font,
|
||||||
bounds: Size,
|
bounds: Size,
|
||||||
|
shaping: Shaping,
|
||||||
point: Point,
|
point: Point,
|
||||||
_nearest_only: bool,
|
_nearest_only: bool,
|
||||||
advanced_shape: bool,
|
|
||||||
) -> Option<Hit> {
|
) -> Option<Hit> {
|
||||||
let mut measurement_cache = self.measurement_cache.borrow_mut();
|
let mut measurement_cache = self.measurement_cache.borrow_mut();
|
||||||
|
|
||||||
|
|
@ -176,7 +176,7 @@ impl Pipeline {
|
||||||
size,
|
size,
|
||||||
font,
|
font,
|
||||||
bounds,
|
bounds,
|
||||||
advanced_shape,
|
shaping,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -396,7 +396,7 @@ impl Cache {
|
||||||
.family(to_family(key.font.family))
|
.family(to_family(key.font.family))
|
||||||
.weight(to_weight(key.font.weight))
|
.weight(to_weight(key.font.weight))
|
||||||
.stretch(to_stretch(key.font.stretch)),
|
.stretch(to_stretch(key.font.stretch)),
|
||||||
!key.advanced_shape,
|
matches!(key.shaping, Shaping::Basic),
|
||||||
);
|
);
|
||||||
|
|
||||||
let _ = entry.insert(buffer);
|
let _ = entry.insert(buffer);
|
||||||
|
|
@ -427,7 +427,7 @@ struct Key<'a> {
|
||||||
size: f32,
|
size: f32,
|
||||||
font: Font,
|
font: Font,
|
||||||
bounds: Size,
|
bounds: Size,
|
||||||
advanced_shape: bool,
|
shaping: Shaping,
|
||||||
}
|
}
|
||||||
|
|
||||||
type KeyHash = u64;
|
type KeyHash = u64;
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -354,10 +354,10 @@ impl backend::Text for Backend {
|
||||||
size: f32,
|
size: f32,
|
||||||
font: Font,
|
font: Font,
|
||||||
bounds: Size,
|
bounds: Size,
|
||||||
advanced_shape: bool,
|
shaping: core::text::Shaping,
|
||||||
) -> (f32, f32) {
|
) -> (f32, f32) {
|
||||||
self.text_pipeline
|
self.text_pipeline
|
||||||
.measure(contents, size, font, bounds, advanced_shape)
|
.measure(contents, size, font, bounds, shaping)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hit_test(
|
fn hit_test(
|
||||||
|
|
@ -366,18 +366,18 @@ impl backend::Text for Backend {
|
||||||
size: f32,
|
size: f32,
|
||||||
font: Font,
|
font: Font,
|
||||||
bounds: Size,
|
bounds: Size,
|
||||||
|
shaping: core::text::Shaping,
|
||||||
point: Point,
|
point: Point,
|
||||||
nearest_only: bool,
|
nearest_only: bool,
|
||||||
advanced_shape: bool,
|
|
||||||
) -> Option<core::text::Hit> {
|
) -> Option<core::text::Hit> {
|
||||||
self.text_pipeline.hit_test(
|
self.text_pipeline.hit_test(
|
||||||
contents,
|
contents,
|
||||||
size,
|
size,
|
||||||
font,
|
font,
|
||||||
bounds,
|
bounds,
|
||||||
|
shaping,
|
||||||
point,
|
point,
|
||||||
nearest_only,
|
nearest_only,
|
||||||
advanced_shape,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -334,7 +334,7 @@ impl Frame {
|
||||||
font: text.font,
|
font: text.font,
|
||||||
horizontal_alignment: text.horizontal_alignment,
|
horizontal_alignment: text.horizontal_alignment,
|
||||||
vertical_alignment: text.vertical_alignment,
|
vertical_alignment: text.vertical_alignment,
|
||||||
advanced_shape: text.advanced_shape,
|
shaping: text.shaping,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ pub use mesh::Mesh;
|
||||||
pub use quad::Quad;
|
pub use quad::Quad;
|
||||||
pub use text::Text;
|
pub use text::Text;
|
||||||
|
|
||||||
|
use crate::core;
|
||||||
use crate::core::alignment;
|
use crate::core::alignment;
|
||||||
use crate::core::{Background, Color, Font, Point, Rectangle, Size, Vector};
|
use crate::core::{Background, Color, Font, Point, Rectangle, Size, Vector};
|
||||||
use crate::graphics::{Primitive, Viewport};
|
use crate::graphics::{Primitive, Viewport};
|
||||||
|
|
@ -64,7 +65,7 @@ impl<'a> Layer<'a> {
|
||||||
font: Font::MONOSPACE,
|
font: Font::MONOSPACE,
|
||||||
horizontal_alignment: alignment::Horizontal::Left,
|
horizontal_alignment: alignment::Horizontal::Left,
|
||||||
vertical_alignment: alignment::Vertical::Top,
|
vertical_alignment: alignment::Vertical::Top,
|
||||||
advanced_shape: false,
|
shaping: core::text::Shaping::Basic,
|
||||||
};
|
};
|
||||||
|
|
||||||
overlay.text.push(text);
|
overlay.text.push(text);
|
||||||
|
|
@ -117,7 +118,7 @@ impl<'a> Layer<'a> {
|
||||||
font,
|
font,
|
||||||
horizontal_alignment,
|
horizontal_alignment,
|
||||||
vertical_alignment,
|
vertical_alignment,
|
||||||
advanced_shape,
|
shaping,
|
||||||
} => {
|
} => {
|
||||||
let layer = &mut layers[current_layer];
|
let layer = &mut layers[current_layer];
|
||||||
|
|
||||||
|
|
@ -129,7 +130,7 @@ impl<'a> Layer<'a> {
|
||||||
font: *font,
|
font: *font,
|
||||||
horizontal_alignment: *horizontal_alignment,
|
horizontal_alignment: *horizontal_alignment,
|
||||||
vertical_alignment: *vertical_alignment,
|
vertical_alignment: *vertical_alignment,
|
||||||
advanced_shape: *advanced_shape,
|
shaping: *shaping,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Primitive::Quad {
|
Primitive::Quad {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::core::alignment;
|
use crate::core::alignment;
|
||||||
|
use crate::core::text;
|
||||||
use crate::core::{Color, Font, Rectangle};
|
use crate::core::{Color, Font, Rectangle};
|
||||||
|
|
||||||
/// A paragraph of text.
|
/// A paragraph of text.
|
||||||
|
|
@ -25,13 +26,6 @@ pub struct Text<'a> {
|
||||||
/// The vertical alignment of the [`Text`].
|
/// The vertical alignment of the [`Text`].
|
||||||
pub vertical_alignment: alignment::Vertical,
|
pub vertical_alignment: alignment::Vertical,
|
||||||
|
|
||||||
/// Whether the text needs advanced shaping and font fallback.
|
/// The shaping strategy of the text.
|
||||||
///
|
pub shaping: text::Shaping,
|
||||||
/// 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.
|
|
||||||
pub advanced_shape: bool,
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::core::alignment;
|
use crate::core::alignment;
|
||||||
use crate::core::font::{self, Font};
|
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::core::{Point, Rectangle, Size};
|
||||||
use crate::layer::Text;
|
use crate::layer::Text;
|
||||||
|
|
||||||
|
|
@ -83,7 +83,7 @@ impl Pipeline {
|
||||||
height: (section.bounds.height * scale_factor)
|
height: (section.bounds.height * scale_factor)
|
||||||
.ceil(),
|
.ceil(),
|
||||||
},
|
},
|
||||||
advanced_shape: section.advanced_shape,
|
shaping: section.shaping,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -214,7 +214,7 @@ impl Pipeline {
|
||||||
size: f32,
|
size: f32,
|
||||||
font: Font,
|
font: Font,
|
||||||
bounds: Size,
|
bounds: Size,
|
||||||
advanced_shape: bool,
|
shaping: Shaping,
|
||||||
) -> (f32, f32) {
|
) -> (f32, f32) {
|
||||||
let mut measurement_cache = self.measurement_cache.borrow_mut();
|
let mut measurement_cache = self.measurement_cache.borrow_mut();
|
||||||
|
|
||||||
|
|
@ -225,7 +225,7 @@ impl Pipeline {
|
||||||
size,
|
size,
|
||||||
font,
|
font,
|
||||||
bounds,
|
bounds,
|
||||||
advanced_shape,
|
shaping,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -245,9 +245,9 @@ impl Pipeline {
|
||||||
size: f32,
|
size: f32,
|
||||||
font: Font,
|
font: Font,
|
||||||
bounds: Size,
|
bounds: Size,
|
||||||
|
shaping: Shaping,
|
||||||
point: Point,
|
point: Point,
|
||||||
_nearest_only: bool,
|
_nearest_only: bool,
|
||||||
advanced_shape: bool,
|
|
||||||
) -> Option<Hit> {
|
) -> Option<Hit> {
|
||||||
let mut measurement_cache = self.measurement_cache.borrow_mut();
|
let mut measurement_cache = self.measurement_cache.borrow_mut();
|
||||||
|
|
||||||
|
|
@ -258,7 +258,7 @@ impl Pipeline {
|
||||||
size,
|
size,
|
||||||
font,
|
font,
|
||||||
bounds,
|
bounds,
|
||||||
advanced_shape,
|
shaping,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -369,7 +369,7 @@ impl Cache {
|
||||||
.family(to_family(key.font.family))
|
.family(to_family(key.font.family))
|
||||||
.weight(to_weight(key.font.weight))
|
.weight(to_weight(key.font.weight))
|
||||||
.stretch(to_stretch(key.font.stretch)),
|
.stretch(to_stretch(key.font.stretch)),
|
||||||
!key.advanced_shape,
|
matches!(key.shaping, Shaping::Basic),
|
||||||
);
|
);
|
||||||
|
|
||||||
let _ = entry.insert(buffer);
|
let _ = entry.insert(buffer);
|
||||||
|
|
@ -394,7 +394,7 @@ struct Key<'a> {
|
||||||
size: f32,
|
size: f32,
|
||||||
font: Font,
|
font: Font,
|
||||||
bounds: Size,
|
bounds: Size,
|
||||||
advanced_shape: bool,
|
shaping: Shaping,
|
||||||
}
|
}
|
||||||
|
|
||||||
type KeyHash = u64;
|
type KeyHash = u64;
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ where
|
||||||
size: f32,
|
size: f32,
|
||||||
spacing: f32,
|
spacing: f32,
|
||||||
text_size: Option<f32>,
|
text_size: Option<f32>,
|
||||||
|
text_shaping: text::Shaping,
|
||||||
font: Option<Renderer::Font>,
|
font: Option<Renderer::Font>,
|
||||||
icon: Icon<Renderer::Font>,
|
icon: Icon<Renderer::Font>,
|
||||||
style: <Renderer::Theme as StyleSheet>::Style,
|
style: <Renderer::Theme as StyleSheet>::Style,
|
||||||
|
|
@ -82,11 +83,13 @@ where
|
||||||
size: Self::DEFAULT_SIZE,
|
size: Self::DEFAULT_SIZE,
|
||||||
spacing: Self::DEFAULT_SPACING,
|
spacing: Self::DEFAULT_SPACING,
|
||||||
text_size: None,
|
text_size: None,
|
||||||
|
text_shaping: text::Shaping::Basic,
|
||||||
font: None,
|
font: None,
|
||||||
icon: Icon {
|
icon: Icon {
|
||||||
font: Renderer::ICON_FONT,
|
font: Renderer::ICON_FONT,
|
||||||
code_point: Renderer::CHECKMARK_ICON,
|
code_point: Renderer::CHECKMARK_ICON,
|
||||||
size: None,
|
size: None,
|
||||||
|
shaping: text::Shaping::Basic,
|
||||||
},
|
},
|
||||||
style: Default::default(),
|
style: Default::default(),
|
||||||
}
|
}
|
||||||
|
|
@ -116,6 +119,12 @@ where
|
||||||
self
|
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`].
|
/// Sets the [`Font`] of the text of the [`Checkbox`].
|
||||||
///
|
///
|
||||||
/// [`Font`]: crate::text::Renderer::Font
|
/// [`Font`]: crate::text::Renderer::Font
|
||||||
|
|
@ -171,7 +180,8 @@ where
|
||||||
.size(
|
.size(
|
||||||
self.text_size
|
self.text_size
|
||||||
.unwrap_or_else(|| renderer.default_size()),
|
.unwrap_or_else(|| renderer.default_size()),
|
||||||
),
|
)
|
||||||
|
.shaping(self.text_shaping),
|
||||||
)
|
)
|
||||||
.layout(renderer, limits)
|
.layout(renderer, limits)
|
||||||
}
|
}
|
||||||
|
|
@ -257,6 +267,7 @@ where
|
||||||
font,
|
font,
|
||||||
code_point,
|
code_point,
|
||||||
size,
|
size,
|
||||||
|
shaping,
|
||||||
} = &self.icon;
|
} = &self.icon;
|
||||||
let size = size.unwrap_or(bounds.height * 0.7);
|
let size = size.unwrap_or(bounds.height * 0.7);
|
||||||
|
|
||||||
|
|
@ -273,7 +284,7 @@ where
|
||||||
color: custom_style.icon_color,
|
color: custom_style.icon_color,
|
||||||
horizontal_alignment: alignment::Horizontal::Center,
|
horizontal_alignment: alignment::Horizontal::Center,
|
||||||
vertical_alignment: alignment::Vertical::Center,
|
vertical_alignment: alignment::Vertical::Center,
|
||||||
advanced_shape: true,
|
shaping: *shaping,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -293,7 +304,7 @@ where
|
||||||
},
|
},
|
||||||
alignment::Horizontal::Left,
|
alignment::Horizontal::Left,
|
||||||
alignment::Vertical::Center,
|
alignment::Vertical::Center,
|
||||||
false,
|
self.text_shaping,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -322,4 +333,6 @@ pub struct Icon<Font> {
|
||||||
pub code_point: char,
|
pub code_point: char,
|
||||||
/// Font size of the content.
|
/// Font size of the content.
|
||||||
pub size: Option<f32>,
|
pub size: Option<f32>,
|
||||||
|
/// The shaping strategy of the icon.
|
||||||
|
pub shaping: text::Shaping,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ where
|
||||||
width: f32,
|
width: f32,
|
||||||
padding: Padding,
|
padding: Padding,
|
||||||
text_size: Option<f32>,
|
text_size: Option<f32>,
|
||||||
|
text_shaping: text::Shaping,
|
||||||
font: Option<Renderer::Font>,
|
font: Option<Renderer::Font>,
|
||||||
style: <Renderer::Theme as StyleSheet>::Style,
|
style: <Renderer::Theme as StyleSheet>::Style,
|
||||||
}
|
}
|
||||||
|
|
@ -58,6 +59,7 @@ where
|
||||||
width: 0.0,
|
width: 0.0,
|
||||||
padding: Padding::ZERO,
|
padding: Padding::ZERO,
|
||||||
text_size: None,
|
text_size: None,
|
||||||
|
text_shaping: text::Shaping::Basic,
|
||||||
font: None,
|
font: None,
|
||||||
style: Default::default(),
|
style: Default::default(),
|
||||||
}
|
}
|
||||||
|
|
@ -81,6 +83,12 @@ where
|
||||||
self
|
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`].
|
/// Sets the font of the [`Menu`].
|
||||||
pub fn font(mut self, font: impl Into<Renderer::Font>) -> Self {
|
pub fn font(mut self, font: impl Into<Renderer::Font>) -> Self {
|
||||||
self.font = Some(font.into());
|
self.font = Some(font.into());
|
||||||
|
|
@ -168,6 +176,7 @@ where
|
||||||
padding,
|
padding,
|
||||||
font,
|
font,
|
||||||
text_size,
|
text_size,
|
||||||
|
text_shaping,
|
||||||
style,
|
style,
|
||||||
} = menu;
|
} = menu;
|
||||||
|
|
||||||
|
|
@ -177,6 +186,7 @@ where
|
||||||
last_selection,
|
last_selection,
|
||||||
font,
|
font,
|
||||||
text_size,
|
text_size,
|
||||||
|
text_shaping,
|
||||||
padding,
|
padding,
|
||||||
style: style.clone(),
|
style: style.clone(),
|
||||||
}));
|
}));
|
||||||
|
|
@ -311,6 +321,7 @@ where
|
||||||
last_selection: &'a mut Option<T>,
|
last_selection: &'a mut Option<T>,
|
||||||
padding: Padding,
|
padding: Padding,
|
||||||
text_size: Option<f32>,
|
text_size: Option<f32>,
|
||||||
|
text_shaping: text::Shaping,
|
||||||
font: Option<Renderer::Font>,
|
font: Option<Renderer::Font>,
|
||||||
style: <Renderer::Theme as StyleSheet>::Style,
|
style: <Renderer::Theme as StyleSheet>::Style,
|
||||||
}
|
}
|
||||||
|
|
@ -500,7 +511,7 @@ where
|
||||||
},
|
},
|
||||||
horizontal_alignment: alignment::Horizontal::Left,
|
horizontal_alignment: alignment::Horizontal::Left,
|
||||||
vertical_alignment: alignment::Vertical::Center,
|
vertical_alignment: alignment::Vertical::Center,
|
||||||
advanced_shape: false,
|
shaping: self.text_shaping,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ where
|
||||||
width: Length,
|
width: Length,
|
||||||
padding: Padding,
|
padding: Padding,
|
||||||
text_size: Option<f32>,
|
text_size: Option<f32>,
|
||||||
|
text_shaping: text::Shaping,
|
||||||
font: Option<Renderer::Font>,
|
font: Option<Renderer::Font>,
|
||||||
handle: Handle<Renderer::Font>,
|
handle: Handle<Renderer::Font>,
|
||||||
style: <Renderer::Theme as StyleSheet>::Style,
|
style: <Renderer::Theme as StyleSheet>::Style,
|
||||||
|
|
@ -71,6 +72,7 @@ where
|
||||||
width: Length::Shrink,
|
width: Length::Shrink,
|
||||||
padding: Self::DEFAULT_PADDING,
|
padding: Self::DEFAULT_PADDING,
|
||||||
text_size: None,
|
text_size: None,
|
||||||
|
text_shaping: text::Shaping::Basic,
|
||||||
font: None,
|
font: None,
|
||||||
handle: Default::default(),
|
handle: Default::default(),
|
||||||
style: Default::default(),
|
style: Default::default(),
|
||||||
|
|
@ -101,6 +103,12 @@ where
|
||||||
self
|
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`].
|
/// Sets the font of the [`PickList`].
|
||||||
pub fn font(mut self, font: impl Into<Renderer::Font>) -> Self {
|
pub fn font(mut self, font: impl Into<Renderer::Font>) -> Self {
|
||||||
self.font = Some(font.into());
|
self.font = Some(font.into());
|
||||||
|
|
@ -164,6 +172,7 @@ where
|
||||||
self.width,
|
self.width,
|
||||||
self.padding,
|
self.padding,
|
||||||
self.text_size,
|
self.text_size,
|
||||||
|
self.text_shaping,
|
||||||
self.font,
|
self.font,
|
||||||
self.placeholder.as_deref(),
|
self.placeholder.as_deref(),
|
||||||
&self.options,
|
&self.options,
|
||||||
|
|
@ -221,6 +230,7 @@ where
|
||||||
cursor_position,
|
cursor_position,
|
||||||
self.padding,
|
self.padding,
|
||||||
self.text_size,
|
self.text_size,
|
||||||
|
self.text_shaping,
|
||||||
font,
|
font,
|
||||||
self.placeholder.as_deref(),
|
self.placeholder.as_deref(),
|
||||||
self.selected.as_ref(),
|
self.selected.as_ref(),
|
||||||
|
|
@ -243,6 +253,7 @@ where
|
||||||
state,
|
state,
|
||||||
self.padding,
|
self.padding,
|
||||||
self.text_size,
|
self.text_size,
|
||||||
|
self.text_shaping,
|
||||||
self.font.unwrap_or_else(|| renderer.default_font()),
|
self.font.unwrap_or_else(|| renderer.default_font()),
|
||||||
&self.options,
|
&self.options,
|
||||||
self.style.clone(),
|
self.style.clone(),
|
||||||
|
|
@ -336,6 +347,8 @@ pub struct Icon<Font> {
|
||||||
pub code_point: char,
|
pub code_point: char,
|
||||||
/// Font size of the content.
|
/// Font size of the content.
|
||||||
pub size: Option<f32>,
|
pub size: Option<f32>,
|
||||||
|
/// The shaping strategy of the icon.
|
||||||
|
pub shaping: text::Shaping,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the layout of a [`PickList`].
|
/// Computes the layout of a [`PickList`].
|
||||||
|
|
@ -345,6 +358,7 @@ pub fn layout<Renderer, T>(
|
||||||
width: Length,
|
width: Length,
|
||||||
padding: Padding,
|
padding: Padding,
|
||||||
text_size: Option<f32>,
|
text_size: Option<f32>,
|
||||||
|
text_shaping: text::Shaping,
|
||||||
font: Option<Renderer::Font>,
|
font: Option<Renderer::Font>,
|
||||||
placeholder: Option<&str>,
|
placeholder: Option<&str>,
|
||||||
options: &[T],
|
options: &[T],
|
||||||
|
|
@ -366,7 +380,7 @@ where
|
||||||
text_size,
|
text_size,
|
||||||
font.unwrap_or_else(|| renderer.default_font()),
|
font.unwrap_or_else(|| renderer.default_font()),
|
||||||
Size::new(f32::INFINITY, f32::INFINITY),
|
Size::new(f32::INFINITY, f32::INFINITY),
|
||||||
false,
|
text_shaping,
|
||||||
);
|
);
|
||||||
|
|
||||||
width.round()
|
width.round()
|
||||||
|
|
@ -516,6 +530,7 @@ pub fn overlay<'a, T, Message, Renderer>(
|
||||||
state: &'a mut State<T>,
|
state: &'a mut State<T>,
|
||||||
padding: Padding,
|
padding: Padding,
|
||||||
text_size: Option<f32>,
|
text_size: Option<f32>,
|
||||||
|
text_shaping: text::Shaping,
|
||||||
font: Renderer::Font,
|
font: Renderer::Font,
|
||||||
options: &'a [T],
|
options: &'a [T],
|
||||||
style: <Renderer::Theme as StyleSheet>::Style,
|
style: <Renderer::Theme as StyleSheet>::Style,
|
||||||
|
|
@ -543,6 +558,7 @@ where
|
||||||
.width(bounds.width)
|
.width(bounds.width)
|
||||||
.padding(padding)
|
.padding(padding)
|
||||||
.font(font)
|
.font(font)
|
||||||
|
.text_shaping(text_shaping)
|
||||||
.style(style);
|
.style(style);
|
||||||
|
|
||||||
if let Some(text_size) = text_size {
|
if let Some(text_size) = text_size {
|
||||||
|
|
@ -563,6 +579,7 @@ pub fn draw<'a, T, Renderer>(
|
||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
padding: Padding,
|
padding: Padding,
|
||||||
text_size: Option<f32>,
|
text_size: Option<f32>,
|
||||||
|
text_shaping: text::Shaping,
|
||||||
font: Renderer::Font,
|
font: Renderer::Font,
|
||||||
placeholder: Option<&str>,
|
placeholder: Option<&str>,
|
||||||
selected: Option<&T>,
|
selected: Option<&T>,
|
||||||
|
|
@ -595,25 +612,34 @@ pub fn draw<'a, T, Renderer>(
|
||||||
);
|
);
|
||||||
|
|
||||||
let handle = match handle {
|
let handle = match handle {
|
||||||
Handle::Arrow { size } => {
|
Handle::Arrow { size } => Some((
|
||||||
Some((Renderer::ICON_FONT, Renderer::ARROW_DOWN_ICON, *size))
|
Renderer::ICON_FONT,
|
||||||
}
|
Renderer::ARROW_DOWN_ICON,
|
||||||
|
*size,
|
||||||
|
text::Shaping::Basic,
|
||||||
|
)),
|
||||||
Handle::Static(Icon {
|
Handle::Static(Icon {
|
||||||
font,
|
font,
|
||||||
code_point,
|
code_point,
|
||||||
size,
|
size,
|
||||||
}) => Some((*font, *code_point, *size)),
|
shaping,
|
||||||
|
}) => Some((*font, *code_point, *size, *shaping)),
|
||||||
Handle::Dynamic { open, closed } => {
|
Handle::Dynamic { open, closed } => {
|
||||||
if state().is_open {
|
if state().is_open {
|
||||||
Some((open.font, open.code_point, open.size))
|
Some((open.font, open.code_point, open.size, open.shaping))
|
||||||
} else {
|
} else {
|
||||||
Some((closed.font, closed.code_point, closed.size))
|
Some((
|
||||||
|
closed.font,
|
||||||
|
closed.code_point,
|
||||||
|
closed.size,
|
||||||
|
closed.shaping,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Handle::None => None,
|
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());
|
let size = size.unwrap_or_else(|| renderer.default_size());
|
||||||
|
|
||||||
renderer.fill_text(Text {
|
renderer.fill_text(Text {
|
||||||
|
|
@ -629,7 +655,7 @@ pub fn draw<'a, T, Renderer>(
|
||||||
},
|
},
|
||||||
horizontal_alignment: alignment::Horizontal::Right,
|
horizontal_alignment: alignment::Horizontal::Right,
|
||||||
vertical_alignment: alignment::Vertical::Center,
|
vertical_alignment: alignment::Vertical::Center,
|
||||||
advanced_shape: false,
|
shaping,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -655,7 +681,7 @@ pub fn draw<'a, T, Renderer>(
|
||||||
},
|
},
|
||||||
horizontal_alignment: alignment::Horizontal::Left,
|
horizontal_alignment: alignment::Horizontal::Left,
|
||||||
vertical_alignment: alignment::Vertical::Center,
|
vertical_alignment: alignment::Vertical::Center,
|
||||||
advanced_shape: false,
|
shaping: text_shaping,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ where
|
||||||
size: f32,
|
size: f32,
|
||||||
spacing: f32,
|
spacing: f32,
|
||||||
text_size: Option<f32>,
|
text_size: Option<f32>,
|
||||||
|
text_shaping: text::Shaping,
|
||||||
font: Option<Renderer::Font>,
|
font: Option<Renderer::Font>,
|
||||||
style: <Renderer::Theme as StyleSheet>::Style,
|
style: <Renderer::Theme as StyleSheet>::Style,
|
||||||
}
|
}
|
||||||
|
|
@ -123,6 +124,7 @@ where
|
||||||
size: Self::DEFAULT_SIZE,
|
size: Self::DEFAULT_SIZE,
|
||||||
spacing: Self::DEFAULT_SPACING, //15
|
spacing: Self::DEFAULT_SPACING, //15
|
||||||
text_size: None,
|
text_size: None,
|
||||||
|
text_shaping: text::Shaping::Basic,
|
||||||
font: None,
|
font: None,
|
||||||
style: Default::default(),
|
style: Default::default(),
|
||||||
}
|
}
|
||||||
|
|
@ -152,6 +154,12 @@ where
|
||||||
self
|
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.
|
/// Sets the text font of the [`Radio`] button.
|
||||||
pub fn font(mut self, font: impl Into<Renderer::Font>) -> Self {
|
pub fn font(mut self, font: impl Into<Renderer::Font>) -> Self {
|
||||||
self.font = Some(font.into());
|
self.font = Some(font.into());
|
||||||
|
|
@ -192,9 +200,15 @@ where
|
||||||
.spacing(self.spacing)
|
.spacing(self.spacing)
|
||||||
.align_items(Alignment::Center)
|
.align_items(Alignment::Center)
|
||||||
.push(Row::new().width(self.size).height(self.size))
|
.push(Row::new().width(self.size).height(self.size))
|
||||||
.push(Text::new(&self.label).width(self.width).size(
|
.push(
|
||||||
self.text_size.unwrap_or_else(|| renderer.default_size()),
|
Text::new(&self.label)
|
||||||
))
|
.width(self.width)
|
||||||
|
.size(
|
||||||
|
self.text_size
|
||||||
|
.unwrap_or_else(|| renderer.default_size()),
|
||||||
|
)
|
||||||
|
.shaping(self.text_shaping),
|
||||||
|
)
|
||||||
.layout(renderer, limits)
|
.layout(renderer, limits)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -309,7 +323,7 @@ where
|
||||||
},
|
},
|
||||||
alignment::Horizontal::Left,
|
alignment::Horizontal::Left,
|
||||||
alignment::Vertical::Center,
|
alignment::Vertical::Center,
|
||||||
false,
|
self.text_shaping,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
pub use crate::core::text::Shaping;
|
||||||
pub use crate::core::widget::text::*;
|
pub use crate::core::widget::text::*;
|
||||||
|
|
||||||
pub type Text<'a, Renderer = crate::Renderer> =
|
pub type Text<'a, Renderer = crate::Renderer> =
|
||||||
|
|
|
||||||
|
|
@ -463,7 +463,7 @@ where
|
||||||
&icon.code_point.to_string(),
|
&icon.code_point.to_string(),
|
||||||
icon.size.unwrap_or_else(|| renderer.default_size()),
|
icon.size.unwrap_or_else(|| renderer.default_size()),
|
||||||
icon.font,
|
icon.font,
|
||||||
true,
|
text::Shaping::Advanced,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut text_node = layout::Node::new(
|
let mut text_node = layout::Node::new(
|
||||||
|
|
@ -976,7 +976,7 @@ pub fn draw<Renderer>(
|
||||||
bounds: icon_layout.bounds(),
|
bounds: icon_layout.bounds(),
|
||||||
horizontal_alignment: alignment::Horizontal::Left,
|
horizontal_alignment: alignment::Horizontal::Left,
|
||||||
vertical_alignment: alignment::Vertical::Top,
|
vertical_alignment: alignment::Vertical::Top,
|
||||||
advanced_shape: true,
|
shaping: text::Shaping::Advanced,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1081,7 +1081,7 @@ pub fn draw<Renderer>(
|
||||||
if text.is_empty() { placeholder } else { &text },
|
if text.is_empty() { placeholder } else { &text },
|
||||||
size,
|
size,
|
||||||
font,
|
font,
|
||||||
true,
|
text::Shaping::Advanced,
|
||||||
);
|
);
|
||||||
|
|
||||||
let render = |renderer: &mut Renderer| {
|
let render = |renderer: &mut Renderer| {
|
||||||
|
|
@ -1109,7 +1109,7 @@ pub fn draw<Renderer>(
|
||||||
size,
|
size,
|
||||||
horizontal_alignment: alignment::Horizontal::Left,
|
horizontal_alignment: alignment::Horizontal::Left,
|
||||||
vertical_alignment: alignment::Vertical::Center,
|
vertical_alignment: alignment::Vertical::Center,
|
||||||
advanced_shape: true,
|
shaping: text::Shaping::Advanced,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1314,8 +1314,12 @@ where
|
||||||
{
|
{
|
||||||
let text_before_cursor = value.until(cursor_index).to_string();
|
let text_before_cursor = value.until(cursor_index).to_string();
|
||||||
|
|
||||||
let text_value_width =
|
let text_value_width = renderer.measure_width(
|
||||||
renderer.measure_width(&text_before_cursor, size, font, true);
|
&text_before_cursor,
|
||||||
|
size,
|
||||||
|
font,
|
||||||
|
text::Shaping::Advanced,
|
||||||
|
);
|
||||||
|
|
||||||
let offset = ((text_value_width + 5.0) - text_bounds.width).max(0.0);
|
let offset = ((text_value_width + 5.0) - text_bounds.width).max(0.0);
|
||||||
|
|
||||||
|
|
@ -1348,9 +1352,9 @@ where
|
||||||
size,
|
size,
|
||||||
font,
|
font,
|
||||||
Size::INFINITY,
|
Size::INFINITY,
|
||||||
|
text::Shaping::Advanced,
|
||||||
Point::new(x + offset, text_bounds.height / 2.0),
|
Point::new(x + offset, text_bounds.height / 2.0),
|
||||||
true,
|
true,
|
||||||
true,
|
|
||||||
)
|
)
|
||||||
.map(text::Hit::cursor)?;
|
.map(text::Hit::cursor)?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ where
|
||||||
size: f32,
|
size: f32,
|
||||||
text_size: Option<f32>,
|
text_size: Option<f32>,
|
||||||
text_alignment: alignment::Horizontal,
|
text_alignment: alignment::Horizontal,
|
||||||
|
text_shaping: text::Shaping,
|
||||||
spacing: f32,
|
spacing: f32,
|
||||||
font: Option<Renderer::Font>,
|
font: Option<Renderer::Font>,
|
||||||
style: <Renderer::Theme as StyleSheet>::Style,
|
style: <Renderer::Theme as StyleSheet>::Style,
|
||||||
|
|
@ -80,6 +81,7 @@ where
|
||||||
size: Self::DEFAULT_SIZE,
|
size: Self::DEFAULT_SIZE,
|
||||||
text_size: None,
|
text_size: None,
|
||||||
text_alignment: alignment::Horizontal::Left,
|
text_alignment: alignment::Horizontal::Left,
|
||||||
|
text_shaping: text::Shaping::Basic,
|
||||||
spacing: 0.0,
|
spacing: 0.0,
|
||||||
font: None,
|
font: None,
|
||||||
style: Default::default(),
|
style: Default::default(),
|
||||||
|
|
@ -110,6 +112,12 @@ where
|
||||||
self
|
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.
|
/// Sets the spacing between the [`Toggler`] and the text.
|
||||||
pub fn spacing(mut self, spacing: impl Into<Pixels>) -> Self {
|
pub fn spacing(mut self, spacing: impl Into<Pixels>) -> Self {
|
||||||
self.spacing = spacing.into().0;
|
self.spacing = spacing.into().0;
|
||||||
|
|
@ -167,7 +175,8 @@ where
|
||||||
.size(
|
.size(
|
||||||
self.text_size
|
self.text_size
|
||||||
.unwrap_or_else(|| renderer.default_size()),
|
.unwrap_or_else(|| renderer.default_size()),
|
||||||
),
|
)
|
||||||
|
.shaping(self.text_shaping),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -249,7 +258,7 @@ where
|
||||||
Default::default(),
|
Default::default(),
|
||||||
self.text_alignment,
|
self.text_alignment,
|
||||||
alignment::Vertical::Center,
|
alignment::Vertical::Center,
|
||||||
false,
|
self.text_shaping,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue