docs: explain Tessera modules and execution flows in Chinese

This commit is contained in:
2026-11-11 23:36:03 +08:00
parent 4c3fc8b5dd
commit 1fedd21d3c
77 changed files with 1418 additions and 0 deletions
+19
View File
@@ -1,17 +1,23 @@
//! 把 DisplayList 写入 CPU 像素缓冲。裁剪栈限定矩形、文字和 3D 表面的实际写入区域。
//! RenderScope 约束递归深度;累计像素预算限制嵌套 3D 和世界 UI 的中间表面分配。错误向上传递,不把半幅结果当成成功帧呈现。
//!
use crate::{
display_list::{Color, DisplayList, DrawCommand},
geometry::{Point, Rect},
text::{self, TextStyle},
};
/// 显示列表的 CPU 执行入口,错误在原生 present 前向上传递。
pub struct SoftwareRenderer;
thread_local! {
static RENDER_DEPTH:std::cell::Cell<usize>=const { std::cell::Cell::new(0) };
static PIXEL_UNITS:std::cell::Cell<usize>=const { std::cell::Cell::new(0) };
}
/// 递归渲染的 RAII 深度保护,最外层还重置累计像素工作预算。
pub(crate) struct RenderScope;
impl RenderScope {
/// 进入一次嵌套渲染并检查深度上限;最外层调用重新开始累计像素预算。
pub fn enter() -> Result<Self, &'static str> {
RENDER_DEPTH.with(|depth| {
let current = depth.get();
@@ -27,10 +33,12 @@ impl RenderScope {
}
}
impl Drop for RenderScope {
/// 在 Rust 所有者离开作用域时执行本类型的配套清理;不能用它代替需要报告错误的显式关闭。
fn drop(&mut self) {
RENDER_DEPTH.with(|depth| depth.set(depth.get() - 1));
}
}
/// 累加本帧中间表面工作量,超过预算立即返回错误。
pub(crate) fn reserve_pixels(units: usize) -> Result<(), &'static str> {
PIXEL_UNITS.with(|pixels| {
let next = pixels.get().saturating_add(units);
@@ -43,6 +51,7 @@ pub(crate) fn reserve_pixels(units: usize) -> Result<(), &'static str> {
}
impl SoftwareRenderer {
/// 顺序执行显示列表并维护裁剪栈;3D 和面板可递归进入同一渲染预算域。
pub fn render(
list: &DisplayList,
target: &mut [u32],
@@ -145,6 +154,7 @@ impl SoftwareRenderer {
}
}
/// 借用目标像素切片并维护当前裁剪,所有像素写入都受该上下文限制。
struct Canvas<'a> {
pixels: &'a mut [u32],
width: u32,
@@ -153,10 +163,12 @@ struct Canvas<'a> {
}
impl Canvas<'_> {
/// 清空本对象维护的当前内容或缓存,后续状态由调用方重新建立。
fn clear(&mut self, color: Color) {
self.pixels.fill(pack(color));
}
/// 只遍历裁剪后的矩形像素,按圆角覆盖决定填充区域。
fn fill_rounded_rect(&mut self, rect: Rect, radius: f32, color: Color) {
let bounds = self.clamped_bounds(rect);
let radius = radius.max(0.0).min(rect.width / 2.0).min(rect.height / 2.0);
@@ -169,6 +181,7 @@ impl Canvas<'_> {
}
}
/// 用外轮廓与内轮廓的差绘制边框,避免把边框当成整个矩形填充。
fn stroke_rounded_rect(&mut self, rect: Rect, radius: f32, width: f32, color: Color) {
let bounds = self.clamped_bounds(rect);
let width = width.max(1.0).min(rect.width / 2.0).min(rect.height / 2.0);
@@ -194,6 +207,7 @@ impl Canvas<'_> {
}
}
/// 把文字原点转换为局部裁剪区域,交给有界字形绘制,再混合到目标缓冲。
fn draw_text(&mut self, origin: Point, value: &str, style: TextStyle, color: Color) {
let x = origin.x.round() as i32;
let y = origin.y.round() as i32;
@@ -208,6 +222,7 @@ impl Canvas<'_> {
});
}
/// 把段落矩形与当前裁剪相交,按受限宽度绘制,再恢复外层裁剪。
fn draw_wrapped_text(&mut self, rect: Rect, value: &str, style: TextStyle, color: Color) {
if rect.width <= 0.0 || rect.height <= 0.0 {
return;
@@ -240,6 +255,7 @@ impl Canvas<'_> {
self.clip = old;
}
/// 把连续矩形转换成目标缓冲内的整数像素范围,避免在不可见区域进行光栅循环。
fn clamped_bounds(&self, rect: Rect) -> (i32, i32, i32, i32) {
(
rect.x.max(self.clip.x).max(0.0).floor() as i32,
@@ -255,6 +271,7 @@ impl Canvas<'_> {
)
}
/// 在画布与当前裁剪范围内进行透明度混合,防止文字/图形写出目标缓冲。
fn blend_pixel(&mut self, x: i32, y: i32, source: Color) {
if x < 0
|| y < 0
@@ -288,6 +305,7 @@ impl Canvas<'_> {
}
}
/// 测试一个像素采样点是否位于圆角矩形内,角区域使用圆弧距离。
fn rounded_rect_contains(rect: Rect, radius: f32, x: f32, y: f32) -> bool {
if rect.width <= 0.0 || rect.height <= 0.0 {
return false;
@@ -306,6 +324,7 @@ fn rounded_rect_contains(rect: Rect, radius: f32, x: f32, y: f32) -> bool {
dx * dx + dy * dy <= radius * radius
}
/// 将颜色通道打包成目标缓冲的整数像素表示。
fn pack(color: Color) -> u32 {
(color.red as u32) << 16 | (color.green as u32) << 8 | color.blue as u32
}