Skip to content

Commit 0dc8473

Browse files
authored
Feature flag raster image formats (#50)
## Notes - Fixes #47 - Allows support for raster images to be completely disabled as well as flagging individual formats (allows the `image` dependency to be disabled entirely as `image` is surprisingly large even with no formats enabled) --------- Signed-off-by: Nico Burns <[email protected]>
1 parent bbfb55f commit 0dc8473

File tree

4 files changed

+45
-28
lines changed

4 files changed

+45
-28
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ You can find its changes [documented below](#050-2024-11-20).
1515

1616
This release has an [MSRV][] of 1.75.
1717

18+
### Changed
19+
20+
- Feature flag raster image formats (enabled by default) ([#50] by [@nicoburns])
21+
1822
## [0.5.0][] (2024-11-20)
1923

2024
This release has an [MSRV][] of 1.75.
@@ -107,6 +111,7 @@ This release has an [MSRV][] of 1.75.
107111
[@MarijnS95]: https://github.com/MarijnS95
108112
[@DasLixou]: https://github.com/DasLixou
109113

114+
[#50]: https://github.com/linebender/vello_svg/pull/50
110115
[#42]: https://github.com/linebender/vello_svg/pull/42
111116
[#34]: https://github.com/linebender/vello_svg/pull/34
112117
[#31]: https://github.com/linebender/vello_svg/pull/31

Cargo.toml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,16 +99,17 @@ workspace = true
9999
vello = { workspace = true }
100100
thiserror = "1.0.69"
101101
usvg = "0.44.0"
102-
image = { version = "0.25.5", default-features = false, features = [
103-
"webp",
104-
"png",
105-
"jpeg",
106-
"gif",
107-
] }
102+
image = { version = "0.25.5", default-features = false, features = [ "webp", "png", "jpeg", "gif"], optional = true }
108103

109104
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
110105
wasm-bindgen-test = "0.3.49"
111106

112107
[features]
108+
default = ["image_format_png", "image_format_gif", "image_format_jpeg", "image_format_webp"]
113109
# Enables the wgpu feature on vello, which is disabled by default
114110
wgpu = ["vello/wgpu"]
111+
image = ["dep:image"]
112+
image_format_png = ["image", "image/png"]
113+
image_format_jpeg = ["image", "image/jpeg"]
114+
image_format_gif = ["image", "image/gif"]
115+
image_format_webp = ["image", "image/webp"]

src/render.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,23 @@ pub(crate) fn render_group<F: FnMut(&mut Scene, &usvg::Node)>(
104104
| usvg::ImageKind::PNG(_)
105105
| usvg::ImageKind::GIF(_)
106106
| usvg::ImageKind::WEBP(_) => {
107-
let Ok(decoded_image) = util::decode_raw_raster_image(img.kind()) else {
107+
#[cfg(feature = "image")]
108+
{
109+
let Ok(decoded_image) = util::decode_raw_raster_image(img.kind())
110+
else {
111+
error_handler(scene, node);
112+
continue;
113+
};
114+
let image = util::into_image(decoded_image);
115+
let image_ts = util::to_affine(&img.abs_transform());
116+
scene.draw_image(&image, image_ts);
117+
}
118+
119+
#[cfg(not(feature = "image"))]
120+
{
108121
error_handler(scene, node);
109122
continue;
110-
};
111-
let image = util::into_image(decoded_image);
112-
let image_ts = util::to_affine(&img.abs_transform());
113-
scene.draw_image(&image, image_ts);
123+
}
114124
}
115125
usvg::ImageKind::SVG(svg) => {
116126
render_group(scene, svg.root(), transform, error_handler);

src/util.rs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22
// SPDX-License-Identifier: Apache-2.0 OR MIT
33

44
use vello::kurbo::{Affine, BezPath, Point, Rect, Stroke};
5-
use vello::peniko::{Blob, Brush, Color, Fill, Image};
5+
use vello::peniko::{Brush, Color, Fill};
66
use vello::Scene;
77

8+
#[cfg(feature = "image")]
9+
use vello::peniko::{Blob, Image};
10+
811
pub fn to_affine(ts: &usvg::Transform) -> Affine {
912
let usvg::Transform {
1013
sx,
@@ -89,6 +92,7 @@ pub fn to_bez_path(path: &usvg::Path) -> BezPath {
8992
local_path
9093
}
9194

95+
#[cfg(feature = "image")]
9296
pub fn into_image(image: image::ImageBuffer<image::Rgba<u8>, Vec<u8>>) -> Image {
9397
let (width, height) = (image.width(), image.height());
9498
let image_data: Vec<u8> = image.into_vec();
@@ -202,24 +206,21 @@ pub fn default_error_handler(scene: &mut Scene, node: &usvg::Node) {
202206
);
203207
}
204208

209+
#[cfg(feature = "image")]
205210
pub fn decode_raw_raster_image(
206211
img: &usvg::ImageKind,
207212
) -> Result<image::RgbaImage, image::ImageError> {
208-
let res = match img {
209-
usvg::ImageKind::JPEG(data) => {
210-
image::load_from_memory_with_format(data, image::ImageFormat::Jpeg)
211-
}
212-
usvg::ImageKind::PNG(data) => {
213-
image::load_from_memory_with_format(data, image::ImageFormat::Png)
214-
}
215-
usvg::ImageKind::GIF(data) => {
216-
image::load_from_memory_with_format(data, image::ImageFormat::Gif)
217-
}
218-
usvg::ImageKind::WEBP(data) => {
219-
image::load_from_memory_with_format(data, image::ImageFormat::WebP)
220-
}
213+
// All `image::ImageFormat` variants exist even if the feature in the image crate is disabled,
214+
// but `image::load_from_memory_with_format` will fail with an Unsupported error if the
215+
// image crate feature flag is disabled. So we don't need any of our own feature handling here.
216+
let (data, format) = match img {
217+
usvg::ImageKind::JPEG(data) => (data, image::ImageFormat::Jpeg),
218+
usvg::ImageKind::PNG(data) => (data, image::ImageFormat::Png),
219+
usvg::ImageKind::GIF(data) => (data, image::ImageFormat::Gif),
220+
usvg::ImageKind::WEBP(data) => (data, image::ImageFormat::WebP),
221221
usvg::ImageKind::SVG(_) => unreachable!(),
222-
}?
223-
.into_rgba8();
224-
Ok(res)
222+
};
223+
224+
let dyn_image = image::load_from_memory_with_format(data, format)?;
225+
Ok(dyn_image.into_rgba8())
225226
}

0 commit comments

Comments
 (0)