Skip to content

Commit

Permalink
Introduce RawText to Primitive in iced_graphics
Browse files Browse the repository at this point in the history
This should allow users to directly render a
`cosmic_text::Buffer`.
  • Loading branch information
hecrj committed Dec 5, 2023
1 parent fc285d3 commit 603832e
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 4 deletions.
5 changes: 5 additions & 0 deletions graphics/src/damage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ impl<T: Damage> Damage for Primitive<T> {

bounds.expand(1.5)
}
Self::RawText(raw) => {
// TODO: Add `size` field to `raw` to compute more accurate
// damage bounds (?)
raw.clip_bounds.expand(1.5)
}
Self::Quad { bounds, .. }
| Self::Image { bounds, .. }
| Self::Svg { bounds, .. } => bounds.expand(1.0),
Expand Down
2 changes: 2 additions & 0 deletions graphics/src/primitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ pub enum Primitive<T> {
/// The clip bounds of the editor.
clip_bounds: Rectangle,
},
/// A raw `cosmic-text` primitive
RawText(crate::text::Raw),
/// A quad primitive
Quad {
/// The bounds of the quad
Expand Down
27 changes: 25 additions & 2 deletions graphics/src/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ pub use cosmic_text;
use crate::color;
use crate::core::font::{self, Font};
use crate::core::text::Shaping;
use crate::core::{Color, Size};
use crate::core::{Color, Point, Rectangle, Size};

use once_cell::sync::OnceCell;
use std::borrow::Cow;
use std::sync::{Arc, RwLock};
use std::sync::{Arc, RwLock, Weak};

/// Returns the global [`FontSystem`].
pub fn font_system() -> &'static RwLock<FontSystem> {
Expand Down Expand Up @@ -68,6 +68,29 @@ impl FontSystem {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Version(u32);

/// A weak reference to a [`cosmic-text::Buffer`] that can be drawn.
#[derive(Debug, Clone)]
pub struct Raw {
/// A weak reference to a [`cosmic_text::Buffer`].
pub buffer: Weak<cosmic_text::Buffer>,
/// The position of the text.
pub position: Point,
/// The color of the text.
pub color: Color,
/// The clip bounds of the text.
pub clip_bounds: Rectangle,
}

impl PartialEq for Raw {
fn eq(&self, _other: &Self) -> bool {
// TODO: There is no proper way to compare raw buffers
// For now, no two instances of `Raw` text will be equal.
// This should be fine, but could trigger unnecessary redraws
// in the future.
false
}
}

/// Measures the dimensions of the given [`cosmic_text::Buffer`].
pub fn measure(buffer: &cosmic_text::Buffer) -> Size {
let (width, total_lines) = buffer
Expand Down
30 changes: 30 additions & 0 deletions tiny_skia/src/backend.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::core::{Background, Color, Gradient, Rectangle, Vector};
use crate::graphics::backend;
use crate::graphics::text;
use crate::graphics::Viewport;
use crate::primitive::{self, Primitive};

Expand Down Expand Up @@ -444,6 +445,35 @@ impl Backend {
clip_mask,
);
}
Primitive::RawText(text::Raw {
buffer,
position,
color,
clip_bounds: text_clip_bounds,
}) => {
let Some(buffer) = buffer.upgrade() else {
return;
};

let physical_bounds =
(*text_clip_bounds + translation) * scale_factor;

if !clip_bounds.intersects(&physical_bounds) {
return;
}

let clip_mask = (!physical_bounds.is_within(&clip_bounds))
.then_some(clip_mask as &_);

self.text_pipeline.draw_raw(
&buffer,
*position + translation,
*color,
scale_factor,
pixels,
clip_mask,
);
}
#[cfg(feature = "image")]
Primitive::Image {
handle,
Expand Down
29 changes: 28 additions & 1 deletion tiny_skia/src/text.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::core::alignment;
use crate::core::text::{LineHeight, Shaping};
use crate::core::{Color, Font, Pixels, Point, Rectangle};
use crate::core::{Color, Font, Pixels, Point, Rectangle, Size};
use crate::graphics::color;
use crate::graphics::text::cache::{self, Cache};
use crate::graphics::text::editor;
Expand Down Expand Up @@ -149,6 +149,33 @@ impl Pipeline {
);
}

pub fn draw_raw(
&mut self,
buffer: &cosmic_text::Buffer,
position: Point,
color: Color,
scale_factor: f32,
pixels: &mut tiny_skia::PixmapMut<'_>,
clip_mask: Option<&tiny_skia::Mask>,
) {
let mut font_system = font_system().write().expect("Write font system");

let (width, height) = buffer.size();

draw(
font_system.raw(),
&mut self.glyph_cache,
buffer,
Rectangle::new(position, Size::new(width, height)),
color,
alignment::Horizontal::Left,
alignment::Vertical::Top,
scale_factor,
pixels,
clip_mask,
);
}

pub fn trim_cache(&mut self) {
self.cache.get_mut().trim();
self.glyph_cache.trim();
Expand Down
15 changes: 15 additions & 0 deletions wgpu/src/layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,21 @@ impl<'a> Layer<'a> {
clip_bounds: *clip_bounds + translation,
}));
}
graphics::Primitive::RawText(graphics::text::Raw {
buffer,
position,
color,
clip_bounds,
}) => {
let layer = &mut layers[current_layer];

layer.text.push(Text::Raw(graphics::text::Raw {
buffer: buffer.clone(),
position: *position + translation,
color: *color,
clip_bounds: *clip_bounds + translation,
}));
}
Primitive::Quad {
bounds,
background,
Expand Down
5 changes: 4 additions & 1 deletion wgpu/src/layer/text.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::core::alignment;
use crate::core::text;
use crate::core::{Color, Font, Pixels, Point, Rectangle};
use crate::graphics;
use crate::graphics::text::editor;
use crate::graphics::text::paragraph;

Expand All @@ -23,8 +24,10 @@ pub enum Text<'a> {
color: Color,
clip_bounds: Rectangle,
},
/// A cached text.
/// Some cached text.
Cached(Cached<'a>),
/// Some raw text.
Raw(graphics::text::Raw),
}

#[derive(Debug, Clone)]
Expand Down
22 changes: 22 additions & 0 deletions wgpu/src/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::layer::Text;

use std::borrow::Cow;
use std::cell::RefCell;
use std::sync::Arc;

#[allow(missing_debug_implementations)]
pub struct Pipeline {
Expand Down Expand Up @@ -76,6 +77,7 @@ impl Pipeline {
Paragraph(Paragraph),
Editor(Editor),
Cache(cache::KeyHash),
Raw(Arc<glyphon::Buffer>),
}

let allocations: Vec<_> = sections
Expand Down Expand Up @@ -107,6 +109,7 @@ impl Pipeline {

Some(Allocation::Cache(key))
}
Text::Raw(text) => text.buffer.upgrade().map(Allocation::Raw),
})
.collect();

Expand Down Expand Up @@ -185,6 +188,25 @@ impl Pipeline {
text.clip_bounds,
)
}
Text::Raw(text) => {
let Some(Allocation::Raw(buffer)) = allocation else {
return None;
};

let (width, height) = buffer.size();

(
buffer.as_ref(),
Rectangle::new(
text.position,
Size::new(width, height),
),
alignment::Horizontal::Left,
alignment::Vertical::Top,
text.color,
text.clip_bounds,
)
}
};

let bounds = bounds * scale_factor;
Expand Down

0 comments on commit 603832e

Please sign in to comment.