feat(app-iced): M93 r2 —— 背景图真图直出 + 面板 α 收敛到 Ui::layer
复审前补齐两处(tower 扩 scope:Cargo.toml / pages/frame.* / theme.rs / presenter::prefs)。 1) 背景图**真图直出** - `iced` 开 `image-without-codecs`(刻意不用 `image`:后者会打开 `image/default` 全套编解码器); 编解码能力由本 crate 的 `image` features 决定,补了 `jpeg` / `bmp`(用户挑的背景图/壁纸多半是 jpg)。 - `pages/appearance/picture.rs`:`Cover`/`Contain` 走渲染器 `ContentFit`,`Tile` 按 `background::tiles` 算行列(上限 64 块)真的铺 N 个图块;暗化 = 一层「版面底色 @ α=dim」叠在图上。 - 36dp 马赛克那条路**已删除**(不再是主路径,也不留死代码)。 - 踩坑记录:`Handle::from_bytes` 的纹理分配赶不上截图第 3 帧(实测画面全空),改用 `Handle::from_path`(渲染器自己解码),已在 `picture::image_handle` 的文档里写明。 2) 面板 α **收敛到唯一来源** - `Ui::layer()` 直接乘上面板 α(新增 `Ui::panel_alpha` / `with_panel_alpha`,默认 1.0、 `scale_alpha(1.0)` 逐字节不变),`app::rebuild_ui` 注入生效值。 - 于是外壳(根容器/标题栏/导航轨)、`frame::card`(实例/下载/日志三页卡片)、 `frame::header_bar`(新增底色)、外观分组卡片、空态图标块**全部同源**, 调用点不再有任何 `panel_color(..)` 自乘(该 helper 已删)。 - 有背景图时根容器不再盖一层实色画布(否则 panel α=1 时背景图整块被挡)。 3) `presenter::prefs` 补重导出 `PANEL_ALPHA_MIN` / `BG_DIM_MAX`,app-iced 里两份 0.4 / 0.95 字面量改为转发常量。 验收:11+3 张图(`C:\Temp\ull-shots\wt-93\r2-*.png`)——三档填充肉眼可分、`.jpg` 能加载、 GPU 档 panel55 时卡片/分组卡/页头带都透出背景、CPU 档仍强制 1.0 且背景在面板空隙可见; 另附实例/下载/日志三页 panel55 各一张,证明三页都吃到同一个 α。
This commit is contained in:
1 parent
b8ab46662c
commit
22e4c423fa
18 files changed
+399
-535
No files matched your search
@@ -44,56 +44,6 @@ use super::background::BG_DIM_MAX;
|
||||
use super::state::State;
|
||||
use super::Change;
|
||||
|
||||
/// 一处面板/卡片表面色:令牌色 × 生效的面板 α。
|
||||
///
|
||||
/// `alpha == 1.0` 时返回**逐字节相同**的令牌色(`scale_alpha(1.0)` 不引入误差),所以没开面板
|
||||
/// 透明度时不会动到任何既有验收图的像素。
|
||||
#[must_use]
|
||||
pub fn panel_color(ui: &Ui, layer: MaterialLayer, alpha: f32) -> Color {
|
||||
let alpha = if alpha.is_finite() {
|
||||
alpha.clamp(0.0, 1.0)
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
ui.layer(layer).scale_alpha(alpha)
|
||||
}
|
||||
|
||||
/// 背景层(铺满整窗、垫在最下面的马赛克)。`None` = 没有背景图(调用方就不叠这一层)。
|
||||
#[must_use]
|
||||
pub fn layer(ui: &Ui, state: &State, viewport: (f32, f32)) -> Option<Element<'static, Message>> {
|
||||
let fallback = ui.layer(MaterialLayer::Canvas);
|
||||
let mosaic = state.mosaic(viewport, rgb8(fallback))?;
|
||||
|
||||
let rows = (0..mosaic.rows)
|
||||
.map(|row| {
|
||||
let cells = (0..mosaic.cols)
|
||||
.map(|col| cell(mosaic.at(row, col), fallback))
|
||||
.collect::<Vec<_>>();
|
||||
iced::widget::row(cells)
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.into()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Some(column(rows).width(Length::Fill).height(Length::Fill).into())
|
||||
}
|
||||
|
||||
/// iced 颜色 → 8 bit RGB(暗化的「底色」方向)。
|
||||
fn rgb8(color: Color) -> [u8; 3] {
|
||||
let channel = |value: f32| (value.clamp(0.0, 1.0) * 255.0).round() as u8;
|
||||
[channel(color.r), channel(color.g), channel(color.b)]
|
||||
}
|
||||
|
||||
fn cell<'a>(color: Option<[u8; 3]>, fallback: Color) -> Element<'a, Message> {
|
||||
let color = color.map_or(fallback, |[r, g, b]| Color::from_rgb8(r, g, b));
|
||||
container(iced::widget::space::horizontal())
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.style(move |_theme| frame::filled(color))
|
||||
.into()
|
||||
}
|
||||
|
||||
/// 「外观」分组整块(一张卡)。
|
||||
pub fn section<'a>(ui: &'a Ui, state: &'a State) -> Element<'a, Message> {
|
||||
let mut rows = column![].spacing(ui.space(Space::X1)).width(Length::Fill);
|
||||
@@ -250,16 +200,13 @@ pub fn section<'a>(ui: &'a Ui, state: &'a State) -> Element<'a, Message> {
|
||||
let resolved = format!("Colours: {}", state.palette_level());
|
||||
rows = rows.push(note_line(ui, &resolved, ui.color(Role::OnSurfaceVariant)));
|
||||
|
||||
card_with_panel_alpha(ui, state, rows)
|
||||
card(ui, rows)
|
||||
}
|
||||
|
||||
fn card_with_panel_alpha<'a>(
|
||||
ui: &'a Ui,
|
||||
state: &State,
|
||||
content: impl Into<Element<'a, Message>>,
|
||||
) -> Element<'a, Message> {
|
||||
/// 外观卡片:底色走 `ui.layer`(面板 α 的唯一来源),与其它页的卡片同源。
|
||||
fn card<'a>(ui: &'a Ui, content: impl Into<Element<'a, Message>>) -> Element<'a, Message> {
|
||||
let spec = Component::OutlinedCard.spec();
|
||||
let background = panel_color(ui, MaterialLayer::Card, state.effective_panel_alpha());
|
||||
let background = ui.layer(MaterialLayer::Card);
|
||||
|
||||
container(content)
|
||||
.width(Length::Fill)
|
||||
|
||||
Reference in new issue
Block a user