Skip to main content

path_kit/
op_builder.rs

1//! 路径操作构建器。Path operation builder for combining multiple paths.
2
3use crate::bridge::ffi;
4use crate::path::Path;
5use crate::PathOp;
6use cxx::UniquePtr;
7
8/// 路径操作构建器,用于批量执行路径布尔运算。
9/// Path operation builder, optimized for unioning/combining many paths.
10///
11/// 底层为 `pk::SkOpBuilder`,与 Skia PathKit 行为一致。
12/// Backed by `pk::SkOpBuilder`, matching Skia PathKit behavior.
13///
14/// 用法:多次 add 后调用 resolve 得到最终结果。
15/// Usage: call add multiple times, then resolve to get the final result.
16pub struct OpBuilder {
17    inner: UniquePtr<ffi::OpBuilderHolder>,
18}
19
20impl Default for OpBuilder {
21    fn default() -> Self {
22        Self::new()
23    }
24}
25
26impl OpBuilder {
27    /// 创建空构建器。Creates an empty builder.
28    pub fn new() -> Self {
29        Self {
30            inner: ffi::op_builder_new(),
31        }
32    }
33
34    /// 添加路径及对应操作(消费 `Path`,C++ 侧会拷贝几何)。
35    /// Adds a path with its boolean operation (consumes `Path`; native side copies geometry).
36    ///
37    /// 第一次 add 时相当于 (空路径 OP path),后续每次为 (当前结果 OP path)。
38    /// First add: (empty OP path). Each subsequent: (current_result OP path).
39    pub fn add(&mut self, path: Path, op: PathOp) -> &mut Self {
40        ffi::op_builder_add(self.inner.pin_mut(), path.as_cpp_ref(), op);
41        self
42    }
43
44    /// 按引用添加路径(C++ 侧拷贝几何,Rust 侧不消费 `Path`)。
45    /// Adds path by reference (native side copies geometry).
46    ///
47    /// 复用同一路径时比 `add(path.clone(), op)` 更简洁。
48    /// Convenient when reusing the same path.
49    pub fn add_ref(&mut self, path: &Path, op: PathOp) -> &mut Self {
50        ffi::op_builder_add(self.inner.pin_mut(), path.as_cpp_ref(), op);
51        self
52    }
53
54    /// 计算并返回所有路径运算的结果。Resolves all operations and returns the result.
55    ///
56    /// 调用后构建器会清空,可继续复用。
57    /// Builder is reset after resolve; can be reused.
58    pub fn resolve(&mut self) -> Option<Path> {
59        let mut result = Path::new();
60        let ok = ffi::op_builder_resolve(self.inner.pin_mut(), result.pin_cpp_mut());
61        if ok {
62            Some(result)
63        } else {
64            None
65        }
66    }
67}