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};
}