summaryrefslogtreecommitdiffstats
path: root/core/src/text.rs
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2023-08-30 04:31:21 +0200
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2023-08-30 04:31:21 +0200
commited3454301e663a7cb7d73cd56b57b188f4d14a2f (patch)
tree8118d1305c2eba3a1b45d04634cd0e8d050fc0fa /core/src/text.rs
parentc9bd48704dd9679c033dd0b8588e2744a3df44a0 (diff)
downloadiced-ed3454301e663a7cb7d73cd56b57b188f4d14a2f.tar.gz
iced-ed3454301e663a7cb7d73cd56b57b188f4d14a2f.tar.bz2
iced-ed3454301e663a7cb7d73cd56b57b188f4d14a2f.zip
Implement explicit text caching in the widget state tree
Diffstat (limited to 'core/src/text.rs')
-rw-r--r--core/src/text.rs161
1 files changed, 103 insertions, 58 deletions
diff --git a/core/src/text.rs b/core/src/text.rs
index fc8aa20e..c59c683a 100644
--- a/core/src/text.rs
+++ b/core/src/text.rs
@@ -1,6 +1,6 @@
//! Draw and interact with text.
use crate::alignment;
-use crate::{Color, Pixels, Point, Rectangle, Size};
+use crate::{Color, Pixels, Point, Size};
use std::borrow::Cow;
use std::hash::{Hash, Hasher};
@@ -12,17 +12,14 @@ pub struct Text<'a, Font> {
pub content: &'a str,
/// The bounds of the paragraph.
- pub bounds: Rectangle,
+ pub bounds: Size,
/// The size of the [`Text`] in logical pixels.
- pub size: f32,
+ pub size: Pixels,
/// The line height of the [`Text`].
pub line_height: LineHeight,
- /// The color of the [`Text`].
- pub color: Color,
-
/// The font of the [`Text`].
pub font: Font,
@@ -132,7 +129,10 @@ impl Hit {
/// A renderer capable of measuring and drawing [`Text`].
pub trait Renderer: crate::Renderer {
/// The font type used.
- type Font: Copy;
+ type Font: Copy + PartialEq;
+
+ /// The [`Paragraph`] of this [`Renderer`].
+ type Paragraph: Paragraph<Font = Self::Font> + 'static;
/// The icon font of the backend.
const ICON_FONT: Self::Font;
@@ -151,62 +151,107 @@ pub trait Renderer: crate::Renderer {
fn default_font(&self) -> Self::Font;
/// Returns the default size of [`Text`].
- fn default_size(&self) -> f32;
+ fn default_size(&self) -> Pixels;
- /// Measures the text in the given bounds and returns the minimum boundaries
- /// that can fit the contents.
- fn measure(
+ /// Loads a [`Self::Font`] from its bytes.
+ fn load_font(&mut self, font: Cow<'static, [u8]>);
+
+ /// Creates a new [`Paragraph`] laid out with the given [`Text`].
+ fn create_paragraph(&self, text: Text<'_, Self::Font>) -> Self::Paragraph;
+
+ /// Lays out the given [`Paragraph`] with some new boundaries.
+ fn resize_paragraph(
&self,
- content: &str,
- size: f32,
- line_height: LineHeight,
- font: Self::Font,
- bounds: Size,
- shaping: Shaping,
- ) -> Size;
-
- /// Measures the width of the text as if it were laid out in a single line.
- fn measure_width(
+ paragraph: &mut Self::Paragraph,
+ new_bounds: Size,
+ );
+
+ /// Updates a [`Paragraph`] to match the given [`Text`], if needed.
+ fn update_paragraph(
&self,
- content: &str,
- size: f32,
- font: Self::Font,
- shaping: Shaping,
- ) -> f32 {
- let bounds = self.measure(
- content,
- size,
- LineHeight::Absolute(Pixels(size)),
- font,
- Size::INFINITY,
- shaping,
- );
-
- bounds.width
+ paragraph: &mut Self::Paragraph,
+ text: Text<'_, Self::Font>,
+ ) {
+ if paragraph.content() != text.content
+ || paragraph.text_size() != text.size
+ || paragraph.line_height().to_absolute(text.size)
+ != text.line_height.to_absolute(text.size)
+ || paragraph.font() != text.font
+ || paragraph.shaping() != text.shaping
+ || paragraph.horizontal_alignment() != text.horizontal_alignment
+ || paragraph.vertical_alignment() != text.vertical_alignment
+ {
+ *paragraph = self.create_paragraph(text);
+ } else if paragraph.bounds() != text.bounds {
+ self.resize_paragraph(paragraph, text.bounds);
+ }
}
- /// Tests whether the provided point is within the boundaries of text
- /// laid out with the given parameters, returning information about
- /// the nearest character.
- ///
- /// If `nearest_only` is true, the hit test does not consider whether the
- /// the point is interior to any glyph bounds, returning only the character
- /// with the nearest centeroid.
- fn hit_test(
- &self,
- contents: &str,
- size: f32,
- line_height: LineHeight,
- font: Self::Font,
- bounds: Size,
- shaping: Shaping,
- point: Point,
- nearest_only: bool,
- ) -> Option<Hit>;
+ /// Draws the given [`Paragraph`] at the given position and with the given
+ /// [`Color`].
+ fn fill_paragraph(
+ &mut self,
+ text: &Self::Paragraph,
+ position: Point,
+ color: Color,
+ );
+
+ /// Draws the given [`Text`] at the given position and with the given
+ /// [`Color`].
+ fn fill_text(
+ &mut self,
+ text: Text<'_, Self::Font>,
+ position: Point,
+ color: Color,
+ );
+}
+/// A text paragraph.
+pub trait Paragraph: Default {
+ /// The font of this [`Paragraph`].
+ type Font;
- /// Loads a [`Self::Font`] from its bytes.
- fn load_font(&mut self, font: Cow<'static, [u8]>);
+ /// Returns the content of the [`Paragraph`].
+ fn content(&self) -> &str;
- /// Draws the given [`Text`].
- fn fill_text(&mut self, text: Text<'_, Self::Font>);
+ /// Returns the text size of the [`Paragraph`].
+ fn text_size(&self) -> Pixels;
+
+ /// Returns the [`LineHeight`] of the [`Paragraph`].
+ fn line_height(&self) -> LineHeight;
+
+ /// Returns the [`Font`] of the [`Paragraph`].
+ fn font(&self) -> Self::Font;
+
+ /// Returns the [`Shaping`] strategy of the [`Paragraph`].
+ fn shaping(&self) -> Shaping;
+
+ /// Returns the horizontal alignment of the [`Paragraph`].
+ fn horizontal_alignment(&self) -> alignment::Horizontal;
+
+ /// Returns the vertical alignment of the [`Paragraph`].
+ fn vertical_alignment(&self) -> alignment::Vertical;
+
+ /// Returns the boundaries of the [`Paragraph`].
+ fn bounds(&self) -> Size;
+
+ /// Returns the minimum boundaries that can fit the contents of the
+ /// [`Paragraph`].
+ fn min_bounds(&self) -> Size;
+
+ /// Tests whether the provided point is within the boundaries of the
+ /// [`Paragraph`], returning information about the nearest character.
+ fn hit_test(&self, point: Point) -> Option<Hit>;
+
+ /// Returns the distance to the given grapheme index in the [`Paragraph`].
+ fn grapheme_position(&self, line: usize, index: usize) -> Option<Point>;
+
+ /// Returns the minimum width that can fit the contents of the [`Paragraph`].
+ fn min_width(&self) -> f32 {
+ self.min_bounds().width
+ }
+
+ /// Returns the minimum height that can fit the contents of the [`Paragraph`].
+ fn min_height(&self) -> f32 {
+ self.min_bounds().height
+ }
}