summaryrefslogtreecommitdiffstats
path: root/tiny_skia
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2023-03-09 04:48:35 +0100
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2023-03-09 04:48:35 +0100
commit424ac8177309440bbd8efe0dd9f7622cb10807ce (patch)
tree0ffa0d1d604780999892b88de85ee93e3ed7d539 /tiny_skia
parentaa4b5bb6b962b48715023e3ce567d1a18473bffa (diff)
downloadiced-424ac8177309440bbd8efe0dd9f7622cb10807ce.tar.gz
iced-424ac8177309440bbd8efe0dd9f7622cb10807ce.tar.bz2
iced-424ac8177309440bbd8efe0dd9f7622cb10807ce.zip
Implement color filter support for `Primitive::Svg` in `iced_tiny_skia`
Diffstat (limited to 'tiny_skia')
-rw-r--r--tiny_skia/src/backend.rs3
-rw-r--r--tiny_skia/src/vector.rs66
2 files changed, 50 insertions, 19 deletions
diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs
index b3c7d2bc..ba063f4e 100644
--- a/tiny_skia/src/backend.rs
+++ b/tiny_skia/src/backend.rs
@@ -197,10 +197,11 @@ impl Backend {
Primitive::Svg {
handle,
bounds,
- color: _, // TODO: Implement color filter
+ color,
} => {
self.vector_pipeline.draw(
handle,
+ *color,
(*bounds + translation) * scale_factor,
pixels,
clip_bounds.map(|_| clip_mask as &_),
diff --git a/tiny_skia/src/vector.rs b/tiny_skia/src/vector.rs
index 89063c4c..8509b761 100644
--- a/tiny_skia/src/vector.rs
+++ b/tiny_skia/src/vector.rs
@@ -1,5 +1,5 @@
use crate::core::svg::{Data, Handle};
-use crate::core::{Rectangle, Size};
+use crate::core::{Color, Rectangle, Size};
use resvg::usvg;
use rustc_hash::{FxHashMap, FxHashSet};
@@ -29,15 +29,16 @@ impl Pipeline {
pub fn draw(
&mut self,
handle: &Handle,
+ color: Option<Color>,
bounds: Rectangle,
pixels: &mut tiny_skia::PixmapMut<'_>,
clip_mask: Option<&tiny_skia::ClipMask>,
) {
- if let Some(image) = self
- .cache
- .borrow_mut()
- .draw(handle, Size::new(bounds.width as u32, bounds.height as u32))
- {
+ if let Some(image) = self.cache.borrow_mut().draw(
+ handle,
+ color,
+ Size::new(bounds.width as u32, bounds.height as u32),
+ ) {
pixels.draw_pixmap(
bounds.x as i32,
bounds.y as i32,
@@ -58,8 +59,15 @@ impl Pipeline {
struct Cache {
trees: FxHashMap<u64, Option<resvg::usvg::Tree>>,
tree_hits: FxHashSet<u64>,
- rasters: FxHashMap<(u64, Size<u32>), tiny_skia::Pixmap>,
- raster_hits: FxHashSet<(u64, Size<u32>)>,
+ rasters: FxHashMap<RasterKey, tiny_skia::Pixmap>,
+ raster_hits: FxHashSet<RasterKey>,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+struct RasterKey {
+ id: u64,
+ color: Option<[u8; 4]>,
+ size: Size<u32>,
}
impl Cache {
@@ -101,16 +109,21 @@ impl Cache {
fn draw(
&mut self,
handle: &Handle,
+ color: Option<Color>,
size: Size<u32>,
) -> Option<tiny_skia::PixmapRef<'_>> {
if size.width == 0 || size.height == 0 {
return None;
}
- let id = handle.id();
+ let key = RasterKey {
+ id: handle.id(),
+ color: color.map(Color::into_rgba8),
+ size,
+ };
#[allow(clippy::map_entry)]
- if !self.rasters.contains_key(&(id, size)) {
+ if !self.rasters.contains_key(&key) {
let tree = self.load(handle)?;
let mut image = tiny_skia::Pixmap::new(size.width, size.height)?;
@@ -126,18 +139,35 @@ impl Cache {
image.as_mut(),
)?;
- // Swap R and B channels for `softbuffer` presentation
- for pixel in bytemuck::cast_slice_mut::<u8, u32>(image.data_mut()) {
- *pixel = *pixel & 0xFF00FF00
- | ((0x000000FF & *pixel) << 16)
- | ((0x00FF0000 & *pixel) >> 16);
+ if let Some([r, g, b, a]) = key.color {
+ // TODO: Blend alpha
+ let color = tiny_skia::ColorU8::from_rgba(b, g, r, a)
+ .premultiply()
+ .get()
+ & 0x00FFFFFF;
+
+ // Apply color filter
+ for pixel in
+ bytemuck::cast_slice_mut::<u8, u32>(image.data_mut())
+ {
+ *pixel = *pixel & 0xFF000000 | color;
+ }
+ } else {
+ // Swap R and B channels for `softbuffer` presentation
+ for pixel in
+ bytemuck::cast_slice_mut::<u8, u32>(image.data_mut())
+ {
+ *pixel = *pixel & 0xFF00FF00
+ | ((0x000000FF & *pixel) << 16)
+ | ((0x00FF0000 & *pixel) >> 16);
+ }
}
- self.rasters.insert((id, size), image);
+ self.rasters.insert(key, image);
}
- self.raster_hits.insert((id, size));
- self.rasters.get(&(id, size)).map(tiny_skia::Pixmap::as_ref)
+ self.raster_hits.insert(key);
+ self.rasters.get(&key).map(tiny_skia::Pixmap::as_ref)
}
fn trim(&mut self) {