//! fig2dev's scene builder (`fig2dev::scene::build`, from the //! objects fig2dev's reader returns) draws every object as RustFig's own //! builder does (`build_scene`, from the document the same objects //! become): the same primitives, up to the order of objects at one depth //! (fig2dev's `compound_dump` order against xfig's). #![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use fig2dev::scene::build::TextOptions; use fig2dev::Ctx; use rustfig_engine::render::{build_scene, Scene, SceneOptions}; use std::path::Path; fn sorted(scene: &Scene) -> Vec { let mut v: Vec = scene.prims.iter().map(|p| format!("{p:?}")).collect(); v.sort(); v } fn check(name: &str, src: &[u8]) { let mut ctx = Ctx::default(); let objects = fig2dev::read::readfp_fig(&mut ctx, src).unwrap(); let doc = rustfig_format::bridge::to_model::to_document(&ctx, &objects); let ours = build_scene(&doc, &SceneOptions::default()); let (theirs, _) = fig2dev::scene::build(&mut ctx, &objects, TextOptions::default()); assert_eq!(ours.prims.len(), theirs.prims.len(), "{name}"); let (a, b) = (sorted(&ours), sorted(&theirs)); for (x, y) in a.iter().zip(&b) { assert_eq!(x, y, "{name}"); } } #[test] fn fig2devs_builder_draws_as_rustfigs() { let dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures"); let mut n = 0; for e in std::fs::read_dir(&dir).unwrap() { let p = e.unwrap().path(); if p.extension().is_some_and(|x| x == "fig") { check(&p.display().to_string(), &std::fs::read(&p).unwrap()); n += 1; } } assert!(n >= 10, "{n} fixtures"); // Old formats: Fig 2.1 at 80 ppi with arrows and an old spline, and a // Fig 1.3 spline. check( "fig 2.1", b"#FIG 2.1\n80 2\n\ 2 2 0 1 -1 0 0 0 0.000 7 0 0\n\t 10 10 90 10 90 50 10 50 10 10 9999 9999\n\ 2 1 1 2 4 0 0 0 4.000 -1 1 0\n\t0 0 1.000 4.000 8.000\n\t 10 70 50 70 9999 9999\n\ 3 0 0 1 -1 0 0 0 0.000 0 0\n\t 10 100 50 120 90 100 9999 9999\n\ 4 0 -1 0 0 0 12 0.00000 4 9 30 10 150 Hello\x01\n", ); check("fig 1.3", b"1200 2 9 9\n3 10 0 1 1 0 0 0 0 0 0\n100 100 200 0 9999 0\n"); } .