| 1 | // Copyright 2017 the Resvg Authors |
| 2 | // SPDX-License-Identifier: Apache-2.0 OR MIT |
| 3 | |
| 4 | /*! |
| 5 | [resvg](https://github.com/linebender/resvg) is an SVG rendering library. |
| 6 | */ |
| 7 | |
| 8 | #![forbid (unsafe_code)] |
| 9 | #![warn (missing_docs)] |
| 10 | #![allow (clippy::field_reassign_with_default)] |
| 11 | #![allow (clippy::identity_op)] |
| 12 | #![allow (clippy::too_many_arguments)] |
| 13 | #![allow (clippy::uninlined_format_args)] |
| 14 | #![allow (clippy::upper_case_acronyms)] |
| 15 | #![allow (clippy::wrong_self_convention)] |
| 16 | |
| 17 | pub use tiny_skia; |
| 18 | pub use usvg; |
| 19 | |
| 20 | mod clip; |
| 21 | mod filter; |
| 22 | mod geom; |
| 23 | mod image; |
| 24 | mod mask; |
| 25 | mod path; |
| 26 | mod render; |
| 27 | |
| 28 | /// Renders a tree onto the pixmap. |
| 29 | /// |
| 30 | /// `transform` will be used as a root transform. |
| 31 | /// Can be used to position SVG inside the `pixmap`. |
| 32 | /// |
| 33 | /// The produced content is in the sRGB color space. |
| 34 | pub fn render( |
| 35 | tree: &usvg::Tree, |
| 36 | transform: tiny_skia::Transform, |
| 37 | pixmap: &mut tiny_skia::PixmapMut, |
| 38 | ) { |
| 39 | let target_size: IntSize = tiny_skia::IntSize::from_wh(pixmap.width(), pixmap.height()).unwrap(); |
| 40 | let max_bbox: IntRect = tiny_skiaOption::IntRect::from_xywh( |
| 41 | -(target_size.width() as i32) * 2, |
| 42 | -(target_size.height() as i32) * 2, |
| 43 | width:target_size.width() * 5, |
| 44 | height:target_size.height() * 5, |
| 45 | ) |
| 46 | .unwrap(); |
| 47 | |
| 48 | let ctx: Context = render::Context { max_bbox }; |
| 49 | render::render_nodes(parent:tree.root(), &ctx, transform, pixmap); |
| 50 | } |
| 51 | |
| 52 | /// Renders a node onto the pixmap. |
| 53 | /// |
| 54 | /// `transform` will be used as a root transform. |
| 55 | /// Can be used to position SVG inside the `pixmap`. |
| 56 | /// |
| 57 | /// The expected pixmap size can be retrieved from `usvg::Node::abs_layer_bounding_box()`. |
| 58 | /// |
| 59 | /// Returns `None` when `node` has a zero size. |
| 60 | /// |
| 61 | /// The produced content is in the sRGB color space. |
| 62 | pub fn render_node( |
| 63 | node: &usvg::Node, |
| 64 | mut transform: tiny_skia::Transform, |
| 65 | pixmap: &mut tiny_skia::PixmapMut, |
| 66 | ) -> Option<()> { |
| 67 | let bbox: NonZeroRect = node.abs_layer_bounding_box()?; |
| 68 | |
| 69 | let target_size: IntSize = tiny_skia::IntSize::from_wh(pixmap.width(), pixmap.height()).unwrap(); |
| 70 | let max_bbox: IntRect = tiny_skiaOption::IntRect::from_xywh( |
| 71 | -(target_size.width() as i32) * 2, |
| 72 | -(target_size.height() as i32) * 2, |
| 73 | width:target_size.width() * 5, |
| 74 | height:target_size.height() * 5, |
| 75 | ) |
| 76 | .unwrap(); |
| 77 | |
| 78 | transform = transform.pre_translate(-bbox.x(), -bbox.y()); |
| 79 | |
| 80 | let ctx: Context = render::Context { max_bbox }; |
| 81 | render::render_node(node, &ctx, transform, pixmap); |
| 82 | |
| 83 | Some(()) |
| 84 | } |
| 85 | |
| 86 | pub(crate) trait OptionLog { |
| 87 | fn log_none<F: FnOnce()>(self, f: F) -> Self; |
| 88 | } |
| 89 | |
| 90 | impl<T> OptionLog for Option<T> { |
| 91 | #[inline ] |
| 92 | fn log_none<F: FnOnce()>(self, f: F) -> Self { |
| 93 | self.or_else(|| { |
| 94 | f(); |
| 95 | None |
| 96 | }) |
| 97 | } |
| 98 | } |
| 99 | |