Files
vectorcraft/crates/render/tests/envelope_ink.rs
T
dotCooCoo b1a35f8428 Tests: envelope ink tests set type in a test face and check its outlines
The three envelope ink tests set "Type" in the default family and
unwrapped ink_bounds(). Without bundled fonts, craft-fonts or system
fonts (vectorcraft-effects' tests on a bare Linux host), no face draws
and the effects test panicked at the unwrap.

Each test now adds the Heighttest Sans face built from the bundled
Source Sans 3 (test-fonts feature, now also on vectorcraft-effects'
dev-dependency), sets the text in it, and computes the expected box
from the layout's glyph outlines. It checks that envelope_ink gives
that box as well as the before and after registration boxes, so a
change to the registered measure fails the test.
2026-11-12 16:23:10 -08:00

49 lines
2.7 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 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<Rect> = 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:?}");
}