diff options
author | 2023-05-04 13:00:16 +0200 | |
---|---|---|
committer | 2023-05-04 18:39:31 +0200 | |
commit | 9499a8f9e6f9971dedfae563cb133232aa3cebc2 (patch) | |
tree | 54074dd8b1fc17d63ad92d84b6d2b4415ad29df6 /core | |
parent | 8e8808f0e187ed6671441f5016f07bfcba426452 (diff) | |
download | iced-9499a8f9e6f9971dedfae563cb133232aa3cebc2.tar.gz iced-9499a8f9e6f9971dedfae563cb133232aa3cebc2.tar.bz2 iced-9499a8f9e6f9971dedfae563cb133232aa3cebc2.zip |
Support configurable `LineHeight` in text widgets
Diffstat (limited to 'core')
-rw-r--r-- | core/src/length.rs | 8 | ||||
-rw-r--r-- | core/src/pixels.rs | 6 | ||||
-rw-r--r-- | core/src/renderer/null.rs | 2 | ||||
-rw-r--r-- | core/src/text.rs | 73 | ||||
-rw-r--r-- | core/src/widget/text.rs | 20 |
5 files changed, 104 insertions, 5 deletions
diff --git a/core/src/length.rs b/core/src/length.rs index bb925c4b..3adb996e 100644 --- a/core/src/length.rs +++ b/core/src/length.rs @@ -1,3 +1,5 @@ +use crate::Pixels; + /// The strategy used to fill space in a specific dimension. #[derive(Debug, Clone, Copy, PartialEq)] pub enum Length { @@ -36,6 +38,12 @@ impl Length { } } +impl From<Pixels> for Length { + fn from(amount: Pixels) -> Self { + Length::Fixed(f32::from(amount)) + } +} + impl From<f32> for Length { fn from(amount: f32) -> Self { Length::Fixed(amount) diff --git a/core/src/pixels.rs b/core/src/pixels.rs index e42cd9f9..6a9e5c88 100644 --- a/core/src/pixels.rs +++ b/core/src/pixels.rs @@ -20,3 +20,9 @@ impl From<u16> for Pixels { Self(f32::from(amount)) } } + +impl From<Pixels> for f32 { + fn from(pixels: Pixels) -> Self { + pixels.0 + } +} diff --git a/core/src/renderer/null.rs b/core/src/renderer/null.rs index 22afb058..f0cc952e 100644 --- a/core/src/renderer/null.rs +++ b/core/src/renderer/null.rs @@ -60,6 +60,7 @@ impl text::Renderer for Null { &self, _content: &str, _size: f32, + _line_height: text::LineHeight, _font: Font, _bounds: Size, _shaping: text::Shaping, @@ -71,6 +72,7 @@ impl text::Renderer for Null { &self, _contents: &str, _size: f32, + _line_height: text::LineHeight, _font: Self::Font, _bounds: Size, _shaping: text::Shaping, diff --git a/core/src/text.rs b/core/src/text.rs index c59d8fce..1a867be3 100644 --- a/core/src/text.rs +++ b/core/src/text.rs @@ -1,8 +1,9 @@ //! Draw and interact with text. use crate::alignment; -use crate::{Color, Point, Rectangle, Size}; +use crate::{Color, Pixels, Point, Rectangle, Size}; use std::borrow::Cow; +use std::hash::{Hash, Hasher}; /// A paragraph. #[derive(Debug, Clone, Copy)] @@ -13,9 +14,12 @@ pub struct Text<'a, Font> { /// The bounds of the paragraph. pub bounds: Rectangle, - /// The size of the [`Text`]. + /// The size of the [`Text`] in logical pixels. pub size: f32, + /// The line height of the [`Text`]. + pub line_height: LineHeight, + /// The color of the [`Text`]. pub color: Color, @@ -56,6 +60,59 @@ pub enum Shaping { Advanced, } +/// The height of a line of text in a paragraph. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum LineHeight { + /// A factor of the size of the text. + Relative(f32), + + /// An absolute height in logical pixels. + Absolute(Pixels), +} + +impl LineHeight { + /// Returns the [`LineHeight`] in absolute logical pixels. + pub fn to_absolute(self, text_size: Pixels) -> Pixels { + match self { + Self::Relative(factor) => Pixels(factor * text_size.0), + Self::Absolute(pixels) => pixels, + } + } +} + +impl Default for LineHeight { + fn default() -> Self { + Self::Relative(1.2) + } +} + +impl From<f32> for LineHeight { + fn from(factor: f32) -> Self { + Self::Relative(factor) + } +} + +impl From<Pixels> for LineHeight { + fn from(pixels: Pixels) -> Self { + Self::Absolute(pixels) + } +} + +impl Hash for LineHeight { + fn hash<H: Hasher>(&self, state: &mut H) { + match self { + Self::Relative(factor) => { + state.write_u8(0); + factor.to_bits().hash(state); + } + Self::Absolute(pixels) => { + state.write_u8(1); + f32::from(*pixels).to_bits().hash(state); + } + } + } +} + /// The result of hit testing on text. #[derive(Debug, Clone, Copy, PartialEq)] pub enum Hit { @@ -102,6 +159,7 @@ pub trait Renderer: crate::Renderer { &self, content: &str, size: f32, + line_height: LineHeight, font: Self::Font, bounds: Size, shaping: Shaping, @@ -115,8 +173,14 @@ pub trait Renderer: crate::Renderer { font: Self::Font, shaping: Shaping, ) -> f32 { - let (width, _) = - self.measure(content, size, font, Size::INFINITY, shaping); + let (width, _) = self.measure( + content, + size, + LineHeight::Absolute(Pixels(size)), + font, + Size::INFINITY, + shaping, + ); width } @@ -132,6 +196,7 @@ pub trait Renderer: crate::Renderer { &self, contents: &str, size: f32, + line_height: LineHeight, font: Self::Font, bounds: Size, shaping: Shaping, diff --git a/core/src/widget/text.rs b/core/src/widget/text.rs index f0392168..2d86e735 100644 --- a/core/src/widget/text.rs +++ b/core/src/widget/text.rs @@ -19,6 +19,7 @@ where { content: Cow<'a, str>, size: Option<f32>, + line_height: text::LineHeight, width: Length, height: Length, horizontal_alignment: alignment::Horizontal, @@ -38,6 +39,7 @@ where Text { content: content.into(), size: None, + line_height: text::LineHeight::default(), font: None, width: Length::Shrink, height: Length::Shrink, @@ -54,6 +56,15 @@ where self } + /// Sets the [`LineHeight`] of the [`Text`]. + pub fn line_height( + mut self, + line_height: impl Into<text::LineHeight>, + ) -> Self { + self.line_height = line_height.into(); + self + } + /// Sets the [`Font`] of the [`Text`]. /// /// [`Font`]: crate::text::Renderer::Font @@ -135,6 +146,7 @@ where let (width, height) = renderer.measure( &self.content, size, + self.line_height, self.font.unwrap_or_else(|| renderer.default_font()), bounds, self.shaping, @@ -161,6 +173,7 @@ where layout, &self.content, self.size, + self.line_height, self.font, theme.appearance(self.style.clone()), self.horizontal_alignment, @@ -186,6 +199,7 @@ pub fn draw<Renderer>( layout: Layout<'_>, content: &str, size: Option<f32>, + line_height: text::LineHeight, font: Option<Renderer::Font>, appearance: Appearance, horizontal_alignment: alignment::Horizontal, @@ -208,9 +222,12 @@ pub fn draw<Renderer>( alignment::Vertical::Bottom => bounds.y + bounds.height, }; + let size = size.unwrap_or_else(|| renderer.default_size()); + renderer.fill_text(crate::Text { content, - size: size.unwrap_or_else(|| renderer.default_size()), + size, + line_height, bounds: Rectangle { x, y, ..bounds }, color: appearance.color.unwrap_or(style.text_color), font: font.unwrap_or_else(|| renderer.default_font()), @@ -240,6 +257,7 @@ where Self { content: self.content.clone(), size: self.size, + line_height: self.line_height, width: self.width, height: self.height, horizontal_alignment: self.horizontal_alignment, |