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

#![doc(html_logo_url = "https://gnome.pages.gitlab.gnome.org/librsvg/Rsvg-2.0/librsvg-r.svg")]
#![allow(rustdoc::private_intra_doc_links)]
#![allow(clippy::clone_on_ref_ptr)]
#![allow(clippy::not_unsafe_ptr_arg_deref)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::derive_partial_eq_without_eq)]
#![warn(nonstandard_style, rust_2018_idioms, unused)]
// Some lints no longer exist
#![warn(renamed_and_removed_lints)]
// Standalone lints
#![warn(trivial_casts, trivial_numeric_casts)]
// The public API is exported here
pub use crate::api::*;

mod accept_language;
mod angle;
mod api;
mod aspect_ratio;
mod bbox;
mod cairo_path;
mod color;
mod cond;
mod coord_units;
mod css;
mod dasharray;
mod document;
mod dpi;
mod drawing_ctx;
mod element;
mod error;
mod filter;
mod filter_func;
mod filters;
mod float_eq_cairo;
mod font_props;
mod gradient;
mod href;
mod image;
mod io;
mod iri;
mod layout;
mod length;
mod limits;
mod log;
mod marker;
mod node;
mod paint_server;
mod parsers;
mod path_builder;
mod path_parser;
mod pattern;
mod properties;
mod property_defs;
mod property_macros;
mod rect;
mod session;
mod shapes;
mod space;
mod structure;
mod style;
mod surface_utils;
mod text;
mod transform;
mod unit_interval;
mod url_resolver;
mod util;
mod viewbox;
mod xml;

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

#[doc(hidden)]
pub mod bench_only {
    pub use crate::filters::lighting::Normal;
    pub use crate::path_builder::PathBuilder;
    pub use crate::path_parser::Lexer;
    pub use crate::rect::IRect;
    pub use crate::surface_utils::{
        iterators::{PixelRectangle, Pixels},
        shared_surface::{
            composite_arithmetic, AlphaOnly, ExclusiveImageSurface, Horizontal, NotAlphaOnly,
            SharedImageSurface, SurfaceType, Vertical,
        },
        srgb::{linearize, map_unpremultiplied_components_loop},
        EdgeMode, ImageSurfaceDataExt, Pixel, PixelOps,
    };
}

#[doc(hidden)]
#[cfg(feature = "capi")]
pub mod c_api_only {
    pub use crate::dpi::Dpi;
    pub use crate::rsvg_log;
    pub use crate::session::Session;
    pub use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
    pub use crate::surface_utils::{Pixel, PixelOps, ToPixel};
}

#[doc(hidden)]
pub mod doctest_only {
    pub use crate::aspect_ratio::AspectRatio;
    pub use crate::error::AttributeResultExt;
    pub use crate::error::ElementError;
    pub use crate::error::ValueErrorKind;
    pub use crate::href::is_href;
    pub use crate::href::set_href;
    pub use crate::length::{Both, CssLength, Horizontal, Length, LengthUnit, ULength, Vertical};
    pub use crate::parsers::{Parse, ParseValue};
}

#[doc(hidden)]
pub mod rsvg_convert_only {
    pub use crate::aspect_ratio::AspectRatio;
    pub use crate::dpi::Dpi;
    pub use crate::drawing_ctx::set_source_color_on_cairo;
    pub use crate::error::ParseError;
    pub use crate::length::{
        CssLength, Horizontal, Length, Normalize, NormalizeParams, Signed, ULength, Unsigned,
        Validate, Vertical,
    };
    pub use crate::parsers::{Parse, ParseValue};
    pub use crate::rect::Rect;
    pub use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
    pub use crate::viewbox::ViewBox;
}

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