From ed3454301e663a7cb7d73cd56b57b188f4d14a2f Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 30 Aug 2023 04:31:21 +0200 Subject: Implement explicit text caching in the widget state tree --- graphics/src/text.rs | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 graphics/src/text.rs (limited to 'graphics/src/text.rs') diff --git a/graphics/src/text.rs b/graphics/src/text.rs new file mode 100644 index 00000000..bbe9d7cb --- /dev/null +++ b/graphics/src/text.rs @@ -0,0 +1,113 @@ +pub mod cache; +pub mod paragraph; + +pub use cache::Cache; +pub use paragraph::Paragraph; + +pub use cosmic_text; + +use crate::core::font::{self, Font}; +use crate::core::text::Shaping; +use crate::core::Size; + +use std::sync::{self, Arc, RwLock}; + +#[allow(missing_debug_implementations)] +pub struct FontSystem(RwLock); + +impl FontSystem { + pub fn new() -> Self { + FontSystem(RwLock::new(cosmic_text::FontSystem::new_with_fonts( + [cosmic_text::fontdb::Source::Binary(Arc::new( + include_bytes!("../fonts/Iced-Icons.ttf").as_slice(), + ))] + .into_iter(), + ))) + } + + pub fn get_mut(&mut self) -> &mut cosmic_text::FontSystem { + self.0.get_mut().expect("Lock font system") + } + + pub fn write(&self) -> sync::RwLockWriteGuard<'_, cosmic_text::FontSystem> { + self.0.write().expect("Write font system") + } +} + +impl Default for FontSystem { + fn default() -> Self { + Self::new() + } +} + +pub fn measure(buffer: &cosmic_text::Buffer) -> Size { + let (width, total_lines) = buffer + .layout_runs() + .fold((0.0, 0usize), |(width, total_lines), run| { + (run.line_w.max(width), total_lines + 1) + }); + + Size::new(width, total_lines as f32 * buffer.metrics().line_height) +} + +pub fn to_attributes(font: Font) -> cosmic_text::Attrs<'static> { + cosmic_text::Attrs::new() + .family(to_family(font.family)) + .weight(to_weight(font.weight)) + .stretch(to_stretch(font.stretch)) + .style(to_style(font.style)) +} + +fn to_family(family: font::Family) -> cosmic_text::Family<'static> { + match family { + font::Family::Name(name) => cosmic_text::Family::Name(name), + font::Family::SansSerif => cosmic_text::Family::SansSerif, + font::Family::Serif => cosmic_text::Family::Serif, + font::Family::Cursive => cosmic_text::Family::Cursive, + font::Family::Fantasy => cosmic_text::Family::Fantasy, + font::Family::Monospace => cosmic_text::Family::Monospace, + } +} + +fn to_weight(weight: font::Weight) -> cosmic_text::Weight { + match weight { + font::Weight::Thin => cosmic_text::Weight::THIN, + font::Weight::ExtraLight => cosmic_text::Weight::EXTRA_LIGHT, + font::Weight::Light => cosmic_text::Weight::LIGHT, + font::Weight::Normal => cosmic_text::Weight::NORMAL, + font::Weight::Medium => cosmic_text::Weight::MEDIUM, + font::Weight::Semibold => cosmic_text::Weight::SEMIBOLD, + font::Weight::Bold => cosmic_text::Weight::BOLD, + font::Weight::ExtraBold => cosmic_text::Weight::EXTRA_BOLD, + font::Weight::Black => cosmic_text::Weight::BLACK, + } +} + +fn to_stretch(stretch: font::Stretch) -> cosmic_text::Stretch { + match stretch { + font::Stretch::UltraCondensed => cosmic_text::Stretch::UltraCondensed, + font::Stretch::ExtraCondensed => cosmic_text::Stretch::ExtraCondensed, + font::Stretch::Condensed => cosmic_text::Stretch::Condensed, + font::Stretch::SemiCondensed => cosmic_text::Stretch::SemiCondensed, + font::Stretch::Normal => cosmic_text::Stretch::Normal, + font::Stretch::SemiExpanded => cosmic_text::Stretch::SemiExpanded, + font::Stretch::Expanded => cosmic_text::Stretch::Expanded, + font::Stretch::ExtraExpanded => cosmic_text::Stretch::ExtraExpanded, + font::Stretch::UltraExpanded => cosmic_text::Stretch::UltraExpanded, + } +} + +fn to_style(style: font::Style) -> cosmic_text::Style { + match style { + font::Style::Normal => cosmic_text::Style::Normal, + font::Style::Italic => cosmic_text::Style::Italic, + font::Style::Oblique => cosmic_text::Style::Oblique, + } +} + +pub fn to_shaping(shaping: Shaping) -> cosmic_text::Shaping { + match shaping { + Shaping::Basic => cosmic_text::Shaping::Basic, + Shaping::Advanced => cosmic_text::Shaping::Advanced, + } +} -- cgit From 3450987355be7fe029db112474d06613929b54c7 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 9 Sep 2023 11:21:32 +0200 Subject: Invalidate existing paragraphs when new fonts are loaded --- graphics/src/text.rs | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) (limited to 'graphics/src/text.rs') diff --git a/graphics/src/text.rs b/graphics/src/text.rs index bbe9d7cb..bc06aa3c 100644 --- a/graphics/src/text.rs +++ b/graphics/src/text.rs @@ -10,30 +10,54 @@ use crate::core::font::{self, Font}; use crate::core::text::Shaping; use crate::core::Size; +use std::borrow::Cow; use std::sync::{self, Arc, RwLock}; #[allow(missing_debug_implementations)] -pub struct FontSystem(RwLock); +pub struct FontSystem { + raw: RwLock, + version: Version, +} impl FontSystem { pub fn new() -> Self { - FontSystem(RwLock::new(cosmic_text::FontSystem::new_with_fonts( - [cosmic_text::fontdb::Source::Binary(Arc::new( - include_bytes!("../fonts/Iced-Icons.ttf").as_slice(), - ))] - .into_iter(), - ))) + FontSystem { + raw: RwLock::new(cosmic_text::FontSystem::new_with_fonts( + [cosmic_text::fontdb::Source::Binary(Arc::new( + include_bytes!("../fonts/Iced-Icons.ttf").as_slice(), + ))] + .into_iter(), + )), + version: Version::default(), + } } pub fn get_mut(&mut self) -> &mut cosmic_text::FontSystem { - self.0.get_mut().expect("Lock font system") + self.raw.get_mut().expect("Lock font system") + } + + pub fn write( + &self, + ) -> (sync::RwLockWriteGuard<'_, cosmic_text::FontSystem>, Version) { + (self.raw.write().expect("Write font system"), self.version) } - pub fn write(&self) -> sync::RwLockWriteGuard<'_, cosmic_text::FontSystem> { - self.0.write().expect("Write font system") + pub fn load_font(&mut self, bytes: Cow<'static, [u8]>) { + let _ = self.get_mut().db_mut().load_font_source( + cosmic_text::fontdb::Source::Binary(Arc::new(bytes.into_owned())), + ); + + self.version = Version(self.version.0 + 1); + } + + pub fn version(&self) -> Version { + self.version } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +pub struct Version(u32); + impl Default for FontSystem { fn default() -> Self { Self::new() -- cgit From 346af3f8b0baa418fd37b878bc2930ff0bd57cc0 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 11 Sep 2023 02:47:24 +0200 Subject: Make `FontSystem` global and simplify `Paragraph` API --- graphics/src/text.rs | 47 ++++++++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 27 deletions(-) (limited to 'graphics/src/text.rs') diff --git a/graphics/src/text.rs b/graphics/src/text.rs index bc06aa3c..f5ccaf52 100644 --- a/graphics/src/text.rs +++ b/graphics/src/text.rs @@ -10,40 +10,39 @@ use crate::core::font::{self, Font}; use crate::core::text::Shaping; use crate::core::Size; +use once_cell::sync::OnceCell; use std::borrow::Cow; -use std::sync::{self, Arc, RwLock}; +use std::sync::{Arc, RwLock}; -#[allow(missing_debug_implementations)] -pub struct FontSystem { - raw: RwLock, - version: Version, -} +pub fn font_system() -> &'static RwLock { + static FONT_SYSTEM: OnceCell> = OnceCell::new(); -impl FontSystem { - pub fn new() -> Self { - FontSystem { - raw: RwLock::new(cosmic_text::FontSystem::new_with_fonts( + FONT_SYSTEM.get_or_init(|| { + RwLock::new(FontSystem { + raw: cosmic_text::FontSystem::new_with_fonts( [cosmic_text::fontdb::Source::Binary(Arc::new( include_bytes!("../fonts/Iced-Icons.ttf").as_slice(), ))] .into_iter(), - )), + ), version: Version::default(), - } - } + }) + }) +} - pub fn get_mut(&mut self) -> &mut cosmic_text::FontSystem { - self.raw.get_mut().expect("Lock font system") - } +#[allow(missing_debug_implementations)] +pub struct FontSystem { + raw: cosmic_text::FontSystem, + version: Version, +} - pub fn write( - &self, - ) -> (sync::RwLockWriteGuard<'_, cosmic_text::FontSystem>, Version) { - (self.raw.write().expect("Write font system"), self.version) +impl FontSystem { + pub fn raw(&mut self) -> &mut cosmic_text::FontSystem { + &mut self.raw } pub fn load_font(&mut self, bytes: Cow<'static, [u8]>) { - let _ = self.get_mut().db_mut().load_font_source( + let _ = self.raw.db_mut().load_font_source( cosmic_text::fontdb::Source::Binary(Arc::new(bytes.into_owned())), ); @@ -58,12 +57,6 @@ impl FontSystem { #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct Version(u32); -impl Default for FontSystem { - fn default() -> Self { - Self::new() - } -} - pub fn measure(buffer: &cosmic_text::Buffer) -> Size { let (width, total_lines) = buffer .layout_runs() -- cgit From 6448429103c9c82b90040ac5a5a097bdded23f82 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 12 Sep 2023 14:51:00 +0200 Subject: Draft `Editor` API and `TextEditor` widget --- graphics/src/text.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'graphics/src/text.rs') diff --git a/graphics/src/text.rs b/graphics/src/text.rs index f5ccaf52..280e4f01 100644 --- a/graphics/src/text.rs +++ b/graphics/src/text.rs @@ -1,7 +1,9 @@ pub mod cache; +pub mod editor; pub mod paragraph; pub use cache::Cache; +pub use editor::Editor; pub use paragraph::Paragraph; pub use cosmic_text; -- cgit From 723111bb0df486bffaedcaed0722b1793d65bfe3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 16 Sep 2023 19:09:31 +0200 Subject: Remove unnecessary `into_iter` call in `graphics::text` --- graphics/src/text.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'graphics/src/text.rs') diff --git a/graphics/src/text.rs b/graphics/src/text.rs index 280e4f01..b4aeb2be 100644 --- a/graphics/src/text.rs +++ b/graphics/src/text.rs @@ -21,12 +21,11 @@ pub fn font_system() -> &'static RwLock { FONT_SYSTEM.get_or_init(|| { RwLock::new(FontSystem { - raw: cosmic_text::FontSystem::new_with_fonts( - [cosmic_text::fontdb::Source::Binary(Arc::new( + raw: cosmic_text::FontSystem::new_with_fonts([ + cosmic_text::fontdb::Source::Binary(Arc::new( include_bytes!("../fonts/Iced-Icons.ttf").as_slice(), - ))] - .into_iter(), - ), + )), + ]), version: Version::default(), }) }) -- cgit From 76dc82e8e8b5201ec10f8d00d851c1decf998583 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 17 Sep 2023 15:29:14 +0200 Subject: Draft `Highlighter` API --- graphics/src/text.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'graphics/src/text.rs') diff --git a/graphics/src/text.rs b/graphics/src/text.rs index b4aeb2be..5fcfc699 100644 --- a/graphics/src/text.rs +++ b/graphics/src/text.rs @@ -10,7 +10,7 @@ pub use cosmic_text; use crate::core::font::{self, Font}; use crate::core::text::Shaping; -use crate::core::Size; +use crate::core::{Color, Size}; use once_cell::sync::OnceCell; use std::borrow::Cow; @@ -129,3 +129,9 @@ pub fn to_shaping(shaping: Shaping) -> cosmic_text::Shaping { Shaping::Advanced => cosmic_text::Shaping::Advanced, } } + +pub fn to_color(color: Color) -> cosmic_text::Color { + let [r, g, b, a] = color.into_rgba8(); + + cosmic_text::Color::rgba(r, g, b, a) +} -- cgit From be340a8cd822be1ea0fe4c1b1f3a62ca66d705b4 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 19 Sep 2023 23:00:20 +0200 Subject: Fix gamma correction for colored glyphs in `iced_wgpu` --- graphics/src/text.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'graphics/src/text.rs') diff --git a/graphics/src/text.rs b/graphics/src/text.rs index 5fcfc699..c10eacad 100644 --- a/graphics/src/text.rs +++ b/graphics/src/text.rs @@ -8,6 +8,7 @@ pub use paragraph::Paragraph; pub use cosmic_text; +use crate::color; use crate::core::font::{self, Font}; use crate::core::text::Shaping; use crate::core::{Color, Size}; @@ -131,7 +132,12 @@ pub fn to_shaping(shaping: Shaping) -> cosmic_text::Shaping { } pub fn to_color(color: Color) -> cosmic_text::Color { - let [r, g, b, a] = color.into_rgba8(); - - cosmic_text::Color::rgba(r, g, b, a) + let [r, g, b, a] = color::pack(color).components(); + + cosmic_text::Color::rgba( + (r * 255.0) as u8, + (g * 255.0) as u8, + (b * 255.0) as u8, + (a * 255.0) as u8, + ) } -- cgit From 625cd745f38215b1cb8f629cdc6d2fa41c9a739a Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 27 Oct 2023 05:04:14 +0200 Subject: Write documentation for the new text APIs --- graphics/src/text.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'graphics/src/text.rs') diff --git a/graphics/src/text.rs b/graphics/src/text.rs index c10eacad..7261900e 100644 --- a/graphics/src/text.rs +++ b/graphics/src/text.rs @@ -1,3 +1,4 @@ +//! Draw text. pub mod cache; pub mod editor; pub mod paragraph; @@ -17,6 +18,7 @@ use once_cell::sync::OnceCell; use std::borrow::Cow; use std::sync::{Arc, RwLock}; +/// Returns the global [`FontSystem`]. pub fn font_system() -> &'static RwLock { static FONT_SYSTEM: OnceCell> = OnceCell::new(); @@ -32,6 +34,7 @@ pub fn font_system() -> &'static RwLock { }) } +/// A set of system fonts. #[allow(missing_debug_implementations)] pub struct FontSystem { raw: cosmic_text::FontSystem, @@ -39,10 +42,12 @@ pub struct FontSystem { } impl FontSystem { + /// Returns the raw [`cosmic_text::FontSystem`]. pub fn raw(&mut self) -> &mut cosmic_text::FontSystem { &mut self.raw } + /// Loads a font from its bytes. pub fn load_font(&mut self, bytes: Cow<'static, [u8]>) { let _ = self.raw.db_mut().load_font_source( cosmic_text::fontdb::Source::Binary(Arc::new(bytes.into_owned())), @@ -51,14 +56,19 @@ impl FontSystem { self.version = Version(self.version.0 + 1); } + /// Returns the current [`Version`] of the [`FontSystem`]. + /// + /// Loading a font will increase the version of a [`FontSystem`]. pub fn version(&self) -> Version { self.version } } +/// A version number. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct Version(u32); +/// Measures the dimensions of the given [`cosmic_text::Buffer`]. pub fn measure(buffer: &cosmic_text::Buffer) -> Size { let (width, total_lines) = buffer .layout_runs() @@ -69,6 +79,7 @@ pub fn measure(buffer: &cosmic_text::Buffer) -> Size { Size::new(width, total_lines as f32 * buffer.metrics().line_height) } +/// Returns the attributes of the given [`Font`]. pub fn to_attributes(font: Font) -> cosmic_text::Attrs<'static> { cosmic_text::Attrs::new() .family(to_family(font.family)) @@ -124,6 +135,7 @@ fn to_style(style: font::Style) -> cosmic_text::Style { } } +/// Converts some [`Shaping`] strategy to a [`cosmic_text::Shaping`] strategy. pub fn to_shaping(shaping: Shaping) -> cosmic_text::Shaping { match shaping { Shaping::Basic => cosmic_text::Shaping::Basic, @@ -131,6 +143,7 @@ pub fn to_shaping(shaping: Shaping) -> cosmic_text::Shaping { } } +/// Converts some [`Color`] to a [`cosmic_text::Color`]. pub fn to_color(color: Color) -> cosmic_text::Color { let [r, g, b, a] = color::pack(color).components(); -- cgit