//! A renderer made without an engine session makes envelopes measure type by its glyph outlines. //! One test in its own process, so nothing else has registered the measure before the renderer is //! made. // Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). #![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use std::sync::Arc; use vectorcraft_doc::{CharStyle, Node, NodeId, NodeKind, TextObject}; use vectorcraft_geom::{Point, Rect, Shape}; use vectorcraft_text::test_fonts::{HEIGHT_FAMILY, height_font}; /// The largest distance between the edges of `a` and `b`. fn off(a: Rect, b: Rect) -> f64 { [a.x0 - b.x0, a.y0 - b.y0, a.x1 - b.x1, a.y1 - b.y1].iter().fold(0.0f64, |m, v| m.max(v.abs())) } /// "Type" at 48 pt in a face the test adds, so its glyphs draw on a machine without craft-fonts or /// system fonts. fn type_in_test_face() -> TextObject { assert!(vectorcraft_text::FontDb::global().add_font(height_font(true).unwrap()) > 0, "the test face loads"); TextObject::point(Point::new(10.0, 60.0), "Type", CharStyle { font_family: HEIGHT_FAMILY.into(), size: 48.0, ..Default::default() }) } /// The box of the outlines `t`'s glyphs draw, in document space, measured glyph by glyph. fn outline_box(t: &TextObject) -> Rect { let laid = vectorcraft_text::layout(vectorcraft_text::FontDb::global(), t); let outlines: Vec = laid.glyphs.iter().filter(|g| !g.outline.elements().is_empty()).map(|g| (t.xf * &g.outline).bounding_box()).collect(); assert_eq!(outlines.len(), 4, "every glyph of \"Type\" draws an outline"); outlines.into_iter().reduce(|a, b| a.union(b)).unwrap() } #[test] fn a_new_renderer_measures_type_in_envelopes_by_its_glyphs() { let t = type_in_test_face(); let n = Arc::new(Node::new(NodeId(1), NodeKind::Text(Box::new(t.clone())))); let laid = n.geometric_bounds().unwrap(); let ink = outline_box(&t); assert!(laid.height() - ink.height() > 1.0, "the laid-out box {laid:?} reaches past the glyphs {ink:?}"); let measured = vectorcraft_text::envelope_ink(&t, t.xf, None).unwrap(); assert!(off(measured, ink) < 1e-6, "the envelope measure gives the glyphs' box: {measured:?} vs {ink:?}"); let before = vectorcraft_doc::live::envelope_content_bounds(std::slice::from_ref(&n)).unwrap(); assert!(off(before, laid) < 1e-6, "with nothing registered, type keeps its laid-out box: {before:?} vs {laid:?}"); let _ = vectorcraft_render::Renderer::new(); let after = vectorcraft_doc::live::envelope_content_bounds(&[n]).unwrap(); assert!(off(after, ink) < 1e-6, "after a renderer is made, type is measured by its glyphs: {after:?} vs {ink:?}"); }