From 603832e66c710ea39a95009ddc905de20c6856bd Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 5 Dec 2023 02:19:17 +0100 Subject: Introduce `RawText` to `Primitive` in `iced_graphics` This should allow users to directly render a `cosmic_text::Buffer`. --- graphics/src/damage.rs | 5 +++++ graphics/src/primitive.rs | 2 ++ graphics/src/text.rs | 27 +++++++++++++++++++++++++-- 3 files changed, 32 insertions(+), 2 deletions(-) (limited to 'graphics') diff --git a/graphics/src/damage.rs b/graphics/src/damage.rs index 595cc274..59e9f5b4 100644 --- a/graphics/src/damage.rs +++ b/graphics/src/damage.rs @@ -73,6 +73,11 @@ impl Damage for Primitive { bounds.expand(1.5) } + Self::RawText(raw) => { + // TODO: Add `size` field to `raw` to compute more accurate + // damage bounds (?) + raw.clip_bounds.expand(1.5) + } Self::Quad { bounds, .. } | Self::Image { bounds, .. } | Self::Svg { bounds, .. } => bounds.expand(1.0), diff --git a/graphics/src/primitive.rs b/graphics/src/primitive.rs index ed75776c..20affaaf 100644 --- a/graphics/src/primitive.rs +++ b/graphics/src/primitive.rs @@ -57,6 +57,8 @@ pub enum Primitive { /// The clip bounds of the editor. clip_bounds: Rectangle, }, + /// A raw `cosmic-text` primitive + RawText(crate::text::Raw), /// A quad primitive Quad { /// The bounds of the quad diff --git a/graphics/src/text.rs b/graphics/src/text.rs index fc7694c2..8fd037fe 100644 --- a/graphics/src/text.rs +++ b/graphics/src/text.rs @@ -12,11 +12,11 @@ pub use cosmic_text; use crate::color; use crate::core::font::{self, Font}; use crate::core::text::Shaping; -use crate::core::{Color, Size}; +use crate::core::{Color, Point, Rectangle, Size}; use once_cell::sync::OnceCell; use std::borrow::Cow; -use std::sync::{Arc, RwLock}; +use std::sync::{Arc, RwLock, Weak}; /// Returns the global [`FontSystem`]. pub fn font_system() -> &'static RwLock { @@ -68,6 +68,29 @@ impl FontSystem { #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct Version(u32); +/// A weak reference to a [`cosmic-text::Buffer`] that can be drawn. +#[derive(Debug, Clone)] +pub struct Raw { + /// A weak reference to a [`cosmic_text::Buffer`]. + pub buffer: Weak, + /// The position of the text. + pub position: Point, + /// The color of the text. + pub color: Color, + /// The clip bounds of the text. + pub clip_bounds: Rectangle, +} + +impl PartialEq for Raw { + fn eq(&self, _other: &Self) -> bool { + // TODO: There is no proper way to compare raw buffers + // For now, no two instances of `Raw` text will be equal. + // This should be fine, but could trigger unnecessary redraws + // in the future. + false + } +} + /// Measures the dimensions of the given [`cosmic_text::Buffer`]. pub fn measure(buffer: &cosmic_text::Buffer) -> Size { let (width, total_lines) = buffer -- cgit From 9c50a7ed7ee439b658f406da9018c9249ffa0b81 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 11 Jan 2024 08:29:44 +0100 Subject: Fix `grapheme_position` when ligatures are present --- graphics/src/text/paragraph.rs | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'graphics') diff --git a/graphics/src/text/paragraph.rs b/graphics/src/text/paragraph.rs index 4a08a8f4..56cd8868 100644 --- a/graphics/src/text/paragraph.rs +++ b/graphics/src/text/paragraph.rs @@ -187,38 +187,43 @@ impl core::text::Paragraph for Paragraph { } fn grapheme_position(&self, line: usize, index: usize) -> Option { + use unicode_segmentation::UnicodeSegmentation; + let run = self.internal().buffer.layout_runs().nth(line)?; // index represents a grapheme, not a glyph // Let's find the first glyph for the given grapheme cluster let mut last_start = None; + let mut last_grapheme_count = 0; let mut graphemes_seen = 0; let glyph = run .glyphs .iter() .find(|glyph| { - if graphemes_seen == index { - return true; - } - if Some(glyph.start) != last_start { + last_grapheme_count = run.text[glyph.start..glyph.end] + .graphemes(false) + .count(); last_start = Some(glyph.start); - graphemes_seen += 1; + graphemes_seen += last_grapheme_count; } - false + graphemes_seen >= index }) .or_else(|| run.glyphs.last())?; - let advance_last = if index == run.glyphs.len() { - glyph.w - } else { + let advance = if index == 0 { 0.0 + } else { + glyph.w + * (1.0 + - graphemes_seen.saturating_sub(index) as f32 + / last_grapheme_count as f32) }; Some(Point::new( - glyph.x + glyph.x_offset * glyph.font_size + advance_last, + glyph.x + glyph.x_offset * glyph.font_size + advance, glyph.y - glyph.y_offset * glyph.font_size, )) } -- cgit From 3d88ceb482855549271fe73165eeea4871222048 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 11 Jan 2024 08:32:30 +0100 Subject: Avoid division by zero in `grapheme_position` --- graphics/src/text/paragraph.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'graphics') diff --git a/graphics/src/text/paragraph.rs b/graphics/src/text/paragraph.rs index 56cd8868..5d027542 100644 --- a/graphics/src/text/paragraph.rs +++ b/graphics/src/text/paragraph.rs @@ -219,7 +219,7 @@ impl core::text::Paragraph for Paragraph { glyph.w * (1.0 - graphemes_seen.saturating_sub(index) as f32 - / last_grapheme_count as f32) + / last_grapheme_count.max(1) as f32) }; Some(Point::new( -- cgit From d948ca6f0979bc8120dcf3ce7ba78eac54755ce3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 15 Jan 2024 23:45:24 +0100 Subject: Update `glyphon` to `0.4` `Color` is now always in the sRGB color space. --- graphics/src/text.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'graphics') diff --git a/graphics/src/text.rs b/graphics/src/text.rs index 8fd037fe..7c4b5e31 100644 --- a/graphics/src/text.rs +++ b/graphics/src/text.rs @@ -9,7 +9,6 @@ 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, Point, Rectangle, Size}; @@ -173,12 +172,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(); + let [r, g, b, a] = color.into_rgba8(); - cosmic_text::Color::rgba( - (r * 255.0) as u8, - (g * 255.0) as u8, - (b * 255.0) as u8, - (a * 255.0) as u8, - ) + cosmic_text::Color::rgba(r, g, b, a) } -- cgit