diff options
| author | 2023-03-09 04:48:35 +0100 | |
|---|---|---|
| committer | 2023-03-09 04:48:35 +0100 | |
| commit | 424ac8177309440bbd8efe0dd9f7622cb10807ce (patch) | |
| tree | 0ffa0d1d604780999892b88de85ee93e3ed7d539 /tiny_skia | |
| parent | aa4b5bb6b962b48715023e3ce567d1a18473bffa (diff) | |
| download | iced-424ac8177309440bbd8efe0dd9f7622cb10807ce.tar.gz iced-424ac8177309440bbd8efe0dd9f7622cb10807ce.tar.bz2 iced-424ac8177309440bbd8efe0dd9f7622cb10807ce.zip | |
Implement color filter support for `Primitive::Svg` in `iced_tiny_skia`
Diffstat (limited to '')
| -rw-r--r-- | tiny_skia/src/backend.rs | 3 | ||||
| -rw-r--r-- | tiny_skia/src/vector.rs | 66 | 
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) { | 
