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#" [l> "#, ).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"); }