feat(workspace): pin Jian submodule and shell wrapper deps (Step 1a Task 1)
Anchor v19 pivot at the workspace level: vendor Jian as a git submodule pinned to fork commit ad13ce6 (P0.5 mini-gate GO; skia-safe 0.78 → 0.97 + new pub draw_on_canvas adapter), wire jian-core / jian-skia / jian-host-desktop as path deps with explicit version per spec §12.2, and re-export the Jian render/geometry/scene types from shell-core so shell-native can translate the OP RenderBackend facade into jian DrawOp commands. shell-core stays wasm32-clean: only jian-core (already wasm32-validated in P0.5) plus glam / bitflags / thiserror / tracing land here. shell-native picks up the full P0-pinned GL stack (skia-safe 0.97.0, glutin 0.32.3, glutin-winit 0.5.0, glow 0.17.0, winit 0.30.13, raw-window-handle 0.6.2, scopeguard 1.2) plus jian-skia (textlayout) and target-gated jian-host-desktop (default-features = false, no `run` feature so we skip Jian's softbuffer raster present path — OP owns its own GPU swap_buffers per spec §3.6). Adds OP RenderBackend trait + Rect / Color (with RED/GREEN/BLUE/BLACK/ WHITE/TRANSPARENT named constants per spec §5.2) + TextLayout facade that wraps jian_core::render::TextRun explicitly (TextRun has no Default impl, fields enumerated to honour spec §5.2 round-2 CONCERN-1 fix). Boundary checks all pass: - wasm32 shell-web metadata: no jian-host-desktop / jian-skia - aarch64-linux-android shell-native metadata: no jian-host-desktop - shell-core src: no glutin / skia_safe / winit / glow imports Tasks 2-4 (SharedSkiaContext + NativeBackend + ShellEvent mapping + acceptance) follow per plan v7.
This commit is contained in:
parent
ae13dc9bef
commit
2dcc8a96d3
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -4,3 +4,6 @@
|
|||
[submodule "vendor/agent"]
|
||||
path = vendor/agent
|
||||
url = https://github.com/ZSeven-W/agent-rs.git
|
||||
[submodule "vendor/jian"]
|
||||
path = vendor/jian
|
||||
url = git@github.com:Kayshen-X/jian.git
|
||||
|
|
|
|||
970
Cargo.lock
generated
970
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -6,6 +6,7 @@ resolver = "2"
|
|||
members = ["crates/*"]
|
||||
exclude = [
|
||||
"vendor/agent",
|
||||
"vendor/jian",
|
||||
"node_modules",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ version.workspace = true
|
|||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
license.workspace = true
|
||||
description = "OpenPencil shell — retained-mode widget tree, RenderBackend trait, parley + taffy (kickoff spec §1.2)"
|
||||
description = "OpenPencil shell — platform-agnostic widget facade + RenderBackend trait, Jian re-export wrapper (spec v19 §1.2 / §5.2)"
|
||||
|
||||
[lib]
|
||||
name = "openpencil_shell_core"
|
||||
|
|
@ -12,11 +12,18 @@ path = "src/lib.rs"
|
|||
|
||||
[dependencies]
|
||||
serde = { workspace = true, optional = true }
|
||||
thiserror = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
# Pinned per Task 0.4 wasm32 feature matrix verdict
|
||||
# (notes/2026-05-02-parley-wasm-feature-matrix.md "## 结论" 段)
|
||||
parley = { version = "0.2", default-features = false, features = ["std"] }
|
||||
taffy = { version = "0.6", default-features = false, features = ["std", "taffy_tree", "flexbox", "grid", "block_layout", "content_size"] }
|
||||
# v19 pivot: glam Vec2 用作 Point2D;bitflags 用于 widget facade 内部 flag。
|
||||
glam = { version = "0.29", default-features = false, features = ["std"] }
|
||||
bitflags = "2"
|
||||
|
||||
# v19 pivot: re-export Jian render/geometry/scene types (spec §5.2 widget-facing facade
|
||||
# wraps jian-core; native-only deps live in shell-native, jian-core itself is wasm32-clean).
|
||||
# 双写 path + version per spec §12.2 ("path dep with explicit version") —— 防 cargo
|
||||
# 在不同 workspace context 下因 version 不一致退化到错版本。
|
||||
jian-core = { path = "../../vendor/jian/crates/jian-core", version = "0.0.1" }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
|
|
|||
41
crates/openpencil-shell-core/src/jian.rs
Normal file
41
crates/openpencil-shell-core/src/jian.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
//! Jian re-export module (spec v19 §2 / §1.2).
|
||||
//!
|
||||
//! `openpencil-shell-core` 是 Jian 薄 wrapper —— 把
|
||||
//! `jian_core::render::{DrawOp, Paint, TextRun, …}` 经 OP 层 re-export 给
|
||||
//! shell-native 内部翻译用。geometry / scene 类型加 `Jian*` 前缀,避免
|
||||
//! 与 OP 自有 `Rect` / `Color` (`render_backend.rs`) 冲突。
|
||||
//!
|
||||
//! **契约(spec §5.2.1 §746 行)**:v19 wrapper 在 NativeBackend impl 内
|
||||
//! **不让 widget code 直接看到 `jian_core::render::DrawOp`** —— widget 只
|
||||
//! 调 OP `RenderBackend` method。这些 re-export 是给 **shell-native 内部**
|
||||
//! 翻译用,不是给 widget code 用。
|
||||
|
||||
// ────────────────────────────────────────────────────────────────────────────
|
||||
// jian_core::render —— DrawOp 命令缓冲 + Paint / TextRun / 其它绘图描述符
|
||||
// ────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
pub use jian_core::render::{
|
||||
BorderRadii, DrawOp, GradientStop, ImageSource, LinearGradient, Paint, PathCommand,
|
||||
RadialGradient, RenderCommand, ShadowSpec, StrokeOp, TextAlign, TextRun,
|
||||
};
|
||||
|
||||
// ────────────────────────────────────────────────────────────────────────────
|
||||
// jian_core::geometry —— 加 Jian* 前缀避免与 OP `Rect` 冲突
|
||||
// ────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/// Jian 的 axis-aligned 矩形 (`euclid::Rect<f32>`)。
|
||||
/// OP 自有 `crate::render_backend::Rect` 是 widget facade 用;shell-native
|
||||
/// 内部翻译时把 OP `Rect` → `JianRect`(`origin/size` → `euclid::Rect::new`)。
|
||||
pub type JianRect = jian_core::geometry::Rect;
|
||||
pub type Size = jian_core::geometry::Size;
|
||||
pub type JianPoint = jian_core::geometry::Point;
|
||||
pub type Affine2 = jian_core::geometry::Affine2;
|
||||
|
||||
// ────────────────────────────────────────────────────────────────────────────
|
||||
// jian_core::scene —— Color (packed u32) 加 Jian* 前缀
|
||||
// ────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/// Jian 的 packed-RGBA 颜色 (`pub struct Color(pub u32)`);与 OP
|
||||
/// `crate::render_backend::Color` (RGBA f32 quad) 不同。NativeBackend 内部
|
||||
/// 翻译 OP Color → JianColor 时用位打包。
|
||||
pub type JianColor = jian_core::scene::Color;
|
||||
|
|
@ -1,20 +1,18 @@
|
|||
//! OpenPencil shell core — platform-agnostic widget tree + render-backend trait.
|
||||
//! OpenPencil shell core — platform-agnostic widget facade + RenderBackend trait.
|
||||
//!
|
||||
//! Per kickoff spec §1.2 (FROZEN 2026-05-02): this crate must compile on
|
||||
//! Per spec v19 §1.2 (FROZEN 2026-05-04): this crate must compile on
|
||||
//! wasm32-unknown-unknown. winit / accesskit_winit / skia-safe live in
|
||||
//! `openpencil-shell-native`; wasm-bindgen / web-sys / CanvasKit live in
|
||||
//! `openpencil-shell-web`.
|
||||
//!
|
||||
//! v19 pivot — 该 crate 是 Jian 薄 wrapper:
|
||||
//! - [`jian`] 模块 re-export `jian_core::render::{DrawOp, Paint, TextRun, …}`
|
||||
//! + geometry/scene aliases,给 shell-native 内部翻译用(widget code 看不到)。
|
||||
//! - [`render_backend`] 模块定义 OP 自有 widget-facing facade
|
||||
//! (`RenderBackend` trait + `Rect` / `Color` / `TextLayout`,spec §5.2)。
|
||||
|
||||
pub fn placeholder() -> &'static str {
|
||||
"openpencil-shell-core skeleton"
|
||||
}
|
||||
pub mod jian;
|
||||
pub mod render_backend;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn skeleton_returns_string() {
|
||||
assert_eq!(placeholder(), "openpencil-shell-core skeleton");
|
||||
}
|
||||
}
|
||||
// Re-export 主要 API 给上层 crate / widgets / tests 用。
|
||||
pub use render_backend::{Color, Point2D, Rect, RenderBackend, TextLayout};
|
||||
|
|
|
|||
181
crates/openpencil-shell-core/src/render_backend.rs
Normal file
181
crates/openpencil-shell-core/src/render_backend.rs
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
//! OP `RenderBackend` widget-facing facade (spec v19 §5.2).
|
||||
//!
|
||||
//! 这是 OP 的设计契约(method-style API:`fill_rect / stroke_rect / draw_text /
|
||||
//! clip_rect / save / restore / translate / resize / dpi_scale`),与 Jian
|
||||
//! `jian_core::render::RenderBackend`(command-buffer style,`new_surface /
|
||||
//! begin_frame / draw(&DrawOp)` etc.)不直接重合。
|
||||
//!
|
||||
//! 实现路径 (per §5.2.1):
|
||||
//! - `NativeBackend` (shell-native, Step 1a 起 frame-scoped 设计):**不**直接
|
||||
//! impl 该 trait,而是 expose 同名 method 但带 `canvas: &skia_safe::Canvas`
|
||||
//! 显式参数。Step 1a basic_window demo 通过 `SharedSkiaContext::with_frame`
|
||||
//! 闭包内调 NativeBackend method。Step 1c+ 真接入 widget tree 时再考虑用
|
||||
//! `WithCanvas<'a>` newtype 把 canvas 注入 trait impl。
|
||||
//! - `WebCanvasKitBackend` (shell-web, Step 1b):内部用 CanvasKit JS binding。
|
||||
//! - `MobileBackend` (Step 1f):内部用 Metal / Vulkan / OpenGL ES。
|
||||
//!
|
||||
//! 该模块**不**引 skia-safe / Canvas / GL 类型 —— shell-core 必须 wasm32-clean
|
||||
//! (per spec §1.2 boundary)。
|
||||
|
||||
use jian_core::render::{TextAlign, TextRun};
|
||||
|
||||
/// 2D 坐标点(spec §5.2 钉死 `glam::Vec2`)。
|
||||
pub type Point2D = glam::Vec2;
|
||||
|
||||
/// 矩形(origin + size 双 Vec2 表示)。
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Rect {
|
||||
pub origin: Point2D,
|
||||
pub size: Point2D,
|
||||
}
|
||||
|
||||
/// RGBA color(widget facade 层;所有分量 0.0..=1.0)。
|
||||
///
|
||||
/// 命名常量定义在 OP 这层(spec v19 round 5 CONCERN-R5-3 fix);
|
||||
/// `jian_core::scene::Color` 是 `Color(pub u32)` packed RGBA,没有
|
||||
/// RED/BLACK/etc 命名常量,调用方用 `JianColor::rgb(...)` 显式构造。
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Color {
|
||||
pub r: f32,
|
||||
pub g: f32,
|
||||
pub b: f32,
|
||||
pub a: f32,
|
||||
}
|
||||
|
||||
impl Color {
|
||||
pub const RED: Self = Self {
|
||||
r: 1.0,
|
||||
g: 0.0,
|
||||
b: 0.0,
|
||||
a: 1.0,
|
||||
};
|
||||
pub const GREEN: Self = Self {
|
||||
r: 0.0,
|
||||
g: 1.0,
|
||||
b: 0.0,
|
||||
a: 1.0,
|
||||
};
|
||||
pub const BLUE: Self = Self {
|
||||
r: 0.0,
|
||||
g: 0.0,
|
||||
b: 1.0,
|
||||
a: 1.0,
|
||||
};
|
||||
pub const BLACK: Self = Self {
|
||||
r: 0.0,
|
||||
g: 0.0,
|
||||
b: 0.0,
|
||||
a: 1.0,
|
||||
};
|
||||
pub const WHITE: Self = Self {
|
||||
r: 1.0,
|
||||
g: 1.0,
|
||||
b: 1.0,
|
||||
a: 1.0,
|
||||
};
|
||||
pub const TRANSPARENT: Self = Self {
|
||||
r: 0.0,
|
||||
g: 0.0,
|
||||
b: 0.0,
|
||||
a: 0.0,
|
||||
};
|
||||
}
|
||||
|
||||
/// OP 的 TextLayout —— v19 删 parley 后定义在 OP 这层;薄薄包装
|
||||
/// `jian_core::render::TextRun`。
|
||||
///
|
||||
/// 不持 layout context / glyph cache(shell-core wasm32-clean,不能引
|
||||
/// skia/parley/icu);真 layout 在 NativeBackend::draw_text 时通过
|
||||
/// `jian_skia::SkiaBackend` 的 textlayout feature(skia textlayout,
|
||||
/// ICU+harfbuzz)做 shape + line break。
|
||||
///
|
||||
/// Step 1a TextLayout 仅作 "已 shape 的 TextRun 集合" 占位;
|
||||
/// caret/selection/bidi/wrap 推 Step 1c+。signatures 钉死,避免后续 Step
|
||||
/// API break。
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TextLayout {
|
||||
runs: Vec<TextRun>,
|
||||
}
|
||||
|
||||
impl TextLayout {
|
||||
/// 单 run 构造(Step 1a 唯一活跃路径;Phase B/C demo + raster_text_smoke 用)。
|
||||
///
|
||||
/// 字段对齐 `jian_core::render::TextRun` (`vendor/jian/crates/jian-core/src/render/paint.rs:77-94`):
|
||||
/// **TextRun 没有 `Default` impl**,必须显式构造所有字段。
|
||||
/// - `content` / `font_family` / `font_size` / `color` / `origin`:调用方传入
|
||||
/// - `font_weight: 400` (CSS Normal)
|
||||
/// - `max_width: 0.0`("unknown; render at origin with no alignment adjustment")
|
||||
/// - `align: TextAlign::Start`
|
||||
/// - `line_height: 0.0`("default")
|
||||
pub fn single_run(
|
||||
content: &str,
|
||||
font_family: &str,
|
||||
font_size: f32,
|
||||
color: jian_core::scene::Color,
|
||||
origin: Point2D,
|
||||
) -> Self {
|
||||
let run = TextRun {
|
||||
content: content.to_string(),
|
||||
font_family: font_family.to_string(),
|
||||
font_size,
|
||||
font_weight: 400,
|
||||
color,
|
||||
origin: jian_core::geometry::Point::new(origin.x, origin.y),
|
||||
max_width: 0.0,
|
||||
align: TextAlign::Start,
|
||||
line_height: 0.0,
|
||||
};
|
||||
Self { runs: vec![run] }
|
||||
}
|
||||
|
||||
/// 已 shape 的 TextRun 集合视图。
|
||||
pub fn runs(&self) -> &[TextRun] {
|
||||
&self.runs
|
||||
}
|
||||
|
||||
/// 平移所有 run 的 origin(NativeBackend::draw_text 在 widget origin
|
||||
/// 基础上做平移)。返回新 layout,原 layout 不动。
|
||||
pub fn translated(&self, offset: Point2D) -> Self {
|
||||
let runs = self
|
||||
.runs
|
||||
.iter()
|
||||
.map(|r| {
|
||||
let mut r2 = r.clone();
|
||||
r2.origin =
|
||||
jian_core::geometry::Point::new(r.origin.x + offset.x, r.origin.y + offset.y);
|
||||
r2
|
||||
})
|
||||
.collect();
|
||||
Self { runs }
|
||||
}
|
||||
}
|
||||
|
||||
/// Backend 抽象(widget-facing facade,spec §5.2)。
|
||||
///
|
||||
/// 注:trait 不加 `Send` bound —— skia-safe 类型 `!Send`(rust-skia
|
||||
/// thread-bound),Backend 在 render thread 内单独使用,无跨线程需求。
|
||||
///
|
||||
/// `NativeBackend` (shell-native) 在 1a **不**直接 impl 该 trait(v19 round 3
|
||||
/// BLOCK-R3-3 fix —— frame-scoped 设计避免跨帧 borrow),而是 expose 同名
|
||||
/// method 但带 `canvas: &skia_safe::Canvas` 显式参数。trait 签名内不出现任何
|
||||
/// Skia / GPU-backend 特定类型。
|
||||
pub trait RenderBackend {
|
||||
/// Begin 帧,backend 内部维护 current frame state(不暴露 canvas 类型)。
|
||||
fn begin_frame(&mut self);
|
||||
fn end_frame(&mut self);
|
||||
|
||||
// 绘图 primitives —— widgets 调这些,不直接操作 canvas。
|
||||
fn fill_rect(&mut self, rect: Rect, color: Color);
|
||||
fn stroke_rect(&mut self, rect: Rect, color: Color, width: f32);
|
||||
fn draw_text(&mut self, layout: &TextLayout, origin: Point2D);
|
||||
fn clip_rect(&mut self, rect: Rect);
|
||||
|
||||
// 变换栈。
|
||||
fn save(&mut self);
|
||||
fn restore(&mut self);
|
||||
fn translate(&mut self, offset: Point2D);
|
||||
|
||||
// viewport / dpi。
|
||||
fn resize(&mut self, width: u32, height: u32);
|
||||
fn dpi_scale(&self) -> f32;
|
||||
}
|
||||
87
crates/openpencil-shell-core/tests/jian_re_export.rs
Normal file
87
crates/openpencil-shell-core/tests/jian_re_export.rs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
//! Task 1 Step 20-21: prove the Jian re-export wrapper compiles & is usable.
|
||||
//!
|
||||
//! Two anchor invariants for spec v19 §2 / §5.2:
|
||||
//! 1. `DrawOp::Rect` constructible **through OP re-export path**
|
||||
//! (`openpencil_shell_core::jian::DrawOp` —— shell-native 内部翻译用)。
|
||||
//! 2. `TextLayout::single_run` 产生**恰好一个** `TextRun`(spec §5.2,
|
||||
//! 确认 `..Default::default()` 替代成显式字段后语义等价)。
|
||||
|
||||
use openpencil_shell_core::jian::{DrawOp, JianRect, Paint};
|
||||
use openpencil_shell_core::render_backend::{Color, Point2D, TextLayout};
|
||||
|
||||
#[test]
|
||||
fn drawop_rect_constructible_via_re_export() {
|
||||
// 通过 OP re-export 路径构造 Jian DrawOp::Rect —— 证明 shell-core 的
|
||||
// jian 模块把 jian_core::render::{DrawOp, Paint} 暴露出来了。
|
||||
let rect = JianRect::new(
|
||||
jian_core::geometry::Point::new(0.0, 0.0),
|
||||
jian_core::geometry::Size::new(100.0, 50.0),
|
||||
);
|
||||
let paint = Paint::solid(jian_core::scene::Color::rgb(255, 0, 0));
|
||||
let op = DrawOp::Rect { rect, paint };
|
||||
|
||||
match op {
|
||||
DrawOp::Rect { rect, .. } => {
|
||||
assert_eq!(rect.size.width, 100.0);
|
||||
assert_eq!(rect.size.height, 50.0);
|
||||
}
|
||||
_ => panic!("expected DrawOp::Rect"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn text_layout_single_run_creates_one_run() {
|
||||
// 显式字段构造(TextRun 没 Default impl)—— 证明 spec §5.2 的
|
||||
// single_run 路径产生恰好一个 run,content/font_family/font_size
|
||||
// 都按调用方传入设置。
|
||||
let layout = TextLayout::single_run(
|
||||
"Hello",
|
||||
"system-ui",
|
||||
16.0,
|
||||
jian_core::scene::Color::rgb(0, 0, 0),
|
||||
Point2D::new(10.0, 20.0),
|
||||
);
|
||||
|
||||
assert_eq!(layout.runs().len(), 1);
|
||||
|
||||
let run = &layout.runs()[0];
|
||||
assert_eq!(run.content, "Hello");
|
||||
assert_eq!(run.font_family, "system-ui");
|
||||
assert_eq!(run.font_size, 16.0);
|
||||
assert_eq!(run.font_weight, 400);
|
||||
assert_eq!(run.origin.x, 10.0);
|
||||
assert_eq!(run.origin.y, 20.0);
|
||||
assert_eq!(run.max_width, 0.0);
|
||||
assert_eq!(run.line_height, 0.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn text_layout_translated_offsets_origin() {
|
||||
// translated() 把 offset 加到每 run origin 上;原 layout 不变。
|
||||
let layout = TextLayout::single_run(
|
||||
"World",
|
||||
"system-ui",
|
||||
14.0,
|
||||
jian_core::scene::Color::rgb(0, 0, 0),
|
||||
Point2D::new(5.0, 10.0),
|
||||
);
|
||||
let shifted = layout.translated(Point2D::new(100.0, 200.0));
|
||||
|
||||
assert_eq!(shifted.runs()[0].origin.x, 105.0);
|
||||
assert_eq!(shifted.runs()[0].origin.y, 210.0);
|
||||
|
||||
// 原 layout 不动
|
||||
assert_eq!(layout.runs()[0].origin.x, 5.0);
|
||||
assert_eq!(layout.runs()[0].origin.y, 10.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_color_constants_distinct() {
|
||||
// spec §5.2 命名常量 6 全 —— RED/GREEN/BLUE/BLACK/WHITE/TRANSPARENT。
|
||||
assert_eq!(Color::RED.r, 1.0);
|
||||
assert_eq!(Color::GREEN.g, 1.0);
|
||||
assert_eq!(Color::BLUE.b, 1.0);
|
||||
assert_eq!(Color::BLACK.r, 0.0);
|
||||
assert_eq!(Color::WHITE.r, 1.0);
|
||||
assert_eq!(Color::TRANSPARENT.a, 0.0);
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ version.workspace = true
|
|||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
license.workspace = true
|
||||
description = "OpenPencil shell — native (winit + skia-safe + accesskit) backend"
|
||||
description = "OpenPencil shell — native (winit + skia-safe + accesskit) backend, integrating jian-skia + jian-host-desktop sub-pieces (spec v19 §3 / §5.2.1)"
|
||||
|
||||
[lib]
|
||||
name = "openpencil_shell_native"
|
||||
|
|
@ -17,17 +17,37 @@ openpencil-shell-core = { path = "../openpencil-shell-core", version = "0.1.0" }
|
|||
# 如果不 cfg-gate,cargo 会先 fetch + run skia-safe 的 build.rs(在 wasm32 上构建失败),
|
||||
# Step 5 grep `must NOT be compiled for wasm32` 永远命中不到——会被 skia 错误盖过。
|
||||
#
|
||||
# Phase 1 skeleton 阶段:故意保持 deps 最小,仅声明意图所需的核心 crate(winit)。
|
||||
# skia-safe / accesskit / accesskit_winit 等在 Stage F 真正实现 RenderBackend 时再加。
|
||||
# 原因:Rust 1.80 toolchain (rust-toolchain.toml) 对 home/hashbrown 等 crate 当前
|
||||
# 版本的 edition2024 / MSRV 1.81+ 需求不兼容,加完整依赖会导致下载阶段失败。
|
||||
# 详见提交说明 + Phase 1 Gate codex review。
|
||||
# v19 pivot (Task 1): 加 P0-pinned GL stack + jian-skia + jian-host-desktop。
|
||||
# - P0 dep-stack pin 来自 P0 probe(plan v7 §Task P0;skia-safe 0.97 + glow 0.17 +
|
||||
# glutin 0.32.3 + glutin-winit 0.5.0 + winit 0.30.13 + raw-window-handle 0.6.2 +
|
||||
# scopeguard 1.2 全在 macOS/Windows/Linux GO)。
|
||||
# - jian-skia (textlayout feature) 提供 SkiaBackend impl + skia textlayout(替代 parley)。
|
||||
# - jian-host-desktop (target-gate desktop only, 不含 `run` feature) 复用 PointerTranslator /
|
||||
# scene::collect_draws_with_state / DesktopHost config helpers;OP 自管 GPU event loop,
|
||||
# 不调 jian_host_desktop::run(softbuffer raster present 不需要)。
|
||||
#
|
||||
# winit features 说明:on Linux 必须显式开 `x11` 和/或 `wayland`,否则
|
||||
# `platform_impl/mod.rs` 触发 `compile_error!("The platform you're compiling for is
|
||||
# not supported by winit")`. macOS / Windows 各自的 backend 通过 cfg(target_os)
|
||||
# 默认启用,不需要 feature flag。Step 1a 只在三大桌面 OS 跑 CI,所以同时打开
|
||||
# x11 + wayland 两个 Linux backend 就够。Stage F 真正接 RenderBackend 时会
|
||||
# 重新审视(可能加 `serde` / `rwh_06` 等)。
|
||||
# `platform_impl/mod.rs` 触发 `compile_error!`. macOS / Windows 各自的 backend 通过
|
||||
# cfg(target_os) 默认启用,不需要 feature flag。Step 1a 三大桌面 OS CI 都跑,
|
||||
# 所以同时打开 x11 + wayland 两个 Linux backend 就够。
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
winit = { version = "0.30", default-features = false, features = ["x11", "wayland", "wayland-csd-adwaita", "rwh_06"] }
|
||||
skia-safe = { version = "0.97.0", features = ["gl"] }
|
||||
glutin = "0.32.3"
|
||||
glutin-winit = "0.5.0"
|
||||
glow = "0.17.0"
|
||||
winit = { version = "0.30.13", default-features = false, features = ["x11", "wayland", "wayland-csd-adwaita", "rwh_06"] }
|
||||
raw-window-handle = "0.6.2"
|
||||
scopeguard = "1.2"
|
||||
|
||||
# Jian path deps —— 双写 path + version per spec §12.2。
|
||||
# jian-skia: 提供 SkiaBackend (RenderBackend impl) + skia textlayout (textlayout feature
|
||||
# 需要 ICU + harfbuzz, ~15MB;P0.5 已升 skia-safe 0.78→0.97 + 新增 pub draw_on_canvas).
|
||||
jian-skia = { path = "../../vendor/jian/crates/jian-skia", version = "0.0.1", features = ["textlayout"] }
|
||||
|
||||
# jian-host-desktop: target-gate desktop only (Linux/macOS/Windows);不进 android/ios
|
||||
# metadata(Task 1 Step 26 boundary check 验证)。
|
||||
# - default-features = false:Jian 默认 features 含 `run = ["dep:softbuffer"]` 拉
|
||||
# raster present;OP 自管 GPU event loop 不需要 softbuffer。
|
||||
# - features = ["textlayout"]:与 jian-skia 对齐文本路径。
|
||||
[target.'cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))'.dependencies]
|
||||
jian-host-desktop = { path = "../../vendor/jian/crates/jian-host-desktop", version = "0.0.1", default-features = false, features = ["textlayout"] }
|
||||
|
|
|
|||
|
|
@ -1,20 +1,27 @@
|
|||
//! OpenPencil shell — native (desktop) backend.
|
||||
//!
|
||||
//! Per kickoff spec §1.2: this crate must NOT be linked into the wasm32-unknown-unknown
|
||||
//! web bundle. Even though some deps (winit) compile silently on wasm32 via web-sys,
|
||||
//! we use an explicit compile_error! guard to make accidental inclusion a hard error.
|
||||
//! Per spec v19 §1.2 (FROZEN 2026-05-04): this crate must NOT be linked into
|
||||
//! the wasm32-unknown-unknown web bundle. Even though some deps (winit) compile
|
||||
//! silently on wasm32 via web-sys, we use an explicit compile_error! guard to
|
||||
//! make accidental inclusion a hard error.
|
||||
//!
|
||||
//! Step 1a Task 1 状态:仅装 deps(P0-pinned GL stack + jian-skia +
|
||||
//! jian-host-desktop);SharedSkiaContext / NativeBackend 实现在 Task 2 加。
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
compile_error!(
|
||||
"openpencil-shell-native must NOT be compiled for wasm32 targets. \
|
||||
Use openpencil-shell-web for browser builds (kickoff spec §1.2)."
|
||||
Use openpencil-shell-web for browser builds (spec v19 §1.2)."
|
||||
);
|
||||
|
||||
pub fn placeholder() -> String {
|
||||
format!(
|
||||
"openpencil-shell-native skeleton ({})",
|
||||
openpencil_shell_core::placeholder()
|
||||
)
|
||||
/// Skeleton placeholder until Task 2 lands `SharedSkiaContext` / `NativeBackend`.
|
||||
///
|
||||
/// 用 OP `Color::RED` 命名常量证明 shell-core re-export 链通了;这是最小
|
||||
/// link-check (Step 1a Task 1 不实现 Skia surface 与 GL provider,那些
|
||||
/// 是 Task 2 的范围)。
|
||||
pub fn placeholder() -> &'static str {
|
||||
let _red = openpencil_shell_core::Color::RED;
|
||||
"openpencil-shell-native skeleton (Task 1: deps wired)"
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
@ -23,6 +30,6 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn skeleton_links_core() {
|
||||
assert!(placeholder().contains("openpencil-shell-core"));
|
||||
assert!(placeholder().contains("Task 1"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,21 @@
|
|||
//! OpenPencil shell — web (wasm32) bundle entry.
|
||||
//!
|
||||
//! Per kickoff spec §1.2: this crate is the web bundle entry. CI invariant
|
||||
//! requires `cargo check --target wasm32-unknown-unknown -p openpencil-shell-web
|
||||
//! --no-default-features --features web` to pass on every PR.
|
||||
//! Per spec v19 §1.2 (FROZEN 2026-05-04): this crate is the web bundle entry.
|
||||
//! CI invariant requires `cargo check --target wasm32-unknown-unknown -p
|
||||
//! openpencil-shell-web --no-default-features --features web` to pass on
|
||||
//! every PR.
|
||||
//!
|
||||
//! Step 1a Task 1 状态:仅 link-check shell-core re-export;CanvasKit
|
||||
//! WebBackend 在 Step 1b 加。
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
/// Skeleton placeholder until Step 1b lands `WebCanvasKitBackend`.
|
||||
///
|
||||
/// 用 OP `Color::TRANSPARENT` 命名常量证明 shell-core re-export 在 wasm32
|
||||
/// 链通了;这是最小 link-check(shell-core 必须 wasm32-clean per spec §1.2)。
|
||||
#[wasm_bindgen]
|
||||
pub fn placeholder() -> String {
|
||||
format!(
|
||||
"openpencil-shell-web skeleton ({})",
|
||||
openpencil_shell_core::placeholder()
|
||||
)
|
||||
let _t = openpencil_shell_core::Color::TRANSPARENT;
|
||||
"openpencil-shell-web skeleton (Task 1: deps wired)".to_string()
|
||||
}
|
||||
|
|
|
|||
1
vendor/jian
vendored
Submodule
1
vendor/jian
vendored
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit ad13ce6283caf402e71608d362e837b09140331b
|
||||
Loading…
Reference in a new issue