Skip to content

Commit 424ac81

Browse files
committed
Implement color filter support for Primitive::Svg in iced_tiny_skia
1 parent aa4b5bb commit 424ac81

File tree

2 files changed

+50
-19
lines changed

2 files changed

+50
-19
lines changed

tiny_skia/src/backend.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,11 @@ impl Backend {
197197
Primitive::Svg {
198198
handle,
199199
bounds,
200-
color: _, // TODO: Implement color filter
200+
color,
201201
} => {
202202
self.vector_pipeline.draw(
203203
handle,
204+
*color,
204205
(*bounds + translation) * scale_factor,
205206
pixels,
206207
clip_bounds.map(|_| clip_mask as &_),

tiny_skia/src/vector.rs

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::core::svg::{Data, Handle};
2-
use crate::core::{Rectangle, Size};
2+
use crate::core::{Color, Rectangle, Size};
33

44
use resvg::usvg;
55
use rustc_hash::{FxHashMap, FxHashSet};
@@ -29,15 +29,16 @@ impl Pipeline {
2929
pub fn draw(
3030
&mut self,
3131
handle: &Handle,
32+
color: Option<Color>,
3233
bounds: Rectangle,
3334
pixels: &mut tiny_skia::PixmapMut<'_>,
3435
clip_mask: Option<&tiny_skia::ClipMask>,
3536
) {
36-
if let Some(image) = self
37-
.cache
38-
.borrow_mut()
39-
.draw(handle, Size::new(bounds.width as u32, bounds.height as u32))
40-
{
37+
if let Some(image) = self.cache.borrow_mut().draw(
38+
handle,
39+
color,
40+
Size::new(bounds.width as u32, bounds.height as u32),
41+
) {
4142
pixels.draw_pixmap(
4243
bounds.x as i32,
4344
bounds.y as i32,
@@ -58,8 +59,15 @@ impl Pipeline {
5859
struct Cache {
5960
trees: FxHashMap<u64, Option<resvg::usvg::Tree>>,
6061
tree_hits: FxHashSet<u64>,
61-
rasters: FxHashMap<(u64, Size<u32>), tiny_skia::Pixmap>,
62-
raster_hits: FxHashSet<(u64, Size<u32>)>,
62+
rasters: FxHashMap<RasterKey, tiny_skia::Pixmap>,
63+
raster_hits: FxHashSet<RasterKey>,
64+
}
65+
66+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
67+
struct RasterKey {
68+
id: u64,
69+
color: Option<[u8; 4]>,
70+
size: Size<u32>,
6371
}
6472

6573
impl Cache {
@@ -101,16 +109,21 @@ impl Cache {
101109
fn draw(
102110
&mut self,
103111
handle: &Handle,
112+
color: Option<Color>,
104113
size: Size<u32>,
105114
) -> Option<tiny_skia::PixmapRef<'_>> {
106115
if size.width == 0 || size.height == 0 {
107116
return None;
108117
}
109118

110-
let id = handle.id();
119+
let key = RasterKey {
120+
id: handle.id(),
121+
color: color.map(Color::into_rgba8),
122+
size,
123+
};
111124

112125
#[allow(clippy::map_entry)]
113-
if !self.rasters.contains_key(&(id, size)) {
126+
if !self.rasters.contains_key(&key) {
114127
let tree = self.load(handle)?;
115128

116129
let mut image = tiny_skia::Pixmap::new(size.width, size.height)?;
@@ -126,18 +139,35 @@ impl Cache {
126139
image.as_mut(),
127140
)?;
128141

129-
// Swap R and B channels for `softbuffer` presentation
130-
for pixel in bytemuck::cast_slice_mut::<u8, u32>(image.data_mut()) {
131-
*pixel = *pixel & 0xFF00FF00
132-
| ((0x000000FF & *pixel) << 16)
133-
| ((0x00FF0000 & *pixel) >> 16);
142+
if let Some([r, g, b, a]) = key.color {
143+
// TODO: Blend alpha
144+
let color = tiny_skia::ColorU8::from_rgba(b, g, r, a)
145+
.premultiply()
146+
.get()
147+
& 0x00FFFFFF;
148+
149+
// Apply color filter
150+
for pixel in
151+
bytemuck::cast_slice_mut::<u8, u32>(image.data_mut())
152+
{
153+
*pixel = *pixel & 0xFF000000 | color;
154+
}
155+
} else {
156+
// Swap R and B channels for `softbuffer` presentation
157+
for pixel in
158+
bytemuck::cast_slice_mut::<u8, u32>(image.data_mut())
159+
{
160+
*pixel = *pixel & 0xFF00FF00
161+
| ((0x000000FF & *pixel) << 16)
162+
| ((0x00FF0000 & *pixel) >> 16);
163+
}
134164
}
135165

136-
self.rasters.insert((id, size), image);
166+
self.rasters.insert(key, image);
137167
}
138168

139-
self.raster_hits.insert((id, size));
140-
self.rasters.get(&(id, size)).map(tiny_skia::Pixmap::as_ref)
169+
self.raster_hits.insert(key);
170+
self.rasters.get(&key).map(tiny_skia::Pixmap::as_ref)
141171
}
142172

143173
fn trim(&mut self) {

0 commit comments

Comments
 (0)