Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_austenite/tests/oracle/fixtures/float_fixture.typ

8.3 KiB, 3 runs

created by r1870400018:46113, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1// The oracle harness's float fixture -- the corpus's first root exercising the A1 FLOAT primitive
2// (`figure(placement: auto | top | bottom)`). Self-contained -- no `#import` of any shared template --
3// so it compiles under typst 0.15.1 with no symbol-modifier patch, and austenite reads the `aside-box`
4// furniture from its own `#let` definition exactly as it does in the books.
5//
6// The page geometry is austenite's own `PageGeometry::a4()` (A4, uniform 56.9 pt margins) set explicitly
7// here so Typst lays the body on the same measure -- austenite ignores a lone `#set page(width/height)`
8// and always uses A4, so the two only agree when the fixture names A4 (see `marginalia_fixture.typ` for
9// the same idiom). The floats are aside-boxes carrying plain text, not `rect`/image figures: austenite
10// renders an image figure as a measure-wide PLACEHOLDER and always sets a "Figure N." caption, so an
11// image float could never match Typst, whereas an aside-box of text sets from the same body in both. Each
12// aside-box is a `figure(placement: auto, ...)` under the bonnet, so it is a floating figure to Typst and
13// a `Float` anchor to austenite -- the two the oracle order-matches, and for THIS root the harness holds
14// them to exact page agreement and a per-float side (top/foot) and y check.
15//
16// The body is long and plain (both engines break it identically), so the document spans more than one page
17// and the four asides are spread across it -- some drawn to the top, some to the foot -- so the engine's
18// queue, midpoint and document-order stacking are all exercised, and the two engines agree float-for-float.
19//
20// TRUE TYPST-PARITY GATE. Each aside's floated placement (page, side, y) is asserted against Typst's own,
21// read through the in-float `#context here().position()` probe above -- Typst's plain `query(figure)`
22// reports a float's ANCHOR position, not where it lands, so the probe is what makes an exact comparison
23// possible. A Fable trace confirmed Austenite's midpoint (`used = base - remaining`, ratio <= 0.5 -> top)
24// reproduces Typst's (compose.rs:319-326) exactly.
25//
26// NO LEVEL-1 HEADING: the fixture opens straight into body on purpose. A lone-file `= Heading` is lowered
27// by austenite as a ~136pt CHAPTER-OPENER grid where Typst (a lone file) sets a plain ~18pt heading; that
28// ~118pt confound pushed the flow deeper and tipped aside-2's midpoint from top to foot, which is a
29// heading-rendering bug (tracked as A18: lone-file/standalone `=` should set a plain heading, not a
30// chapter opener), NOT a float bug. Removing the heading isolates this fixture to what it gates -- FLOAT
31// placement -- so it stays green through the A18 fix rather than coupling to it.
32
33#set page(width: 595.276pt, height: 841.89pt, margin: 56.9pt)
34#set text(size: 11pt, font: "Libertinus Serif")
35#set par(justify: true, leading: 0.65em, spacing: 1.2em, first-line-indent: 0pt)
36
37#let aside-box(float: true, body) = {
38 let inner = box(
39 width: 100%,
40 inset: (x: 10pt, y: 10pt),
41 fill: luma(240),
42 stroke: (left: 2pt + luma(80)),
43 // The `#context here().position()` probe reports the aside's TRUE floated position (it is laid out
44 // inside the floated box, so context resolves to where the float lands, not its in-flow anchor). Typst
45 // reads it through the `<fp>` label; austenite ignores the unknown `#context` construct, so it changes
46 // no ink in either engine and the aside's height is identical to a plain one.
47 [#text(size: 0.9em)[#context [#metadata((page: here().position().page, y: int(calc.round(here().position().y / 1pt))))<fp>]#body]],
48 )
49 if float { figure(placement: auto, inner, caption: none) } else { inner }
50}
51
52This opening section runs on at plain length so that both engines break its lines at exactly the same
53points and the reading cursor reaches the same depth in each. The words carry no emphasis and no special
54construct, only ordinary prose set to the same measure, so that the page fills identically and the first
55aside, when it is met, has the same space above it in both engines. We write on to fill the upper part of
56the first page before the aside arrives, so its midpoint sits high and it is drawn to the top of the page.
57Line after plain line, the same in both engines, the measure the same, the leading the same, the breaks
58the same, until the aside is due.
59
60#aside-box[A first aside, met high on the first page, so its midpoint sits in the upper half and it is
61drawn to the top of the page above the prose that continues beneath it.]
62
63The body continues after the first aside with a solid block of ordinary prose whose only job is to carry
64the reading cursor down the first page, so that the second aside, arriving low, has its midpoint in the
65lower half and is drawn to the foot. We keep writing plainly and at length, without emphasis or any
66special construct, so that both engines break these lines at exactly the same points and the cursor
67reaches the same depth in each before the second aside is met. A little more prose keeps the measure
68honest and the paragraph long enough to matter for the placement decision that follows it, which is the
69whole point of setting this fixture down at this deliberate length. Line after plain line accumulates,
70each the same in both engines, until the page is better than half full and the midpoint rule has a clear
71answer to give for the aside that comes next in the source, drawing it down to the foot of the page.
72
73#aside-box[A second aside, met once the cursor has run well down the first page, so its midpoint falls in
74the lower half and the engine draws it to the foot of the page instead of the top -- the midpoint rule
75that tells an automatic float which end of the page it belongs on. It carries a couple of sentences so it
76has real height, and its clearance is laid above it where it meets the body rather than below.]
77
78Now a longer passage of prose carries the reader onto the second page and down it. There is nothing to
79read here and nothing to see but text, which is the whole intent: text is what the two engines set
80identically, so text is what makes their page breaks agree. We set it down line by line, plain and
81unadorned, at the one size and the one measure, the leading fixed and the justification on, so the ragged
82edge never enters into it and every line is full to the same width in both. On the prose goes, filling the
83column, turning the page, resuming at the head of the next, the same words at the same places, carrying
84the cursor down the second page toward its foot, so that the tall aside that comes next cannot fit in the
85space that remains and must defer. We write on to be sure the cursor is deep when the tall aside is
86reached, and that there is real prose after it to do the backfilling, because a float that fits where it
87stands is not deferred and would not exercise the queue at all.
88
89#aside-box[A third and much taller aside. It carries several sentences so that its height is large enough
90that, arriving low on the second page, it cannot fit in the space that remains. It therefore defers to the
91queue and is set at the top of the next page, while the prose written after it in the source flows up to
92fill the foot of the second page. This is the backfill behaviour that distinguishes a real float queue
93from the old in-flow lowering, and it is the reason a document with floats paginates as Typst does. A few
94more sentences give the aside the height it needs to be certain of deferring rather than fitting in
95whatever slack the page still holds, so the scenario is robust to small differences in where the cursor
96happens to sit when the aside is reached, and the deferred aside opens the third page at its very top.]
97
98A short paragraph of plain prose follows the tall aside in the source and backfills the foot of the second
99page, set before the deferred aside on the page it was carried to. It is ordinary text, the same in both
100engines, so it fills the same space in each and the backfill is identical.
101
102#aside-box[A fourth aside, met just after the tall one, so it queues behind it and is set on the third
103page beneath the deferred aside -- document order running down the top band, the earlier float highest.]
104
105A closing paragraph of plain prose ends the document on the third page, part of the material that fills
106the page the floats settled on, so the fixture finishes cleanly with body below the floats drawn there,
107and both engines set that closing prose at the same place because it is, like all the rest, only text.