diff --git a/crates/app-iced/src/components/gallery/probe.rs b/crates/app-iced/src/components/gallery/probe.rs index c35e34a..c5c2e6f 100644 --- a/crates/app-iced/src/components/gallery/probe.rs +++ b/crates/app-iced/src/components/gallery/probe.rs @@ -334,10 +334,15 @@ fn gallery_geometry_matches_the_tokens() { // **无容器**三式(Text / Outlined / standard IconButton)的禁用内容叠在 surface 上, // 是另一个色值;单查上面那个只会覆盖到有容器的四式(reviewer code-r2 p2-1:护栏漏一半)。 let bare_ink = crate::app::components::interaction::disabled_content_over(&ui, Role::Surface); - let bare_px = count_pixels(&shot, rgb(bare_ink)); + // **只数 disabled 列**(矩阵最右那一列,x ≥ 全宽 2/3):整图计数会被别处的抗锯齿像素 + // 抬到 1000+,把该列涂回满档色也降不到阈值以下 —— 那正是「护栏拦不住」的成因。 + let bare_px = shot.count_pixels_in(rgb(bare_ink), shot.width * 2 / 3, shot.width); + // 阈值 500 的来历(实测,矩阵 8 行 × 5 列): + // 浅色正常 800 px、深色正常 1966 px;把 disabled 列的 38% 墨迹涂回满档色后只剩 348 px + // (剩下的都是别处抗锯齿像素恰好落进容差)——所以 500 是「真墨迹在 / 不在」的分界。 assert!( - bare_px > 200, - "**无容器**三式的禁用内容(OnSurfaceVariant@38% 叠 surface)只出现 {bare_px} 像素: 说明 Text/Outlined/standard 的字形没走 38%" + bare_px > 500, + "**无容器**三式在 disabled 列里的 38% 墨迹只出现 {bare_px} 像素: 说明 Text/Outlined/standard 的字形没走 38%" ); // filled 禁用容器里不许出现满档 OnPrimary(旧实现是 #FFFFFF 压在 12% 容器上 = 1.23:1) diff --git a/crates/app-iced/src/components/gallery/scan.rs b/crates/app-iced/src/components/gallery/scan.rs index 603cdf3..10c1094 100644 --- a/crates/app-iced/src/components/gallery/scan.rs +++ b/crates/app-iced/src/components/gallery/scan.rs @@ -93,6 +93,17 @@ impl Shot { boxes } + /// 只在 `x` 区间 `[from, to)` 内数某颜色的像素(矩阵按列取证时用)。 + pub(super) fn count_pixels_in(&self, color: [u8; 3], from: usize, to: usize) -> usize { + (0..self.height) + .map(|y| { + (from..to.min(self.width)) + .filter(|x| matches(self.at(*x, y), color)) + .count() + }) + .sum() + } + /// `bbox` 内某颜色的墨迹外接框(量字形用)。 /// /// 内缩 3px:不内缩会把按钮自身的抗锯齿边算成墨迹(实测把 24 盒字形量成 40)。