From f05f658721eb02c743607d83be2301ed94c58b1b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 19 Dec 2023 14:02:28 -0700 Subject: [PATCH 1/3] Update to cosmic-text refactor --- Cargo.toml | 6 +- graphics/src/text/editor.rs | 532 +++++++++++++++++++----------------- tiny_skia/src/text.rs | 26 +- 3 files changed, 302 insertions(+), 262 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 960e3a2065..d0548f6844 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -133,10 +133,10 @@ iced_accessibility = { version = "0.1", path = "accessibility" } async-std = "1.0" bitflags = "1.0" bytemuck = { version = "1.0", features = ["derive"] } -cosmic-text = "0.10" +cosmic-text = { git = "https://github.com/pop-os/cosmic-text.git", branch = "refactor" } futures = "0.3" glam = "0.24" -glyphon = { git = "https://github.com/grovesNL/glyphon.git", rev = "2caa9fc5e5923c1d827d177c3619cab7e9885b85" } +glyphon = { git = "https://github.com/jackpot51/glyphon.git", branch = "refactor" } guillotiere = "0.6" half = "2.2" image = "0.24" @@ -174,4 +174,4 @@ winapi = "0.3" window_clipboard = "0.3" [workspace.dependencies.winit] git = "https://github.com/pop-os/winit.git" -branch = "master" \ No newline at end of file +branch = "master" diff --git a/graphics/src/text/editor.rs b/graphics/src/text/editor.rs index d5262ae820..dbbff6f748 100644 --- a/graphics/src/text/editor.rs +++ b/graphics/src/text/editor.rs @@ -17,7 +17,7 @@ use std::sync::{self, Arc}; pub struct Editor(Option>); struct Internal { - editor: cosmic_text::Editor, + editor: cosmic_text::Editor<'static>, font: Font, bounds: Size, topmost_line_changed: Option, @@ -30,9 +30,12 @@ impl Editor { Self::default() } - /// Returns the buffer of the [`Editor`]. - pub fn buffer(&self) -> &cosmic_text::Buffer { - self.internal().editor.buffer() + /// Runs a closure with the buffer of the [`Editor`]. + pub fn with_buffer T, T>( + &self, + f: F, + ) -> T { + self.internal().editor.with_buffer(f) } /// Creates a [`Weak`] reference to the [`Editor`]. @@ -83,14 +86,16 @@ impl editor::Editor for Editor { } fn line(&self, index: usize) -> Option<&str> { - self.buffer() - .lines - .get(index) - .map(cosmic_text::BufferLine::text) + let buffer = match self.internal().editor.buffer_ref() { + cosmic_text::BufferRef::Owned(buffer) => buffer, + cosmic_text::BufferRef::Borrowed(buffer) => buffer, + cosmic_text::BufferRef::Arc(buffer) => buffer, + }; + buffer.lines.get(index).map(cosmic_text::BufferLine::text) } fn line_count(&self) -> usize { - self.buffer().lines.len() + self.with_buffer(|buffer| buffer.lines.len()) } fn selection(&self) -> Option { @@ -101,133 +106,132 @@ impl editor::Editor for Editor { let internal = self.internal(); let cursor = internal.editor.cursor(); - let buffer = internal.editor.buffer(); + internal.editor.with_buffer(|buffer| { + match internal.editor.selection_bounds() { + Some((start, end)) => { + let line_height = buffer.metrics().line_height; + let selected_lines = end.line - start.line + 1; + + let visual_lines_offset = + visual_lines_offset(start.line, buffer); + + let regions = buffer + .lines + .iter() + .skip(start.line) + .take(selected_lines) + .enumerate() + .flat_map(|(i, line)| { + highlight_line( + line, + if i == 0 { start.index } else { 0 }, + if i == selected_lines - 1 { + end.index + } else { + line.text().len() + }, + ) + }) + .enumerate() + .filter_map(|(visual_line, (x, width))| { + if width > 0.0 { + Some(Rectangle { + x, + width, + y: (visual_line as i32 + + visual_lines_offset) + as f32 + * line_height, + height: line_height, + }) + } else { + None + } + }) + .collect(); - match internal.editor.select_opt() { - Some(selection) => { - let (start, end) = if cursor < selection { - (cursor, selection) - } else { - (selection, cursor) - }; + Cursor::Selection(regions) + } + _ => { + let line_height = buffer.metrics().line_height; - let line_height = buffer.metrics().line_height; - let selected_lines = end.line - start.line + 1; - - let visual_lines_offset = - visual_lines_offset(start.line, buffer); - - let regions = buffer - .lines - .iter() - .skip(start.line) - .take(selected_lines) - .enumerate() - .flat_map(|(i, line)| { - highlight_line( - line, - if i == 0 { start.index } else { 0 }, - if i == selected_lines - 1 { - end.index - } else { - line.text().len() - }, - ) - }) - .enumerate() - .filter_map(|(visual_line, (x, width))| { - if width > 0.0 { - Some(Rectangle { - x, - width, - y: (visual_line as i32 + visual_lines_offset) - as f32 - * line_height, - height: line_height, - }) - } else { - None - } - }) - .collect(); + let visual_lines_offset = + visual_lines_offset(cursor.line, buffer); - Cursor::Selection(regions) - } - _ => { - let line_height = buffer.metrics().line_height; - - let visual_lines_offset = - visual_lines_offset(cursor.line, buffer); - - let line = buffer - .lines - .get(cursor.line) - .expect("Cursor line should be present"); - - let layout = line - .layout_opt() - .as_ref() - .expect("Line layout should be cached"); - - let mut lines = layout.iter().enumerate(); - - let (visual_line, offset) = lines - .find_map(|(i, line)| { - let start = line - .glyphs - .first() - .map(|glyph| glyph.start) - .unwrap_or(0); - let end = line - .glyphs - .last() - .map(|glyph| glyph.end) - .unwrap_or(0); - - let is_cursor_before_start = start > cursor.index; - - let is_cursor_before_end = match cursor.affinity { - cosmic_text::Affinity::Before => { - cursor.index <= end - } - cosmic_text::Affinity::After => cursor.index < end, - }; - - if is_cursor_before_start { - // Sometimes, the glyph we are looking for is right - // between lines. This can happen when a line wraps - // on a space. - // In that case, we can assume the cursor is at the - // end of the previous line. - // i is guaranteed to be > 0 because `start` is always - // 0 for the first line, so there is no way for the - // cursor to be before it. - Some((i - 1, layout[i - 1].w)) - } else if is_cursor_before_end { - let offset = line + let line = buffer + .lines + .get(cursor.line) + .expect("Cursor line should be present"); + + let layout = line + .layout_opt() + .as_ref() + .expect("Line layout should be cached"); + + let mut lines = layout.iter().enumerate(); + + let (visual_line, offset) = lines + .find_map(|(i, line)| { + let start = line .glyphs - .iter() - .take_while(|glyph| cursor.index > glyph.start) - .map(|glyph| glyph.w) - .sum(); - - Some((i, offset)) - } else { - None - } - }) - .unwrap_or(( - layout.len().saturating_sub(1), - layout.last().map(|line| line.w).unwrap_or(0.0), - )); + .first() + .map(|glyph| glyph.start) + .unwrap_or(0); + let end = line + .glyphs + .last() + .map(|glyph| glyph.end) + .unwrap_or(0); + + let is_cursor_before_start = start > cursor.index; + + let is_cursor_before_end = match cursor.affinity { + cosmic_text::Affinity::Before => { + cursor.index <= end + } + cosmic_text::Affinity::After => { + cursor.index < end + } + }; + + if is_cursor_before_start { + // Sometimes, the glyph we are looking for is right + // between lines. This can happen when a line wraps + // on a space. + // In that case, we can assume the cursor is at the + // end of the previous line. + // i is guaranteed to be > 0 because `start` is always + // 0 for the first line, so there is no way for the + // cursor to be before it. + Some((i - 1, layout[i - 1].w)) + } else if is_cursor_before_end { + let offset = line + .glyphs + .iter() + .take_while(|glyph| { + cursor.index > glyph.start + }) + .map(|glyph| glyph.w) + .sum(); - Cursor::Caret(Point::new( - offset, - (visual_lines_offset + visual_line as i32) as f32 - * line_height, - )) + Some((i, offset)) + } else { + None + } + }) + .unwrap_or(( + layout.len().saturating_sub(1), + layout.last().map(|line| line.w).unwrap_or(0.0), + )); + + Cursor::Caret(Point::new( + offset, + (visual_lines_offset + visual_line as i32) as f32 + * line_height, + )) + } } - } + }) } fn cursor_position(&self) -> (usize, usize) { @@ -252,16 +256,8 @@ impl editor::Editor for Editor { match action { // Motion events Action::Move(motion) => { - if let Some(selection) = editor.select_opt() { - let cursor = editor.cursor(); - - let (left, right) = if cursor < selection { - (cursor, selection) - } else { - (selection, cursor) - }; - - editor.set_select_opt(None); + if let Some((left, right)) = editor.selection_bounds() { + editor.set_selection(cosmic_text::Selection::None); match motion { // These motions are performed as-is even when a selection @@ -290,20 +286,23 @@ impl editor::Editor for Editor { Action::Select(motion) => { let cursor = editor.cursor(); - if editor.select_opt().is_none() { - editor.set_select_opt(Some(cursor)); + if editor.selection() == cosmic_text::Selection::None { + editor + .set_selection(cosmic_text::Selection::Normal(cursor)); } editor.action(font_system.raw(), motion_to_action(motion)); // Deselect if selection matches cursor position - if let Some(selection) = editor.select_opt() { + if let cosmic_text::Selection::Normal(selection) = + editor.selection() + { let cursor = editor.cursor(); if cursor.line == selection.line && cursor.index == selection.index { - editor.set_select_opt(None); + editor.set_selection(cosmic_text::Selection::None); } } } @@ -311,10 +310,12 @@ impl editor::Editor for Editor { use unicode_segmentation::UnicodeSegmentation; let cursor = editor.cursor(); - - if let Some(line) = editor.buffer().lines.get(cursor.line) { - let (start, end) = - UnicodeSegmentation::unicode_word_indices(line.text()) + let start_end_opt = editor.with_buffer(|buffer| { + if let Some(line) = buffer.lines.get(cursor.line) { + let (start, end) = + UnicodeSegmentation::unicode_word_indices( + line.text(), + ) // Split words with dots .flat_map(|(i, word)| { word.split('.').scan(i, |current, word| { @@ -354,35 +355,43 @@ impl editor::Editor for Editor { (start, end) }); + Some((start, end)) + } else { + None + } + }); + + if let Some((start, end)) = start_end_opt { if start != end { editor.set_cursor(cosmic_text::Cursor { index: start, ..cursor }); - editor.set_select_opt(Some(cosmic_text::Cursor { - index: end, - ..cursor - })); + editor.set_selection(cosmic_text::Selection::Normal( + cosmic_text::Cursor { + index: end, + ..cursor + }, + )); } } } Action::SelectLine => { let cursor = editor.cursor(); - if let Some(line_length) = editor - .buffer() - .lines - .get(cursor.line) - .map(|line| line.text().len()) - { + if let Some(line_length) = editor.with_buffer(|buffer| { + buffer.lines.get(cursor.line).map(|line| line.text().len()) + }) { editor .set_cursor(cosmic_text::Cursor { index: 0, ..cursor }); - editor.set_select_opt(Some(cosmic_text::Cursor { - index: line_length, - ..cursor - })); + editor.set_selection(cosmic_text::Selection::Normal( + cosmic_text::Cursor { + index: line_length, + ..cursor + }, + )); } } @@ -419,7 +428,12 @@ impl editor::Editor for Editor { } let cursor = editor.cursor(); - let selection = editor.select_opt().unwrap_or(cursor); + let selection = match editor.selection() { + cosmic_text::Selection::Normal(selection) => selection, + cosmic_text::Selection::Line(selection) => selection, + cosmic_text::Selection::Word(selection) => selection, + cosmic_text::Selection::None => cursor, + }; internal.topmost_line_changed = Some(cursor.min(selection).line); @@ -445,13 +459,15 @@ impl editor::Editor for Editor { ); // Deselect if selection matches cursor position - if let Some(selection) = editor.select_opt() { + if let cosmic_text::Selection::Normal(selection) = + editor.selection() + { let cursor = editor.cursor(); if cursor.line == selection.line && cursor.index == selection.index { - editor.set_select_opt(None); + editor.set_selection(cosmic_text::Selection::None); } } } @@ -490,9 +506,11 @@ impl editor::Editor for Editor { if font_system.version() != internal.version { log::trace!("Updating `FontSystem` of `Editor`..."); - for line in internal.editor.buffer_mut().lines.iter_mut() { - line.reset(); - } + internal.editor.with_buffer_mut(|buffer| { + for line in buffer.lines.iter_mut() { + line.reset(); + } + }); internal.version = font_system.version(); internal.topmost_line_changed = Some(0); @@ -501,17 +519,19 @@ impl editor::Editor for Editor { if new_font != internal.font { log::trace!("Updating font of `Editor`..."); - for line in internal.editor.buffer_mut().lines.iter_mut() { - let _ = line.set_attrs_list(cosmic_text::AttrsList::new( - text::to_attributes(new_font), - )); - } + internal.editor.with_buffer_mut(|buffer| { + for line in buffer.lines.iter_mut() { + let _ = line.set_attrs_list(cosmic_text::AttrsList::new( + text::to_attributes(new_font), + )); + } + }); internal.font = new_font; internal.topmost_line_changed = Some(0); } - let metrics = internal.editor.buffer().metrics(); + let metrics = internal.editor.with_buffer(|buffer| buffer.metrics()); let new_line_height = new_line_height.to_absolute(new_size); if new_size.0 != metrics.font_size @@ -519,20 +539,24 @@ impl editor::Editor for Editor { { log::trace!("Updating `Metrics` of `Editor`..."); - internal.editor.buffer_mut().set_metrics( - font_system.raw(), - cosmic_text::Metrics::new(new_size.0, new_line_height.0), - ); + internal.editor.with_buffer_mut(|buffer| { + buffer.set_metrics( + font_system.raw(), + cosmic_text::Metrics::new(new_size.0, new_line_height.0), + ) + }); } if new_bounds != internal.bounds { log::trace!("Updating size of `Editor`..."); - internal.editor.buffer_mut().set_size( - font_system.raw(), - new_bounds.width, - new_bounds.height, - ); + internal.editor.with_buffer_mut(|buffer| { + buffer.set_size( + font_system.raw(), + new_bounds.width, + new_bounds.height, + ) + }); internal.bounds = new_bounds; } @@ -546,7 +570,10 @@ impl editor::Editor for Editor { new_highlighter.change_line(topmost_line_changed); } - internal.editor.shape_as_needed(font_system.raw()); + internal.editor.shape_as_needed( + font_system.raw(), + false, /*TODO: support trimming caches*/ + ); self.0 = Some(Arc::new(internal)); } @@ -558,29 +585,32 @@ impl editor::Editor for Editor { format_highlight: impl Fn(&H::Highlight) -> highlighter::Format, ) { let internal = self.internal(); - let buffer = internal.editor.buffer(); - - let mut window = buffer.scroll() + buffer.visible_lines(); - - let last_visible_line = buffer - .lines - .iter() - .enumerate() - .find_map(|(i, line)| { - let visible_lines = line - .layout_opt() - .as_ref() - .expect("Line layout should be cached") - .len() as i32; - - if window > visible_lines { - window -= visible_lines; - None - } else { - Some(i) - } - }) - .unwrap_or(buffer.lines.len().saturating_sub(1)); + + let last_visible_line = internal.editor.with_buffer(|buffer| { + let scroll = buffer.scroll(); + let mut window = scroll.layout + buffer.visible_lines(); + + buffer + .lines + .iter() + .enumerate() + .skip(scroll.line) + .find_map(|(i, line)| { + let visible_lines = line + .layout_opt() + .as_ref() + .expect("Line layout should be cached") + .len() as i32; + + if window > visible_lines { + window -= visible_lines; + None + } else { + Some(i) + } + }) + .unwrap_or(buffer.lines.len().saturating_sub(1)) + }); let current_line = highlighter.current_line(); @@ -599,33 +629,38 @@ impl editor::Editor for Editor { let attributes = text::to_attributes(font); - for line in &mut internal.editor.buffer_mut().lines - [current_line..=last_visible_line] - { - let mut list = cosmic_text::AttrsList::new(attributes); - - for (range, highlight) in highlighter.highlight_line(line.text()) { - let format = format_highlight(&highlight); - - if format.color.is_some() || format.font.is_some() { - list.add_span( - range, - cosmic_text::Attrs { - color_opt: format.color.map(text::to_color), - ..if let Some(font) = format.font { - text::to_attributes(font) - } else { - attributes - } - }, - ); + internal.editor.with_buffer_mut(|buffer| { + for line in &mut buffer.lines[current_line..=last_visible_line] { + let mut list = cosmic_text::AttrsList::new(attributes); + + for (range, highlight) in + highlighter.highlight_line(line.text()) + { + let format = format_highlight(&highlight); + + if format.color.is_some() || format.font.is_some() { + list.add_span( + range, + cosmic_text::Attrs { + color_opt: format.color.map(text::to_color), + ..if let Some(font) = format.font { + text::to_attributes(font) + } else { + attributes + } + }, + ); + } } - } - let _ = line.set_attrs_list(list); - } + let _ = line.set_attrs_list(list); + } + }); - internal.editor.shape_as_needed(font_system.raw()); + internal.editor.shape_as_needed( + font_system.raw(), + false, /*TODO: support trimming caches*/ + ); self.0 = Some(Arc::new(internal)); } @@ -641,7 +676,8 @@ impl PartialEq for Internal { fn eq(&self, other: &Self) -> bool { self.font == other.font && self.bounds == other.bounds - && self.editor.buffer().metrics() == other.editor.buffer().metrics() + && self.editor.with_buffer(|buffer| buffer.metrics()) + == other.editor.with_buffer(|buffer| buffer.metrics()) } } @@ -746,9 +782,11 @@ fn highlight_line( } fn visual_lines_offset(line: usize, buffer: &cosmic_text::Buffer) -> i32 { + let scroll = buffer.scroll(); let visual_lines_before_start: usize = buffer .lines .iter() + .skip(scroll.line) .take(line) .map(|line| { line.layout_opt() @@ -758,22 +796,22 @@ fn visual_lines_offset(line: usize, buffer: &cosmic_text::Buffer) -> i32 { }) .sum(); - visual_lines_before_start as i32 - buffer.scroll() + visual_lines_before_start as i32 - scroll.layout } fn motion_to_action(motion: Motion) -> cosmic_text::Action { - match motion { - Motion::Left => cosmic_text::Action::Left, - Motion::Right => cosmic_text::Action::Right, - Motion::Up => cosmic_text::Action::Up, - Motion::Down => cosmic_text::Action::Down, - Motion::WordLeft => cosmic_text::Action::LeftWord, - Motion::WordRight => cosmic_text::Action::RightWord, - Motion::Home => cosmic_text::Action::Home, - Motion::End => cosmic_text::Action::End, - Motion::PageUp => cosmic_text::Action::PageUp, - Motion::PageDown => cosmic_text::Action::PageDown, - Motion::DocumentStart => cosmic_text::Action::BufferStart, - Motion::DocumentEnd => cosmic_text::Action::BufferEnd, - } + cosmic_text::Action::Motion(match motion { + Motion::Left => cosmic_text::Motion::Left, + Motion::Right => cosmic_text::Motion::Right, + Motion::Up => cosmic_text::Motion::Up, + Motion::Down => cosmic_text::Motion::Down, + Motion::WordLeft => cosmic_text::Motion::LeftWord, + Motion::WordRight => cosmic_text::Motion::RightWord, + Motion::Home => cosmic_text::Motion::Home, + Motion::End => cosmic_text::Motion::End, + Motion::PageUp => cosmic_text::Motion::PageUp, + Motion::PageDown => cosmic_text::Motion::PageDown, + Motion::DocumentStart => cosmic_text::Motion::BufferStart, + Motion::DocumentEnd => cosmic_text::Motion::BufferEnd, + }) } diff --git a/tiny_skia/src/text.rs b/tiny_skia/src/text.rs index a5a0a1b64f..251e89abbe 100644 --- a/tiny_skia/src/text.rs +++ b/tiny_skia/src/text.rs @@ -83,18 +83,20 @@ impl Pipeline { let mut font_system = font_system().write().expect("Write font system"); - draw( - font_system.raw(), - &mut self.glyph_cache, - editor.buffer(), - Rectangle::new(position, editor.bounds()), - color, - alignment::Horizontal::Left, - alignment::Vertical::Top, - scale_factor, - pixels, - clip_mask, - ); + editor.with_buffer(|buffer| { + draw( + font_system.raw(), + &mut self.glyph_cache, + buffer, + Rectangle::new(position, editor.bounds()), + color, + alignment::Horizontal::Left, + alignment::Vertical::Top, + scale_factor, + pixels, + clip_mask, + ); + }); } pub fn draw_cached( From d074817bafbb5acd6c54bcb62caaaa03c5d06512 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 19 Dec 2023 14:13:08 -0700 Subject: [PATCH 2/3] Fixes for last commit --- Cargo.toml | 2 +- graphics/src/text/editor.rs | 25 ++++++++++++------------- tiny_skia/src/text.rs | 26 ++++++++++++-------------- 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d0548f6844..8b72473cac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -152,7 +152,7 @@ ouroboros = "0.17" palette = "0.7" qrcode = { version = "0.12", default-features = false } raw-window-handle = "0.5" -resvg = "0.36" +resvg = "0.37" rustc-hash = "1.0" sctk = { package = "smithay-client-toolkit", git = "https://github.com/smithay/client-toolkit", rev = "2e9bf9f" } smol = "1.0" diff --git a/graphics/src/text/editor.rs b/graphics/src/text/editor.rs index dbbff6f748..e6f12d9300 100644 --- a/graphics/src/text/editor.rs +++ b/graphics/src/text/editor.rs @@ -30,12 +30,13 @@ impl Editor { Self::default() } - /// Runs a closure with the buffer of the [`Editor`]. - pub fn with_buffer T, T>( - &self, - f: F, - ) -> T { - self.internal().editor.with_buffer(f) + /// Returns the buffer of the [`Editor`]. + pub fn buffer(&self) -> &cosmic_text::Buffer { + match self.internal().editor.buffer_ref() { + cosmic_text::BufferRef::Owned(buffer) => buffer, + cosmic_text::BufferRef::Borrowed(buffer) => buffer, + cosmic_text::BufferRef::Arc(buffer) => buffer, + } } /// Creates a [`Weak`] reference to the [`Editor`]. @@ -86,16 +87,14 @@ impl editor::Editor for Editor { } fn line(&self, index: usize) -> Option<&str> { - let buffer = match self.internal().editor.buffer_ref() { - cosmic_text::BufferRef::Owned(buffer) => buffer, - cosmic_text::BufferRef::Borrowed(buffer) => buffer, - cosmic_text::BufferRef::Arc(buffer) => buffer, - }; - buffer.lines.get(index).map(cosmic_text::BufferLine::text) + self.buffer() + .lines + .get(index) + .map(cosmic_text::BufferLine::text) } fn line_count(&self) -> usize { - self.with_buffer(|buffer| buffer.lines.len()) + self.buffer().lines.len() } fn selection(&self) -> Option { diff --git a/tiny_skia/src/text.rs b/tiny_skia/src/text.rs index 251e89abbe..a5a0a1b64f 100644 --- a/tiny_skia/src/text.rs +++ b/tiny_skia/src/text.rs @@ -83,20 +83,18 @@ impl Pipeline { let mut font_system = font_system().write().expect("Write font system"); - editor.with_buffer(|buffer| { - draw( - font_system.raw(), - &mut self.glyph_cache, - buffer, - Rectangle::new(position, editor.bounds()), - color, - alignment::Horizontal::Left, - alignment::Vertical::Top, - scale_factor, - pixels, - clip_mask, - ); - }); + draw( + font_system.raw(), + &mut self.glyph_cache, + editor.buffer(), + Rectangle::new(position, editor.bounds()), + color, + alignment::Horizontal::Left, + alignment::Vertical::Top, + scale_factor, + pixels, + clip_mask, + ); } pub fn draw_cached( From 730237d350427d921751029fdda3a9ed63d161fd Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 19 Dec 2023 15:00:32 -0700 Subject: [PATCH 3/3] Add function to fill a Raw --- core/src/renderer/null.rs | 3 +++ core/src/text.rs | 6 ++++++ graphics/src/renderer.rs | 5 +++++ renderer/src/lib.rs | 8 ++++++-- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/core/src/renderer/null.rs b/core/src/renderer/null.rs index b048ae97b2..0ad1f82455 100644 --- a/core/src/renderer/null.rs +++ b/core/src/renderer/null.rs @@ -44,6 +44,7 @@ impl text::Renderer for Null { type Font = Font; type Paragraph = (); type Editor = (); + type Raw = (); const ICON_FONT: Font = Font::DEFAULT; const CHECKMARK_ICON: char = '0'; @@ -77,6 +78,8 @@ impl text::Renderer for Null { ) { } + fn fill_raw(&mut self, _raw: Self::Raw) {} + fn fill_text( &mut self, _paragraph: Text<'_, Self::Font>, diff --git a/core/src/text.rs b/core/src/text.rs index 3ff76be479..8d6ba6f916 100644 --- a/core/src/text.rs +++ b/core/src/text.rs @@ -173,6 +173,9 @@ pub trait Renderer: crate::Renderer { /// The [`Editor`] of this [`Renderer`]. type Editor: Editor + 'static; + /// The [`Raw`] of this [`Renderer`]. + type Raw; + /// The icon font of the backend. const ICON_FONT: Self::Font; @@ -215,6 +218,9 @@ pub trait Renderer: crate::Renderer { clip_bounds: Rectangle, ); + /// Draws the given [`Raw`] + fn fill_raw(&mut self, raw: Self::Raw); + /// Draws the given [`Text`] at the given position and with the given /// [`Color`]. fn fill_text( diff --git a/graphics/src/renderer.rs b/graphics/src/renderer.rs index fc171a1901..4b8968d95a 100644 --- a/graphics/src/renderer.rs +++ b/graphics/src/renderer.rs @@ -142,6 +142,7 @@ where type Font = Font; type Paragraph = text::Paragraph; type Editor = text::Editor; + type Raw = text::Raw; const ICON_FONT: Font = Font::with_name("Iced-Icons"); const CHECKMARK_ICON: char = '\u{f00c}'; @@ -189,6 +190,10 @@ where }); } + fn fill_raw(&mut self, raw: Self::Raw) { + self.primitives.push(Primitive::RawText(raw)); + } + fn fill_text( &mut self, text: Text<'_, Self::Font>, diff --git a/renderer/src/lib.rs b/renderer/src/lib.rs index 300077a248..26e75f6db8 100644 --- a/renderer/src/lib.rs +++ b/renderer/src/lib.rs @@ -23,8 +23,7 @@ pub use geometry::Geometry; use crate::core::renderer; use crate::core::text::{self, Text}; use crate::core::{Background, Color, Font, Pixels, Point, Rectangle, Vector}; -use crate::graphics::text::Editor; -use crate::graphics::text::Paragraph; +use crate::graphics::text::{Editor, Paragraph, Raw}; use crate::graphics::Mesh; use std::borrow::Cow; @@ -152,6 +151,7 @@ impl text::Renderer for Renderer { type Font = Font; type Paragraph = Paragraph; type Editor = Editor; + type Raw = Raw; const ICON_FONT: Font = iced_tiny_skia::Renderer::::ICON_FONT; const CHECKMARK_ICON: char = iced_tiny_skia::Renderer::::CHECKMARK_ICON; @@ -198,6 +198,10 @@ impl text::Renderer for Renderer { ); } + fn fill_raw(&mut self, raw: Self::Raw) { + delegate!(self, renderer, renderer.fill_raw(raw)); + } + fn fill_text( &mut self, text: Text<'_, Self::Font>,