summaryrefslogtreecommitdiffstats
path: root/graphics/src
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2023-09-11 02:47:24 +0200
committerLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2023-09-11 02:47:24 +0200
commit346af3f8b0baa418fd37b878bc2930ff0bd57cc0 (patch)
treeb11cde03595fb28bddb055507d272dd973634ab5 /graphics/src
parent9245423c5d82f88c99adecaaf5dd2ac3559a05a8 (diff)
downloadiced-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.rs4
-rw-r--r--graphics/src/renderer.rs35
-rw-r--r--graphics/src/text.rs47
-rw-r--r--graphics/src/text/paragraph.rs147
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
}