1 //! Load and render SVG images into Cairo surfaces. 2 //! 3 //! This crate can load SVG images and render them to Cairo surfaces, 4 //! using a mixture of SVG's [static mode] and [secure static mode]. 5 //! Librsvg does not do animation nor scripting, and can load 6 //! references to external data only in some situations; see below. 7 //! 8 //! Librsvg supports reading [SVG 1.1] data, and is gradually adding 9 //! support for features in [SVG 2]. Librsvg also supports SVGZ 10 //! files, which are just an SVG stream compressed with the GZIP 11 //! algorithm. 12 //! 13 //! # Basic usage 14 //! 15 //! * Create a [`Loader`] struct. 16 //! * Get an [`SvgHandle`] from the [`Loader`]. 17 //! * Create a [`CairoRenderer`] for the [`SvgHandle`] and render to a Cairo context. 18 //! 19 //! You can put the following in your `Cargo.toml`: 20 //! 21 //! ```toml 22 //! [dependencies] 23 //! librsvg = { git="https://gitlab.gnome.org/GNOME/librsvg" } 24 //! cairo-rs = "0.8.0" 25 //! glib = "0.9.0" # only if you need streams 26 //! gio = { version="0.8.1", features=["v2_50"] } # likewise 27 //! ``` 28 //! 29 //! # Example 30 //! 31 //! ``` 32 //! 33 //! const WIDTH: i32 = 640; 34 //! const HEIGHT: i32 = 480; 35 //! 36 //! fn main() { 37 //! // Loading from a file 38 //! 39 //! let handle = librsvg::Loader::new().read_path("example.svg").unwrap(); 40 //! 41 //! let surface = cairo::ImageSurface::create(cairo::Format::ARgb32, WIDTH, HEIGHT).unwrap(); 42 //! let cr = cairo::Context::new(&surface).expect("Failed to create a cairo context"); 43 //! 44 //! let renderer = librsvg::CairoRenderer::new(&handle); 45 //! renderer.render_document( 46 //! &cr, 47 //! &cairo::Rectangle { 48 //! x: 0.0, 49 //! y: 0.0, 50 //! width: f64::from(WIDTH), 51 //! height: f64::from(HEIGHT), 52 //! }, 53 //! ).unwrap(); 54 //! 55 //! // Loading from a static SVG asset 56 //! 57 //! let bytes = glib::Bytes::from_static( 58 //! br#"<?xml version="1.0" encoding="UTF-8"?> 59 //! <svg xmlns="http://www.w3.org/2000/svg" width="50" height="50"> 60 //! <rect id="foo" x="10" y="10" width="30" height="30"/> 61 //! </svg> 62 //! "# 63 //! ); 64 //! let stream = gio::MemoryInputStream::from_bytes(&bytes); 65 //! 66 //! let handle = librsvg::Loader::new().read_stream( 67 //! &stream, 68 //! None::<&gio::File>, // no base file as this document has no references 69 //! None::<&gio::Cancellable>, // no cancellable 70 //! ).unwrap(); 71 //! } 72 //! ``` 73 //! 74 //! # The "base file" and resolving references to external files 75 //! 76 //! When you load an SVG, librsvg needs to know the location of the "base file" 77 //! for it. This is so that librsvg can determine the location of referenced 78 //! entities. For example, say you have an SVG in <filename>/foo/bar/foo.svg</filename> 79 //! and that it has an image element like this: 80 //! 81 //! ```xml 82 //! <image href="resources/foo.png" .../> 83 //! ``` 84 //! 85 //! In this case, librsvg needs to know the location of the toplevel 86 //! `/foo/bar/foo.svg` so that it can generate the appropriate 87 //! reference to `/foo/bar/resources/foo.png`. 88 //! 89 //! ## Security and locations of referenced files 90 //! 91 //! When processing an SVG, librsvg will only load referenced files if 92 //! they are in the same directory as the base file, or in a 93 //! subdirectory of it. That is, if the base file is 94 //! `/foo/bar/baz.svg`, then librsvg will only try to load referenced 95 //! files (from SVG's `<image>` element, for example, or from content 96 //! included through XML entities) if those files are in `/foo/bar/*` 97 //! or in `/foo/bar/*/.../*`. This is so that malicious SVG documents 98 //! cannot include files that are in a directory above. 99 //! 100 //! The full set of rules for deciding which URLs may be loaded is as follows; 101 //! they are applied in order. A referenced URL will not be loaded as soon as 102 //! one of these rules fails: 103 //! 104 //! 1. All `data:` URLs may be loaded. These are sometimes used to 105 //! include raster image data, encoded as base-64, directly in an SVG 106 //! file. 107 //! 108 //! 2. All other URL schemes in references require a base URL. For 109 //! example, this means that if you load an SVG with [`Loader::read_stream`] 110 //! without providing a `base_file`, then any referenced files will not 111 //! be allowed (e.g. raster images to be loaded from other files will 112 //! not work). 113 //! 114 //! 3. If referenced URLs are absolute, rather than relative, then 115 //! they must have the same scheme as the base URL. For example, if 116 //! the base URL has a "`file`" scheme, then all URL references inside 117 //! the SVG must also have the "`file`" scheme, or be relative 118 //! references which will be resolved against the base URL. 119 //! 120 //! 4. If referenced URLs have a "`resource`" scheme, that is, if they 121 //! are included into your binary program with GLib's resource 122 //! mechanism, they are allowed to be loaded (provided that the base 123 //! URL is also a "`resource`", per the previous rule). 124 //! 125 //! 5. Otherwise, non-`file` schemes are not allowed. For example, 126 //! librsvg will not load `http` resources, to keep malicious SVG data 127 //! from "phoning home". 128 //! 129 //! 6. A relative URL must resolve to the same directory as the base 130 //! URL, or to one of its subdirectories. Librsvg will canonicalize 131 //! filenames, by removing "`..`" path components and resolving symbolic 132 //! links, to decide whether files meet these conditions. 133 //! 134 //! [static mode]: https://www.w3.org/TR/SVG2/conform.html#static-mode 135 //! [secure static mode]: https://www.w3.org/TR/SVG2/conform.html#secure-static-mode 136 //! [SVG 1.1]: https://www.w3.org/TR/SVG11/ 137 //! [SVG 2]: https://www.w3.org/TR/SVG2/ 138 139 #![allow(rustdoc::private_intra_doc_links)] 140 #![allow(clippy::clone_on_ref_ptr)] 141 #![allow(clippy::not_unsafe_ptr_arg_deref)] 142 #![allow(clippy::too_many_arguments)] 143 #![warn(nonstandard_style, rust_2018_idioms, unused)] 144 // Some lints no longer exist 145 #![warn(renamed_and_removed_lints)] 146 // Standalone lints 147 #![warn(trivial_casts, trivial_numeric_casts)] 148 // The public API is exported here 149 pub use crate::api::*; 150 151 pub use crate::color::Color; 152 153 pub use crate::parsers::Parse; 154 155 pub use crate::rect::{IRect, Rect}; 156 157 #[macro_use] 158 pub mod log; 159 160 #[macro_use] 161 mod parsers; 162 163 #[macro_use] 164 mod coord_units; 165 166 #[macro_use] 167 mod float_eq_cairo; 168 169 #[macro_use] 170 mod node; 171 172 #[macro_use] 173 mod property_macros; 174 175 #[macro_use] 176 mod util; 177 178 mod accept_language; 179 mod angle; 180 mod api; 181 mod aspect_ratio; 182 mod bbox; 183 pub mod c_api; 184 mod color; 185 mod cond; 186 mod css; 187 mod dasharray; 188 mod document; 189 mod dpi; 190 mod drawing_ctx; 191 mod element; 192 mod error; 193 mod filter; 194 mod filter_func; 195 pub mod filters; 196 mod font_props; 197 mod gradient; 198 mod handle; 199 mod href; 200 mod image; 201 mod io; 202 mod iri; 203 mod layout; 204 mod length; 205 mod limits; 206 mod marker; 207 mod paint_server; 208 mod path_builder; 209 mod path_parser; 210 mod pattern; 211 mod properties; 212 mod property_defs; 213 mod rect; 214 mod shapes; 215 mod space; 216 mod structure; 217 mod style; 218 pub mod surface_utils; 219 mod text; 220 mod transform; 221 mod unit_interval; 222 mod url_resolver; 223 mod viewbox; 224 mod xml; 225 226 #[doc(hidden)] 227 pub mod bench_only { 228 pub use crate::path_builder::PathBuilder; 229 pub use crate::path_parser::Lexer; 230 } 231 232 #[doc(hidden)] 233 pub mod doctest_only { 234 pub use crate::aspect_ratio::AspectRatio; 235 pub use crate::error::AttributeResultExt; 236 pub use crate::error::ElementError; 237 pub use crate::error::ValueErrorKind; 238 pub use crate::href::is_href; 239 pub use crate::href::set_href; 240 pub use crate::length::{Both, CssLength, Horizontal, Length, LengthUnit, ULength, Vertical}; 241 pub use crate::parsers::{Parse, ParseValue}; 242 } 243 244 #[doc(hidden)] 245 pub mod rsvg_convert_only { 246 pub use crate::c_api::handle::PathOrUrl; 247 pub use crate::c_api::sizing::LegacySize; 248 pub use crate::dpi::Dpi; 249 pub use crate::error::ParseError; 250 pub use crate::length::{ 251 CssLength, Horizontal, Length, Normalize, NormalizeParams, ULength, Validate, Vertical, 252 }; 253 } 254