diff options
author | 2023-09-11 02:47:24 +0200 | |
---|---|---|
committer | 2023-09-11 02:47:24 +0200 | |
commit | 346af3f8b0baa418fd37b878bc2930ff0bd57cc0 (patch) | |
tree | b11cde03595fb28bddb055507d272dd973634ab5 /graphics/src | |
parent | 9245423c5d82f88c99adecaaf5dd2ac3559a05a8 (diff) | |
download | iced-346af3f8b0baa418fd37b878bc2930ff0bd57cc0.tar.gz iced-346af3f8b0baa418fd37b878bc2930ff0bd57cc0.tar.bz2 iced-346af3f8b0baa418fd37b878bc2930ff0bd57cc0.zip |
Make `FontSystem` global and simplify `Paragraph` API
Diffstat (limited to 'graphics/src')
-rw-r--r-- | graphics/src/backend.rs | 4 | ||||
-rw-r--r-- | graphics/src/renderer.rs | 35 | ||||
-rw-r--r-- | graphics/src/text.rs | 47 | ||||
-rw-r--r-- | graphics/src/text/paragraph.rs | 147 |
4 files changed, 89 insertions, 144 deletions
diff --git a/graphics/src/backend.rs b/graphics/src/backend.rs index c2ac82ba..10eb337f 100644 --- a/graphics/src/backend.rs +++ b/graphics/src/backend.rs @@ -2,7 +2,6 @@ use crate::core::image; use crate::core::svg; use crate::core::Size; -use crate::text; use std::borrow::Cow; @@ -18,9 +17,6 @@ pub trait Backend { pub trait Text { /// Loads a font from its bytes. fn load_font(&mut self, font: Cow<'static, [u8]>); - - /// Returns the [`cosmic_text::FontSystem`] of the [`Backend`]. - fn font_system(&self) -> &text::FontSystem; } /// A graphics backend that supports image rendering. diff --git a/graphics/src/renderer.rs b/graphics/src/renderer.rs index d4df29a5..c5033d36 100644 --- a/graphics/src/renderer.rs +++ b/graphics/src/renderer.rs @@ -158,41 +158,6 @@ where self.backend.load_font(bytes); } - fn create_paragraph(&self, text: Text<'_, Self::Font>) -> text::Paragraph { - text::Paragraph::with_text(text, self.backend.font_system()) - } - - fn update_paragraph( - &self, - paragraph: &mut Self::Paragraph, - text: Text<'_, Self::Font>, - ) { - let font_system = self.backend.font_system(); - - if paragraph.version() != font_system.version() { - // The font system has changed, paragraph fonts may be outdated - *paragraph = self.create_paragraph(text); - } else { - match core::text::compare(paragraph, text) { - core::text::Difference::None => {} - core::text::Difference::Bounds => { - self.resize_paragraph(paragraph, text.bounds); - } - core::text::Difference::Shape => { - *paragraph = self.create_paragraph(text); - } - } - } - } - - fn resize_paragraph( - &self, - paragraph: &mut Self::Paragraph, - new_bounds: Size, - ) { - paragraph.resize(new_bounds, self.backend.font_system()); - } - fn fill_paragraph( &mut self, paragraph: &Self::Paragraph, 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<cosmic_text::FontSystem>, - version: Version, -} +pub fn font_system() -> &'static RwLock<FontSystem> { + static FONT_SYSTEM: OnceCell<RwLock<FontSystem>> = 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() diff --git a/graphics/src/text/paragraph.rs b/graphics/src/text/paragraph.rs index e4350cff..d0396e8e 100644 --- a/graphics/src/text/paragraph.rs +++ b/graphics/src/text/paragraph.rs @@ -2,7 +2,7 @@ use crate::core; use crate::core::alignment; use crate::core::text::{Hit, LineHeight, Shaping, Text}; use crate::core::{Font, Pixels, Point, Size}; -use crate::text::{self, FontSystem}; +use crate::text; use std::fmt; use std::sync::{self, Arc}; @@ -27,13 +27,39 @@ impl Paragraph { Self::default() } - pub fn with_text(text: Text<'_, Font>, font_system: &FontSystem) -> Self { + pub fn buffer(&self) -> &cosmic_text::Buffer { + &self.internal().buffer + } + + pub fn downgrade(&self) -> Weak { + let paragraph = self.internal(); + + Weak { + raw: Arc::downgrade(paragraph), + min_bounds: paragraph.min_bounds, + horizontal_alignment: paragraph.horizontal_alignment, + vertical_alignment: paragraph.vertical_alignment, + } + } + + fn internal(&self) -> &Arc<Internal> { + self.0 + .as_ref() + .expect("paragraph should always be initialized") + } +} + +impl core::text::Paragraph for Paragraph { + type Font = Font; + + fn with_text(text: Text<'_, Font>) -> Self { log::trace!("Allocating paragraph: {}", text.content); - let (mut font_system, version) = font_system.write(); + let mut font_system = + text::font_system().write().expect("Write font system"); let mut buffer = cosmic_text::Buffer::new( - &mut font_system, + font_system.raw(), cosmic_text::Metrics::new( text.size.into(), text.line_height.to_absolute(text.size).into(), @@ -41,13 +67,13 @@ impl Paragraph { ); buffer.set_size( - &mut font_system, + font_system.raw(), text.bounds.width, text.bounds.height, ); buffer.set_text( - &mut font_system, + font_system.raw(), text.content, text::to_attributes(text.font), text::to_shaping(text.shaping), @@ -64,30 +90,11 @@ impl Paragraph { shaping: text.shaping, bounds: text.bounds, min_bounds, - version, + version: font_system.version(), }))) } - pub fn buffer(&self) -> &cosmic_text::Buffer { - &self.internal().buffer - } - - pub fn version(&self) -> text::Version { - self.internal().version - } - - pub fn downgrade(&self) -> Weak { - let paragraph = self.internal(); - - Weak { - raw: Arc::downgrade(paragraph), - min_bounds: paragraph.min_bounds, - horizontal_alignment: paragraph.horizontal_alignment, - vertical_alignment: paragraph.vertical_alignment, - } - } - - pub fn resize(&mut self, new_bounds: Size, font_system: &FontSystem) { + fn resize(&mut self, new_bounds: Size) { let paragraph = self .0 .take() @@ -95,10 +102,11 @@ impl Paragraph { match Arc::try_unwrap(paragraph) { Ok(mut internal) => { - let (mut font_system, _) = font_system.write(); + let mut font_system = + text::font_system().write().expect("Write font system"); internal.buffer.set_size( - &mut font_system, + font_system.raw(), new_bounds.width, new_bounds.height, ); @@ -113,55 +121,42 @@ impl Paragraph { // If there is a strong reference somewhere, we recompute the // buffer from scratch - *self = Self::with_text( - Text { - content: &internal.content, - bounds: internal.bounds, - size: Pixels(metrics.font_size), - line_height: LineHeight::Absolute(Pixels( - metrics.line_height, - )), - font: internal.font, - horizontal_alignment: internal.horizontal_alignment, - vertical_alignment: internal.vertical_alignment, - shaping: internal.shaping, - }, - font_system, - ); + *self = Self::with_text(Text { + content: &internal.content, + bounds: internal.bounds, + size: Pixels(metrics.font_size), + line_height: LineHeight::Absolute(Pixels( + metrics.line_height, + )), + font: internal.font, + horizontal_alignment: internal.horizontal_alignment, + vertical_alignment: internal.vertical_alignment, + shaping: internal.shaping, + }); } } } - fn internal(&self) -> &Arc<Internal> { - self.0 - .as_ref() - .expect("paragraph should always be initialized") - } -} - -impl core::text::Paragraph for Paragraph { - type Font = Font; - - fn content(&self) -> &str { - &self.internal().content - } - - fn text_size(&self) -> Pixels { - Pixels(self.internal().buffer.metrics().font_size) - } - - fn line_height(&self) -> LineHeight { - LineHeight::Absolute(Pixels( - self.internal().buffer.metrics().line_height, - )) - } - - fn font(&self) -> Font { - self.internal().font - } - - fn shaping(&self) -> Shaping { - self.internal().shaping + fn compare(&self, text: Text<'_, Font>) -> core::text::Difference { + let font_system = text::font_system().read().expect("Read font system"); + let paragraph = self.internal(); + let metrics = paragraph.buffer.metrics(); + + if paragraph.version != font_system.version + || paragraph.content != text.content + || metrics.font_size != text.size.0 + || metrics.line_height != text.line_height.to_absolute(text.size).0 + || paragraph.font != text.font + || paragraph.shaping != text.shaping + || paragraph.horizontal_alignment != text.horizontal_alignment + || paragraph.vertical_alignment != text.vertical_alignment + { + core::text::Difference::Shape + } else if paragraph.bounds != text.bounds { + core::text::Difference::Bounds + } else { + core::text::Difference::None + } } fn horizontal_alignment(&self) -> alignment::Horizontal { @@ -172,10 +167,6 @@ impl core::text::Paragraph for Paragraph { self.internal().vertical_alignment } - fn bounds(&self) -> Size { - self.internal().bounds - } - fn min_bounds(&self) -> Size { self.internal().min_bounds } |