From 4d7b198822a4382854e0162460cf6199faf2437f Mon Sep 17 00:00:00 2001 From: AskaEth Date: Mon, 2 Nov 2026 04:45:54 +0800 Subject: [PATCH] =?UTF-8?q?fix(app-iced):=20M75=20r6=20=E2=80=94=E2=80=94?= =?UTF-8?q?=20probe=20=E5=88=A0=2019=20=E8=A1=8C=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E5=9D=97=20+=20=E8=A1=A5=E7=AC=AC=208=20=E8=A1=8C(icon=C2=B7to?= =?UTF-8?q?nal)=20+=20=E4=B8=89=E5=A4=84=E6=B3=A8=E9=87=8A=E6=8C=89=20visu?= =?UTF-8?q?al-r4=20P2-2=20=E6=9B=B4=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ① 19 行重复块(第 4 次报):probe.rs 218-236 与 198-216 逐字重复(on_primary/left_ink 双层循环/ icon_pad/assert 各两遍,靠 shadowing 编过),已删;粘在一起的注释头随之消失。 滑动窗口脚本:改前 'DUP at 199 and 219' → 改后 'no 19-line duplicate'。 ② 逐行护栏补到 8 行:(7, OnSurface, true, "icon·tonal");汇总打印 '8 行通过'。 变异(该行墨迹涂回满档色)→ probe 红。 ③ 三处过期注释按 review 的 §P2-2 逐条改: - probe 模块文档 药丸顶行宽 ≈9 → 左内缩 ≈14; - 圆角推导改成像素中心闭式 inset(k)=r−√(r²−(r−k−0.5)²),r=20,k=1 给 12.40; - gallery/mod.rs 列宽注释 132 → 160(cell_width 的实际值)。 --- crates/app-iced/src/components/gallery/mod.rs | 2 +- .../app-iced/src/components/gallery/probe.rs | 32 +++++-------------- 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/crates/app-iced/src/components/gallery/mod.rs b/crates/app-iced/src/components/gallery/mod.rs index eaac1e7..16ddaaf 100644 --- a/crates/app-iced/src/components/gallery/mod.rs +++ b/crates/app-iced/src/components/gallery/mod.rs @@ -202,7 +202,7 @@ pub(super) fn heading<'a>(ui: &'a Ui, title: &'a str, note: &'a str) -> Element< /// 状态矩阵的列头:五态的固定次序(`Interaction::ALL` 的口径)。 /// -/// 列宽 = 按钮最常见的自然宽 132(用作矩阵栅格,不是组件尺寸)。 +/// 列宽 = [`cell_width`](**160** = `Space::X8 × 5`,是矩阵栅格,不是组件尺寸)。 pub(super) fn state_cells(ui: &Ui) -> Vec<(&'static str, f32)> { Interaction::ALL .iter() diff --git a/crates/app-iced/src/components/gallery/probe.rs b/crates/app-iced/src/components/gallery/probe.rs index 282408e..945d7a0 100644 --- a/crates/app-iced/src/components/gallery/probe.rs +++ b/crates/app-iced/src/components/gallery/probe.rs @@ -14,7 +14,7 @@ //! ULL_GALLERY_SHOT=target/m75/gallery-light.png cargo test -p unlucky-app-iced gallery::probe //! ``` //! -//! 量什么(每条对一个已发生过的错误):实心块高 **40**(12b 1.1)· 药丸顶行宽 ≈9 ⇒ 圆角 full=20 +//! 量什么(每条对一个已发生过的错误):实心块高 **40**(12b 1.1)· 药丸顶行**左内缩 ≈14** ⇒ 圆角 full=20 //! (12b 1.2,8 圆角会接近通栏)· IconButton **40×40**(12b 2.1)· 字形墨迹 **16~26** //! (Q9:24 盒被填满会到 40)· 分隔线 **1px**(22.1)· 禁用容器 **on-surface@12%** 存在(12b 1.8)。 @@ -184,8 +184,9 @@ fn gallery_geometry_matches_the_tokens() { "可见高必须精确 40(12b 1.1);变异成 42 这里就会红" ); - // 圆角档位:量**顶部那一行的左内缩**。药丸(r = 高/2 = 20)在离顶端 1px 处内缩 - // ≈ r − √(2r−1) = 13.8;r=8 只有 ≈4.1;直角为 0。比「数圆角行数」抗锯齿得多。 + // 圆角档位:量**顶部那一行的左内缩**。按像素中心口径,第 k 行(k 从 0 起)的闭式是 + // inset(k) = r − √(r² − (r − k − 0.5)²);r=20、k=1 给 **12.40**(实测 12~14), + // r=8 只有 ≈3.6,直角为 0。比「数圆角行数」抗锯齿得多。 let top_row_left = (label_button.left..=label_button.right) .find(|x| matches(shot.at(*x, label_button.top), fill)) .expect("顶部行应至少有一个填充像素"); @@ -215,26 +216,6 @@ fn gallery_geometry_matches_the_tokens() { "12b 1.4:带图标左内边距应 16(墨迹 ≈21),实测 {icon_pad}" ); - // ---- Q9:IconButton 的字形不许撑满 40 盒 --- // ---- 12b 1.4:带前置图标的左内边距 = 16(用 Filled 格量,避开圆角只扫中间带)---- - // 判「墨迹」的方式:比容器色更接近 OnPrimary。不要用字面量白——浅色页面底色 (246,250,255) - // 与白在容差内,会把圆角外的底色当成墨迹(首次实现就踩了,量出 3)。 - let on_primary = rgb(ui.color(Role::OnPrimary)); - let mut left_ink: Option = None; - for y in (label_button.top + 12)..=(label_button.bottom - 12) { - for x in (label_button.left + 4)..=label_button.right { - if nearer(shot.at(x, y), on_primary, fill) { - left_ink = Some(left_ink.map_or(x, |best: usize| best.min(x))); - } - } - } - let icon_pad = left_ink.expect("Filled 格应带前置图标(量内边距用)") - label_button.left; - // 图标盒左缘 = 16;字形在 24 viewBox 里自带 ≈5.3 左边距 ⇒ 墨迹落在 21 附近 - // (16 → 21;24 → 29;8 → 13,三档互不重叠) - assert!( - (18..=24).contains(&icon_pad), - "12b 1.4:带图标左内边距应 16(墨迹 ≈21),实测 {icon_pad}" - ); - // ---- Q9:IconButton 的字形不许撑满 40 盒 ----------------------------------- let tonal = rgb(ui.color(Role::SecondaryContainer)); let tonal_boxes = shot.bbox_of(tonal); @@ -318,7 +299,7 @@ fn gallery_geometry_matches_the_tokens() { // 矩阵行序(gallery/buttons.rs 的 Variant::ALL + IconVariant::ALL),行距 48 = 40 + 8 let row_step = 48usize; - let rows: [(usize, Role, bool, &str); 7] = [ + let rows: [(usize, Role, bool, &str); 8] = [ (0, Role::OnSurfaceVariant, true, "filled"), (1, Role::OnSurface, true, "tonal"), // A1:FilledTonal 是例外 (2, Role::OnSurfaceVariant, true, "elevated"), @@ -326,6 +307,9 @@ fn gallery_geometry_matches_the_tokens() { (4, Role::OnSurfaceVariant, false, "text"), (5, Role::OnSurface, false, "icon·standard"), // A1:IconButton 全是 OnSurface (6, Role::OnSurface, false, "icon·filled"), + // 第 7 行(矩阵最后一行的 tonal IconButton)上一版漏了 —— reviewer 把它的禁用墨迹涂回 + // 满档色时 probe 全绿。A1 同样是 OnSurface(`FilledTonalIconButtonTokens`)。 + (7, Role::OnSurface, true, "icon·tonal"), ]; let column_from = shot.width * 2 / 3; // 矩阵最右列 = disabled 列 for (index, role, on_container, name) in rows {