summaryrefslogtreecommitdiffstats
path: root/cairo-renderer
diff options
context:
space:
mode:
Diffstat (limited to 'cairo-renderer')
-rw-r--r--cairo-renderer/Cargo.toml11
-rw-r--r--cairo-renderer/src/lib.rs83
2 files changed, 77 insertions, 17 deletions
diff --git a/cairo-renderer/Cargo.toml b/cairo-renderer/Cargo.toml
index 53f95be..f5db906 100644
--- a/cairo-renderer/Cargo.toml
+++ b/cairo-renderer/Cargo.toml
@@ -9,7 +9,10 @@ edition = "2021"
9[dependencies] 9[dependencies]
10diaphragm-core = { path = "../core" } 10diaphragm-core = { path = "../core" }
11 11
12cairo-rs = { version = "0.16", features = ["svg", "png"] } 12cairo-rs = { version = "0.17", features = ["svg", "png"] }
13gdk = "0.16" 13gdk = "0.17"
14pango = "0.16" 14pango = "0.17"
15pangocairo = "0.16" 15pangocairo = "0.17"
16librsvg = { git = "https://gitlab.gnome.org/GNOME/librsvg", version = "2"}
17
18mime_guess = "2"
diff --git a/cairo-renderer/src/lib.rs b/cairo-renderer/src/lib.rs
index 01eb7ef..d49e5ce 100644
--- a/cairo-renderer/src/lib.rs
+++ b/cairo-renderer/src/lib.rs
@@ -4,6 +4,8 @@ use std::{
4}; 4};
5 5
6use gdk::{gdk_pixbuf::Pixbuf, prelude::GdkContextExt}; 6use gdk::{gdk_pixbuf::Pixbuf, prelude::GdkContextExt};
7use librsvg::SvgHandle;
8use mime_guess::mime;
7 9
8use diaphragm_core::{ 10use diaphragm_core::{
9 styles::{DefinedDashStyle, Pattern}, 11 styles::{DefinedDashStyle, Pattern},
@@ -11,9 +13,38 @@ use diaphragm_core::{
11 Renderer, 13 Renderer,
12}; 14};
13 15
16enum Image {
17 Pixbuf(Pixbuf),
18 Svg(SvgHandle),
19}
20
21impl Image {
22 fn width(&self) -> f64 {
23 match self {
24 Image::Pixbuf(pixbuf) => pixbuf.width() as f64,
25 Image::Svg(handle) => {
26 let dimensions = librsvg::CairoRenderer::new(handle).intrinsic_dimensions();
27 // TODO: this doesn't check if the SVG has different unit for width of height
28 dimensions.width.length
29 }
30 }
31 }
32
33 fn height(&self) -> f64 {
34 match self {
35 Image::Pixbuf(pixbuf) => pixbuf.height() as f64,
36 Image::Svg(handle) => {
37 let dimensions = librsvg::CairoRenderer::new(handle).intrinsic_dimensions();
38 // TODO: this doesn't check if the SVG has different unit for width of height
39 dimensions.height.length
40 }
41 }
42 }
43}
44
14pub struct CairoRenderer { 45pub struct CairoRenderer {
15 ctx: cairo::Context, 46 ctx: cairo::Context,
16 loaded_images: HashMap<PathBuf, Pixbuf>, 47 loaded_images: HashMap<PathBuf, Image>,
17} 48}
18 49
19impl CairoRenderer { 50impl CairoRenderer {
@@ -29,11 +60,24 @@ impl CairoRenderer {
29 } 60 }
30 } 61 }
31 62
32 fn get_image(&mut self, path: &Path) -> &Pixbuf { 63 fn load_image(&mut self, path: &Path) {
33 let path = path.to_owned(); 64 if self.loaded_images.contains_key(path) {
34 self.loaded_images 65 return;
35 .entry(path.clone()) 66 }
36 .or_insert_with(|| Pixbuf::from_file(path).unwrap()) 67
68 let mime_type = mime_guess::from_path(&path).first().unwrap();
69 assert_eq!(mime_type.type_(), "image", "File is not an image");
70 let image = match mime_type.subtype() {
71 mime::SVG => Image::Svg(librsvg::Loader::new().read_path(path).unwrap()),
72 // TODO: use Pixbuf::formats() to check for supported formats
73 mime::PNG | mime::GIF | mime::JPEG => Image::Pixbuf(Pixbuf::from_file(path).unwrap()),
74 other => panic!("Unsupported image type: {}", other),
75 };
76 self.loaded_images.insert(path.to_owned(), image);
77 }
78
79 fn get_image(&self, path: &Path) -> &Image {
80 self.loaded_images.get(path).unwrap()
37 } 81 }
38} 82}
39 83
@@ -134,23 +178,36 @@ impl Renderer for CairoRenderer {
134 } 178 }
135 179
136 fn show_image(&mut self, path: &Path, x: f64, y: f64, width: f64, height: f64) { 180 fn show_image(&mut self, path: &Path, x: f64, y: f64, width: f64, height: f64) {
137 let image = self.get_image(path).clone(); 181 self.load_image(path);
182 let image = self.get_image(path);
138 183
139 self.ctx.save().unwrap(); 184 self.ctx.save().unwrap();
140 185
141 let scale_x = width / image.width() as f64; 186 match image {
142 let scale_y = height / image.height() as f64; 187 Image::Pixbuf(pixbuf) => {
188 let scale_x = width / image.width();
189 let scale_y = height / image.height();
143 190
144 self.ctx.scale(scale_x, scale_y); 191 self.ctx.scale(scale_x, scale_y);
145 192
146 self.ctx.set_source_pixbuf(&image, x / scale_x, y / scale_y); 193 self.ctx.set_source_pixbuf(pixbuf, x / scale_x, y / scale_y);
147 self.ctx.paint().unwrap(); 194 self.ctx.paint().unwrap();
195 }
196 Image::Svg(handle) => {
197 // TODO: if aspect ratio is not kept, the image is not "scaled", only margins are
198 // added
199 librsvg::CairoRenderer::new(handle)
200 .render_document(&self.ctx, &cairo::Rectangle::new(x, y, width, height))
201 .unwrap();
202 }
203 }
148 204
149 self.ctx.restore().unwrap(); 205 self.ctx.restore().unwrap();
150 } 206 }
151 207
152 fn geometry_for_image(&mut self, path: &Path) -> (f64, f64) { 208 fn geometry_for_image(&mut self, path: &Path) -> (f64, f64) {
209 self.load_image(path);
153 let image = self.get_image(path); 210 let image = self.get_image(path);
154 (image.width() as f64, image.height() as f64) 211 (image.width(), image.height())
155 } 212 }
156} 213}