rsvg/lib.rs
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 = "2.62.1"
24//! cairo-rs = "0.22.0"
25//! gio = "0.22.0" # only if you need streams
26//! ```
27//!
28//! # Example
29//!
30//! ```
31//! const WIDTH: i32 = 640;
32//! const HEIGHT: i32 = 480;
33//!
34//! fn main() {
35//! // Loading from a file
36//!
37//! let handle = rsvg::Loader::new().read_path("example.svg").unwrap();
38//!
39//! let surface = cairo::ImageSurface::create(cairo::Format::ARgb32, WIDTH, HEIGHT).unwrap();
40//! let cr = cairo::Context::new(&surface).expect("Failed to create a cairo context");
41//!
42//! let renderer = rsvg::CairoRenderer::new(&handle);
43//! renderer.render_document(
44//! &cr,
45//! &cairo::Rectangle::new(0.0, 0.0, f64::from(WIDTH), f64::from(HEIGHT))
46//! ).unwrap();
47//!
48//! // Loading from a static SVG asset
49//!
50//! let bytes = glib::Bytes::from_static(
51//! br#"<?xml version="1.0" encoding="UTF-8"?>
52//! <svg xmlns="http://www.w3.org/2000/svg" width="50" height="50">
53//! <rect id="foo" x="10" y="10" width="30" height="30"/>
54//! </svg>
55//! "#
56//! );
57//! let stream = gio::MemoryInputStream::from_bytes(&bytes);
58//!
59//! let handle = rsvg::Loader::new().read_stream(
60//! &stream,
61//! None::<&gio::File>, // no base file as this document has no references
62//! None::<&gio::Cancellable>, // no cancellable
63//! ).unwrap();
64//! }
65//! ```
66//!
67//! # The "base file" and resolving references to external files
68//!
69//! When you load an SVG, librsvg needs to know the location of the "base file"
70//! for it. This is so that librsvg can determine the location of referenced
71//! entities. For example, say you have an SVG in <filename>/foo/bar/foo.svg</filename>
72//! and that it has an image element like this:
73//!
74//! ```xml
75//! <image href="resources/foo.png" .../>
76//! ```
77//!
78//! In this case, librsvg needs to know the location of the toplevel
79//! `/foo/bar/foo.svg` so that it can generate the appropriate
80//! reference to `/foo/bar/resources/foo.png`.
81//!
82//! ## Security and locations of referenced files
83//!
84//! When processing an SVG, librsvg will only load referenced files if
85//! they are in the same directory as the base file, or in a
86//! subdirectory of it. That is, if the base file is
87//! `/foo/bar/baz.svg`, then librsvg will only try to load referenced
88//! files (from SVG's `<image>` element, for example, or from content
89//! included through XML entities) if those files are in `/foo/bar/*`
90//! or in `/foo/bar/*/.../*`. This is so that malicious SVG documents
91//! cannot include files that are in a directory above.
92//!
93//! The full set of rules for deciding which URLs may be loaded is as follows;
94//! they are applied in order. A referenced URL will not be loaded as soon as
95//! one of these rules fails:
96//!
97//! 1. All `data:` URLs may be loaded. These are sometimes used to
98//! include raster image data, encoded as base-64, directly in an SVG
99//! file.
100//!
101//! 2. URLs with queries ("?") or fragment identifiers ("#") are not allowed.
102//!
103//! 3. All URL schemes other than data: in references require a base URL. For
104//! example, this means that if you load an SVG with [`Loader::read_stream`]
105//! without providing a `base_file`, then any referenced files will not
106//! be allowed (e.g. raster images to be loaded from other files will
107//! not work).
108//!
109//! 4. If referenced URLs are absolute, rather than relative, then
110//! they must have the same scheme as the base URL. For example, if
111//! the base URL has a "`file`" scheme, then all URL references inside
112//! the SVG must also have the "`file`" scheme, or be relative
113//! references which will be resolved against the base URL.
114//!
115//! 5. If referenced URLs have a "`resource`" scheme, that is, if they
116//! are included into your binary program with GLib's resource
117//! mechanism, they are allowed to be loaded (provided that the base
118//! URL is also a "`resource`", per the previous rule).
119//!
120//! 6. Otherwise, non-`file` schemes are not allowed. For example,
121//! librsvg will not load `http` resources, to keep malicious SVG data
122//! from "phoning home".
123//!
124//! 7. URLs with a `file` scheme are rejected if they contain a hostname, as in
125//! `file://hostname/some/directory/foo.svg`. Windows UNC paths with a hostname are
126//! also rejected. This is to prevent documents from trying to access resources on
127//! other machines.
128//!
129//! 8. 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#![doc(html_logo_url = "https://gnome.pages.gitlab.gnome.org/librsvg/Rsvg-2.0/librsvg-r.svg")]
140#![allow(rustdoc::private_intra_doc_links)]
141#![allow(clippy::clone_on_ref_ptr)]
142#![allow(clippy::not_unsafe_ptr_arg_deref)]
143#![allow(clippy::too_many_arguments)]
144#![allow(clippy::derive_partial_eq_without_eq)]
145#![warn(nonstandard_style, rust_2018_idioms, unused)]
146// Some lints no longer exist
147#![warn(renamed_and_removed_lints)]
148// Standalone lints
149#![warn(trivial_casts, trivial_numeric_casts)]
150// The public API is exported here
151pub use crate::api::*;
152
153mod accept_language;
154mod angle;
155mod api;
156mod aspect_ratio;
157mod bbox;
158mod cairo_path;
159mod color;
160mod cond;
161mod coord_units;
162mod css;
163mod dasharray;
164mod document;
165mod dpi;
166mod drawing_ctx;
167mod element;
168mod error;
169mod filter;
170mod filter_func;
171mod filters;
172mod float_eq_cairo;
173mod font_props;
174mod gradient;
175mod href;
176mod image;
177mod io;
178mod iri;
179mod layout;
180mod length;
181mod limits;
182mod log;
183mod marker;
184mod node;
185mod paint_server;
186mod parsers;
187mod path_builder;
188mod path_parser;
189mod pattern;
190mod properties;
191mod property_defs;
192mod property_macros;
193mod rect;
194mod session;
195mod shapes;
196mod space;
197mod structure;
198mod style;
199mod surface_utils;
200mod text;
201mod text2;
202mod transform;
203mod unit_interval;
204mod url_resolver;
205mod util;
206mod viewbox;
207mod xml;
208
209#[cfg(feature = "test-utils")]
210#[doc(hidden)]
211pub mod test_utils;
212
213#[doc(hidden)]
214pub mod bench_only {
215 pub use crate::filters::lighting::Normal;
216 pub use crate::path_builder::PathBuilder;
217 pub use crate::path_parser::Lexer;
218 pub use crate::rect::IRect;
219 pub use crate::surface_utils::{
220 EdgeMode, ImageSurfaceDataExt, Pixel, PixelOps,
221 iterators::{PixelRectangle, Pixels},
222 shared_surface::{
223 AlphaOnly, ExclusiveImageSurface, Horizontal, NotAlphaOnly, SharedImageSurface,
224 SurfaceType, Vertical, composite_arithmetic,
225 },
226 srgb::{linearize, map_unpremultiplied_components_loop},
227 };
228}
229
230#[doc(hidden)]
231#[cfg(feature = "capi")]
232pub mod c_api_only {
233 pub use crate::dpi::Dpi;
234 pub use crate::rsvg_log;
235 pub use crate::session::Session;
236 pub use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
237 pub use crate::surface_utils::{Pixel, PixelOps, ToPixel};
238}
239
240#[doc(hidden)]
241pub mod doctest_only {
242 pub use crate::aspect_ratio::AspectRatio;
243 pub use crate::error::AttributeResultExt;
244 pub use crate::error::ElementError;
245 pub use crate::error::ValueErrorKind;
246 pub use crate::href::is_href;
247 pub use crate::href::set_href;
248 pub use crate::length::{Both, CssLength, Horizontal, Length, LengthUnit, ULength, Vertical};
249 pub use crate::parsers::{Parse, ParseValue};
250}
251
252#[doc(hidden)]
253pub mod rsvg_convert_only {
254 pub use crate::aspect_ratio::AspectRatio;
255 pub use crate::color::Color;
256 pub use crate::dpi::Dpi;
257 pub use crate::drawing_ctx::set_source_color_on_cairo;
258 pub use crate::error::ParseError;
259 pub use crate::length::{
260 CssLength, Horizontal, Length, Normalize, NormalizeParams, Signed, ULength, Unsigned,
261 Validate, Vertical,
262 };
263 pub use crate::parsers::{Parse, ParseValue};
264 pub use crate::rect::Rect;
265 pub use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
266 pub use crate::viewbox::ViewBox;
267}
268
269#[doc(hidden)]
270pub mod tests_only {
271 pub use crate::rect::Rect;
272 pub use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
273}