1
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.59.0-beta.1"
24
//! cairo-rs = "0.19"
25
//! gio = "0.19"   # 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
146
pub use crate::api::*;
147

            
148
mod accept_language;
149
mod angle;
150
mod api;
151
mod aspect_ratio;
152
mod bbox;
153
mod color;
154
mod cond;
155
mod coord_units;
156
mod css;
157
mod dasharray;
158
mod document;
159
mod dpi;
160
mod drawing_ctx;
161
mod element;
162
mod error;
163
mod filter;
164
mod filter_func;
165
mod filters;
166
mod float_eq_cairo;
167
mod font_props;
168
mod gradient;
169
mod href;
170
mod image;
171
mod io;
172
mod iri;
173
mod layout;
174
mod length;
175
mod limits;
176
mod log;
177
mod marker;
178
mod node;
179
mod paint_server;
180
mod parsers;
181
mod path_builder;
182
mod path_parser;
183
mod pattern;
184
mod properties;
185
mod property_defs;
186
mod property_macros;
187
mod rect;
188
mod session;
189
mod shapes;
190
mod space;
191
mod structure;
192
mod style;
193
mod surface_utils;
194
mod text;
195
mod transform;
196
mod unit_interval;
197
mod url_resolver;
198
mod util;
199
mod viewbox;
200
mod xml;
201

            
202
#[cfg(feature = "test-utils")]
203
#[doc(hidden)]
204
pub mod test_utils;
205

            
206
#[doc(hidden)]
207
pub mod bench_only {
208
    pub use crate::filters::lighting::Normal;
209
    pub use crate::path_builder::PathBuilder;
210
    pub use crate::path_parser::Lexer;
211
    pub use crate::rect::IRect;
212
    pub use crate::surface_utils::{
213
        iterators::{PixelRectangle, Pixels},
214
        shared_surface::{
215
            composite_arithmetic, AlphaOnly, ExclusiveImageSurface, Horizontal, NotAlphaOnly,
216
            SharedImageSurface, SurfaceType, Vertical,
217
        },
218
        srgb::{linearize, map_unpremultiplied_components_loop},
219
        EdgeMode, ImageSurfaceDataExt, Pixel, PixelOps,
220
    };
221
}
222

            
223
#[doc(hidden)]
224
#[cfg(feature = "capi")]
225
pub mod c_api_only {
226
    pub use crate::dpi::Dpi;
227
    pub use crate::rsvg_log;
228
    pub use crate::session::Session;
229
    pub use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
230
    pub use crate::surface_utils::{Pixel, PixelOps, ToPixel};
231
}
232

            
233
#[doc(hidden)]
234
pub mod doctest_only {
235
    pub use crate::aspect_ratio::AspectRatio;
236
    pub use crate::error::AttributeResultExt;
237
    pub use crate::error::ElementError;
238
    pub use crate::error::ValueErrorKind;
239
    pub use crate::href::is_href;
240
    pub use crate::href::set_href;
241
    pub use crate::length::{Both, CssLength, Horizontal, Length, LengthUnit, ULength, Vertical};
242
    pub use crate::parsers::{Parse, ParseValue};
243
}
244

            
245
#[doc(hidden)]
246
pub mod rsvg_convert_only {
247
    pub use crate::aspect_ratio::AspectRatio;
248
    pub use crate::dpi::Dpi;
249
    pub use crate::drawing_ctx::set_source_color_on_cairo;
250
    pub use crate::error::ParseError;
251
    pub use crate::length::{
252
        CssLength, Horizontal, Length, Normalize, NormalizeParams, Signed, ULength, Unsigned,
253
        Validate, Vertical,
254
    };
255
    pub use crate::parsers::{Parse, ParseValue};
256
    pub use crate::rect::Rect;
257
    pub use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
258
    pub use crate::viewbox::ViewBox;
259
}
260

            
261
#[doc(hidden)]
262
pub mod tests_only {
263
    pub use crate::rect::Rect;
264
    pub use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
265
}