Implement draw_paragraph in iced_tiny_skia
This commit is contained in:
parent
601e5563d1
commit
8129e2c208
3 changed files with 115 additions and 68 deletions
|
|
@ -405,7 +405,7 @@ impl Backend {
|
||||||
let clip_mask = (!physical_bounds.is_within(&clip_bounds))
|
let clip_mask = (!physical_bounds.is_within(&clip_bounds))
|
||||||
.then_some(clip_mask as &_);
|
.then_some(clip_mask as &_);
|
||||||
|
|
||||||
self.text_pipeline.draw(
|
self.text_pipeline.draw_cached(
|
||||||
content,
|
content,
|
||||||
*bounds + translation,
|
*bounds + translation,
|
||||||
*color,
|
*color,
|
||||||
|
|
|
||||||
|
|
@ -41,16 +41,34 @@ impl Pipeline {
|
||||||
|
|
||||||
pub fn draw_paragraph(
|
pub fn draw_paragraph(
|
||||||
&mut self,
|
&mut self,
|
||||||
_paragraph: ¶graph::Weak,
|
paragraph: ¶graph::Weak,
|
||||||
_position: Point,
|
position: Point,
|
||||||
_color: Color,
|
color: Color,
|
||||||
_scale_factor: f32,
|
scale_factor: f32,
|
||||||
_pixels: &mut tiny_skia::PixmapMut<'_>,
|
pixels: &mut tiny_skia::PixmapMut<'_>,
|
||||||
_clip_mask: Option<&tiny_skia::Mask>,
|
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,
|
&mut self,
|
||||||
content: &str,
|
content: &str,
|
||||||
bounds: Rectangle,
|
bounds: Rectangle,
|
||||||
|
|
@ -79,54 +97,25 @@ impl Pipeline {
|
||||||
|
|
||||||
let (_, entry) = self.cache.get_mut().allocate(font_system, key);
|
let (_, entry) = self.cache.get_mut().allocate(font_system, key);
|
||||||
|
|
||||||
let max_width = entry.min_bounds.width * scale_factor;
|
let width = entry.min_bounds.width;
|
||||||
let total_height = entry.min_bounds.height * scale_factor;
|
let height = entry.min_bounds.height;
|
||||||
|
|
||||||
let bounds = bounds * scale_factor;
|
draw(
|
||||||
|
font_system,
|
||||||
let x = match horizontal_alignment {
|
&mut self.glyph_cache,
|
||||||
alignment::Horizontal::Left => bounds.x,
|
&entry.buffer,
|
||||||
alignment::Horizontal::Center => bounds.x - max_width / 2.0,
|
Rectangle {
|
||||||
alignment::Horizontal::Right => bounds.x - max_width,
|
width,
|
||||||
};
|
height,
|
||||||
|
..bounds
|
||||||
let y = match vertical_alignment {
|
},
|
||||||
alignment::Vertical::Top => bounds.y,
|
color,
|
||||||
alignment::Vertical::Center => bounds.y - total_height / 2.0,
|
horizontal_alignment,
|
||||||
alignment::Vertical::Bottom => bounds.y - total_height,
|
vertical_alignment,
|
||||||
};
|
scale_factor,
|
||||||
|
pixels,
|
||||||
let mut swash = cosmic_text::SwashCache::new();
|
clip_mask,
|
||||||
|
);
|
||||||
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,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trim_cache(&mut self) {
|
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)]
|
#[derive(Debug, Clone, Default)]
|
||||||
struct GlyphCache {
|
struct GlyphCache {
|
||||||
entries: FxHashMap<
|
entries: FxHashMap<
|
||||||
|
|
|
||||||
|
|
@ -159,29 +159,28 @@ impl Pipeline {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let x = bounds.x * scale_factor;
|
let bounds = bounds * 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 {
|
let left = match horizontal_alignment {
|
||||||
alignment::Horizontal::Left => x,
|
alignment::Horizontal::Left => bounds.x,
|
||||||
alignment::Horizontal::Center => x - max_width / 2.0,
|
alignment::Horizontal::Center => {
|
||||||
alignment::Horizontal::Right => x - max_width,
|
bounds.x - bounds.width / 2.0
|
||||||
|
}
|
||||||
|
alignment::Horizontal::Right => bounds.x - bounds.width,
|
||||||
};
|
};
|
||||||
|
|
||||||
let top = match vertical_alignment {
|
let top = match vertical_alignment {
|
||||||
alignment::Vertical::Top => y,
|
alignment::Vertical::Top => bounds.y,
|
||||||
alignment::Vertical::Center => y - total_height / 2.0,
|
alignment::Vertical::Center => {
|
||||||
alignment::Vertical::Bottom => y - total_height,
|
bounds.y - bounds.height / 2.0
|
||||||
|
}
|
||||||
|
alignment::Vertical::Bottom => bounds.y - bounds.height,
|
||||||
};
|
};
|
||||||
|
|
||||||
let section_bounds = Rectangle {
|
let section_bounds = Rectangle {
|
||||||
x: left,
|
x: left,
|
||||||
y: top,
|
y: top,
|
||||||
width: max_width,
|
..bounds
|
||||||
height: total_height,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let clip_bounds = layer_bounds.intersection(§ion_bounds)?;
|
let clip_bounds = layer_bounds.intersection(§ion_bounds)?;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue