Implement explicit text caching in the widget state tree
This commit is contained in:
parent
c9bd48704d
commit
ed3454301e
79 changed files with 1910 additions and 1705 deletions
167
core/src/text.rs
167
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;
|
||||
|
||||
/// Measures the text in the given bounds and returns the minimum boundaries
|
||||
/// that can fit the contents.
|
||||
fn measure(
|
||||
&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(
|
||||
&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
|
||||
}
|
||||
|
||||
/// 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>;
|
||||
fn default_size(&self) -> Pixels;
|
||||
|
||||
/// Loads a [`Self::Font`] from its bytes.
|
||||
fn load_font(&mut self, font: Cow<'static, [u8]>);
|
||||
|
||||
/// Draws the given [`Text`].
|
||||
fn fill_text(&mut self, text: Text<'_, Self::Font>);
|
||||
/// 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,
|
||||
paragraph: &mut Self::Paragraph,
|
||||
new_bounds: Size,
|
||||
);
|
||||
|
||||
/// Updates a [`Paragraph`] to match the given [`Text`], if needed.
|
||||
fn update_paragraph(
|
||||
&self,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// 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;
|
||||
|
||||
/// Returns the content of the [`Paragraph`].
|
||||
fn content(&self) -> &str;
|
||||
|
||||
/// 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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue