summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2023-09-03 08:08:27 +0200
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2023-09-03 08:08:27 +0200
commit8129e2c208d9b13dbd32a309058b0547c723dede (patch)
treec9c5d9e383a2956b4e9b5cf7a48a5202fc6f249b
parent601e5563d101788cbaa6febbe15cdf52e9f3ae9b (diff)
downloadiced-8129e2c208d9b13dbd32a309058b0547c723dede.tar.gz
iced-8129e2c208d9b13dbd32a309058b0547c723dede.tar.bz2
iced-8129e2c208d9b13dbd32a309058b0547c723dede.zip
Implement `draw_paragraph` in `iced_tiny_skia`
-rw-r--r--tiny_skia/src/backend.rs2
-rw-r--r--tiny_skia/src/text.rs158
-rw-r--r--wgpu/src/text.rs25
3 files changed, 116 insertions, 69 deletions
diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs
index ef587bac..c721d96e 100644
--- a/tiny_skia/src/backend.rs
+++ b/tiny_skia/src/backend.rs
@@ -405,7 +405,7 @@ impl Backend {
let clip_mask = (!physical_bounds.is_within(&clip_bounds))
.then_some(clip_mask as &_);
- self.text_pipeline.draw(
+ self.text_pipeline.draw_cached(
content,
*bounds + translation,
*color,
diff --git a/tiny_skia/src/text.rs b/tiny_skia/src/text.rs
index 6047a826..3f57f9b1 100644
--- a/tiny_skia/src/text.rs
+++ b/tiny_skia/src/text.rs
@@ -41,16 +41,34 @@ impl Pipeline {
pub fn draw_paragraph(
&mut self,
- _paragraph: &paragraph::Weak,
- _position: Point,
- _color: Color,
- _scale_factor: f32,
- _pixels: &mut tiny_skia::PixmapMut<'_>,
- _clip_mask: Option<&tiny_skia::Mask>,
+ paragraph: &paragraph::Weak,
+ position: Point,
+ color: Color,
+ scale_factor: f32,
+ pixels: &mut tiny_skia::PixmapMut<'_>,
+ clip_mask: Option<&tiny_skia::Mask>,
) {
+ use crate::core::text::Paragraph as _;
+
+ let Some(paragraph) = paragraph.upgrade() else {
+ return;
+ };
+
+ draw(
+ &mut self.font_system.get_mut(),
+ &mut self.glyph_cache,
+ paragraph.buffer(),
+ Rectangle::new(position, paragraph.min_bounds()),
+ color,
+ paragraph.horizontal_alignment(),
+ paragraph.vertical_alignment(),
+ scale_factor,
+ pixels,
+ clip_mask,
+ );
}
- pub fn draw(
+ pub fn draw_cached(
&mut self,
content: &str,
bounds: Rectangle,
@@ -79,54 +97,25 @@ impl Pipeline {
let (_, entry) = self.cache.get_mut().allocate(font_system, key);
- let max_width = entry.min_bounds.width * scale_factor;
- let total_height = entry.min_bounds.height * scale_factor;
-
- let bounds = bounds * scale_factor;
-
- let x = match horizontal_alignment {
- alignment::Horizontal::Left => bounds.x,
- alignment::Horizontal::Center => bounds.x - max_width / 2.0,
- alignment::Horizontal::Right => bounds.x - max_width,
- };
-
- let y = match vertical_alignment {
- alignment::Vertical::Top => bounds.y,
- alignment::Vertical::Center => bounds.y - total_height / 2.0,
- alignment::Vertical::Bottom => bounds.y - total_height,
- };
-
- let mut swash = cosmic_text::SwashCache::new();
-
- for run in entry.buffer.layout_runs() {
- for glyph in run.glyphs {
- let physical_glyph = glyph.physical((x, y), scale_factor);
-
- if let Some((buffer, placement)) = self.glyph_cache.allocate(
- physical_glyph.cache_key,
- color,
- font_system,
- &mut swash,
- ) {
- let pixmap = tiny_skia::PixmapRef::from_bytes(
- buffer,
- placement.width,
- placement.height,
- )
- .expect("Create glyph pixel map");
-
- pixels.draw_pixmap(
- physical_glyph.x + placement.left,
- physical_glyph.y - placement.top
- + (run.line_y * scale_factor).round() as i32,
- pixmap,
- &tiny_skia::PixmapPaint::default(),
- tiny_skia::Transform::identity(),
- clip_mask,
- );
- }
- }
- }
+ let width = entry.min_bounds.width;
+ let height = entry.min_bounds.height;
+
+ draw(
+ font_system,
+ &mut self.glyph_cache,
+ &entry.buffer,
+ Rectangle {
+ width,
+ height,
+ ..bounds
+ },
+ color,
+ horizontal_alignment,
+ vertical_alignment,
+ scale_factor,
+ pixels,
+ clip_mask,
+ );
}
pub fn trim_cache(&mut self) {
@@ -135,6 +124,65 @@ impl Pipeline {
}
}
+fn draw(
+ font_system: &mut cosmic_text::FontSystem,
+ glyph_cache: &mut GlyphCache,
+ buffer: &cosmic_text::Buffer,
+ bounds: Rectangle,
+ color: Color,
+ horizontal_alignment: alignment::Horizontal,
+ vertical_alignment: alignment::Vertical,
+ scale_factor: f32,
+ pixels: &mut tiny_skia::PixmapMut<'_>,
+ clip_mask: Option<&tiny_skia::Mask>,
+) {
+ let bounds = bounds * scale_factor;
+
+ let x = match horizontal_alignment {
+ alignment::Horizontal::Left => bounds.x,
+ alignment::Horizontal::Center => bounds.x - bounds.width / 2.0,
+ alignment::Horizontal::Right => bounds.x - bounds.width,
+ };
+
+ let y = match vertical_alignment {
+ alignment::Vertical::Top => bounds.y,
+ alignment::Vertical::Center => bounds.y - bounds.height / 2.0,
+ alignment::Vertical::Bottom => bounds.y - bounds.height,
+ };
+
+ let mut swash = cosmic_text::SwashCache::new();
+
+ for run in buffer.layout_runs() {
+ for glyph in run.glyphs {
+ let physical_glyph = glyph.physical((x, y), scale_factor);
+
+ if let Some((buffer, placement)) = glyph_cache.allocate(
+ physical_glyph.cache_key,
+ color,
+ font_system,
+ &mut swash,
+ ) {
+ let pixmap = tiny_skia::PixmapRef::from_bytes(
+ buffer,
+ placement.width,
+ placement.height,
+ )
+ .expect("Create glyph pixel map");
+
+ pixels.draw_pixmap(
+ physical_glyph.x + placement.left,
+ physical_glyph.y - placement.top
+ + (run.line_y * scale_factor).round() as i32,
+ pixmap,
+ &tiny_skia::PixmapPaint::default(),
+ tiny_skia::Transform::identity(),
+ clip_mask,
+ );
+ }
+ }
+ }
+}
+
#[derive(Debug, Clone, Default)]
struct GlyphCache {
entries: FxHashMap<
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(&section_bounds)?;