diff options
Diffstat (limited to '')
-rw-r--r-- | graphics/src/text.rs | 129 | ||||
-rw-r--r-- | graphics/src/text/cache.rs | 16 | ||||
-rw-r--r-- | graphics/src/text/paragraph.rs | 4 |
3 files changed, 136 insertions, 13 deletions
diff --git a/graphics/src/text.rs b/graphics/src/text.rs index 0310ead7..30269e69 100644 --- a/graphics/src/text.rs +++ b/graphics/src/text.rs @@ -9,14 +9,141 @@ pub use paragraph::Paragraph; pub use cosmic_text; +use crate::core::alignment; use crate::core::font::{self, Font}; use crate::core::text::Shaping; -use crate::core::{Color, Point, Rectangle, Size}; +use crate::core::{Color, Pixels, Point, Rectangle, Size, Transformation}; use once_cell::sync::OnceCell; use std::borrow::Cow; use std::sync::{Arc, RwLock, Weak}; +/// A text primitive. +#[derive(Debug, Clone, PartialEq)] +pub enum Text { + /// A paragraph. + #[allow(missing_docs)] + Paragraph { + paragraph: paragraph::Weak, + position: Point, + color: Color, + clip_bounds: Rectangle, + transformation: Transformation, + }, + /// An editor. + #[allow(missing_docs)] + Editor { + editor: editor::Weak, + position: Point, + color: Color, + clip_bounds: Rectangle, + transformation: Transformation, + }, + /// Some cached text. + Cached { + /// The contents of the text. + content: String, + /// The bounds of the text. + bounds: Rectangle, + /// The color of the text. + color: Color, + /// The size of the text in logical pixels. + size: Pixels, + /// The line height of the text. + line_height: Pixels, + /// The font of the text. + font: Font, + /// The horizontal alignment of the text. + horizontal_alignment: alignment::Horizontal, + /// The vertical alignment of the text. + vertical_alignment: alignment::Vertical, + /// The shaping strategy of the text. + shaping: Shaping, + /// The clip bounds of the text. + clip_bounds: Rectangle, + }, + /// Some raw text. + #[allow(missing_docs)] + Raw { + raw: Raw, + transformation: Transformation, + }, +} + +impl Text { + /// Returns the visible bounds of the [`Text`]. + pub fn visible_bounds(&self) -> Option<Rectangle> { + let (bounds, horizontal_alignment, vertical_alignment) = match self { + Text::Paragraph { + position, + paragraph, + clip_bounds, + transformation, + .. + } => ( + Rectangle::new(*position, paragraph.min_bounds) + .intersection(clip_bounds) + .map(|bounds| bounds * *transformation), + Some(paragraph.horizontal_alignment), + Some(paragraph.vertical_alignment), + ), + Text::Editor { + editor, + position, + clip_bounds, + transformation, + .. + } => ( + Rectangle::new(*position, editor.bounds) + .intersection(clip_bounds) + .map(|bounds| bounds * *transformation), + None, + None, + ), + Text::Cached { + bounds, + clip_bounds, + horizontal_alignment, + vertical_alignment, + .. + } => ( + bounds.intersection(clip_bounds), + Some(*horizontal_alignment), + Some(*vertical_alignment), + ), + Text::Raw { raw, .. } => (Some(raw.clip_bounds), None, None), + }; + + let mut bounds = bounds?; + + if let Some(alignment) = horizontal_alignment { + match alignment { + alignment::Horizontal::Left => {} + alignment::Horizontal::Center => { + bounds.x -= bounds.width / 2.0; + } + alignment::Horizontal::Right => { + bounds.x -= bounds.width; + } + } + } + + if let Some(alignment) = vertical_alignment { + match alignment { + alignment::Vertical::Top => {} + alignment::Vertical::Center => { + bounds.y -= bounds.height / 2.0; + } + alignment::Vertical::Bottom => { + bounds.y -= bounds.height; + } + } + } + + Some(bounds) + } +} + /// The regular variant of the [Fira Sans] font. /// /// It is loaded as part of the default fonts in Wasm builds. diff --git a/graphics/src/text/cache.rs b/graphics/src/text/cache.rs index 7fb33567..822b61c4 100644 --- a/graphics/src/text/cache.rs +++ b/graphics/src/text/cache.rs @@ -2,22 +2,18 @@ use crate::core::{Font, Size}; use crate::text; -use rustc_hash::{FxHashMap, FxHashSet}; +use rustc_hash::{FxHashMap, FxHashSet, FxHasher}; use std::collections::hash_map; -use std::hash::{BuildHasher, Hash, Hasher}; +use std::hash::{Hash, Hasher}; /// A store of recently used sections of text. -#[allow(missing_debug_implementations)] -#[derive(Default)] +#[derive(Debug, Default)] pub struct Cache { entries: FxHashMap<KeyHash, Entry>, aliases: FxHashMap<KeyHash, KeyHash>, recently_used: FxHashSet<KeyHash>, - hasher: HashBuilder, } -type HashBuilder = xxhash_rust::xxh3::Xxh3Builder; - impl Cache { /// Creates a new empty [`Cache`]. pub fn new() -> Self { @@ -35,7 +31,7 @@ impl Cache { font_system: &mut cosmic_text::FontSystem, key: Key<'_>, ) -> (KeyHash, &mut Entry) { - let hash = key.hash(self.hasher.build_hasher()); + let hash = key.hash(FxHasher::default()); if let Some(hash) = self.aliases.get(&hash) { let _ = self.recently_used.insert(*hash); @@ -77,7 +73,7 @@ impl Cache { ] { if key.bounds != bounds { let _ = self.aliases.insert( - Key { bounds, ..key }.hash(self.hasher.build_hasher()), + Key { bounds, ..key }.hash(FxHasher::default()), hash, ); } @@ -138,7 +134,7 @@ impl Key<'_> { pub type KeyHash = u64; /// A cache entry. -#[allow(missing_debug_implementations)] +#[derive(Debug)] pub struct Entry { /// The buffer of text, ready for drawing. pub buffer: cosmic_text::Buffer, diff --git a/graphics/src/text/paragraph.rs b/graphics/src/text/paragraph.rs index 5d027542..31a323ac 100644 --- a/graphics/src/text/paragraph.rs +++ b/graphics/src/text/paragraph.rs @@ -61,7 +61,7 @@ impl Paragraph { impl core::text::Paragraph for Paragraph { type Font = Font; - fn with_text(text: Text<'_, Font>) -> Self { + fn with_text(text: Text<&str>) -> Self { log::trace!("Allocating paragraph: {}", text.content); let mut font_system = @@ -146,7 +146,7 @@ impl core::text::Paragraph for Paragraph { } } - fn compare(&self, text: Text<'_, Font>) -> core::text::Difference { + fn compare(&self, text: Text<&str>) -> core::text::Difference { let font_system = text::font_system().read().expect("Read font system"); let paragraph = self.internal(); let metrics = paragraph.buffer.metrics(); |