105 lines
4.2 KiB
Rust
105 lines
4.2 KiB
Rust
//! 合成整个原生窗口的显示列表:页面画面、宿主侧栏和开发工具绘制。
|
|
//! 窗口逻辑尺寸与设备像素比例在这里衔接。页面内容先应用其视角并裁剪,宿主控件的区域和命中布局另外返回。
|
|
//!
|
|
use crate::{
|
|
activity::Activity,
|
|
developer_tools::{self, DeveloperToolsLayout, Workspace as DeveloperToolsState},
|
|
display_list::{DisplayList, DrawCommand},
|
|
document::RenderDocument,
|
|
geometry::{Point, Rect},
|
|
};
|
|
|
|
#[derive(Clone, Debug, Default)]
|
|
/// 宿主管理区域的几何布局,供窗口事件分辨页面与工具命中。
|
|
pub struct SceneLayout {
|
|
pub developer_tools: DeveloperToolsLayout,
|
|
}
|
|
|
|
/// 组合页面、开发工具和侧栏的设备像素显示列表,同时返回供命中使用的宿主布局。
|
|
pub fn build_scene(
|
|
width: u32,
|
|
height: u32,
|
|
scale: f32,
|
|
document: &RenderDocument,
|
|
developer_tools_state: &mut DeveloperToolsState,
|
|
activity: &Activity,
|
|
sidebar: &mut crate::sidebar::State,
|
|
) -> DisplayScene {
|
|
// 活动标签的 developer_tool 标记决定管理页类型,不靠当前窗口标题猜测;同步工具状态后再合成。
|
|
let tool = document
|
|
.frame
|
|
.tabs
|
|
.iter()
|
|
.find(|tab| tab.active)
|
|
.and_then(|tab| tab.developer_tool.as_deref());
|
|
developer_tools_state.select(tool);
|
|
developer_tools_state.document_updated(document);
|
|
let left = sidebar.left();
|
|
let surface = &document.frame.surface;
|
|
// width/height 为设备像素,sidebar.left 为逻辑单位,先乘 scale 得到页面可用裁剪区域。
|
|
let content = Rect::new(
|
|
left * scale,
|
|
0.0,
|
|
(width as f32 - left * scale).max(0.0),
|
|
height as f32,
|
|
);
|
|
// 管理页使用单位页面缩放,避免业务 Page 相机改变宿主工具字号;普通页叠加旧 Surface zoom。
|
|
let zoom = if tool.is_some() { 1.0 } else { surface.zoom };
|
|
// 显示列表转换失败时降级为空默认文档;这只保护原生绘制,不把无效命令伪装成成功执行。
|
|
let mut page = document.display_list(scale * zoom).unwrap_or_else(|_| {
|
|
RenderDocument::default()
|
|
.display_list(scale)
|
|
.expect("default document is valid")
|
|
});
|
|
// 页面显示列表先已乘设备比例/zoom,再加入侧栏偏移和世界 pan 的设备像素平移,保持缩放顺序一致。
|
|
page.translate(Point::new(
|
|
(left - surface.pan.x * zoom) * scale,
|
|
-surface.pan.y * zoom * scale,
|
|
));
|
|
let mut display_list = DisplayList::default();
|
|
// 全窗只做一次 Clear,后续跳过页面列表自身 Clear,防止其覆盖侧栏或突破页面裁剪。
|
|
display_list.push(DrawCommand::Clear(
|
|
crate::document::parse_color(&document.frame.background)
|
|
.unwrap_or(crate::system_ui::theme::BG),
|
|
));
|
|
display_list.push(DrawCommand::PushClip(content));
|
|
for command in page.commands() {
|
|
if !matches!(command, DrawCommand::Clear(_)) {
|
|
display_list.push(command.clone());
|
|
}
|
|
}
|
|
display_list.push(DrawCommand::PopClip);
|
|
let (mut developer_list, mut developer_layout) = developer_tools::build(
|
|
width.saturating_sub((left * scale) as u32),
|
|
height,
|
|
scale,
|
|
document,
|
|
developer_tools_state,
|
|
activity,
|
|
);
|
|
// 工具命令在设备空间平移,交互布局在逻辑空间平移,两者比例不同但实际对齐同一页面起点。
|
|
developer_list.translate(Point::new(left * scale, 0.0));
|
|
developer_layout.translate(left, 0.0);
|
|
display_list.extend(developer_list);
|
|
// 侧栏最后覆盖合成,内部按逻辑尺寸绘制后统一设备缩放,不受页面相机影响。
|
|
let mut chrome = sidebar.draw(
|
|
&document.frame.tabs,
|
|
height as f32 / scale,
|
|
developer_tools_state.accent,
|
|
);
|
|
chrome.scale(scale);
|
|
display_list.extend(chrome);
|
|
DisplayScene {
|
|
display_list,
|
|
layout: SceneLayout {
|
|
developer_tools: developer_layout,
|
|
},
|
|
}
|
|
}
|
|
|
|
/// 整窗合成结果:显示列表与同帧管理交互几何一起返回。
|
|
pub struct DisplayScene {
|
|
pub display_list: DisplayList,
|
|
pub layout: SceneLayout,
|
|
}
|