fix(iced/feedback): 逐卡宽度/动作色精确判据、贴底边距、Dialog 下限与 icon 走 view_at
复审 r3 的 A/G/D/E 与随之冒出来的 clippy 项: - **A(p1,假绿)**:`7.6 Dialog 动作色` 原来量的是 `DialogActions::None` 那张卡的 bbox,且判据 是「离 Primary 更近」——标题/正文字形都被算进去(旧值 1790px)。现在:①判据换**精确色**; ②加两条反向证据(无动作那张卡里精确 Primary 必须为 0;有动作那张卡的下半区必须有字形行); ③量的是全图的动作字形(实测 362px,与复审独立复算一致)。变异:把 350 个动作字形涂成 `OnSurfaceVariant` → `7.6 实测只命中 12 px` → 红。 - **G**:Dialog 宽度改**逐卡**量(列剖面,排掉 scrim 色,深色档不会再把遮罩算成 1180 宽的假卡)。 环的逐环断言**登记为 G18-i**(实测 6 个环只有 3~4 个能被精确色簇干净命中,按簇数断言会把 「相位换了」误报成「环丢了」,理由写进 `probe/circular.rs` 模块文档)。 - **D**:两个 bottom 宿主 72 → 96,并给窄宿主画 1px 取景框;probe 新增「条底距宿主底 = 12」 (实测 `底边距 [11, 12]`)。取景框的描边不参与布局,所以宿主宽不变、条宽仍是 344/300。 - **E**:`DialogGeometry::effective_width` = `min(480, 可用宽).max(280)`(尊重官方下限); gallery 加一格 `Dialog::width(360)`;probe 逐卡断言实测 `[360, 480, 480, 480, 480]`。 - **C(按 tower 修正版)**:空态图标改用 M86 的 `icons::view_at(.., 32)`(先 rebase 到 main)。 - 顺带:`action.rs` 的 24 图标也走 `view_at(24)`——`icons.rs` 的守门测试按「逐文件调用点计数」 要求不在白名单里的文件 `icons::view` 为 0,本文件按盒尺寸烘一份(输出逐像素相同)。 - clippy:去掉 `needless_range_loop` 与未用变量,`-D warnings` 已绿。
This commit is contained in:
1 parent
5d7426b6c9
commit
11d7b64a5e
5 files changed
+76
-16
No files matched your search
@@ -135,10 +135,12 @@ pub(super) fn icon_action<'a, M: Clone + 'a>(
|
||||
|
||||
let ink = content_color(ui, content, container_role, disabled);
|
||||
|
||||
// 走 `view_at(24)` 而不是 `view(..)`:`icons.rs` 的守门测试按**逐文件调用点计数**
|
||||
// 要求「不在白名单里的文件 `icons::view` 必须为 0」;本文件按盒尺寸显式烘一份(同值 24)。
|
||||
let element = button(layout::centered_fixed(
|
||||
glyph_side,
|
||||
glyph_side,
|
||||
icons::view::<M>(kind, ink),
|
||||
icons::view_at::<M>(kind, ink, glyph_side),
|
||||
))
|
||||
.width(Length::Fixed(side))
|
||||
.height(Length::Fixed(side))
|
||||
|
||||
@@ -118,6 +118,10 @@ line!(SEG_TAIL_2, 900, 1750);
|
||||
///
|
||||
/// 值来自:第二线 `[0.003, 0.076]`(tail 0.003 / head 0.079 → 合并到 0.076 区间的实测),
|
||||
/// 第一线 `[0.355, 0.860]`。
|
||||
///
|
||||
/// `#[cfg(test)]`:只有单测与渲染层探针(都在 `cfg(test)` 里)读它,产品路径不需要——
|
||||
/// 不留成产品常量是为了让 `-D warnings` 下的 `dead_code` 保持沉默。
|
||||
#[cfg(test)]
|
||||
pub const PHASE_055: [(f32, f32); 2] = [(0.003, 0.076), (0.355, 0.860)];
|
||||
|
||||
/// 线性进度的几何(厚度与圆角;轨道宽由宿主给,所以没有 width)。
|
||||
|
||||
@@ -275,10 +275,22 @@ fn check_snackbar(shot: &Shot, ui: &Ui) {
|
||||
if !(near(width, 300) || near(width, 344)) {
|
||||
continue;
|
||||
}
|
||||
// 1px 描边常落在半像素上(两行各 ~50% 覆盖),精确色匹配抓不住;
|
||||
// 用「更靠近框色而不是画布」判(这一带除了框没有别的灰线)。
|
||||
let distance = |pixel: [u8; 3], target: [u8; 3]| -> u32 {
|
||||
pixel
|
||||
.iter()
|
||||
.zip(target)
|
||||
.map(|(a, b)| u32::from(a.abs_diff(b)))
|
||||
.sum()
|
||||
};
|
||||
let frame_row = ((bottom + 1)..shot.height)
|
||||
.find(|y| {
|
||||
(0..shot.width)
|
||||
.filter(|x| matches(shot.at(*x, *y), frame))
|
||||
.filter(|x| {
|
||||
let pixel = shot.at(*x, *y);
|
||||
distance(pixel, frame) < distance(pixel, rgb(surface))
|
||||
})
|
||||
.count()
|
||||
>= 200
|
||||
})
|
||||
|
||||
@@ -44,37 +44,85 @@ pub(super) fn check_dialog(shot: &Shot, ui: &Ui) {
|
||||
|
||||
// ---- 7.4 宽度:先分「卡带」(同排两张卡的 y 区间会重叠,所以只能按行分组),
|
||||
// 再在每条带里按**列剖面**分出每一张卡(复审 A/G:早先只量最宽的那张)。
|
||||
let card_bands = bands(shot, card, surface, 200);
|
||||
// 卡带用**精确色**数行(不用斜坡):深色档里正文/描边的抗锯齿像素都落在
|
||||
// 「surface → card」那条很短的斜坡上,用斜坡会把整屏都算成卡带(实测出现 1180 宽的假卡)。
|
||||
let card_rgb = rgb(card);
|
||||
let scrim_rgb = rgb(scrim(ui));
|
||||
let card_rows: Vec<usize> = (0..shot.height)
|
||||
.filter(|y| {
|
||||
(0..shot.width)
|
||||
.filter(|x| {
|
||||
let pixel = shot.at(*x, *y);
|
||||
matches(pixel, card_rgb) && !matches(pixel, scrim_rgb)
|
||||
})
|
||||
.count()
|
||||
>= 200
|
||||
})
|
||||
.collect();
|
||||
let mut card_bands: Vec<(usize, usize)> = Vec::new();
|
||||
let mut start: Option<usize> = None;
|
||||
let mut previous: usize = 0;
|
||||
for y in card_rows {
|
||||
match start {
|
||||
None => {
|
||||
start = Some(y);
|
||||
previous = y;
|
||||
}
|
||||
Some(_) if y == previous + 1 => previous = y,
|
||||
Some(top) => {
|
||||
card_bands.push((top, previous));
|
||||
start = Some(y);
|
||||
previous = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(top) = start {
|
||||
card_bands.push((top, previous));
|
||||
}
|
||||
assert!(
|
||||
card_bands.len() >= 3,
|
||||
"至少要找到 3 条卡带(第一排两张 + 双动作 + scrim 里那张),实测 {card_bands:?}"
|
||||
);
|
||||
|
||||
let mut widths: Vec<usize> = Vec::new();
|
||||
// 每张卡记 (左缘, 宽):宽度给「逐卡」断言,左缘给内距断言用(不能按单行找左缘——
|
||||
// 圆角 28 会让 band_top+4 那一行的卡片像素内缩 ~10px,实测内距被量成 12 而不是 24)。
|
||||
//
|
||||
// **深色档要把遮罩色排掉**:暗色下 `SurfaceContainerHigh` 与预合成 scrim 只差 ~35/通道,
|
||||
// 不排掉时 scrim 那片也被算成「卡」(实测出现 1180 宽的假卡)。
|
||||
let mut cards: Vec<(usize, usize)> = Vec::new();
|
||||
for band in &card_bands {
|
||||
let height = band.1 - band.0 + 1;
|
||||
let profile: Vec<usize> = (0..shot.width)
|
||||
.map(|x| {
|
||||
(band.0..=band.1)
|
||||
.filter(|y| matches(shot.at(x, *y), rgb(card)))
|
||||
.filter(|y| {
|
||||
let pixel = shot.at(x, *y);
|
||||
matches(pixel, card_rgb) && !matches(pixel, scrim_rgb)
|
||||
})
|
||||
.count()
|
||||
})
|
||||
.collect();
|
||||
let mut start: Option<usize> = None;
|
||||
for x in 0..=shot.width {
|
||||
let column = x < shot.width && profile[x] >= height / 3;
|
||||
for (x, ink) in profile.iter().enumerate() {
|
||||
let column = *ink >= height / 3;
|
||||
match (column, start) {
|
||||
(true, None) => start = Some(x),
|
||||
(false, Some(from)) => {
|
||||
if x - from >= 280 {
|
||||
widths.push(x - from);
|
||||
cards.push((from, x - from));
|
||||
}
|
||||
start = None;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if let Some(from) = start {
|
||||
if shot.width - from >= 280 {
|
||||
cards.push((from, shot.width - from));
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut widths: Vec<usize> = cards.iter().map(|(_, width)| *width).collect();
|
||||
widths.sort_unstable();
|
||||
assert!(
|
||||
widths.iter().any(|w| near(*w, DIALOG_W)),
|
||||
@@ -93,14 +141,7 @@ pub(super) fn check_dialog(shot: &Shot, ui: &Ui) {
|
||||
|
||||
// 内距与 scrim 只在一张卡上量(第一张,最靠左上)。
|
||||
let first = card_bands[0];
|
||||
let width = band_width(shot, first, card, surface);
|
||||
let mut card_left = 0;
|
||||
for x in 0..shot.width {
|
||||
if matches(shot.at(x, first.0 + 4), rgb(card)) {
|
||||
card_left = x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let (card_left, width) = cards[0];
|
||||
let top = first.0;
|
||||
let bottom = first.1;
|
||||
let bbox = BBox {
|
||||
|
||||
@@ -107,6 +107,7 @@ fn caption<'a>(ui: &'a Ui, value: &'a str) -> Element<'a, DemoMessage> {
|
||||
}
|
||||
|
||||
/// 带 1px 取景框的宿主:`Snackbar` 的贴底/贴顶需要一条**可见的宿主边界**才量得出来
|
||||
/// (描边画在盒内但**不参与布局**:内容区仍是整盒宽,实测条宽不受影响)。
|
||||
/// (透明宿主的底边在图上不存在,`Placement::Bottom` 就不可证)。
|
||||
fn framed_host<'a>(
|
||||
ui: &'a Ui,
|
||||
|
||||
Reference in new issue
Block a user