diff options
author | 2023-08-30 04:31:21 +0200 | |
---|---|---|
committer | 2023-08-30 04:31:21 +0200 | |
commit | ed3454301e663a7cb7d73cd56b57b188f4d14a2f (patch) | |
tree | 8118d1305c2eba3a1b45d04634cd0e8d050fc0fa /core/src/text.rs | |
parent | c9bd48704dd9679c033dd0b8588e2744a3df44a0 (diff) | |
download | iced-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.rs | 161 |
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 + } } |