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