Skip to content

Commit

Permalink
Add support for additional image-rendering attributes (#833)
Browse files Browse the repository at this point in the history
Closes #828
  • Loading branch information
LaurenzV authored Oct 15, 2024
1 parent 6298c1d commit fc4d020
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 7 deletions.
13 changes: 9 additions & 4 deletions crates/resvg/src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ fn render_vector(
#[cfg(feature = "raster-images")]
mod raster_images {
use crate::OptionLog;
use usvg::ImageRendering;

fn decode_raster(image: &usvg::ImageKind) -> Option<tiny_skia::Pixmap> {
match image {
Expand Down Expand Up @@ -169,10 +170,14 @@ mod raster_images {
let rect = tiny_skia::Size::from_wh(raster.width() as f32, raster.height() as f32)?
.to_rect(0.0, 0.0)?;

let mut quality = tiny_skia::FilterQuality::Bicubic;
if rendering_mode == usvg::ImageRendering::OptimizeSpeed {
quality = tiny_skia::FilterQuality::Nearest;
}
let quality = match rendering_mode {
ImageRendering::OptimizeQuality => tiny_skia::FilterQuality::Bicubic,
ImageRendering::OptimizeSpeed => tiny_skia::FilterQuality::Nearest,
ImageRendering::Smooth => tiny_skia::FilterQuality::Bilinear,
ImageRendering::HighQuality => tiny_skia::FilterQuality::Bicubic,
ImageRendering::CrispEdges => tiny_skia::FilterQuality::Nearest,
ImageRendering::Pixelated => tiny_skia::FilterQuality::Nearest,
};

let pattern = tiny_skia::Pattern::new(
raster.as_ref(),
Expand Down
2 changes: 1 addition & 1 deletion crates/resvg/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ OPTIONS:
geometricPrecision]
--image-rendering HINT Selects the default image rendering method
[default: optimizeQuality]
[possible values: optimizeQuality, optimizeSpeed]
[possible values: optimizeQuality, optimizeSpeed, smooth, high-quality, crisp-edges, pixelated]
--resources-dir DIR Sets a directory that will be used during
relative paths resolving.
Expected to be the same as the directory that
Expand Down
1 change: 1 addition & 0 deletions crates/resvg/tests/integration/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,7 @@ use crate::render;
#[test] fn painting_fill_opacity_with_pattern() { assert_eq!(render("tests/painting/fill-opacity/with-pattern"), 0); }
#[test] fn painting_fill_rule_evenodd() { assert_eq!(render("tests/painting/fill-rule/evenodd"), 0); }
#[test] fn painting_fill_rule_nonzero() { assert_eq!(render("tests/painting/fill-rule/nonzero"), 0); }
#[test] fn painting_image_rendering_high_quality() { assert_eq!(render("tests/painting/image-rendering/high-quality"), 0); }
#[test] fn painting_image_rendering_on_feImage() { assert_eq!(render("tests/painting/image-rendering/on-feImage"), 0); }
#[test] fn painting_image_rendering_optimizeSpeed_on_SVG() { assert_eq!(render("tests/painting/image-rendering/optimizeSpeed-on-SVG"), 0); }
#[test] fn painting_image_rendering_optimizeSpeed() { assert_eq!(render("tests/painting/image-rendering/optimizeSpeed"), 0); }
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 62 additions & 0 deletions crates/resvg/tests/tests/painting/image-rendering/high-quality.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion crates/usvg/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ OPTIONS:
geometricPrecision]
--image-rendering HINT Selects the default image rendering method
[default: optimizeQuality]
[possible values: optimizeQuality, optimizeSpeed]
[possible values: optimizeQuality, optimizeSpeed, smooth, high-quality, crisp-edges, pixelated]
--resources-dir DIR Sets a directory that will be used during
relative paths resolving.
Expected to be the same as the directory that
Expand Down
4 changes: 4 additions & 0 deletions crates/usvg/src/parser/svgtree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1020,6 +1020,10 @@ impl<'a, 'input: 'a> FromValue<'a, 'input> for ImageRendering {
match value {
"auto" | "optimizeQuality" => Some(ImageRendering::OptimizeQuality),
"optimizeSpeed" => Some(ImageRendering::OptimizeSpeed),
"smooth" => Some(ImageRendering::Smooth),
"high-quality" => Some(ImageRendering::HighQuality),
"crisp-edges" => Some(ImageRendering::CrispEdges),
"pixelated" => Some(ImageRendering::Pixelated),
_ => None,
}
}
Expand Down
7 changes: 7 additions & 0 deletions crates/usvg/src/parser/svgtree/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,13 @@ pub(crate) fn parse_svg_element<'input>(
// For some reason those properties are allowed only inside a `style` attribute and CSS.
if matches!(aid, AId::MixBlendMode | AId::Isolation | AId::FontKerning) {
continue;
} else if aid == AId::ImageRendering
&& matches!(
attr.value(),
"smooth" | "high-quality" | "crisp-edges" | "pixelated"
)
{
continue;
}

append_attribute(parent_id, tag_name, aid, attr.value_storage().clone(), doc);
Expand Down
9 changes: 9 additions & 0 deletions crates/usvg/src/tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,11 @@ impl std::str::FromStr for TextRendering {
pub enum ImageRendering {
OptimizeQuality,
OptimizeSpeed,
// The following can only appear as presentation attributes.
Smooth,
HighQuality,
CrispEdges,
Pixelated,
}

impl Default for ImageRendering {
Expand All @@ -185,6 +190,10 @@ impl std::str::FromStr for ImageRendering {
match s {
"optimizeQuality" => Ok(ImageRendering::OptimizeQuality),
"optimizeSpeed" => Ok(ImageRendering::OptimizeSpeed),
"smooth" => Ok(ImageRendering::Smooth),
"high-quality" => Ok(ImageRendering::HighQuality),
"crisp-edges" => Ok(ImageRendering::CrispEdges),
"pixelated" => Ok(ImageRendering::Pixelated),
_ => Err("invalid"),
}
}
Expand Down
12 changes: 12 additions & 0 deletions crates/usvg/src/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,18 @@ fn write_element(node: &Node, is_clip_path: bool, opt: &WriteOptions, xml: &mut
ImageRendering::OptimizeSpeed => {
xml.write_svg_attribute(AId::ImageRendering, "optimizeSpeed");
}
ImageRendering::Smooth => {
xml.write_attribute(AId::Style.to_str(), "image-rendering:smooth");
}
ImageRendering::HighQuality => {
xml.write_attribute(AId::Style.to_str(), "image-rendering:high-quality");
}
ImageRendering::CrispEdges => {
xml.write_attribute(AId::Style.to_str(), "image-rendering:crisp-edges");
}
ImageRendering::Pixelated => {
xml.write_attribute(AId::Style.to_str(), "image-rendering:pixelated");
}
}

xml.write_image_data(&img.kind);
Expand Down
2 changes: 1 addition & 1 deletion docs/svg2-changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ Basically everything from [CSS Text Module Level 3](https://www.w3.org/TR/css-te
- [x] An [`isolation`](https://www.w3.org/TR/compositing-1/#isolation) property.
- [ ] `left`, `center` and `right` variants to `refX` and `refY` properties of the [`marker`](https://www.w3.org/TR/SVG2/painting.html#MarkerElement) element.
- [x] An `auto-start-reverse` variant to [`orient`](https://www.w3.org/TR/SVG2/painting.html#OrientAttribute) property of the [`marker`](https://www.w3.org/TR/SVG2/painting.html#MarkerElement) element

- [x] The `image-rendering` can appear as a presentation attribute with additional possible values. Currently, there is only best-effort support for "pixelated".
### Changed

- [x] Markers can be set on all shapes and not only on `path`.
Expand Down

0 comments on commit fc4d020

Please sign in to comment.