From 95ff96f71f8f8069608ad08985e2b1214dd42284 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 7 Jul 2023 07:12:37 +0200 Subject: Update `cosmic-text` and `glyphon` --- wgpu/src/text.rs | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'wgpu/src/text.rs') diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs index 65d3b818..ef910c39 100644 --- a/wgpu/src/text.rs +++ b/wgpu/src/text.rs @@ -35,7 +35,7 @@ impl Pipeline { .into_iter(), )), renderers: Vec::new(), - atlas: glyphon::TextAtlas::new( + atlas: glyphon::TextAtlas::with_color_mode( device, queue, format, @@ -66,7 +66,7 @@ impl Pipeline { bounds: Rectangle, scale_factor: f32, target_size: Size, - ) -> bool { + ) { if self.renderers.len() <= self.prepare_layer { self.renderers.push(glyphon::TextRenderer::new( &mut self.atlas, @@ -188,21 +188,11 @@ impl Pipeline { match result { Ok(()) => { self.prepare_layer += 1; - - true } - Err(glyphon::PrepareError::AtlasFull(content_type)) => { - self.prepare_layer = 0; - - #[allow(clippy::needless_bool)] - if self.atlas.grow(device, content_type) { - false - } else { - // If the atlas cannot grow, then all bets are off. - // Instead of panicking, we will just pray that the result - // will be somewhat readable... - true - } + Err(glyphon::PrepareError::AtlasFull) => { + // If the atlas cannot grow, then all bets are off. + // Instead of panicking, we will just pray that the result + // will be somewhat readable... } } } -- cgit From e86363837d8e3a6241a90cb5b895034f07106059 Mon Sep 17 00:00:00 2001 From: lufte Date: Fri, 18 Aug 2023 18:46:22 -0300 Subject: Make the style attribute available on Font --- wgpu/src/text.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'wgpu/src/text.rs') diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs index ef910c39..fb13545d 100644 --- a/wgpu/src/text.rs +++ b/wgpu/src/text.rs @@ -339,6 +339,14 @@ fn to_stretch(stretch: font::Stretch) -> glyphon::Stretch { } } +fn to_style(style: font::Style) -> glyphon::Style { + match style { + font::Style::Normal => glyphon::Style::Normal, + font::Style::Italic => glyphon::Style::Italic, + font::Style::Oblique => glyphon::Style::Oblique, + } +} + fn to_shaping(shaping: Shaping) -> glyphon::Shaping { match shaping { Shaping::Basic => glyphon::Shaping::Basic, @@ -420,7 +428,8 @@ impl Cache { glyphon::Attrs::new() .family(to_family(key.font.family)) .weight(to_weight(key.font.weight)) - .stretch(to_stretch(key.font.stretch)), + .stretch(to_stretch(key.font.stretch)) + .style(to_style(key.font.style)), to_shaping(key.shaping), ); -- cgit 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 --- wgpu/src/text.rs | 509 +++++++++++++++---------------------------------------- 1 file changed, 133 insertions(+), 376 deletions(-) (limited to 'wgpu/src/text.rs') diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs index fb13545d..da2062fe 100644 --- a/wgpu/src/text.rs +++ b/wgpu/src/text.rs @@ -1,20 +1,17 @@ use crate::core::alignment; -use crate::core::font::{self, Font}; -use crate::core::text::{Hit, LineHeight, Shaping}; -use crate::core::{Pixels, Point, Rectangle, Size}; +use crate::core::{Rectangle, Size}; use crate::graphics::color; +use crate::graphics::text::cache::{self, Cache}; +use crate::graphics::text::{FontSystem, Paragraph}; use crate::layer::Text; -use rustc_hash::{FxHashMap, FxHashSet}; use std::borrow::Cow; use std::cell::RefCell; -use std::collections::hash_map; -use std::hash::{BuildHasher, Hash, Hasher}; use std::sync::Arc; #[allow(missing_debug_implementations)] pub struct Pipeline { - font_system: RefCell, + font_system: FontSystem, renderers: Vec, atlas: glyphon::TextAtlas, prepare_layer: usize, @@ -28,12 +25,7 @@ impl Pipeline { format: wgpu::TextureFormat, ) -> Self { Pipeline { - font_system: RefCell::new(glyphon::FontSystem::new_with_fonts( - [glyphon::fontdb::Source::Binary(Arc::new( - include_bytes!("../fonts/Iced-Icons.ttf").as_slice(), - ))] - .into_iter(), - )), + font_system: FontSystem::new(), renderers: Vec::new(), atlas: glyphon::TextAtlas::with_color_mode( device, @@ -50,6 +42,10 @@ impl Pipeline { } } + pub fn font_system(&self) -> &FontSystem { + &self.font_system + } + pub fn load_font(&mut self, bytes: Cow<'static, [u8]>) { let _ = self.font_system.get_mut().db_mut().load_font_source( glyphon::fontdb::Source::Binary(Arc::new(bytes.into_owned())), @@ -80,97 +76,137 @@ impl Pipeline { let renderer = &mut self.renderers[self.prepare_layer]; let cache = self.cache.get_mut(); - if self.prepare_layer == 0 { - cache.trim(Purpose::Drawing); + enum Allocation { + Paragraph(Paragraph), + Cache(cache::KeyHash), } - let keys: Vec<_> = sections + let allocations: Vec<_> = sections .iter() - .map(|section| { - let (key, _) = cache.allocate( - font_system, - Key { - content: section.content, - size: section.size, - line_height: f32::from( - section - .line_height - .to_absolute(Pixels(section.size)), - ), - font: section.font, - bounds: Size { - width: section.bounds.width, - height: section.bounds.height, + .map(|section| match section { + Text::Managed { paragraph, .. } => { + paragraph.upgrade().map(Allocation::Paragraph) + } + Text::Cached(text) => { + let (key, _) = cache.allocate( + font_system, + cache::Key { + content: text.content, + size: text.size.into(), + line_height: f32::from( + text.line_height.to_absolute(text.size), + ), + font: text.font, + bounds: Size { + width: bounds.width, + height: bounds.height, + }, + shaping: text.shaping, }, - shaping: section.shaping, - }, - Purpose::Drawing, - ); + ); - key + Some(Allocation::Cache(key)) + } }) .collect(); - let bounds = bounds * scale_factor; - - let text_areas = - sections - .iter() - .zip(keys.iter()) - .filter_map(|(section, key)| { - let entry = cache.get(key).expect("Get cached buffer"); - - let x = section.bounds.x * scale_factor; - let y = section.bounds.y * scale_factor; - - let max_width = entry.bounds.width * scale_factor; - let total_height = entry.bounds.height * scale_factor; - - let left = match section.horizontal_alignment { - alignment::Horizontal::Left => x, - alignment::Horizontal::Center => x - max_width / 2.0, - alignment::Horizontal::Right => x - max_width, - }; - - let top = match section.vertical_alignment { - alignment::Vertical::Top => y, - alignment::Vertical::Center => y - total_height / 2.0, - alignment::Vertical::Bottom => y - total_height, - }; - - let section_bounds = Rectangle { - x: left, - y: top, - width: section.bounds.width * scale_factor, - height: section.bounds.height * scale_factor, - }; - - let clip_bounds = bounds.intersection(§ion_bounds)?; - - Some(glyphon::TextArea { - buffer: &entry.buffer, - left, - top, - scale: scale_factor, - bounds: glyphon::TextBounds { - left: clip_bounds.x as i32, - top: clip_bounds.y as i32, - right: (clip_bounds.x + clip_bounds.width) as i32, - bottom: (clip_bounds.y + clip_bounds.height) as i32, - }, - default_color: { - let [r, g, b, a] = - color::pack(section.color).components(); - - glyphon::Color::rgba( - (r * 255.0) as u8, - (g * 255.0) as u8, - (b * 255.0) as u8, - (a * 255.0) as u8, - ) - }, - }) - }); + let layer_bounds = bounds * scale_factor; + + let text_areas = sections.iter().zip(allocations.iter()).filter_map( + |(section, allocation)| { + let ( + buffer, + bounds, + horizontal_alignment, + vertical_alignment, + color, + ) = match section { + Text::Managed { + position, color, .. + } => { + use crate::core::text::Paragraph as _; + + let Some(Allocation::Paragraph(paragraph)) = allocation + else { + return None; + }; + + ( + paragraph.buffer(), + Rectangle::new(*position, paragraph.min_bounds()), + paragraph.horizontal_alignment(), + paragraph.vertical_alignment(), + *color, + ) + } + Text::Cached(text) => { + let Some(Allocation::Cache(key)) = allocation else { + return None; + }; + + let buffer = cache.get(key).expect("Get cached buffer"); + + ( + buffer, + text.bounds, + text.horizontal_alignment, + text.vertical_alignment, + text.color, + ) + } + }; + + let x = bounds.x * scale_factor; + let y = bounds.y * scale_factor; + + let max_width = bounds.width * scale_factor; + let total_height = bounds.height * scale_factor; + + let left = match horizontal_alignment { + alignment::Horizontal::Left => x, + alignment::Horizontal::Center => x - max_width / 2.0, + alignment::Horizontal::Right => x - max_width, + }; + + let top = match vertical_alignment { + alignment::Vertical::Top => y, + alignment::Vertical::Center => y - total_height / 2.0, + alignment::Vertical::Bottom => y - total_height, + }; + + let section_bounds = Rectangle { + x: left, + y: top, + width: max_width, + height: total_height, + }; + + let clip_bounds = layer_bounds.intersection(§ion_bounds)?; + + Some(glyphon::TextArea { + buffer, + left, + top, + scale: scale_factor, + bounds: glyphon::TextBounds { + left: clip_bounds.x as i32, + top: clip_bounds.y as i32, + right: (clip_bounds.x + clip_bounds.width) as i32, + bottom: (clip_bounds.y + clip_bounds.height) as i32, + }, + default_color: { + let [r, g, b, a] = color::pack(color).components(); + + glyphon::Color::rgba( + (r * 255.0) as u8, + (g * 255.0) as u8, + (b * 255.0) as u8, + (a * 255.0) as u8, + ) + }, + }) + }, + ); let result = renderer.prepare( device, @@ -219,287 +255,8 @@ impl Pipeline { pub fn end_frame(&mut self) { self.atlas.trim(); + self.cache.get_mut().trim(); self.prepare_layer = 0; } - - pub fn trim_measurements(&mut self) { - self.cache.get_mut().trim(Purpose::Measuring); - } - - pub fn measure( - &self, - content: &str, - size: f32, - line_height: LineHeight, - font: Font, - bounds: Size, - shaping: Shaping, - ) -> Size { - let mut cache = self.cache.borrow_mut(); - - let line_height = f32::from(line_height.to_absolute(Pixels(size))); - - let (_, entry) = cache.allocate( - &mut self.font_system.borrow_mut(), - Key { - content, - size, - line_height, - font, - bounds, - shaping, - }, - Purpose::Measuring, - ); - - entry.bounds - } - - pub fn hit_test( - &self, - content: &str, - size: f32, - line_height: LineHeight, - font: Font, - bounds: Size, - shaping: Shaping, - point: Point, - _nearest_only: bool, - ) -> Option { - let mut cache = self.cache.borrow_mut(); - - let line_height = f32::from(line_height.to_absolute(Pixels(size))); - - let (_, entry) = cache.allocate( - &mut self.font_system.borrow_mut(), - Key { - content, - size, - line_height, - font, - bounds, - shaping, - }, - Purpose::Measuring, - ); - - let cursor = entry.buffer.hit(point.x, point.y)?; - - Some(Hit::CharOffset(cursor.index)) - } } - -fn measure(buffer: &glyphon::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) -} - -fn to_family(family: font::Family) -> glyphon::Family<'static> { - match family { - font::Family::Name(name) => glyphon::Family::Name(name), - font::Family::SansSerif => glyphon::Family::SansSerif, - font::Family::Serif => glyphon::Family::Serif, - font::Family::Cursive => glyphon::Family::Cursive, - font::Family::Fantasy => glyphon::Family::Fantasy, - font::Family::Monospace => glyphon::Family::Monospace, - } -} - -fn to_weight(weight: font::Weight) -> glyphon::Weight { - match weight { - font::Weight::Thin => glyphon::Weight::THIN, - font::Weight::ExtraLight => glyphon::Weight::EXTRA_LIGHT, - font::Weight::Light => glyphon::Weight::LIGHT, - font::Weight::Normal => glyphon::Weight::NORMAL, - font::Weight::Medium => glyphon::Weight::MEDIUM, - font::Weight::Semibold => glyphon::Weight::SEMIBOLD, - font::Weight::Bold => glyphon::Weight::BOLD, - font::Weight::ExtraBold => glyphon::Weight::EXTRA_BOLD, - font::Weight::Black => glyphon::Weight::BLACK, - } -} - -fn to_stretch(stretch: font::Stretch) -> glyphon::Stretch { - match stretch { - font::Stretch::UltraCondensed => glyphon::Stretch::UltraCondensed, - font::Stretch::ExtraCondensed => glyphon::Stretch::ExtraCondensed, - font::Stretch::Condensed => glyphon::Stretch::Condensed, - font::Stretch::SemiCondensed => glyphon::Stretch::SemiCondensed, - font::Stretch::Normal => glyphon::Stretch::Normal, - font::Stretch::SemiExpanded => glyphon::Stretch::SemiExpanded, - font::Stretch::Expanded => glyphon::Stretch::Expanded, - font::Stretch::ExtraExpanded => glyphon::Stretch::ExtraExpanded, - font::Stretch::UltraExpanded => glyphon::Stretch::UltraExpanded, - } -} - -fn to_style(style: font::Style) -> glyphon::Style { - match style { - font::Style::Normal => glyphon::Style::Normal, - font::Style::Italic => glyphon::Style::Italic, - font::Style::Oblique => glyphon::Style::Oblique, - } -} - -fn to_shaping(shaping: Shaping) -> glyphon::Shaping { - match shaping { - Shaping::Basic => glyphon::Shaping::Basic, - Shaping::Advanced => glyphon::Shaping::Advanced, - } -} - -struct Cache { - entries: FxHashMap, - aliases: FxHashMap, - recently_measured: FxHashSet, - recently_drawn: FxHashSet, - hasher: HashBuilder, -} - -struct Entry { - buffer: glyphon::Buffer, - bounds: Size, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum Purpose { - Measuring, - Drawing, -} - -#[cfg(not(target_arch = "wasm32"))] -type HashBuilder = twox_hash::RandomXxHashBuilder64; - -#[cfg(target_arch = "wasm32")] -type HashBuilder = std::hash::BuildHasherDefault; - -impl Cache { - fn new() -> Self { - Self { - entries: FxHashMap::default(), - aliases: FxHashMap::default(), - recently_measured: FxHashSet::default(), - recently_drawn: FxHashSet::default(), - hasher: HashBuilder::default(), - } - } - - fn get(&self, key: &KeyHash) -> Option<&Entry> { - self.entries.get(key) - } - - fn allocate( - &mut self, - font_system: &mut glyphon::FontSystem, - key: Key<'_>, - purpose: Purpose, - ) -> (KeyHash, &mut Entry) { - let hash = key.hash(self.hasher.build_hasher()); - - let recently_used = match purpose { - Purpose::Measuring => &mut self.recently_measured, - Purpose::Drawing => &mut self.recently_drawn, - }; - - if let Some(hash) = self.aliases.get(&hash) { - let _ = recently_used.insert(*hash); - - return (*hash, self.entries.get_mut(hash).unwrap()); - } - - if let hash_map::Entry::Vacant(entry) = self.entries.entry(hash) { - let metrics = glyphon::Metrics::new(key.size, key.line_height); - let mut buffer = glyphon::Buffer::new(font_system, metrics); - - buffer.set_size( - font_system, - key.bounds.width, - key.bounds.height.max(key.line_height), - ); - buffer.set_text( - font_system, - key.content, - glyphon::Attrs::new() - .family(to_family(key.font.family)) - .weight(to_weight(key.font.weight)) - .stretch(to_stretch(key.font.stretch)) - .style(to_style(key.font.style)), - to_shaping(key.shaping), - ); - - let bounds = measure(&buffer); - let _ = entry.insert(Entry { buffer, bounds }); - - for bounds in [ - bounds, - Size { - width: key.bounds.width, - ..bounds - }, - ] { - if key.bounds != bounds { - let _ = self.aliases.insert( - Key { bounds, ..key }.hash(self.hasher.build_hasher()), - hash, - ); - } - } - } - - let _ = recently_used.insert(hash); - - (hash, self.entries.get_mut(&hash).unwrap()) - } - - fn trim(&mut self, purpose: Purpose) { - self.entries.retain(|key, _| { - self.recently_measured.contains(key) - || self.recently_drawn.contains(key) - }); - self.aliases.retain(|_, value| { - self.recently_measured.contains(value) - || self.recently_drawn.contains(value) - }); - - match purpose { - Purpose::Measuring => { - self.recently_measured.clear(); - } - Purpose::Drawing => { - self.recently_drawn.clear(); - } - } - } -} - -#[derive(Debug, Clone, Copy)] -struct Key<'a> { - content: &'a str, - size: f32, - line_height: f32, - font: Font, - bounds: Size, - shaping: Shaping, -} - -impl Key<'_> { - fn hash(self, mut hasher: H) -> KeyHash { - self.content.hash(&mut hasher); - self.size.to_bits().hash(&mut hasher); - self.line_height.to_bits().hash(&mut hasher); - self.font.hash(&mut hasher); - self.bounds.width.to_bits().hash(&mut hasher); - self.bounds.height.to_bits().hash(&mut hasher); - self.shaping.hash(&mut hasher); - - hasher.finish() - } -} - -type KeyHash = u64; -- cgit From 89acf0217e0acd92a82bff1fd516cd4266c0878a Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 30 Aug 2023 05:06:08 +0200 Subject: Use `min_bounds` for cached text --- wgpu/src/text.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'wgpu/src/text.rs') diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs index da2062fe..ee352368 100644 --- a/wgpu/src/text.rs +++ b/wgpu/src/text.rs @@ -59,7 +59,7 @@ impl Pipeline { device: &wgpu::Device, queue: &wgpu::Queue, sections: &[Text<'_>], - bounds: Rectangle, + layer_bounds: Rectangle, scale_factor: f32, target_size: Size, ) { @@ -98,8 +98,8 @@ impl Pipeline { ), font: text.font, bounds: Size { - width: bounds.width, - height: bounds.height, + width: text.bounds.width, + height: text.bounds.height, }, shaping: text.shaping, }, @@ -110,7 +110,7 @@ impl Pipeline { }) .collect(); - let layer_bounds = bounds * scale_factor; + let layer_bounds = layer_bounds * scale_factor; let text_areas = sections.iter().zip(allocations.iter()).filter_map( |(section, allocation)| { @@ -144,11 +144,14 @@ impl Pipeline { return None; }; - let buffer = cache.get(key).expect("Get cached buffer"); + let entry = cache.get(key).expect("Get cached buffer"); ( - buffer, - text.bounds, + &entry.buffer, + Rectangle::new( + text.bounds.position(), + entry.min_bounds, + ), text.horizontal_alignment, text.vertical_alignment, text.color, -- cgit From 8129e2c208d9b13dbd32a309058b0547c723dede Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 3 Sep 2023 08:08:27 +0200 Subject: Implement `draw_paragraph` in `iced_tiny_skia` --- wgpu/src/text.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'wgpu/src/text.rs') diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs index ee352368..a1ec511b 100644 --- a/wgpu/src/text.rs +++ b/wgpu/src/text.rs @@ -159,29 +159,28 @@ impl Pipeline { } }; - let x = bounds.x * scale_factor; - let y = bounds.y * scale_factor; - - let max_width = bounds.width * scale_factor; - let total_height = bounds.height * scale_factor; + let bounds = bounds * scale_factor; let left = match horizontal_alignment { - alignment::Horizontal::Left => x, - alignment::Horizontal::Center => x - max_width / 2.0, - alignment::Horizontal::Right => x - max_width, + alignment::Horizontal::Left => bounds.x, + alignment::Horizontal::Center => { + bounds.x - bounds.width / 2.0 + } + alignment::Horizontal::Right => bounds.x - bounds.width, }; let top = match vertical_alignment { - alignment::Vertical::Top => y, - alignment::Vertical::Center => y - total_height / 2.0, - alignment::Vertical::Bottom => y - total_height, + alignment::Vertical::Top => bounds.y, + alignment::Vertical::Center => { + bounds.y - bounds.height / 2.0 + } + alignment::Vertical::Bottom => bounds.y - bounds.height, }; let section_bounds = Rectangle { x: left, y: top, - width: max_width, - height: total_height, + ..bounds }; let clip_bounds = layer_bounds.intersection(§ion_bounds)?; -- 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 --- wgpu/src/text.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'wgpu/src/text.rs') diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs index a1ec511b..bd4f3e06 100644 --- a/wgpu/src/text.rs +++ b/wgpu/src/text.rs @@ -7,7 +7,6 @@ use crate::layer::Text; use std::borrow::Cow; use std::cell::RefCell; -use std::sync::Arc; #[allow(missing_debug_implementations)] pub struct Pipeline { @@ -47,9 +46,7 @@ impl Pipeline { } pub fn load_font(&mut self, bytes: Cow<'static, [u8]>) { - let _ = self.font_system.get_mut().db_mut().load_font_source( - glyphon::fontdb::Source::Binary(Arc::new(bytes.into_owned())), - ); + self.font_system.load_font(bytes); self.cache = RefCell::new(Cache::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 --- wgpu/src/text.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'wgpu/src/text.rs') diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs index bd4f3e06..5c9f4d7e 100644 --- a/wgpu/src/text.rs +++ b/wgpu/src/text.rs @@ -2,7 +2,7 @@ use crate::core::alignment; use crate::core::{Rectangle, Size}; use crate::graphics::color; use crate::graphics::text::cache::{self, Cache}; -use crate::graphics::text::{FontSystem, Paragraph}; +use crate::graphics::text::{font_system, Paragraph}; use crate::layer::Text; use std::borrow::Cow; @@ -10,7 +10,6 @@ use std::cell::RefCell; #[allow(missing_debug_implementations)] pub struct Pipeline { - font_system: FontSystem, renderers: Vec, atlas: glyphon::TextAtlas, prepare_layer: usize, @@ -24,7 +23,6 @@ impl Pipeline { format: wgpu::TextureFormat, ) -> Self { Pipeline { - font_system: FontSystem::new(), renderers: Vec::new(), atlas: glyphon::TextAtlas::with_color_mode( device, @@ -41,12 +39,11 @@ impl Pipeline { } } - pub fn font_system(&self) -> &FontSystem { - &self.font_system - } - pub fn load_font(&mut self, bytes: Cow<'static, [u8]>) { - self.font_system.load_font(bytes); + font_system() + .write() + .expect("Write font system") + .load_font(bytes); self.cache = RefCell::new(Cache::new()); } @@ -69,7 +66,9 @@ impl Pipeline { )); } - let font_system = self.font_system.get_mut(); + let mut font_system = font_system().write().expect("Write font system"); + let font_system = font_system.raw(); + let renderer = &mut self.renderers[self.prepare_layer]; let cache = self.cache.get_mut(); -- 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 --- wgpu/src/text.rs | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'wgpu/src/text.rs') diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs index 5c9f4d7e..397c38dd 100644 --- a/wgpu/src/text.rs +++ b/wgpu/src/text.rs @@ -2,7 +2,7 @@ use crate::core::alignment; use crate::core::{Rectangle, Size}; use crate::graphics::color; use crate::graphics::text::cache::{self, Cache}; -use crate::graphics::text::{font_system, Paragraph}; +use crate::graphics::text::{font_system, Editor, Paragraph}; use crate::layer::Text; use std::borrow::Cow; @@ -74,15 +74,19 @@ impl Pipeline { enum Allocation { Paragraph(Paragraph), + Editor(Editor), Cache(cache::KeyHash), } let allocations: Vec<_> = sections .iter() .map(|section| match section { - Text::Managed { paragraph, .. } => { + Text::Paragraph { paragraph, .. } => { paragraph.upgrade().map(Allocation::Paragraph) } + Text::Editor { editor, .. } => { + editor.upgrade().map(Allocation::Editor) + } Text::Cached(text) => { let (key, _) = cache.allocate( font_system, @@ -117,7 +121,7 @@ impl Pipeline { vertical_alignment, color, ) = match section { - Text::Managed { + Text::Paragraph { position, color, .. } => { use crate::core::text::Paragraph as _; @@ -135,6 +139,24 @@ impl Pipeline { *color, ) } + Text::Editor { + position, color, .. + } => { + use crate::core::text::Editor as _; + + let Some(Allocation::Editor(editor)) = allocation + else { + return None; + }; + + ( + editor.buffer(), + Rectangle::new(*position, editor.min_bounds()), + alignment::Horizontal::Left, + alignment::Vertical::Top, + *color, + ) + } Text::Cached(text) => { let Some(Allocation::Cache(key)) = allocation else { return None; -- cgit From c7d02e24e6f8265c205a68bd97b2643d40ae30ee Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 14 Sep 2023 18:57:09 +0200 Subject: Remove `Editor::min_bounds` and use `bounds` instead --- wgpu/src/text.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wgpu/src/text.rs') diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs index 397c38dd..581df0cb 100644 --- a/wgpu/src/text.rs +++ b/wgpu/src/text.rs @@ -151,7 +151,7 @@ impl Pipeline { ( editor.buffer(), - Rectangle::new(*position, editor.min_bounds()), + Rectangle::new(*position, editor.bounds()), alignment::Horizontal::Left, alignment::Vertical::Top, *color, -- 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` --- wgpu/src/text.rs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'wgpu/src/text.rs') diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs index 581df0cb..f746be63 100644 --- a/wgpu/src/text.rs +++ b/wgpu/src/text.rs @@ -2,7 +2,7 @@ use crate::core::alignment; use crate::core::{Rectangle, Size}; use crate::graphics::color; use crate::graphics::text::cache::{self, Cache}; -use crate::graphics::text::{font_system, Editor, Paragraph}; +use crate::graphics::text::{font_system, to_color, Editor, Paragraph}; use crate::layer::Text; use std::borrow::Cow; @@ -214,16 +214,7 @@ impl Pipeline { right: (clip_bounds.x + clip_bounds.width) as i32, bottom: (clip_bounds.y + clip_bounds.height) as i32, }, - default_color: { - let [r, g, b, a] = color::pack(color).components(); - - glyphon::Color::rgba( - (r * 255.0) as u8, - (g * 255.0) as u8, - (b * 255.0) as u8, - (a * 255.0) as u8, - ) - }, + default_color: to_color(color), }) }, ); -- cgit From 42ed90bc6f92b2085d193e7f143430b8d3847c21 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 20 Sep 2023 04:51:08 +0200 Subject: Fix `clippy::default_trait_access` --- wgpu/src/text.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wgpu/src/text.rs') diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs index bd4f3e06..2a530cad 100644 --- a/wgpu/src/text.rs +++ b/wgpu/src/text.rs @@ -64,7 +64,7 @@ impl Pipeline { self.renderers.push(glyphon::TextRenderer::new( &mut self.atlas, device, - Default::default(), + wgpu::MultisampleState::default(), None, )); } -- cgit