use matches::matches;
use rsvg::{CairoRenderer, Loader, LoadingError, SvgHandle};
use rsvg::test_utils::reference_utils::{Compare, Evaluate, Reference};
use rsvg::test_utils::{load_svg, render_document, setup_font_map, setup_language, SurfaceSize};
// https://gitlab.gnome.org/GNOME/librsvg/issues/335
#[test]
fn non_svg_root() {
assert!(matches!(load_svg(b""), Err(LoadingError::NoSvgRoot)));
}
// https://gitlab.gnome.org/GNOME/librsvg/issues/496
#[test]
fn inf_width() {
let svg = load_svg(
br#"
"#,
).unwrap();
let _output_surf = render_document(
&svg,
SurfaceSize(150, 150),
|cr| cr.translate(50.0, 50.0),
cairo::Rectangle::new(0.0, 0.0, 50.0, 50.0),
)
.unwrap();
}
// https://gitlab.gnome.org/GNOME/librsvg/issues/547
#[test]
fn nonexistent_image_shouldnt_cancel_rendering() {
let svg = load_svg(
br#"
"#,
)
.unwrap();
let output_surf = render_document(
&svg,
SurfaceSize(50, 50),
|_| (),
cairo::Rectangle::new(0.0, 0.0, 50.0, 50.0),
)
.unwrap();
let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 50, 50).unwrap();
{
let cr = cairo::Context::new(&reference_surf).unwrap();
cr.rectangle(10.0, 10.0, 30.0, 30.0);
cr.set_source_rgba(0.0, 0.0, 1.0, 1.0);
cr.fill().unwrap();
}
Reference::from_surface(reference_surf)
.compare(&output_surf)
.evaluate(&output_surf, "nonexistent_image_shouldnt_cancel_rendering");
}
// https://gitlab.gnome.org/GNOME/librsvg/-/issues/568
#[test]
fn href_attribute_overrides_xlink_href() {
let svg = load_svg(
br##"
"##,
)
.unwrap();
let output_surf = render_document(
&svg,
SurfaceSize(500, 500),
|_| (),
cairo::Rectangle::new(0.0, 0.0, 500.0, 500.0),
)
.unwrap();
let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 500, 500).unwrap();
{
let cr = cairo::Context::new(&reference_surf).unwrap();
cr.rectangle(100.0, 100.0, 100.0, 100.0);
cr.set_source_rgba(0.0, 1.0, 0.0, 1.0);
cr.fill().unwrap();
}
Reference::from_surface(reference_surf)
.compare(&output_surf)
.evaluate(&output_surf, "href_attribute_overrides_xlink_href");
}
// https://gitlab.gnome.org/GNOME/librsvg/-/issues/560
#[test]
fn nonexistent_filter_leaves_object_unfiltered() {
let svg = load_svg(
br##"
"##,
)
.unwrap();
let output_surf = render_document(
&svg,
SurfaceSize(500, 500),
|_| (),
cairo::Rectangle::new(0.0, 0.0, 500.0, 500.0),
)
.unwrap();
let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 500, 500).unwrap();
{
let cr = cairo::Context::new(&reference_surf).unwrap();
cr.rectangle(100.0, 100.0, 100.0, 100.0);
cr.set_source_rgba(0.0, 1.0, 0.0, 1.0);
cr.fill().unwrap();
}
Reference::from_surface(reference_surf)
.compare(&output_surf)
.evaluate(&output_surf, "nonexistent_filter_leaves_object_unfiltered");
}
// https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint says this:
//
// A allows a paint server reference, to be optionally
// followed by a or the keyword none. When this optional value
// is given, the value or the value none is a fallback value
// to use if the paint server reference in the layer is invalid (due
// to pointing to an element that does not exist or which is not a
// valid paint server).
//
// I'm interpreting this to mean that if we have
// fill="url(#recursive_paint_server) fallback_color", then the
// recursive paint server is not valid, and should fall back to to the
// specified color.
#[test]
fn recursive_paint_servers_fallback_to_color() {
let svg = load_svg(
br##"
"##,
)
.unwrap();
let output_surf = render_document(
&svg,
SurfaceSize(200, 200),
|_| (),
cairo::Rectangle::new(0.0, 0.0, 200.0, 200.0),
)
.unwrap();
let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 200, 200).unwrap();
{
let cr = cairo::Context::new(&reference_surf).unwrap();
cr.rectangle(0.0, 100.0, 200.0, 100.0);
cr.set_source_rgba(0.0, 1.0, 0.0, 1.0);
cr.fill().unwrap();
}
Reference::from_surface(reference_surf)
.compare(&output_surf)
.evaluate(&output_surf, "recursive_paint_servers_fallback_to_color");
}
fn test_renders_as_empty(svg: &SvgHandle, test_name: &str) {
let output_surf = render_document(
svg,
SurfaceSize(100, 100),
|_| (),
cairo::Rectangle::new(0.0, 0.0, 100.0, 100.0),
)
.unwrap();
let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 100, 100).unwrap();
Reference::from_surface(reference_surf)
.compare(&output_surf)
.evaluate(&output_surf, test_name);
}
// https://gitlab.gnome.org/GNOME/librsvg/-/issues/308
#[test]
fn recursive_use() {
let svg = load_svg(
br##"
"##,
)
.unwrap();
test_renders_as_empty(&svg, "308-recursive-use");
}
// https://gitlab.gnome.org/GNOME/librsvg/-/issues/308
#[test]
fn use_self_ref() {
let svg = load_svg(
br##"
"##,
)
.unwrap();
test_renders_as_empty(&svg, "308-use-self-ref");
}
// https://gitlab.gnome.org/GNOME/librsvg/-/issues/308
#[test]
fn doubly_recursive_use() {
let svg = load_svg(
br##"
"##,
)
.unwrap();
test_renders_as_empty(&svg, "308-doubly-recursive-use");
}
// https://gitlab.gnome.org/GNOME/librsvg/-/issues/347
#[test]
fn test_text_bounds() {
setup_font_map();
let handle = Loader::new()
.read_path("tests/fixtures/dimensions/bug347-wrapper.svg")
.unwrap_or_else(|e| panic!("could not load: {}", e));
let renderer = CairoRenderer::new(&handle).test_mode(true);
let (ink_r, _) = renderer
.geometry_for_layer(
Some("#LabelA"),
&cairo::Rectangle::new(0.0, 0.0, 248.0, 176.0),
)
.unwrap();
assert!(ink_r.x() >= 80.0 && ink_r.x() < 80.1);
// This is kind of suspicious, but we don't know the actual height of the
// text set at y=49 in the test SVG. However, this test is more "text
// elements compute sensible bounds"; the bug #347 was that their ink_rect
// was not being computed correctly at all.
assert!(ink_r.y() > 48.0 && ink_r.y() < 49.0);
}
// https://gitlab.gnome.org/GNOME/librsvg/-/issues/703
#[test]
fn switch_element_should_ignore_elements_in_error() {
setup_language();
let svg = load_svg(
br##"
"##,
)
.unwrap();
let output_surf = render_document(
&svg,
SurfaceSize(100, 100),
|_| (),
cairo::Rectangle::new(0.0, 0.0, 100.0, 100.0),
)
.unwrap();
let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 100, 100).unwrap();
{
let cr = cairo::Context::new(&reference_surf).unwrap();
cr.rectangle(10.0, 10.0, 10.0, 10.0);
cr.set_source_rgba(0.0, 0.0, 1.0, 1.0);
cr.fill().unwrap();
}
Reference::from_surface(reference_surf)
.compare(&output_surf)
.evaluate(
&output_surf,
"switch_element_should_ignore_elements_in_error",
);
}
// https://gitlab.gnome.org/GNOME/librsvg/-/issues/566
#[test]
fn accepted_children_inside_clip_path() {
let svg = load_svg(
br##"
"##,
)
.unwrap();
let output_surf = render_document(
&svg,
SurfaceSize(200, 200),
|_| (),
cairo::Rectangle::new(0.0, 0.0, 200.0, 200.0),
)
.unwrap();
let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 200, 200).unwrap();
{
let cr = cairo::Context::new(&reference_surf).unwrap();
cr.rectangle(10.0, 10.0, 100.0, 100.0);
cr.set_source_rgba(0.0, 1.0, 0.0, 1.0);
cr.fill().unwrap();
}
Reference::from_surface(reference_surf)
.compare(&output_surf)
.evaluate(&output_surf, "accepted_children_inside_clip_path");
}
#[test]
fn can_draw_to_non_image_surface() {
// This tries to exercise the various tricky code paths in DrawingCtx::with_discrete_layer()
// that depend on whether there are filter/masks/opacity - they are easy to break when
// the application is using something other than a cairo::ImageSurface.
let svg = load_svg(
br##"
"##,
)
.unwrap();
let renderer = CairoRenderer::new(&svg);
let viewport = cairo::Rectangle::new(0.0, 0.0, 200.0, 200.0);
let output =
cairo::RecordingSurface::create(cairo::Content::ColorAlpha, Some(viewport)).unwrap();
let cr = cairo::Context::new(&output).expect("Failed to create a cairo context");
renderer
.render_document(&cr, &viewport)
.expect("Failed to render to non-image surface");
}