mirror of
https://github.com/storytold/wordcraft.git
synced 2026-11-10 20:51:50 +00:00
Layout tests: initialize the fixed fonts centrally in the layout entry points
layout, layout_para and layout_equation call crate::test_fonts() first in test builds, so no test can reach font lookup through them before the pinned fonts are installed. Tests and helpers that look up fonts directly (word::resolve, FontDb::global, the nbsp fixture) call it themselves. Fixes init_test_fonts() returning false when an uninitialised test ran first in a shared process. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f5038a12e3
commit
7e967d4a3a
8 files changed
+21
-2
No files matched your search
@@ -8,8 +8,12 @@
|
||||
//! - [`hit`]: point ↔ position, caret geometry, line navigation, selection rectangles.
|
||||
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
|
||||
|
||||
/// Every unit test calls this before any font lookup (including its fixture construction).
|
||||
/// A process-wide immutable choice keeps font and math caches consistent across test threads.
|
||||
/// Installs the pinned test fonts as the process-wide font database. The layout entry points
|
||||
/// (`layout`, `layout_para`, `layout_equation`) call it first in test builds; a test that looks
|
||||
/// up fonts itself before any layout call (fixtures, `word::resolve`, `FontDb::global`) calls it
|
||||
/// at its start. It is idempotent and never calls back into layout, so it cannot recurse. The
|
||||
/// choice is process-wide and immutable, which keeps font and math caches consistent across
|
||||
/// test threads.
|
||||
#[cfg(test)]
|
||||
fn test_fonts() {
|
||||
assert!(wordcraft_fonts::FontDb::init_test_fonts(), "layout tests must initialize fixed fonts before any global font lookup");
|
||||
@@ -314,6 +318,8 @@ pub struct DocLayout {
|
||||
|
||||
/// Lay out the whole document.
|
||||
pub fn layout(doc: &Document, cache: &mut LayoutCache, opts: &LayoutOptions) -> DocLayout {
|
||||
#[cfg(test)]
|
||||
crate::test_fonts();
|
||||
let t0 = now_ms();
|
||||
// Page totals shown in the body (`NUMPAGES`, `SECTIONPAGES`) are known only after
|
||||
// paginating: lay out again with the totals found until they hold (bounded). Footnotes
|
||||
|
||||
@@ -207,6 +207,8 @@ pub fn layout_equation(
|
||||
props: &MathProps,
|
||||
counter: &mut u32,
|
||||
) -> MathLayout {
|
||||
#[cfg(test)]
|
||||
crate::test_fonts();
|
||||
let parsed;
|
||||
let nodes: &Arg = if math.nodes.is_empty() && !math.linear {
|
||||
parsed = parse_linear(linear);
|
||||
|
||||
@@ -35,6 +35,7 @@ fn lay_in(math: &Math, lin: &str, display: bool, avail: f32, mp: &MathProps) ->
|
||||
|
||||
#[test]
|
||||
fn eq_array_rows_without_ampersand_are_centred() {
|
||||
crate::test_fonts();
|
||||
// Word centres a row with no `&` in the array (#2617: a case row "a, n odd" above
|
||||
// "|a|, &n even"), whether or not the other rows have one.
|
||||
use wordcraft_doc::math::*;
|
||||
|
||||
@@ -553,6 +553,8 @@ fn joined_cluster_starts(p: &Paragraph, clusters: &[Cluster]) -> Vec<usize> {
|
||||
|
||||
/// Lay out one paragraph.
|
||||
pub fn layout_para(p: &Paragraph, env: &ParaEnv) -> ParaLayout {
|
||||
#[cfg(test)]
|
||||
crate::test_fonts();
|
||||
let doc = env.doc;
|
||||
let rp = paragraph_props(p, env);
|
||||
let res = Resolver { doc, style: p.props.style.as_deref(), table: env.table.map(|t| &t.chr) };
|
||||
|
||||
@@ -1345,6 +1345,7 @@ fn a_missing_roman_font_is_drawn_as_word_draws_it() {
|
||||
|
||||
#[test]
|
||||
fn a_missing_roman_font_with_its_own_substitute_keeps_it() {
|
||||
crate::test_fonts();
|
||||
// Times New Roman is roman in every font table. Where it isn't installed it keeps its metric
|
||||
// clone (Liberation Serif), not Cambria: Word, which always has it, never draws it missing.
|
||||
let mut d = Document::from_text("Serif");
|
||||
@@ -1970,6 +1971,7 @@ fn bullet_first_line(label_font: Option<&str>) -> (f32, f32, f32, f32) {
|
||||
|
||||
#[test]
|
||||
fn a_symbol_bullet_sizes_its_line_by_the_symbol_font() {
|
||||
crate::test_fonts();
|
||||
// Measured in Word: a Symbol bullet makes its line taller than the text alone (Calibri 11 pt
|
||||
// at 1.08 spacing: 15.1 pt, not 14.5 pt), the extra ascent added unscaled. Symbol isn't an open
|
||||
// font; without it the bullet is drawn from another face but its line keeps Symbol's height.
|
||||
@@ -6396,6 +6398,7 @@ fn graphic_text_in_a_degenerate_rectangle_is_not_drawn() {
|
||||
|
||||
#[test]
|
||||
fn chart_text_the_font_lacks_is_drawn_in_a_fallback_face() {
|
||||
crate::test_fonts();
|
||||
// #4720: a Chinese legend in a chart drawn in the body font (which has no Chinese) showed boxes.
|
||||
use wordcraft_doc::graphic::{Graphic, GraphicItem, GraphicKind, TextAlign};
|
||||
use wordcraft_doc::props::Rgb;
|
||||
|
||||
@@ -314,6 +314,7 @@ fn hostile_bidi_text_never_panics() {
|
||||
|
||||
/// A face that has Arabic letters (installed system fonts), or `None` to skip.
|
||||
fn arabic_face() -> Option<wordcraft_fonts::FaceRef> {
|
||||
crate::test_fonts();
|
||||
wordcraft_fonts::FontDb::global().fallback_for('ب', 0).map(|f| wordcraft_fonts::FaceRef::of(&f)).filter(|f| f.covers('پ'))
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ fn myanmar_without_spaces_wraps_between_syllables() {
|
||||
|
||||
/// A face with Myanmar letters (an installed system font), or `None` to skip.
|
||||
fn myanmar_face() -> Option<wordcraft_fonts::FaceRef> {
|
||||
crate::test_fonts();
|
||||
wordcraft_fonts::FontDb::global().fallback_for('\u{1000}', 0).map(|f| wordcraft_fonts::FaceRef::of(&f)).filter(|f| f.has_layout_tables())
|
||||
}
|
||||
|
||||
@@ -119,12 +120,14 @@ const THAI_RUN: &str = "[D] น้ำ ค่ำ ปั้น ฝั่ง ปู
|
||||
|
||||
/// Is a font with Thai letters installed? `false` skips the test.
|
||||
fn thai_font_installed() -> bool {
|
||||
crate::test_fonts();
|
||||
wordcraft_fonts::FontDb::global().fallback_for('\u{0E19}', 0).is_some()
|
||||
}
|
||||
|
||||
/// Is a Thai font with Latin letters and digits installed (Tahoma, Leelawadee UI, Thonburi, the
|
||||
/// TLWG fonts…)? Noto Sans Thai alone has none, so no face covers [`THAI_RUN`]: `false` skips.
|
||||
fn thai_latin_font_installed() -> bool {
|
||||
crate::test_fonts();
|
||||
let face = wordcraft_fonts::word::resolve("TH Sarabun New", false, false).face;
|
||||
THAI_RUN.chars().filter(|c| !c.is_whitespace()).all(|c| face.covers(c))
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::{Document, LayoutCache, LayoutOptions, Placed, layout};
|
||||
/// Inter with its U+00A0 glyph twice as wide as its space, under the family name "Wnbsp".
|
||||
/// Built from the bundled font so the test needs no installed font.
|
||||
fn wide_nbsp_family() -> &'static str {
|
||||
crate::test_fonts();
|
||||
const FAMILY: &str = "Wnbsp";
|
||||
let inter = wordcraft_fonts::word::resolve("Inter", false, false).face;
|
||||
let mut data = inter.data().to_vec();
|
||||
|
||||
Reference in new issue
Block a user