Skip to content

Commit

Permalink
Merge pull request #1828 from iced-rs/feature/line-height
Browse files Browse the repository at this point in the history
Support configurable `LineHeight` in text widgets
  • Loading branch information
hecrj authored May 5, 2023
2 parents 8e8808f + 9499a8f commit 7ae549a
Show file tree
Hide file tree
Showing 24 changed files with 337 additions and 42 deletions.
8 changes: 8 additions & 0 deletions core/src/length.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions core/src/pixels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
2 changes: 2 additions & 0 deletions core/src/renderer/null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down
73 changes: 69 additions & 4 deletions core/src/text.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand All @@ -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,

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -102,6 +159,7 @@ pub trait Renderer: crate::Renderer {
&self,
content: &str,
size: f32,
line_height: LineHeight,
font: Self::Font,
bounds: Size,
shaping: Shaping,
Expand All @@ -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
}
Expand All @@ -132,6 +196,7 @@ pub trait Renderer: crate::Renderer {
&self,
contents: &str,
size: f32,
line_height: LineHeight,
font: Self::Font,
bounds: Size,
shaping: Shaping,
Expand Down
20 changes: 19 additions & 1 deletion core/src/widget/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ where
{
content: Cow<'a, str>,
size: Option<f32>,
line_height: text::LineHeight,
width: Length,
height: Length,
horizontal_alignment: alignment::Horizontal,
Expand All @@ -38,6 +39,7 @@ where
Text {
content: content.into(),
size: None,
line_height: text::LineHeight::default(),
font: None,
width: Length::Shrink,
height: Length::Shrink,
Expand All @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -161,6 +173,7 @@ where
layout,
&self.content,
self.size,
self.line_height,
self.font,
theme.appearance(self.style.clone()),
self.horizontal_alignment,
Expand All @@ -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,
Expand All @@ -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()),
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions graphics/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub trait Text {
&self,
contents: &str,
size: f32,
line_height: text::LineHeight,
font: Font,
bounds: Size,
shaping: text::Shaping,
Expand All @@ -62,6 +63,7 @@ pub trait Text {
&self,
contents: &str,
size: f32,
line_height: text::LineHeight,
font: Font,
bounds: Size,
shaping: text::Shaping,
Expand Down
5 changes: 4 additions & 1 deletion graphics/src/geometry/text.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::core::alignment;
use crate::core::text::Shaping;
use crate::core::text::{LineHeight, Shaping};
use crate::core::{Color, Font, Point};

/// A bunch of text that can be drawn to a canvas
Expand All @@ -20,6 +20,8 @@ pub struct Text {
pub color: Color,
/// The size of the text
pub size: f32,
/// The line height of the text.
pub line_height: LineHeight,
/// The font of the text
pub font: Font,
/// The horizontal alignment of the text
Expand All @@ -37,6 +39,7 @@ impl Default for Text {
position: Point::ORIGIN,
color: Color::BLACK,
size: 16.0,
line_height: LineHeight::Relative(1.2),
font: Font::default(),
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
Expand Down
4 changes: 3 additions & 1 deletion graphics/src/primitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ pub enum Primitive {
bounds: Rectangle,
/// The color of the text
color: Color,
/// The size of the text
/// The size of the text in logical pixels
size: f32,
/// The line height of the text
line_height: text::LineHeight,
/// The font of the text
font: Font,
/// The horizontal alignment of the text
Expand Down
13 changes: 12 additions & 1 deletion graphics/src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,17 +136,26 @@ where
&self,
content: &str,
size: f32,
line_height: text::LineHeight,
font: Font,
bounds: Size,
shaping: text::Shaping,
) -> (f32, f32) {
self.backend().measure(content, size, font, bounds, shaping)
self.backend().measure(
content,
size,
line_height,
font,
bounds,
shaping,
)
}

fn hit_test(
&self,
content: &str,
size: f32,
line_height: text::LineHeight,
font: Font,
bounds: Size,
shaping: text::Shaping,
Expand All @@ -156,6 +165,7 @@ where
self.backend().hit_test(
content,
size,
line_height,
font,
bounds,
shaping,
Expand All @@ -173,6 +183,7 @@ where
content: text.content.to_string(),
bounds: text.bounds,
size: text.size,
line_height: text.line_height,
color: text.color,
font: text.font,
horizontal_alignment: text.horizontal_alignment,
Expand Down
5 changes: 4 additions & 1 deletion renderer/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,23 @@ impl backend::Text for Backend {
&self,
contents: &str,
size: f32,
line_height: text::LineHeight,
font: Font,
bounds: Size,
shaping: text::Shaping,
) -> (f32, f32) {
delegate!(
self,
backend,
backend.measure(contents, size, font, bounds, shaping)
backend.measure(contents, size, line_height, font, bounds, shaping)
)
}

fn hit_test(
&self,
contents: &str,
size: f32,
line_height: text::LineHeight,
font: Font,
bounds: Size,
shaping: text::Shaping,
Expand All @@ -73,6 +75,7 @@ impl backend::Text for Backend {
backend.hit_test(
contents,
size,
line_height,
font,
bounds,
shaping,
Expand Down
Loading

0 comments on commit 7ae549a

Please sign in to comment.