The port agent produced a genuine second witness for the pixel-cost claim: it
re-checked GP_TITLE entry 12 in Godot, which shares no code with compose,
swapping only paint_order. 59 530 px ink with the rule, exactly 0 without it.
The strong form -- the screen ceasing to exist, not merely changing a lot --
now has two real renderers behind it on that entry.
Its figures did not match ours, so I counted the same composite every way:
RGB > 0 ours 49 771 Godot 59 530 16 % apart
RGB > 1 ours 48 043 Godot 48 368 0.68 % apart
The entire disagreement lives in pixels whose value is exactly 1. That is a
1-LSB sampling artefact between two samplers, not a different set of inked
pixels. So '>0' is not a portable ink convention between renderers on a
mostly-dark frame and '>1' is; any future cross-renderer ink figure should say
which it used.
Also worth recording: our 49 771 was never a threshold figure. It is exact RGBA
inequality between the two paint orders, which over a black backdrop coincides
with ink>0 -- so it belongs against the port's 59 530, not its 48 368. Matching
it to the 48 368 would have made the two renderers look like they agreed for
the wrong reason.
The without-the-rule column is 0 at every threshold here too, matching Godot:
the strong form is not threshold-sensitive in either renderer.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
91 lines
3.5 KiB
Rust
91 lines
3.5 KiB
Rust
//! Reconcile two ink counts for one screen that were never counting the same pixels.
|
|
//!
|
|
//! The port agent double-witnessed the pixel-cost claim in Godot — a renderer
|
|
//! sharing no code with `compose` — and got `GP_TITLE` entry 12 at **59 530 px**
|
|
//! ink above threshold 0 and **48 368** above 1. This crate reported **49 771**.
|
|
//! Neither is wrong; the question is which convention each was using, and on a
|
|
//! mostly-dark frame the answer moves thousands of pixels.
|
|
//!
|
|
//! So: count the same composite every way, and print the family. Whichever row
|
|
//! the port's numbers land in is the convention, and then the two renderers can be
|
|
//! compared on purpose rather than by coincidence.
|
|
//!
|
|
//! cargo run -p sylpheed-formats --example forced_backdrop_ink_thresholds
|
|
|
|
use std::path::PathBuf;
|
|
|
|
use sylpheed_formats::{pak::PakArchive, ui_layout};
|
|
use ui_layout::ComposeOptions;
|
|
|
|
fn order_without_rule(build: &ui_layout::UiBuild, bundle: &[u8]) -> Vec<usize> {
|
|
let mut idx: Vec<usize> = (0..build.elements.len()).collect();
|
|
idx.sort_by_key(|&i| {
|
|
let el = &build.elements[i];
|
|
(
|
|
ui_layout::sprite_layer_key(build, bundle, el)
|
|
.or_else(|| ui_layout::implied_layer_key(&el.name))
|
|
.unwrap_or(u32::MAX),
|
|
i,
|
|
)
|
|
});
|
|
idx
|
|
}
|
|
|
|
fn counts(rgba: &[u8], t: u8) -> (usize, usize) {
|
|
let rgb = rgba
|
|
.chunks_exact(4)
|
|
.filter(|p| p[0] > t || p[1] > t || p[2] > t)
|
|
.count();
|
|
let alpha = rgba.chunks_exact(4).filter(|p| p[3] > t).count();
|
|
(rgb, alpha)
|
|
}
|
|
|
|
fn main() {
|
|
let root = PathBuf::from(std::env::var("SYLPHEED_DISC").expect("SYLPHEED_DISC"));
|
|
let ar = PakArchive::open(root.join("dat/GP_TITLE.pak")).expect("GP_TITLE.pak");
|
|
|
|
for entry in [12usize, 15] {
|
|
let by = ar.read(&ar.entries()[entry]).expect("entry");
|
|
let b = ui_layout::parse_build(&by).expect("parse");
|
|
for (label, opts) in [
|
|
(
|
|
"primitives on (what the cost run used)",
|
|
ComposeOptions {
|
|
include_primitives: true,
|
|
backdrop: [0, 0, 0, 255],
|
|
..Default::default()
|
|
},
|
|
),
|
|
(
|
|
"primitives+focus+animated",
|
|
ComposeOptions {
|
|
include_primitives: true,
|
|
include_focus: true,
|
|
include_animated: true,
|
|
backdrop: [0, 0, 0, 255],
|
|
..Default::default()
|
|
},
|
|
),
|
|
] {
|
|
let with = ui_layout::derived_paint_order(&b, &by);
|
|
let without = order_without_rule(&b, &by);
|
|
let a = ui_layout::compose_with_order(&b, &by, opts.clone(), None, Some(&with));
|
|
let c = ui_layout::compose_with_order(&b, &by, opts, None, Some(&without));
|
|
println!("\n== GP_TITLE entry {entry} — {label} ({}x{})", a.width, a.height);
|
|
println!(" threshold | RGB>t with rule | A>t with rule | RGB>t WITHOUT | A>t WITHOUT");
|
|
for t in [0u8, 1, 2, 4, 8, 16] {
|
|
let (r1, a1) = counts(&a.rgba, t);
|
|
let (r0, a0) = counts(&c.rgba, t);
|
|
println!(" >{t:<8} | {r1:>16} | {a1:>14} | {r0:>13} | {a0:>11}");
|
|
}
|
|
let changed = a
|
|
.rgba
|
|
.chunks_exact(4)
|
|
.zip(c.rgba.chunks_exact(4))
|
|
.filter(|(x, y)| x != y)
|
|
.count();
|
|
println!(" exact-RGBA changed pixels between the two orders: {changed}");
|
|
}
|
|
}
|
|
}
|