diff options
Diffstat (limited to 'graphics/src/text')
-rw-r--r-- | graphics/src/text/cache.rs | 4 | ||||
-rw-r--r-- | graphics/src/text/editor.rs | 304 | ||||
-rw-r--r-- | graphics/src/text/paragraph.rs | 240 |
3 files changed, 331 insertions, 217 deletions
diff --git a/graphics/src/text/cache.rs b/graphics/src/text/cache.rs index 822b61c4..e64d93f1 100644 --- a/graphics/src/text/cache.rs +++ b/graphics/src/text/cache.rs @@ -48,8 +48,8 @@ impl Cache { buffer.set_size( font_system, - key.bounds.width, - key.bounds.height.max(key.line_height), + Some(key.bounds.width), + Some(key.bounds.height.max(key.line_height)), ); buffer.set_text( font_system, diff --git a/graphics/src/text/editor.rs b/graphics/src/text/editor.rs index c488a51c..1f1d0050 100644 --- a/graphics/src/text/editor.rs +++ b/graphics/src/text/editor.rs @@ -3,7 +3,7 @@ use crate::core::text::editor::{ self, Action, Cursor, Direction, Edit, Motion, }; use crate::core::text::highlighter::{self, Highlighter}; -use crate::core::text::LineHeight; +use crate::core::text::{LineHeight, Wrapping}; use crate::core::{Font, Pixels, Point, Rectangle, Size}; use crate::text; @@ -17,7 +17,7 @@ use std::sync::{self, Arc}; pub struct Editor(Option<Arc<Internal>>); struct Internal { - editor: cosmic_text::Editor, + editor: cosmic_text::Editor<'static>, font: Font, bounds: Size, topmost_line_changed: Option<usize>, @@ -32,7 +32,7 @@ impl Editor { /// Returns the buffer of the [`Editor`]. pub fn buffer(&self) -> &cosmic_text::Buffer { - self.internal().editor.buffer() + buffer_from_editor(&self.internal().editor) } /// Creates a [`Weak`] reference to the [`Editor`]. @@ -82,6 +82,13 @@ impl editor::Editor for Editor { }))) } + fn is_empty(&self) -> bool { + let buffer = self.buffer(); + + buffer.lines.is_empty() + || (buffer.lines.len() == 1 && buffer.lines[0].text().is_empty()) + } + fn line(&self, index: usize) -> Option<&str> { self.buffer() .lines @@ -101,16 +108,10 @@ impl editor::Editor for Editor { let internal = self.internal(); let cursor = internal.editor.cursor(); - let buffer = internal.editor.buffer(); - - match internal.editor.select_opt() { - Some(selection) => { - let (start, end) = if cursor < selection { - (cursor, selection) - } else { - (selection, cursor) - }; + let buffer = buffer_from_editor(&internal.editor); + match internal.editor.selection_bounds() { + Some((start, end)) => { let line_height = buffer.metrics().line_height; let selected_lines = end.line - start.line + 1; @@ -142,7 +143,8 @@ impl editor::Editor for Editor { width, y: (visual_line as i32 + visual_lines_offset) as f32 - * line_height, + * line_height + - buffer.scroll().vertical, height: line_height, }) } else { @@ -224,7 +226,8 @@ impl editor::Editor for Editor { Cursor::Caret(Point::new( offset, (visual_lines_offset + visual_line as i32) as f32 - * line_height, + * line_height + - buffer.scroll().vertical, )) } } @@ -252,16 +255,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((start, end)) = editor.selection_bounds() { + editor.set_selection(cosmic_text::Selection::None); match motion { // These motions are performed as-is even when a selection @@ -272,17 +267,20 @@ impl editor::Editor for Editor { | Motion::DocumentEnd => { editor.action( font_system.raw(), - motion_to_action(motion), + cosmic_text::Action::Motion(to_motion(motion)), ); } // Other motions simply move the cursor to one end of the selection _ => editor.set_cursor(match motion.direction() { - Direction::Left => left, - Direction::Right => right, + Direction::Left => start, + Direction::Right => end, }), } } else { - editor.action(font_system.raw(), motion_to_action(motion)); + editor.action( + font_system.raw(), + cosmic_text::Action::Motion(to_motion(motion)), + ); } } @@ -290,99 +288,58 @@ 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_bounds().is_none() { + editor + .set_selection(cosmic_text::Selection::Normal(cursor)); } - editor.action(font_system.raw(), motion_to_action(motion)); + editor.action( + font_system.raw(), + cosmic_text::Action::Motion(to_motion(motion)), + ); // Deselect if selection matches cursor position - if let Some(selection) = editor.select_opt() { - let cursor = editor.cursor(); - - if cursor.line == selection.line - && cursor.index == selection.index - { - editor.set_select_opt(None); + if let Some((start, end)) = editor.selection_bounds() { + if start.line == end.line && start.index == end.index { + editor.set_selection(cosmic_text::Selection::None); } } } Action::SelectWord => { - 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()) - // Split words with dots - .flat_map(|(i, word)| { - word.split('.').scan(i, |current, word| { - let start = *current; - *current += word.len() + 1; - - Some((start, word)) - }) - }) - // Turn words into ranges - .map(|(i, word)| (i, i + word.len())) - // Find the word at cursor - .find(|&(start, end)| { - start <= cursor.index && cursor.index < end - }) - // Cursor is not in a word. Let's select its punctuation cluster. - .unwrap_or_else(|| { - let start = line.text()[..cursor.index] - .char_indices() - .rev() - .take_while(|(_, c)| { - c.is_ascii_punctuation() - }) - .map(|(i, _)| i) - .last() - .unwrap_or(cursor.index); - - let end = line.text()[cursor.index..] - .char_indices() - .skip_while(|(_, c)| { - c.is_ascii_punctuation() - }) - .map(|(i, _)| i + cursor.index) - .next() - .unwrap_or(cursor.index); - - (start, end) - }); - - 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::Word(cursor)); } Action::SelectLine => { let cursor = editor.cursor(); - if let Some(line_length) = editor - .buffer() - .lines - .get(cursor.line) - .map(|line| line.text().len()) + editor.set_selection(cosmic_text::Selection::Line(cursor)); + } + Action::SelectAll => { + let buffer = buffer_from_editor(editor); + + if buffer.lines.len() > 1 + || buffer + .lines + .first() + .is_some_and(|line| !line.text().is_empty()) { - editor - .set_cursor(cosmic_text::Cursor { index: 0, ..cursor }); + let cursor = editor.cursor(); + + editor.set_selection(cosmic_text::Selection::Normal( + cosmic_text::Cursor { + line: 0, + index: 0, + ..cursor + }, + )); - editor.set_select_opt(Some(cosmic_text::Cursor { - index: line_length, - ..cursor - })); + editor.action( + font_system.raw(), + cosmic_text::Action::Motion( + cosmic_text::Motion::BufferEnd, + ), + ); } } @@ -419,10 +376,12 @@ impl editor::Editor for Editor { } let cursor = editor.cursor(); - let selection = editor.select_opt().unwrap_or(cursor); + let selection_start = editor + .selection_bounds() + .map(|(start, _)| start) + .unwrap_or(cursor); - internal.topmost_line_changed = - Some(cursor.min(selection).line); + internal.topmost_line_changed = Some(selection_start.line); } // Mouse events @@ -445,13 +404,9 @@ impl editor::Editor for Editor { ); // Deselect if selection matches cursor position - if let Some(selection) = editor.select_opt() { - let cursor = editor.cursor(); - - if cursor.line == selection.line - && cursor.index == selection.index - { - editor.set_select_opt(None); + if let Some((start, end)) = editor.selection_bounds() { + if start.line == end.line && start.index == end.index { + editor.set_selection(cosmic_text::Selection::None); } } } @@ -473,7 +428,7 @@ impl editor::Editor for Editor { fn min_bounds(&self) -> Size { let internal = self.internal(); - text::measure(internal.editor.buffer()) + text::measure(buffer_from_editor(&internal.editor)) } fn update( @@ -482,6 +437,7 @@ impl editor::Editor for Editor { new_font: Font, new_size: Pixels, new_line_height: LineHeight, + new_wrapping: Wrapping, new_highlighter: &mut impl Highlighter, ) { let editor = @@ -493,10 +449,12 @@ impl editor::Editor for Editor { let mut font_system = text::font_system().write().expect("Write font system"); + let buffer = buffer_mut_from_editor(&mut internal.editor); + if font_system.version() != internal.version { log::trace!("Updating `FontSystem` of `Editor`..."); - for line in internal.editor.buffer_mut().lines.iter_mut() { + for line in buffer.lines.iter_mut() { line.reset(); } @@ -507,7 +465,7 @@ 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() { + for line in buffer.lines.iter_mut() { let _ = line.set_attrs_list(cosmic_text::AttrsList::new( text::to_attributes(new_font), )); @@ -517,7 +475,7 @@ impl editor::Editor for Editor { internal.topmost_line_changed = Some(0); } - let metrics = internal.editor.buffer().metrics(); + let metrics = buffer.metrics(); let new_line_height = new_line_height.to_absolute(new_size); if new_size.0 != metrics.font_size @@ -525,19 +483,27 @@ impl editor::Editor for Editor { { log::trace!("Updating `Metrics` of `Editor`..."); - internal.editor.buffer_mut().set_metrics( + buffer.set_metrics( font_system.raw(), cosmic_text::Metrics::new(new_size.0, new_line_height.0), ); } + let new_wrap = text::to_wrap(new_wrapping); + + if new_wrap != buffer.wrap() { + log::trace!("Updating `Wrap` strategy of `Editor`..."); + + buffer.set_wrap(font_system.raw(), new_wrap); + } + if new_bounds != internal.bounds { log::trace!("Updating size of `Editor`..."); - internal.editor.buffer_mut().set_size( + buffer.set_size( font_system.raw(), - new_bounds.width, - new_bounds.height, + Some(new_bounds.width), + Some(new_bounds.height), ); internal.bounds = new_bounds; @@ -552,7 +518,7 @@ 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); self.0 = Some(Arc::new(internal)); } @@ -564,12 +530,13 @@ impl editor::Editor for Editor { format_highlight: impl Fn(&H::Highlight) -> highlighter::Format<Self::Font>, ) { let internal = self.internal(); - let buffer = internal.editor.buffer(); + let buffer = buffer_from_editor(&internal.editor); - let mut window = buffer.scroll() + buffer.visible_lines(); + let scroll = buffer.scroll(); + let mut window = (internal.bounds.height / buffer.metrics().line_height) + .ceil() as i32; - let last_visible_line = buffer - .lines + let last_visible_line = buffer.lines[scroll.line..] .iter() .enumerate() .find_map(|(i, line)| { @@ -583,7 +550,7 @@ impl editor::Editor for Editor { window -= visible_lines; None } else { - Some(i) + Some(scroll.line + i) } }) .unwrap_or(buffer.lines.len().saturating_sub(1)); @@ -605,7 +572,7 @@ impl editor::Editor for Editor { let attributes = text::to_attributes(font); - for line in &mut internal.editor.buffer_mut().lines + for line in &mut buffer_mut_from_editor(&mut internal.editor).lines [current_line..=last_visible_line] { let mut list = cosmic_text::AttrsList::new(attributes); @@ -631,7 +598,7 @@ impl editor::Editor for Editor { let _ = line.set_attrs_list(list); } - internal.editor.shape_as_needed(font_system.raw()); + internal.editor.shape_as_needed(font_system.raw(), false); self.0 = Some(Arc::new(internal)); } @@ -647,7 +614,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() + && buffer_from_editor(&self.editor).metrics() + == buffer_from_editor(&other.editor).metrics() } } @@ -709,7 +677,8 @@ fn highlight_line( let layout = line .layout_opt() .as_ref() - .expect("Line layout should be cached"); + .map(Vec::as_slice) + .unwrap_or_default(); layout.iter().map(move |visual_line| { let start = visual_line @@ -752,34 +721,61 @@ fn highlight_line( } fn visual_lines_offset(line: usize, buffer: &cosmic_text::Buffer) -> i32 { - let visual_lines_before_start: usize = buffer - .lines + let scroll = buffer.scroll(); + + let start = scroll.line.min(line); + let end = scroll.line.max(line); + + let visual_lines_offset: usize = buffer.lines[start..] .iter() - .take(line) + .take(end - start) .map(|line| { - line.layout_opt() - .as_ref() - .expect("Line layout should be cached") - .len() + line.layout_opt().as_ref().map(Vec::len).unwrap_or_default() }) .sum(); - visual_lines_before_start as i32 - buffer.scroll() + visual_lines_offset as i32 * if scroll.line < line { 1 } else { -1 } } -fn motion_to_action(motion: Motion) -> cosmic_text::Action { +fn to_motion(motion: Motion) -> cosmic_text::Motion { 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, + 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, + } +} + +fn buffer_from_editor<'a, 'b>( + editor: &'a impl cosmic_text::Edit<'b>, +) -> &'a cosmic_text::Buffer +where + 'b: 'a, +{ + match editor.buffer_ref() { + cosmic_text::BufferRef::Owned(buffer) => buffer, + cosmic_text::BufferRef::Borrowed(buffer) => buffer, + cosmic_text::BufferRef::Arc(buffer) => buffer, + } +} + +fn buffer_mut_from_editor<'a, 'b>( + editor: &'a mut impl cosmic_text::Edit<'b>, +) -> &'a mut cosmic_text::Buffer +where + 'b: 'a, +{ + match editor.buffer_ref_mut() { + cosmic_text::BufferRef::Owned(buffer) => buffer, + cosmic_text::BufferRef::Borrowed(buffer) => buffer, + cosmic_text::BufferRef::Arc(_buffer) => unreachable!(), } } diff --git a/graphics/src/text/paragraph.rs b/graphics/src/text/paragraph.rs index 31a323ac..07ddbb82 100644 --- a/graphics/src/text/paragraph.rs +++ b/graphics/src/text/paragraph.rs @@ -1,8 +1,8 @@ //! Draw paragraphs. use crate::core; use crate::core::alignment; -use crate::core::text::{Hit, LineHeight, Shaping, Text}; -use crate::core::{Font, Pixels, Point, Size}; +use crate::core::text::{Hit, Shaping, Span, Text, Wrapping}; +use crate::core::{Font, Point, Rectangle, Size}; use crate::text; use std::fmt; @@ -10,13 +10,14 @@ use std::sync::{self, Arc}; /// A bunch of text. #[derive(Clone, PartialEq)] -pub struct Paragraph(Option<Arc<Internal>>); +pub struct Paragraph(Arc<Internal>); +#[derive(Clone)] struct Internal { buffer: cosmic_text::Buffer, - content: String, // TODO: Reuse from `buffer` (?) font: Font, shaping: Shaping, + wrapping: Wrapping, horizontal_alignment: alignment::Horizontal, vertical_alignment: alignment::Vertical, bounds: Size, @@ -52,9 +53,7 @@ impl Paragraph { } fn internal(&self) -> &Arc<Internal> { - self.0 - .as_ref() - .expect("paragraph should always be initialized") + &self.0 } } @@ -62,7 +61,7 @@ impl core::text::Paragraph for Paragraph { type Font = Font; fn with_text(text: Text<&str>) -> Self { - log::trace!("Allocating paragraph: {}", text.content); + log::trace!("Allocating plain paragraph: {}", text.content); let mut font_system = text::font_system().write().expect("Write font system"); @@ -77,8 +76,8 @@ impl core::text::Paragraph for Paragraph { buffer.set_size( font_system.raw(), - text.bounds.width, - text.bounds.height, + Some(text.bounds.width), + Some(text.bounds.height), ); buffer.set_text( @@ -90,73 +89,113 @@ impl core::text::Paragraph for Paragraph { let min_bounds = text::measure(&buffer); - Self(Some(Arc::new(Internal { + Self(Arc::new(Internal { buffer, - content: text.content.to_owned(), font: text.font, horizontal_alignment: text.horizontal_alignment, vertical_alignment: text.vertical_alignment, shaping: text.shaping, + wrapping: text.wrapping, bounds: text.bounds, min_bounds, version: font_system.version(), - }))) + })) + } + + fn with_spans<Link>(text: Text<&[Span<'_, Link>]>) -> Self { + log::trace!("Allocating rich paragraph: {} spans", text.content.len()); + + let mut font_system = + text::font_system().write().expect("Write font system"); + + let mut buffer = cosmic_text::Buffer::new( + font_system.raw(), + cosmic_text::Metrics::new( + text.size.into(), + text.line_height.to_absolute(text.size).into(), + ), + ); + + buffer.set_size( + font_system.raw(), + Some(text.bounds.width), + Some(text.bounds.height), + ); + + buffer.set_rich_text( + font_system.raw(), + text.content.iter().enumerate().map(|(i, span)| { + let attrs = text::to_attributes(span.font.unwrap_or(text.font)); + + let attrs = match (span.size, span.line_height) { + (None, None) => attrs, + _ => { + let size = span.size.unwrap_or(text.size); + + attrs.metrics(cosmic_text::Metrics::new( + size.into(), + span.line_height + .unwrap_or(text.line_height) + .to_absolute(size) + .into(), + )) + } + }; + + let attrs = if let Some(color) = span.color { + attrs.color(text::to_color(color)) + } else { + attrs + }; + + (span.text.as_ref(), attrs.metadata(i)) + }), + text::to_attributes(text.font), + text::to_shaping(text.shaping), + ); + + let min_bounds = text::measure(&buffer); + + Self(Arc::new(Internal { + buffer, + font: text.font, + horizontal_alignment: text.horizontal_alignment, + vertical_alignment: text.vertical_alignment, + shaping: text.shaping, + wrapping: text.wrapping, + bounds: text.bounds, + min_bounds, + version: font_system.version(), + })) } fn resize(&mut self, new_bounds: Size) { - let paragraph = self - .0 - .take() - .expect("paragraph should always be initialized"); - - match Arc::try_unwrap(paragraph) { - Ok(mut internal) => { - let mut font_system = - text::font_system().write().expect("Write font system"); - - internal.buffer.set_size( - font_system.raw(), - new_bounds.width, - new_bounds.height, - ); - - internal.bounds = new_bounds; - internal.min_bounds = text::measure(&internal.buffer); - - self.0 = Some(Arc::new(internal)); - } - Err(internal) => { - let metrics = internal.buffer.metrics(); - - // 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, - }); - } - } + let paragraph = Arc::make_mut(&mut self.0); + + let mut font_system = + text::font_system().write().expect("Write font system"); + + paragraph.buffer.set_size( + font_system.raw(), + Some(new_bounds.width), + Some(new_bounds.height), + ); + + paragraph.bounds = new_bounds; + paragraph.min_bounds = text::measure(¶graph.buffer); } - fn compare(&self, text: Text<&str>) -> core::text::Difference { + fn compare(&self, text: Text<()>) -> 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.wrapping != text.wrapping || paragraph.horizontal_alignment != text.horizontal_alignment || paragraph.vertical_alignment != text.vertical_alignment { @@ -186,6 +225,87 @@ impl core::text::Paragraph for Paragraph { Some(Hit::CharOffset(cursor.index)) } + fn hit_span(&self, point: Point) -> Option<usize> { + let internal = self.internal(); + + let cursor = internal.buffer.hit(point.x, point.y)?; + let line = internal.buffer.lines.get(cursor.line)?; + + let mut last_glyph = None; + let mut glyphs = line + .layout_opt() + .as_ref()? + .iter() + .flat_map(|line| line.glyphs.iter()) + .peekable(); + + while let Some(glyph) = glyphs.peek() { + if glyph.start <= cursor.index && cursor.index < glyph.end { + break; + } + + last_glyph = glyphs.next(); + } + + let glyph = match cursor.affinity { + cosmic_text::Affinity::Before => last_glyph, + cosmic_text::Affinity::After => glyphs.next(), + }?; + + Some(glyph.metadata) + } + + fn span_bounds(&self, index: usize) -> Vec<Rectangle> { + let internal = self.internal(); + + let mut bounds = Vec::new(); + let mut current_bounds = None; + + let glyphs = internal + .buffer + .layout_runs() + .flat_map(|run| { + let line_top = run.line_top; + let line_height = run.line_height; + + run.glyphs + .iter() + .map(move |glyph| (line_top, line_height, glyph)) + }) + .skip_while(|(_, _, glyph)| glyph.metadata != index) + .take_while(|(_, _, glyph)| glyph.metadata == index); + + for (line_top, line_height, glyph) in glyphs { + let y = line_top + glyph.y; + + let new_bounds = || { + Rectangle::new( + Point::new(glyph.x, y), + Size::new( + glyph.w, + glyph.line_height_opt.unwrap_or(line_height), + ), + ) + }; + + match current_bounds.as_mut() { + None => { + current_bounds = Some(new_bounds()); + } + Some(current_bounds) if y != current_bounds.y => { + bounds.push(*current_bounds); + *current_bounds = new_bounds(); + } + Some(current_bounds) => { + current_bounds.width += glyph.w; + } + } + } + + bounds.extend(current_bounds); + bounds + } + fn grapheme_position(&self, line: usize, index: usize) -> Option<Point> { use unicode_segmentation::UnicodeSegmentation; @@ -231,7 +351,7 @@ impl core::text::Paragraph for Paragraph { impl Default for Paragraph { fn default() -> Self { - Self(Some(Arc::new(Internal::default()))) + Self(Arc::new(Internal::default())) } } @@ -240,7 +360,6 @@ impl fmt::Debug for Paragraph { let paragraph = self.internal(); f.debug_struct("Paragraph") - .field("content", ¶graph.content) .field("font", ¶graph.font) .field("shaping", ¶graph.shaping) .field("horizontal_alignment", ¶graph.horizontal_alignment) @@ -253,8 +372,7 @@ impl fmt::Debug for Paragraph { impl PartialEq for Internal { fn eq(&self, other: &Self) -> bool { - self.content == other.content - && self.font == other.font + self.font == other.font && self.shaping == other.shaping && self.horizontal_alignment == other.horizontal_alignment && self.vertical_alignment == other.vertical_alignment @@ -271,9 +389,9 @@ impl Default for Internal { font_size: 1.0, line_height: 1.0, }), - content: String::new(), font: Font::default(), shaping: Shaping::default(), + wrapping: Wrapping::default(), horizontal_alignment: alignment::Horizontal::Left, vertical_alignment: alignment::Vertical::Top, bounds: Size::ZERO, @@ -298,7 +416,7 @@ pub struct Weak { impl Weak { /// Tries to update the reference into a [`Paragraph`]. pub fn upgrade(&self) -> Option<Paragraph> { - self.raw.upgrade().map(Some).map(Paragraph) + self.raw.upgrade().map(Paragraph) } } |