re(ui): the focus ring's position is decoded -- a .rat leaf parses as a build

The port needed ptbtneff01.t32's placement and was about to author it from an
eyeballed PNG measurement. It does not have to: a `.rat` leaf needs no new
reader. Its first 32 bytes have a bundle header's shape -- "RATC", 0x3c
declaration-entry size at +4, element count at +20, design 1280x720 at +24/+28 --
so ui_layout::parse_build reads it unchanged.

The control is the base record, whose position is known independently: the parent
screen reports ptbtn01.rat resting at (542,162), and parsing the leaf alone
returns ptbtn01.t32 at (542,162). It reproduces all five buttons.

Positions are absolute design-space top-left. The ring rests at (500, 156/236/
316/396/476) for buttons 1-5 -- a uniform (-42,-6) from each button's own rest,
identical in the Japanese bundle. The bright label is a uniform (-7,-7).

Two things recorded rather than smoothed over: a leaf's placement DUPLICATES the
parent's rather than being relative to it, and the two copies are not always
byte-equal (ptbtn04's parent says y=401, its leaf says 402) -- the parent is what
compose honours, so the leaf is the source only for elements the parent does not
declare, which is exactly the ring. And `screen render --focus` is blind to the
ring for the same reason the port's exporter was: el.focused is name-based on
top-level elements and neither walks into the leaf.
This commit is contained in:
Sylpheed RE agent
2026-08-29 08:36:53 +00:00
parent 9ca1eb50fd
commit b21c8e4118
2 changed files with 110 additions and 6 deletions

View File

@@ -98,13 +98,53 @@ corpus can resolve. **Either choice is defensible; neither is measurable.**
Replacing is the cheaper one and is what the file's structure suggests, since
`ptbtn0Nf.t32` is a whole label rather than an overlay.
## ❔ Not established
## ✅ Where the ring is placed — DECODED 2026-08-29, no authoring needed
* **Where `ptbtneff01.t32` is placed.** The record declares two elements; the
per-element placement inside a `.rat` leaf was not decoded here. The capture
shows the ring **left of** the label, roughly on the underline's left end.
A port should take the offset from the record, and until it is decoded, from
the capture.
This page previously said the per-element placement inside a `.rat` leaf was not
decoded and that a consumer should eyeball it off a capture. **That was wrong by
omission**: a leaf needs no new reader. Its first 32 bytes have the same shape as
a bundle header — `"RATC"`, `0x3c` declaration-entry size at `+4`, element count
at `+20`, design size `1280x720` at `+24`/`+28` — so `ui_layout::parse_build`
reads it **unchanged**.
**The control is the base record**, whose position is known independently: the
parent screen reports `ptbtn01.rat` resting at `(542,162)`, and parsing the leaf
on its own returns `ptbtn01.t32` at `(542,162)`. It reproduces all five.
Positions are **absolute design-space top-left**, not offsets
([`examples/rat_leaf_placement.rs`](../../../crates/sylpheed-formats/examples/rat_leaf_placement.rs)):
| button | base | ring `ptbtneff01.t32` | Δ | label `ptbtn0Nf.t32` | Δ |
|---|---|---|---|---|---|
| `ptbtn01` | (542,162) | **(500,156)** | (−42,−6) | (535,155) | (−7,−7) |
| `ptbtn02` | (542,242) | **(500,236)** | (−42,−6) | (535,235) | (−7,−7) |
| `ptbtn03` | (542,322) | **(500,316)** | (−42,−6) | (535,315) | (−7,−7) |
| `ptbtn04` | (542,402) | **(500,396)** | (−42,−6) | (535,395) | (−7,−7) |
| `ptbtn05` | (542,482) | **(500,476)** | (−42,−6) | (535,475) | (−7,−7) |
The offset is **uniform**: `(−42,−6)` for the ring and `(−7,−7)` for the label on
every button, and identical in the Japanese bundle (pak entry 8).
⚠️ **One 1-unit disagreement, and it is real.** `ptbtn04`'s parent element rests
at y **401** while its own leaf says y **402** (and in the JP bundle the leaf says
401 against a parent 401). So a leaf's placement **duplicates** the parent's
rather than being relative to it, and the two copies are not always byte-equal.
The parent's is what `compose` honours; treat the leaf's as the source only for
elements the parent does not declare — which is exactly the ring's case.
🟡 The ring carries **2 keyframes** where the label carries 1, so it animates.
What it does between them is not decoded here.
## ⚠️ `screen render --focus` is blind to the ring, and so was this page
`el.focused` is name-based on **top-level** elements, and a screen's buttons are
`.rat` records whose focused twin is not itself a top-level element — so
rendering build 5 with and without `--focus` produces an identical image. The
reference renderer has the same blind spot the port reported, for the same
reason: neither walks into the leaf. Fixing it is a renderer change, not a
format question; the format is decoded above.
## ❔ Not established
* **`ptbtn02b.t32`** — a third variant, `b`, exists for button 02 only, same size
as the base. Not seen on any capture. Not chased.
* Whether a **non-title** archive uses the same two-element convention. Checked