Skip to content

Commit

Permalink
Simple refactoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
RazrFalcon committed Feb 12, 2022
1 parent 56830fa commit e3cd65d
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 38 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
This changelog also contains important changes in dependencies.

## [Unreleased]
### Added
- `usvg::ImageHrefResolver` that allows a custom `xlink:href` handling.
Thanks to [antmelnyk](https://github.com/antmelnyk).

## [0.20.0] - 2021-12-29
### Changed
Expand Down
8 changes: 1 addition & 7 deletions examples/custom_href_resolver.rs
Expand Up @@ -25,13 +25,7 @@ fn main() {
let pixmap_size = rtree.svg_node().size.to_screen_size();
let mut pixmap = tiny_skia::Pixmap::new(pixmap_size.width(), pixmap_size.height()).unwrap();

resvg::render(
&rtree,
usvg::FitTo::Original,
tiny_skia::Transform::default(),
pixmap.as_mut(),
)
.unwrap();
resvg::render(&rtree, usvg::FitTo::Original, tiny_skia::Transform::default(), pixmap.as_mut()).unwrap();

pixmap.save_png("custom_href_resolver.png").unwrap();
}
Binary file modified examples/ferris.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion usvg/src/filter/image.rs
Expand Up @@ -64,7 +64,6 @@ pub(crate) fn convert(fe: svgtree::Node, state: &converter::State) -> Kind {
};

let href = crate::image::get_href_data(href, state.opt);

let img_data = match href {
Some(data) => data,
None => return super::create_dummy_primitive(),
Expand Down
69 changes: 45 additions & 24 deletions usvg/src/image.rs
Expand Up @@ -37,22 +37,47 @@ impl std::fmt::Debug for ImageKind {
}
}

/// Functions that accept various representations of `xlink:href` value of the `<image>`
/// element and return ImageKind that holds reference to the image buffer determined by these functions.
#[allow(clippy::type_complexity)]
/// A shorthand for [ImageHrefResolver]'s data function.
pub type ImageHrefDataResolverFn = Box<dyn Fn(&str, Arc<Vec<u8>>, &OptionsRef) -> Option<ImageKind> + Send + Sync>;
/// A shorthand for [ImageHrefResolver]'s string function.
pub type ImageHrefStringResolverFn = Box<dyn Fn(&str, &OptionsRef) -> Option<ImageKind> + Send + Sync>;

/// An `xlink:href` resolver for `<image>` elements.
///
/// This type can be useful if you want to have an alternative `xlink:href` handling
/// to the default one. For example, you can forbid access to local files (which is allowed by default)
/// or add support for resolving actual URLs (usvg doesn't do any network requests).
pub struct ImageHrefResolver {
/// Resolver function that will be used if `xlink:href` is a DataUrl with encoded base64 string.
pub resolve_data: Box<dyn Fn(&str, Arc<Vec<u8>>, &OptionsRef) -> Option<ImageKind> + Send + Sync>,
/// Resolver function that will be used when `xlink:href` contains a
/// [Data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs).
///
/// A function would be called with mime, decoded base64 data and parsing options.
pub resolve_data: ImageHrefDataResolverFn,

/// Resolver function that will be used to handle arbitrary string in `xlink:href`.
pub resolve_string: Box<dyn Fn(&str, &OptionsRef) -> Option<ImageKind> + Send + Sync>,
/// Resolver function that will be used to handle an arbitrary string in `xlink:href`.
pub resolve_string: ImageHrefStringResolverFn,
}

impl Default for ImageHrefResolver {
fn default() -> Self {
ImageHrefResolver {
resolve_data: ImageHrefResolver::default_data_resolver(),
resolve_string: ImageHrefResolver::default_string_resolver()
}
}
}

impl ImageHrefResolver {
/// Create DataUrl resolver function that handles standard mime types for JPEG, PNG and SVG.
#[allow(clippy::type_complexity)]
pub fn default_data_resolver<'a>(
) -> Box<dyn Fn(&str, Arc<Vec<u8>>, &OptionsRef) -> Option<ImageKind> + Send + Sync + 'a> {
/// Creates a default
/// [Data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs)
/// resolver closure.
///
/// base64 encoded data is already decoded.
///
/// The default implementation would try to load JPEG, PNG, SVG and SVGZ types.
/// Note that it will simply match the `mime` or data's magic.
/// The actual images would not be decoded. It's up to the renderer.
pub fn default_data_resolver() -> ImageHrefDataResolverFn {
Box::new(
move |mime: &str, data: Arc<Vec<u8>>, opts: &OptionsRef| match mime {
"image/jpg" | "image/jpeg" => Some(ImageKind::JPEG(data)),
Expand All @@ -64,13 +89,18 @@ impl ImageHrefResolver {
_ => load_sub_svg(&data, opts),
},
_ => None,
},
}
)
}

/// Create resolver function that handles `href` string as path to local JPEG, PNG or SVG file.
pub fn default_string_resolver<'a>(
) -> Box<dyn Fn(&str, &OptionsRef) -> Option<ImageKind> + Send + Sync + 'a> {
/// Creates a default string resolver.
///
/// The default implementation treats an input string as a file path and tries to open.
/// If a string is an URL or something else it would be ignored.
///
/// Paths have to be absolute or relative to the input SVG file or relative to
/// [Options::resources_dir](crate::Options::resources_dir).
pub fn default_string_resolver() -> ImageHrefStringResolverFn {
Box::new(move |href: &str, opts: &OptionsRef| {
let path = opts.get_abs_path(std::path::Path::new(href));

Expand Down Expand Up @@ -106,15 +136,6 @@ impl std::fmt::Debug for ImageHrefResolver {
}
}

impl Default for ImageHrefResolver {
fn default() -> Self {
ImageHrefResolver {
resolve_data: ImageHrefResolver::default_data_resolver(),
resolve_string: ImageHrefResolver::default_string_resolver()
}
}
}

/// A raster image element.
///
/// `image` element in SVG.
Expand Down
9 changes: 3 additions & 6 deletions usvg/src/options.rs
Expand Up @@ -2,10 +2,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use crate::{
image::ImageHrefResolver,
ImageRendering, ShapeRendering, TextRendering, Size, ScreenSize,
};
use crate::{ImageHrefResolver, ImageRendering, ShapeRendering, TextRendering, Size, ScreenSize};

/// Image fit options.
///
Expand Down Expand Up @@ -135,9 +132,9 @@ pub struct Options {
#[cfg(feature = "text")]
pub fontdb: fontdb::Database,

/// Specifies the way to parse `<image>` elements `xlink:href` value.
/// Specifies the way `xlink:href` in `<image>` elements should be handled.
///
/// Default: either parse `href` as DataUrl, or parse it as a path to the local image file.
/// Default: see type's documentation for details
pub image_href_resolver: ImageHrefResolver,
}

Expand Down

0 comments on commit e3cd65d

Please sign in to comment.