fix(app-iced): 探针补回宽度判据,并订正覆盖面与 12.4 的口径(M248 r1 P2-1/P2-2)
P2-1:`TRACK_MIN_RUN = 200` 把「轨道被宿主裁短」这类几何回归从红变成绿——复审把 after 图里 0% 那条轨道右半截涂回画布色(连续段 160px)之后,那一行直接不成带,check_linear 靠另一条带 照样绿。现在拆成两条判据:成带阈值降到 **100**(实测:确定态行 318~320、不定态行 306~308、 文字行 22,两头都留得住),宽度**单独**判 ≥300(`TRACK_MIN_WIDTH`),不再藏在圆角检查的 find 里。反例复跑:两套主题都红「实测最宽段 160px @ 行 163」。 新增 `feedback/tests/bands.rs`(合成图,不依赖真实截图)两条用例,把两个阈值的取值区间钉住: 窄轨道必须仍成带且过不了宽度判据、22px 的文字段永远不成带。变异自证:调用点换回 `bands(.., 200)` → 两条用例都红(`left: [(12,15)] / right: [(5,8),(12,15)]`); `TRACK_MIN_WIDTH=150` → 窄轨道用例红。 P2-2:订正两处写反的账——实测 `轨道带 2 条(高 [4, 5])`,**两条带都在**厚度/宽度判据里 (5 行那条含 1 行抗锯齿,near 容 ±1),不是「只剩一条」;12.4 只量主色两段的左右端点, **不量**轨道厚度。根因(按单条 320 轨道心算 ~88px vs bands_by_run 按整行取 306px)已写进 `TRACK_MIN_RUN` 的文档。 顺带:12.1 的判据从 probe.rs 搬进 `probe/track.rs`——加完这几行 probe.rs 正好 401 行, 撞 400 红线;顺着 circular / panels 的先例一族几何一个文件。
This commit is contained in:
1 parent
8f5dac2ed6
commit
31cb109445
5 files changed
+264
-52
No files matched your search
@@ -60,6 +60,29 @@ impl Shot {
|
|||||||
pub(super) fn at(&self, x: usize, y: usize) -> [u8; 3] {
|
pub(super) fn at(&self, x: usize, y: usize) -> [u8; 3] {
|
||||||
self.pixels[y * self.width + x]
|
self.pixels[y * self.width + x]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// **合成图**(不读盘):按 `(x, y) → RGB` 造一张 `width × height` 的图。
|
||||||
|
///
|
||||||
|
/// 只给回归用例用:有些几何错误在真截图上**不会自然出现**(例如「轨道被宿主裁短」——
|
||||||
|
/// 真实渲染里轨道永远占满宿主,只有把像素涂掉才看得到,那是复审的一次性动作)。
|
||||||
|
/// 合成图让这类形状变成可复现的夹具,见 `tests/bands.rs`。
|
||||||
|
pub(super) fn from_rows(
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
pixel: impl Fn(usize, usize) -> [u8; 3],
|
||||||
|
) -> Self {
|
||||||
|
let mut pixels = Vec::with_capacity(width * height);
|
||||||
|
for y in 0..height {
|
||||||
|
for x in 0..width {
|
||||||
|
pixels.push(pixel(x, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
pixels,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 一个外接框(闭区间)。
|
/// 一个外接框(闭区间)。
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
mod circular;
|
mod circular;
|
||||||
mod panels;
|
mod panels;
|
||||||
|
pub(super) mod track;
|
||||||
|
|
||||||
use unlucky_design::color::{Role, SchemeFlavor};
|
use unlucky_design::color::{Role, SchemeFlavor};
|
||||||
use unlucky_design::typography::Platform;
|
use unlucky_design::typography::Platform;
|
||||||
@@ -54,15 +55,9 @@ const TRACK3_X0: usize = 688;
|
|||||||
/// 单条轨道宽(gallery 的 `TRACK_HOST`)。
|
/// 单条轨道宽(gallery 的 `TRACK_HOST`)。
|
||||||
const TRACK3_W: usize = 320;
|
const TRACK3_W: usize = 320;
|
||||||
|
|
||||||
/// 认定为「轨道行」所需的**连续**同色段长度(见 `pixel::bands_by_run`)。
|
|
||||||
///
|
|
||||||
/// 确定态那一格是整条 360 宽,取 200 留出「指示条压在轨道上把它切段」的余量;
|
|
||||||
/// 文字行的最长连续段只有 20px 上下。
|
|
||||||
const TRACK_MIN_RUN: usize = 200;
|
|
||||||
|
|
||||||
/// 认定为「主色进度行」所需的连续主色段长度。
|
/// 认定为「主色进度行」所需的连续主色段长度。
|
||||||
///
|
///
|
||||||
/// phase 0.55 的两段分别是 ≈24px 与 ≈165px,取 60 既收得住第二段、又挡得住文字行(≤20px)。
|
/// phase 0.55 的两段分别是 ≈24px 与 ≈165px,取 60 既收得住第二段、又挡得住文字行(实测 ≤22px)。
|
||||||
const INDETERMINATE_MIN_RUN: usize = 60;
|
const INDETERMINATE_MIN_RUN: usize = 60;
|
||||||
|
|
||||||
/// 一条测试覆盖当前截图对应的那一段(段由 `ULL_FEEDBACK_PART` 指定,默认 `all`)。
|
/// 一条测试覆盖当前截图对应的那一段(段由 `ULL_FEEDBACK_PART` 指定,默认 `all`)。
|
||||||
@@ -117,45 +112,10 @@ fn check_linear(shot: &Shot, ui: &Ui) {
|
|||||||
// 参考值写字面量(A1):**不能**从 `LinearGeometry` 读回期望值——那样把 4 改成 6 之后
|
// 参考值写字面量(A1):**不能**从 `LinearGeometry` 读回期望值——那样把 4 改成 6 之后
|
||||||
// 「实测 6 == 期望 6」会照样绿,等于没有断言。
|
// 「实测 6 == 期望 6」会照样绿,等于没有断言。
|
||||||
let surface = ui.color(Role::Surface);
|
let surface = ui.color(Role::Surface);
|
||||||
// M248:轨道角色改成容器面(`SurfaceContainerHighest`),参考值仍写**字面角色**——
|
|
||||||
// 不从 `progress::progress_roles()` 读回期望值,否则「把角色改成别的」会两边一起变、照样绿。
|
|
||||||
let track = ui.color(Role::SurfaceContainerHighest);
|
|
||||||
let active = ui.color(Role::Primary);
|
let active = ui.color(Role::Primary);
|
||||||
|
|
||||||
// ---- 12.1 厚度:轨道带恰好 4 行(宿主 320 宽 ⇒ 每行 ~320 个轨道墨点)--------
|
// §12.1(厚度 / 宽度 / 圆角)搬去 `probe/track.rs`:那边撞了 400 行红线,见该文件文档。
|
||||||
//
|
track::check(shot, ui);
|
||||||
// 用 [`bands_by_run`] 而不是 [`bands`]:M248 把轨道换成中性容器面之后,「画布 → 轨道」
|
|
||||||
// 这条混色轴穿过中性文字,按**计数**判会把图注行也数成轨道(浅色板实测多出 3 条假带:6/2/6 行),
|
|
||||||
// 按**连续段**判就不受影响(详见 `pixel::bands_by_run` 的文档)。
|
|
||||||
// 于是这条断言现在只覆盖「确定态那一条」(360 宽整段);不定态那一条的轨道被指示条切成
|
|
||||||
// 最长 ~88px 的几段,它由下面的 12.4 两段判据覆盖。
|
|
||||||
let bar_bands = bands_by_run(shot, track, surface, TRACK_MIN_RUN);
|
|
||||||
assert!(
|
|
||||||
!bar_bands.is_empty(),
|
|
||||||
"没找到线性进度轨道(宿主宽 320,应有 ≥{TRACK_MIN_RUN} 个连续墨点的行)"
|
|
||||||
);
|
|
||||||
for (top, bottom) in &bar_bands {
|
|
||||||
let height = bottom - top + 1;
|
|
||||||
assert!(
|
|
||||||
near(height, 4),
|
|
||||||
"12.1:线性进度厚必须 4(A1 Height;实测 {height} @ 行 {top})"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- 12.1 圆角 full:条的四角必须透出底色(直角会把角填满)------------------
|
|
||||||
let (top, _) = bar_bands[0];
|
|
||||||
let (left, len) = runs(shot, top + 1, track, surface)
|
|
||||||
.into_iter()
|
|
||||||
.find(|(_, len)| *len >= 300)
|
|
||||||
.expect("轨道那一行必须有 ≥300 的长段");
|
|
||||||
assert!(
|
|
||||||
!matches(shot.at(left, top), rgb(track)),
|
|
||||||
"12.1:圆角 full(2) 的左上角必须透出底色(直角会填满)"
|
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
matches(shot.at(left + len / 2, top + 1), rgb(track)),
|
|
||||||
"条的中间必须有墨(否则是没画出来,不是圆角)"
|
|
||||||
);
|
|
||||||
|
|
||||||
// ---- 12.4 不定态:phase 0.55 那一列必须**数出两段**(复审 P1-A 的回归断言)----
|
// ---- 12.4 不定态:phase 0.55 那一列必须**数出两段**(复审 P1-A 的回归断言)----
|
||||||
//
|
//
|
||||||
@@ -193,14 +153,7 @@ fn check_linear(shot: &Shot, ui: &Ui) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln!(
|
eprintln!("[feedback-probe] progress·12.4:phase 0.55 两段 {found:?}(行 {row})");
|
||||||
"[feedback-probe] progress:轨道带 {} 条(高 {:?})· phase 0.55 两段 {found:?}",
|
|
||||||
bar_bands.len(),
|
|
||||||
bar_bands
|
|
||||||
.iter()
|
|
||||||
.map(|(top, bottom)| bottom - top + 1)
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 线性不定态那一行的 y:主色墨迹在**第一条轨道**里出现、且不在确定态行的最上一组。
|
/// 线性不定态那一行的 y:主色墨迹在**第一条轨道**里出现、且不在确定态行的最上一组。
|
||||||
|
|||||||
@@ -0,0 +1,112 @@
|
|||||||
|
//! 线性进度**轨道本身**的判据(§12.1:厚度 / 宽度 / 圆角)。
|
||||||
|
//!
|
||||||
|
//! 从 `probe.rs` 拆出来(M248 r1 复审时那边正好 401 行,撞 400 红线):顺着 `circular` /
|
||||||
|
//! `panels` 的同一先例,一族几何一个文件。
|
||||||
|
//!
|
||||||
|
//! ## 取带规则(M248 r1 P2-1 / P2-2 的教训)
|
||||||
|
//!
|
||||||
|
//! 轨道的配色从强调色族换成中性容器面(`SurfaceContainerHighest`)之后,「画布 → 轨道」这条
|
||||||
|
//! 混色轴正好穿过中性文字:按**计数**判(`bands`,一行里有多少个覆盖率 ≥50% 的像素)会把
|
||||||
|
//! 图注行也数成轨道(浅色板实测多出 3 条假带:6/2/6 行)。所以这里改成按**连续段**判
|
||||||
|
//! (`pixel::bands_by_run`)。
|
||||||
|
//!
|
||||||
|
//! 复审判过这条改动:「换判据」的方向对,但第一版把阈值定成 200,**顺手丢了半个守卫**——
|
||||||
|
//! 把 after 图里 0% 那条轨道右半截涂回画布色(连续段 160px = 轨道被宿主裁短的形态)之后,
|
||||||
|
//! 那一行直接不再成带,`check_linear` 靠另一条带照样绿。现在分两条判据:
|
||||||
|
//!
|
||||||
|
//! | 判据 | 常量 | 决定什么 | 实测口径(两套主题一致) |
|
||||||
|
//! |---|---|---|---|
|
||||||
|
//! | 成带 | [`TRACK_MIN_RUN`] = **100** | 这一行算不算轨道行 | 确定态行最长段 318~320、不定态行 306~308、文字行 **22** |
|
||||||
|
//! | 宽度 | [`TRACK_MIN_WIDTH`] = **300** | 这条轨道的宽度对不对 | 宿主 320/360,砍半(160)必须判不合格 |
|
||||||
|
//!
|
||||||
|
//! ⚠️ **别按「单条轨道」心算阈值**:`bands_by_run` 是按**整行**取最长连续段(三个宿主在同一
|
||||||
|
//! y 上,取其中最长那一段),不是按单条 320 轨道取。按单条轨道算会得到 ~88px 的错值,
|
||||||
|
//! 于是把阈值定到 200,160px 的窄轨道就整行掉出判据——复审就是这么抓到第一版的漏洞的。
|
||||||
|
//!
|
||||||
|
//! 取值区间由 `tests/bands.rs` 的合成图钉住(成带阈值调大到 >160、或小到 ≤22,那里都红)。
|
||||||
|
|
||||||
|
use unlucky_design::color::Role;
|
||||||
|
|
||||||
|
use super::super::pixel::{band_width, bands_by_run, matches, near, rgb, runs, Shot};
|
||||||
|
use crate::theme::Ui;
|
||||||
|
|
||||||
|
/// 认定为「轨道行」所需的**连续**同色段长度。
|
||||||
|
///
|
||||||
|
/// `pub(crate)`:`tests/bands.rs` 的合成图要断言这两个阈值本身(`probe` 是 `#[cfg(test)]` 模块)。
|
||||||
|
pub(crate) const TRACK_MIN_RUN: usize = 100;
|
||||||
|
|
||||||
|
/// 轨道必须占满宿主带来的宽度(线性进度宿主 320/360,下限取 300)。
|
||||||
|
pub(crate) const TRACK_MIN_WIDTH: usize = 300;
|
||||||
|
|
||||||
|
/// `check` 的**取带规则**(`pub(crate)` 是为了让 `tests/bands.rs` 的合成图跑同一段逻辑)。
|
||||||
|
///
|
||||||
|
/// 抽函数而不是让用例直接调 `bands_by_run`:用例要能在「调用点被改回计数判据」时变红,
|
||||||
|
/// 那就得覆盖调用点本身。
|
||||||
|
pub(crate) fn track_bands(
|
||||||
|
shot: &Shot,
|
||||||
|
track: iced::Color,
|
||||||
|
surface: iced::Color,
|
||||||
|
) -> Vec<(usize, usize)> {
|
||||||
|
bands_by_run(shot, track, surface, TRACK_MIN_RUN)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// §12.1:线性轨道的厚度(4 行)、宽度(占满宿主)、圆角(full)。
|
||||||
|
///
|
||||||
|
/// 参考值写字面量(A1):**不能**从 `LinearGeometry` 读回期望值——那样把 4 改成 6 之后
|
||||||
|
/// 「实测 6 == 期望 6」会照样绿,等于没有断言。轨道的**角色**同理,由调用方给字面角色
|
||||||
|
/// (`SurfaceContainerHighest`),不从 `progress::progress_roles()` 读回。
|
||||||
|
pub(super) fn check(shot: &Shot, ui: &Ui) {
|
||||||
|
let surface = ui.color(Role::Surface);
|
||||||
|
let track = ui.color(Role::SurfaceContainerHighest);
|
||||||
|
|
||||||
|
let bar_bands = track_bands(shot, track, surface);
|
||||||
|
assert!(
|
||||||
|
bar_bands.len() >= 2,
|
||||||
|
"线性进度应有两条轨道带(确定态 + 不定态),实测 {bar_bands:?}:\
|
||||||
|
某一条整行掉出判据 = 它被裁到 <{TRACK_MIN_RUN}px 连不成段了"
|
||||||
|
);
|
||||||
|
for (top, bottom) in &bar_bands {
|
||||||
|
let height = bottom - top + 1;
|
||||||
|
assert!(
|
||||||
|
near(height, 4),
|
||||||
|
"12.1:线性进度厚必须 4(A1 Height;实测 {height} @ 行 {top})"
|
||||||
|
);
|
||||||
|
// 宽度**单独**判(M248 r1 P2-1):阈值 100 会把被裁短的轨道也认成一条带,
|
||||||
|
// 所以「窄了」不能再靠「找不到带」兜——复审反例(砍到 160px)走的就是这条路。
|
||||||
|
let widest = band_width(shot, (*top, *bottom), track, surface);
|
||||||
|
assert!(
|
||||||
|
widest >= TRACK_MIN_WIDTH,
|
||||||
|
"12.1:轨道必须占满宿主(≥{TRACK_MIN_WIDTH}px 的连续段),实测最宽段 {widest}px @ 行 {top}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 圆角 full:条的四角必须透出底色(直角会把角填满)。
|
||||||
|
let (top, _) = bar_bands[0];
|
||||||
|
let (left, len) = runs(shot, top + 1, track, surface)
|
||||||
|
.into_iter()
|
||||||
|
.find(|(_, len)| *len >= TRACK_MIN_WIDTH)
|
||||||
|
.expect("上面刚判过宽度 ≥300,这一行必须能找到长段");
|
||||||
|
assert!(
|
||||||
|
!matches(shot.at(left, top), rgb(track)),
|
||||||
|
"12.1:圆角 full(2) 的左上角必须透出底色(直角会填满)"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
matches(shot.at(left + len / 2, top + 1), rgb(track)),
|
||||||
|
"条的中间必须有墨(否则是没画出来,不是圆角)"
|
||||||
|
);
|
||||||
|
|
||||||
|
// 覆盖面账(复审可对 `--nocapture` 输出核):两条带**都在**厚度/宽度判据里;
|
||||||
|
// 不定态那条 5 行是含 1 行抗锯齿(`near(·, 4)` 容 ±1)。12.4 只量主色两端点,不量厚度。
|
||||||
|
eprintln!(
|
||||||
|
"[feedback-probe] 轨道带 {} 条(高 {:?})· 最宽段 {:?}",
|
||||||
|
bar_bands.len(),
|
||||||
|
bar_bands
|
||||||
|
.iter()
|
||||||
|
.map(|(top, bottom)| bottom - top + 1)
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
bar_bands
|
||||||
|
.iter()
|
||||||
|
.map(|band| band_width(shot, *band, track, surface))
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@ use super::progress::Progress;
|
|||||||
use super::snackbar::{Placement, Snackbar};
|
use super::snackbar::{Placement, Snackbar};
|
||||||
use super::{circular, dialog, empty_state, linear, snackbar, Dialog, EmptyState};
|
use super::{circular, dialog, empty_state, linear, snackbar, Dialog, EmptyState};
|
||||||
|
|
||||||
|
mod bands;
|
||||||
mod progress;
|
mod progress;
|
||||||
|
|
||||||
const FAMILIES: Families = Families {
|
const FAMILIES: Families = Families {
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
//! 探针**取带规则**的回归(M248 r1 复审 P2-1 / P2-2)——用合成图,不依赖真实截图。
|
||||||
|
//!
|
||||||
|
//! ## 为什么必须用合成图
|
||||||
|
//!
|
||||||
|
//! 真实渲染里轨道**永远占满宿主**,「轨道被裁短」这类几何回归在图上不会自然出现。
|
||||||
|
//! 复审是手工把 after 图里 0% 那条轨道右半截涂回画布色才造出反例的(一次性动作),
|
||||||
|
//! 而那一涂正好打中第一版的漏洞:阈值 200 时该行**直接不再被认成轨道行**,
|
||||||
|
//! `check_linear` 靠另一条带照样绿——「判据被放宽」在真实图上永远不露馅。
|
||||||
|
//! 合成图把这个形状变成可复现夹具。
|
||||||
|
//!
|
||||||
|
//! ## 两条用例各钉住什么
|
||||||
|
//!
|
||||||
|
//! | 用例 | 钉住的取值区间 | 打红它的变异 |
|
||||||
|
//! |---|---|---|
|
||||||
|
//! | [`narrowed_track_is_still_a_band`] | `TRACK_MIN_RUN` ≤ 160(窄轨道必须仍成带),且 `TRACK_MIN_WIDTH` > 160(它必须过不了宽度判据) | ① 调用点换回计数判据 `bands(.., 200)`(窄轨道那条带消失 → `bands.len()` 变 1);② `TRACK_MIN_WIDTH` 调到 ≤160(宽度判据失去区分力) |
|
||||||
|
//! | [`text_rows_are_never_track_bands`] | `TRACK_MIN_RUN` > 22(文字行最长连续段就是 22) | 阈值调到 ≤22(图注行会被数成轨道,正是第一版的假红) |
|
||||||
|
//!
|
||||||
|
//! **抓不住**:真实截图里轨道被裁/被折线的具体像素形态(那仍要复审涂图或用真实 probe),
|
||||||
|
//! 也抓不住厚度那一条(厚度仍由真实截图的 `track::check` 判)。
|
||||||
|
|
||||||
|
use unlucky_design::color::{BrandBoard, Role};
|
||||||
|
use unlucky_design::typography::Platform;
|
||||||
|
|
||||||
|
use super::super::pixel::{band_width, rgb, Shot};
|
||||||
|
use super::super::probe::track::{track_bands, TRACK_MIN_RUN, TRACK_MIN_WIDTH};
|
||||||
|
use super::FAMILIES;
|
||||||
|
use crate::theme::Ui;
|
||||||
|
|
||||||
|
/// 合成图的配色来源:用 Ink 板(深色)——轨道 `SurfaceContainerHighest` 与画布 `Surface`
|
||||||
|
/// 在这里是**两个不同的中性色**,正好复现「混色轴穿过中性文字」那一幕的坐标轴。
|
||||||
|
fn strip_ui() -> Ui {
|
||||||
|
Ui::with_board(BrandBoard::Ink, Platform::Windows, FAMILIES)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 一段横线:`y0..=y1` 行里前 `len` 个像素涂 `color`,其余留底色。
|
||||||
|
fn strip(
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
rows: &[(usize, usize, usize)],
|
||||||
|
color: [u8; 3],
|
||||||
|
under: [u8; 3],
|
||||||
|
) -> Shot {
|
||||||
|
Shot::from_rows(width, height, |x, y| {
|
||||||
|
let hit = rows
|
||||||
|
.iter()
|
||||||
|
.any(|(top, bottom, len)| (*top..=*bottom).contains(&y) && x < *len);
|
||||||
|
if hit {
|
||||||
|
color
|
||||||
|
} else {
|
||||||
|
under
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 复审反例的形态:**轨道比宿主窄一半**(160 = 320 宿主的一半)。
|
||||||
|
///
|
||||||
|
/// 阈值 200 的版本在这里会**只找到一条带**(窄的那条整行掉出判据)——这正是那条 p2 的漏判,
|
||||||
|
/// 所以 `bands.len() == 2` 是这条用例的主断言之一。
|
||||||
|
#[test]
|
||||||
|
fn narrowed_track_is_still_a_band() {
|
||||||
|
let ui = strip_ui();
|
||||||
|
let track = rgb(ui.color(Role::SurfaceContainerHighest));
|
||||||
|
let surface = rgb(ui.color(Role::Surface));
|
||||||
|
|
||||||
|
// 360×20:y=5..8 是**被裁到 160px** 的轨道;y=12..15 是占满宿主的轨道。
|
||||||
|
let shot = strip(360, 20, &[(5, 8, 160), (12, 15, 360)], track, surface);
|
||||||
|
|
||||||
|
let bands = track_bands(
|
||||||
|
&shot,
|
||||||
|
ui.color(Role::SurfaceContainerHighest),
|
||||||
|
ui.color(Role::Surface),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
bands,
|
||||||
|
vec![(5, 8), (12, 15)],
|
||||||
|
"窄轨道也必须被认成一条带(TRACK_MIN_RUN={TRACK_MIN_RUN};调大到 ≥160 时它会消失,\
|
||||||
|
于是 `check_linear` 只能看见另一条带、漏判——复审就是在这里抓到第一版的)"
|
||||||
|
);
|
||||||
|
|
||||||
|
let widths: Vec<usize> = bands
|
||||||
|
.iter()
|
||||||
|
.map(|band| {
|
||||||
|
band_width(
|
||||||
|
&shot,
|
||||||
|
*band,
|
||||||
|
ui.color(Role::SurfaceContainerHighest),
|
||||||
|
ui.color(Role::Surface),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
assert_eq!(widths, vec![160, 360], "两条带的最宽连续段");
|
||||||
|
assert!(
|
||||||
|
widths[0] < TRACK_MIN_WIDTH,
|
||||||
|
"窄轨道必须过不了宽度判据(TRACK_MIN_WIDTH={TRACK_MIN_WIDTH}),否则「轨道被裁短」\
|
||||||
|
这类回归会绿着过"
|
||||||
|
);
|
||||||
|
assert!(widths[1] >= TRACK_MIN_WIDTH, "占满宿主的轨道必须过宽度判据");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 文字行永远不能进判据:图注行的最长连续段实测就是 **22px**(`after/gallery-progress-*`)。
|
||||||
|
///
|
||||||
|
/// 这条是「阈值别调得太小」的那一侧:阈值 ≤22 时,图注行会被数成轨道带,
|
||||||
|
/// 浅色板那次假红(`12.1:线性进度厚必须 4(实测 6 @ 行 63)`)就会回来。
|
||||||
|
#[test]
|
||||||
|
fn text_rows_are_never_track_bands() {
|
||||||
|
let ui = strip_ui();
|
||||||
|
let track = rgb(ui.color(Role::SurfaceContainerHighest));
|
||||||
|
let surface = rgb(ui.color(Role::Surface));
|
||||||
|
|
||||||
|
// 6 行「文字」:每段 22px、段间隔 12px(字形与字距的粗略形态),整行铺满。
|
||||||
|
let shot = Shot::from_rows(360, 6, |x, _y| if x % 34 < 22 { track } else { surface });
|
||||||
|
|
||||||
|
let bands = track_bands(
|
||||||
|
&shot,
|
||||||
|
ui.color(Role::SurfaceContainerHighest),
|
||||||
|
ui.color(Role::Surface),
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
bands.is_empty(),
|
||||||
|
"22px 的文字段不能算轨道行(TRACK_MIN_RUN={TRACK_MIN_RUN};调到 ≤22 时这里会红,\
|
||||||
|
那正是浅色板假红 `实测 6 @ 行 63` 的来源),实测 {bands:?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user