path_kit/lib.rs
1//! # path-kit
2//!
3//! 基于 Skia PathOps 和 PathKit 的 Rust 路径运算库,提供 safe 的 API 封装。
4//! A Rust path operations library based on Skia PathOps and PathKit with safe API wrappers.
5//!
6//! ## 功能 / Features
7//!
8//! - **路径构建**:线段、二次/三次贝塞尔、矩形、椭圆、圆、圆角矩形、RRect(四角独立半径)
9//! Path construction: lines, quadratic/cubic bezier, rect, oval, circle, round rect, RRect (per-corner radii)
10//! - **路径布尔运算**:并集、交集、差集、异或
11//! Path boolean operations: union, intersect, difference, xor
12//! - **路径简化、包围盒**:`simplify`, `path.tight_bounds`, `pathops_tight_bounds`
13//! Path simplification and tight bounds computation
14//! - **路径迭代**:按动词遍历 Move/Line/Quad/Cubic/Close
15//! Path iteration over verbs and points
16//! - **描边**:将路径转为描边轮廓
17//! Stroke: convert path to stroked outline
18//!
19//! ## 线程安全 / Thread safety
20//!
21//! 当前未保证 `Send` / `Sync`,请勿跨线程共享 `Path`、`RRect`、`StrokeRec` 等类型。
22//! `Send` / `Sync` are not guaranteed; do not share `Path`, `RRect`, `StrokeRec`, etc. across threads.
23//!
24//! ## 类型概览 / Types
25//!
26//! | 类型 | 说明 |
27//! |------|------|
28//! | [`Path`] | 路径 |
29//! | [`Rect`] | 矩形 |
30//! | [`RRect`] | 圆角矩形(支持四角独立半径) |
31//! | [`Point`] | 二维点 |
32//! | [`Direction`] | 绘制方向 Cw/Ccw |
33//! | [`RectCorner`] | 矩形起始角 |
34//! | [`PathOp`] | 布尔运算类型 |
35//! | [`PathVerbItem`] | 路径迭代项 |
36//! | [`PathMeasure`] | 路径测量(长度、位置、切线、段提取) |
37//! | [`StrokeRec`] | 描边参数 |
38//! | [`StrokeCap`] | 线端样式 Butt/Round/Square |
39//! | [`StrokeJoin`] | 转角样式 Miter/Round/Bevel |
40//! | [`Paint`] | 绘图参数(含 Style、Stroke) |
41//! | [`PaintStyle`] | 绘图样式 Fill/Stroke/StrokeAndFill |
42//!
43//! ## 示例 / Examples
44//!
45//! ### 路径布尔运算 / Path boolean ops
46//!
47//! ```rust
48//! use path_kit::{Path, Rect, Direction, RectCorner, PathOp, path_op, OpBuilder};
49//!
50//! let mut path1 = Path::new();
51//! path1.add_rect(&Rect::new(0.0, 0.0, 100.0, 100.0), Direction::Cw, RectCorner::UpperLeft);
52//!
53//! let mut path2 = Path::new();
54//! path2.add_rect(&Rect::new(50.0, 50.0, 150.0, 150.0), Direction::Cw, RectCorner::UpperLeft);
55//!
56//! let union = path_op(&path1, &path2, PathOp::Union).unwrap();
57//!
58//! // 批量运算 / Batch operations (use add_ref to avoid clone when reusing paths)
59//! let result = OpBuilder::new()
60//! .add_ref(&path1, PathOp::Union)
61//! .add_ref(&path2, PathOp::Union)
62//! .resolve()
63//! .unwrap();
64//! ```
65//!
66//! ### 圆角矩形 RRect / Rounded rect with per-corner radii
67//!
68//! ```rust
69//! use path_kit::{Path, Rect, RRect, Radii, Direction, RectCorner};
70//!
71//! // 统一圆角 / Uniform radii
72//! let rr = RRect::from_rect_xy(&Rect::new(0.0, 0.0, 100.0, 50.0), 10.0, 10.0);
73//! let mut path = Path::new();
74//! path.add_rrect(&rr, Direction::Cw);
75//!
76//! // 四角独立半径 / Per-corner radii
77//! let radii = [
78//! Radii { x: 10.0, y: 10.0 },
79//! Radii { x: 20.0, y: 10.0 },
80//! Radii { x: 10.0, y: 20.0 },
81//! Radii { x: 5.0, y: 5.0 },
82//! ];
83//! let rr2 = RRect::from_rect_radii(&Rect::new(0.0, 0.0, 80.0, 60.0), &radii);
84//! path.add_rrect(&rr2, Direction::Ccw);
85//! ```
86//!
87//! ### 路径迭代 / Path iteration
88//!
89//! ```rust
90//! use path_kit::{Path, PathVerbItem};
91//!
92//! let mut path = Path::new();
93//! path.move_to(0.0, 0.0).line_to(100.0, 0.0).line_to(100.0, 100.0).close();
94//!
95//! for item in path.iter(false) {
96//! match item {
97//! PathVerbItem::Move(p) => println!("Move to {:?}", p),
98//! PathVerbItem::Line(from, to) => println!("Line {:?} -> {:?}", from, to),
99//! PathVerbItem::Quad(c, to) => println!("Quad {:?} -> {:?}", c, to),
100//! PathVerbItem::Cubic(c1, c2, to) => println!("Cubic -> {:?}", to),
101//! PathVerbItem::Close => println!("Close"),
102//! _ => {}
103//! }
104//! }
105//! ```
106//!
107//! ### 描边 / Stroke
108//!
109//! ```rust
110//! use path_kit::{Path, StrokeRec};
111//!
112//! let rec = StrokeRec::new_stroke(4.0, false);
113//! let mut path = Path::new();
114//! path.move_to(0.0, 0.0).line_to(100.0, 0.0);
115//! let stroked = rec.apply_to_path(&path).unwrap();
116//! ```
117//!
118//! ### 路径测量 / Path measure
119//!
120//! ```rust
121//! use path_kit::{Path, PathMeasure};
122//!
123//! let mut path = Path::new();
124//! path.move_to(0.0, 0.0).line_to(100.0, 0.0);
125//! let mut measure = PathMeasure::from_path(&path, false, 1.0);
126//! let len = measure.length(); // ~100
127//! let (pos, tan) = measure.pos_tan(50.0).unwrap(); // position & tangent at midpoint
128//! let mut segment = Path::new();
129//! measure.get_segment(25.0, 75.0, &mut segment, true); // extract sub-path
130//! ```
131//!
132//! ### 路径简化与包围盒 / Simplify and bounds
133//!
134//! ```rust
135//! use path_kit::{Path, simplify, pathops_tight_bounds};
136//!
137//! let mut path = Path::new();
138//! path.move_to(0.0, 0.0)
139//! .line_to(100.0, 0.0)
140//! .line_to(100.0, 100.0)
141//! .line_to(50.0, 50.0)
142//! .line_to(0.0, 100.0)
143//! .close();
144//!
145//! let simplified = simplify(&path).unwrap();
146//! let bounds = pathops_tight_bounds(&path).unwrap(); // or path.tight_bounds() for infallible
147//! ```
148
149/// PathKit(Skia PathOps)FFI 绑定(仅内部使用,不对外暴露)。
150/// PathKit (Skia PathOps) FFI bindings (internal only, not exposed to external users).
151#[doc(hidden)]
152#[allow(warnings)]
153mod pathkit {
154 pub use root::pk::*;
155 include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
156}
157
158mod corner_path_effect;
159mod dash_path_effect;
160mod direction;
161mod op_builder;
162mod ops;
163mod path;
164mod path_iter;
165mod path_measure;
166mod path_op;
167mod point;
168mod rect;
169mod rect_corner;
170mod rrect;
171mod paint;
172mod stroke_rec;
173
174pub use corner_path_effect::CornerPathEffect;
175pub use dash_path_effect::DashPathEffect;
176pub use direction::Direction;
177pub use op_builder::OpBuilder;
178pub use ops::{path_op, pathops_tight_bounds, simplify};
179pub use path::Path;
180pub use path_iter::{PathIter, PathVerb, PathVerbItem};
181pub use path_measure::PathMeasure;
182pub use path_op::PathOp;
183pub use point::Point;
184pub use rect::Rect;
185pub use rect_corner::RectCorner;
186pub use rrect::{Radii, RRect};
187pub use paint::{Paint, PaintStyle};
188pub use stroke_rec::{StrokeCap, StrokeJoin, StrokeRec, StrokeStyle};
189
190#[cfg(test)]
191mod tests;