summaryrefslogtreecommitdiffstats
path: root/tiny_skia
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2024-08-04 03:28:43 +0200
committerLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2024-08-04 03:28:43 +0200
commit0ceee1cf3ae49f5bd0e3f2b346a4b34076e4523a (patch)
treec44e036220ea40734a00bb8e05e4afa6a9504bea /tiny_skia
parent87a613edd186461f1a8d224394043527a372571c (diff)
downloadiced-0ceee1cf3ae49f5bd0e3f2b346a4b34076e4523a.tar.gz
iced-0ceee1cf3ae49f5bd0e3f2b346a4b34076e4523a.tar.bz2
iced-0ceee1cf3ae49f5bd0e3f2b346a4b34076e4523a.zip
Implement image support for `canvas` widget
Diffstat (limited to 'tiny_skia')
-rw-r--r--tiny_skia/Cargo.toml2
-rw-r--r--tiny_skia/src/engine.rs1
-rw-r--r--tiny_skia/src/geometry.rs86
-rw-r--r--tiny_skia/src/layer.rs43
-rw-r--r--tiny_skia/src/lib.rs11
5 files changed, 138 insertions, 5 deletions
diff --git a/tiny_skia/Cargo.toml b/tiny_skia/Cargo.toml
index 32ead3e0..323233f0 100644
--- a/tiny_skia/Cargo.toml
+++ b/tiny_skia/Cargo.toml
@@ -15,7 +15,7 @@ workspace = true
[features]
image = ["iced_graphics/image"]
-svg = ["resvg"]
+svg = ["iced_graphics/svg", "resvg"]
geometry = ["iced_graphics/geometry"]
[dependencies]
diff --git a/tiny_skia/src/engine.rs b/tiny_skia/src/engine.rs
index 898657c8..c5c4d494 100644
--- a/tiny_skia/src/engine.rs
+++ b/tiny_skia/src/engine.rs
@@ -556,6 +556,7 @@ impl Engine {
bounds,
rotation,
opacity,
+ snap: _,
} => {
let physical_bounds = *bounds * _transformation;
diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs
index 02b6e1b9..398b54f7 100644
--- a/tiny_skia/src/geometry.rs
+++ b/tiny_skia/src/geometry.rs
@@ -1,10 +1,12 @@
+use crate::core::image;
+use crate::core::svg;
use crate::core::text::LineHeight;
-use crate::core::{Pixels, Point, Radians, Rectangle, Size, Vector};
+use crate::core::{Color, Pixels, Point, Radians, Rectangle, Size, Vector};
use crate::graphics::cache::{self, Cached};
use crate::graphics::geometry::fill::{self, Fill};
use crate::graphics::geometry::stroke::{self, Stroke};
use crate::graphics::geometry::{self, Path, Style};
-use crate::graphics::{Gradient, Text};
+use crate::graphics::{Gradient, Image, Text};
use crate::Primitive;
use std::rc::Rc;
@@ -13,6 +15,7 @@ use std::rc::Rc;
pub enum Geometry {
Live {
text: Vec<Text>,
+ images: Vec<Image>,
primitives: Vec<Primitive>,
clip_bounds: Rectangle,
},
@@ -22,6 +25,7 @@ pub enum Geometry {
#[derive(Debug, Clone)]
pub struct Cache {
pub text: Rc<[Text]>,
+ pub images: Rc<[Image]>,
pub primitives: Rc<[Primitive]>,
pub clip_bounds: Rectangle,
}
@@ -37,10 +41,12 @@ impl Cached for Geometry {
match self {
Self::Live {
primitives,
+ images,
text,
clip_bounds,
} => Cache {
primitives: Rc::from(primitives),
+ images: Rc::from(images),
text: Rc::from(text),
clip_bounds,
},
@@ -55,6 +61,7 @@ pub struct Frame {
transform: tiny_skia::Transform,
stack: Vec<tiny_skia::Transform>,
primitives: Vec<Primitive>,
+ images: Vec<Image>,
text: Vec<Text>,
}
@@ -68,6 +75,7 @@ impl Frame {
clip_bounds,
stack: Vec::new(),
primitives: Vec::new(),
+ images: Vec::new(),
text: Vec::new(),
transform: tiny_skia::Transform::from_translate(
clip_bounds.x,
@@ -238,7 +246,7 @@ impl geometry::frame::Backend for Frame {
Self::with_clip(clip_bounds)
}
- fn paste(&mut self, frame: Self, _at: Point) {
+ fn paste(&mut self, frame: Self) {
self.primitives.extend(frame.primitives);
self.text.extend(frame.text);
}
@@ -269,10 +277,82 @@ impl geometry::frame::Backend for Frame {
fn into_geometry(self) -> Geometry {
Geometry::Live {
primitives: self.primitives,
+ images: self.images,
text: self.text,
clip_bounds: self.clip_bounds,
}
}
+
+ fn draw_image(
+ &mut self,
+ handle: &image::Handle,
+ bounds: Rectangle,
+ filter_method: image::FilterMethod,
+ rotation: Radians,
+ opacity: f32,
+ ) {
+ let (bounds, external_rotation) =
+ transform_rectangle(bounds, self.transform);
+
+ self.images.push(Image::Raster {
+ handle: handle.clone(),
+ filter_method,
+ bounds,
+ rotation: rotation + external_rotation,
+ opacity,
+ snap: false,
+ });
+ }
+
+ fn draw_svg(
+ &mut self,
+ handle: &svg::Handle,
+ bounds: Rectangle,
+ color: Option<Color>,
+ rotation: Radians,
+ opacity: f32,
+ ) {
+ let (bounds, external_rotation) =
+ transform_rectangle(bounds, self.transform);
+
+ self.images.push(Image::Vector {
+ handle: handle.clone(),
+ bounds,
+ color,
+ rotation: rotation + external_rotation,
+ opacity,
+ });
+ }
+}
+
+fn transform_rectangle(
+ rectangle: Rectangle,
+ transform: tiny_skia::Transform,
+) -> (Rectangle, Radians) {
+ let mut top_left = tiny_skia::Point {
+ x: rectangle.x,
+ y: rectangle.y,
+ };
+
+ let mut top_right = tiny_skia::Point {
+ x: rectangle.x + rectangle.width,
+ y: rectangle.y,
+ };
+
+ let mut bottom_left = tiny_skia::Point {
+ x: rectangle.x,
+ y: rectangle.y + rectangle.height,
+ };
+
+ transform.map_point(&mut top_left);
+ transform.map_point(&mut top_right);
+ transform.map_point(&mut bottom_left);
+
+ Rectangle::with_vertices(
+ Point::new(top_left.x, top_left.y),
+ Point::new(top_right.x, top_right.y),
+ Point::new(bottom_left.x, bottom_left.y),
+ )
}
fn convert_path(path: &Path) -> Option<tiny_skia::Path> {
diff --git a/tiny_skia/src/layer.rs b/tiny_skia/src/layer.rs
index 48fca1d8..9a169f46 100644
--- a/tiny_skia/src/layer.rs
+++ b/tiny_skia/src/layer.rs
@@ -117,6 +117,48 @@ impl Layer {
pub fn draw_image(
&mut self,
+ image: &Image,
+ transformation: Transformation,
+ ) {
+ match image {
+ Image::Raster {
+ handle,
+ filter_method,
+ bounds,
+ rotation,
+ opacity,
+ snap: _,
+ } => {
+ self.draw_raster(
+ handle.clone(),
+ *filter_method,
+ *bounds,
+ transformation,
+ *rotation,
+ *opacity,
+ );
+ }
+ Image::Vector {
+ handle,
+ color,
+ bounds,
+ rotation,
+ opacity,
+ } => {
+ self.draw_svg(
+ handle.clone(),
+ *color,
+ *bounds,
+ transformation,
+ *rotation,
+ *opacity,
+ );
+ }
+ }
+ }
+
+ pub fn draw_raster(
+ &mut self,
handle: image::Handle,
filter_method: image::FilterMethod,
bounds: Rectangle,
@@ -130,6 +172,7 @@ impl Layer {
bounds: bounds * transformation,
rotation,
opacity,
+ snap: false,
};
self.images.push(image);
diff --git a/tiny_skia/src/lib.rs b/tiny_skia/src/lib.rs
index 6ec60158..f09e5aa3 100644
--- a/tiny_skia/src/lib.rs
+++ b/tiny_skia/src/lib.rs
@@ -330,6 +330,7 @@ impl graphics::geometry::Renderer for Renderer {
match geometry {
Geometry::Live {
primitives,
+ images,
text,
clip_bounds,
} => {
@@ -339,6 +340,10 @@ impl graphics::geometry::Renderer for Renderer {
transformation,
);
+ for image in images {
+ layer.draw_image(&image, transformation);
+ }
+
layer.draw_text_group(text, clip_bounds, transformation);
}
Geometry::Cache(cache) => {
@@ -348,6 +353,10 @@ impl graphics::geometry::Renderer for Renderer {
transformation,
);
+ for image in cache.images.iter() {
+ layer.draw_image(image, transformation);
+ }
+
layer.draw_text_cache(
cache.text,
cache.clip_bounds,
@@ -381,7 +390,7 @@ impl core::image::Renderer for Renderer {
opacity: f32,
) {
let (layer, transformation) = self.layers.current_mut();
- layer.draw_image(
+ layer.draw_raster(
handle,
filter_method,
bounds,