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.60.0"
24//! cairo-rs = "0.20"
25//! gio = "0.20"   # 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. A relative URL must resolve to the same directory as the base
125//!    URL, or to one of its subdirectories.  Librsvg will canonicalize
126//!    filenames, by removing "`..`" path components and resolving symbolic
127//!    links, to decide whether files meet these conditions.
128//!
129//! [static mode]: https://www.w3.org/TR/SVG2/conform.html#static-mode
130//! [secure static mode]: https://www.w3.org/TR/SVG2/conform.html#secure-static-mode
131//! [SVG 1.1]: https://www.w3.org/TR/SVG11/
132//! [SVG 2]: https://www.w3.org/TR/SVG2/
133
134#![doc(html_logo_url = "https://gnome.pages.gitlab.gnome.org/librsvg/Rsvg-2.0/librsvg-r.svg")]
135#![allow(rustdoc::private_intra_doc_links)]
136#![allow(clippy::clone_on_ref_ptr)]
137#![allow(clippy::not_unsafe_ptr_arg_deref)]
138#![allow(clippy::too_many_arguments)]
139#![allow(clippy::derive_partial_eq_without_eq)]
140#![warn(nonstandard_style, rust_2018_idioms, unused)]
141// Some lints no longer exist
142#![warn(renamed_and_removed_lints)]
143// Standalone lints
144#![warn(trivial_casts, trivial_numeric_casts)]
145// The public API is exported here
146pub use crate::api::*;
147
148mod accept_language;
149mod angle;
150mod api;
151mod aspect_ratio;
152mod bbox;
153mod cairo_path;
154mod color;
155mod cond;
156mod coord_units;
157mod css;
158mod dasharray;
159mod document;
160mod dpi;
161mod drawing_ctx;
162mod element;
163mod error;
164mod filter;
165mod filter_func;
166mod filters;
167mod float_eq_cairo;
168mod font_props;
169mod gradient;
170mod href;
171mod image;
172mod io;
173mod iri;
174mod layout;
175mod length;
176mod limits;
177mod log;
178mod marker;
179mod node;
180mod paint_server;
181mod parsers;
182mod path_builder;
183mod path_parser;
184mod pattern;
185mod properties;
186mod property_defs;
187mod property_macros;
188mod rect;
189mod session;
190mod shapes;
191mod space;
192mod structure;
193mod style;
194mod surface_utils;
195mod text;
196mod text2;
197mod transform;
198mod unit_interval;
199mod url_resolver;
200mod util;
201mod viewbox;
202mod xml;
203
204#[cfg(feature = "test-utils")]
205#[doc(hidden)]
206pub mod test_utils;
207
208#[doc(hidden)]
209pub mod bench_only {
210    pub use crate::filters::lighting::Normal;
211    pub use crate::path_builder::PathBuilder;
212    pub use crate::path_parser::Lexer;
213    pub use crate::rect::IRect;
214    pub use crate::surface_utils::{
215        iterators::{PixelRectangle, Pixels},
216        shared_surface::{
217            composite_arithmetic, AlphaOnly, ExclusiveImageSurface, Horizontal, NotAlphaOnly,
218            SharedImageSurface, SurfaceType, Vertical,
219        },
220        srgb::{linearize, map_unpremultiplied_components_loop},
221        EdgeMode, ImageSurfaceDataExt, Pixel, PixelOps,
222    };
223}
224
225#[doc(hidden)]
226#[cfg(feature = "capi")]
227pub mod c_api_only {
228    pub use crate::dpi::Dpi;
229    pub use crate::rsvg_log;
230    pub use crate::session::Session;
231    pub use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
232    pub use crate::surface_utils::{Pixel, PixelOps, ToPixel};
233}
234
235#[doc(hidden)]
236pub mod doctest_only {
237    pub use crate::aspect_ratio::AspectRatio;
238    pub use crate::error::AttributeResultExt;
239    pub use crate::error::ElementError;
240    pub use crate::error::ValueErrorKind;
241    pub use crate::href::is_href;
242    pub use crate::href::set_href;
243    pub use crate::length::{Both, CssLength, Horizontal, Length, LengthUnit, ULength, Vertical};
244    pub use crate::parsers::{Parse, ParseValue};
245}
246
247#[doc(hidden)]
248pub mod rsvg_convert_only {
249    pub use crate::aspect_ratio::AspectRatio;
250    pub use crate::dpi::Dpi;
251    pub use crate::drawing_ctx::set_source_color_on_cairo;
252    pub use crate::error::ParseError;
253    pub use crate::length::{
254        CssLength, Horizontal, Length, Normalize, NormalizeParams, Signed, ULength, Unsigned,
255        Validate, Vertical,
256    };
257    pub use crate::parsers::{Parse, ParseValue};
258    pub use crate::rect::Rect;
259    pub use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
260    pub use crate::viewbox::ViewBox;
261}
262
263#[doc(hidden)]
264pub mod tests_only {
265    pub use crate::rect::Rect;
266    pub use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
267}