Skip to main content

path_kit/
path_iter.rs

1//! 路径迭代器。Path iterator over verbs and points.
2
3use crate::bridge::ffi;
4use crate::path::Path;
5use crate::point::Point;
6use cxx::UniquePtr;
7
8/// 路径动词,与 `pk::SkPath::Verb` 一致。
9/// Path verb, matches `pk::SkPath::Verb`.
10pub use crate::bridge::ffi::PathVerb;
11
12/// 单步迭代结果,含动词与关联点。Single iteration result with verb and points.
13#[derive(Debug, Clone)]
14pub enum PathVerbItem {
15    /// 移动到新起点 / Move to new contour start
16    Move(Point),
17    /// 直线段 (from, to),from 为上一端点 / Line segment (from, to), from is previous point
18    Line(Point, Point),
19    /// 二次贝塞尔 (control, to) / Quadratic bezier (control, to)
20    Quad(Point, Point),
21    /// 圆锥曲线 (control, to, weight) / Conic (control, to, weight)
22    Conic(Point, Point, f32),
23    /// 三次贝塞尔 (ctrl1, ctrl2, to) / Cubic bezier (ctrl1, ctrl2, to)
24    Cubic(Point, Point, Point),
25    /// 闭合轮廓 / Close contour
26    Close,
27}
28
29impl PathVerbItem {
30    /// 返回动词类型。Returns the verb kind.
31    pub fn verb(&self) -> PathVerb {
32        match self {
33            PathVerbItem::Move(_) => PathVerb::Move,
34            PathVerbItem::Line(_, _) => PathVerb::Line,
35            PathVerbItem::Quad(_, _) => PathVerb::Quad,
36            PathVerbItem::Conic(_, _, _) => PathVerb::Conic,
37            PathVerbItem::Cubic(_, _, _) => PathVerb::Cubic,
38            PathVerbItem::Close => PathVerb::Close,
39        }
40    }
41}
42
43/// 路径迭代器,按动词顺序遍历路径。Path iterator over verbs and points.
44pub struct PathIter<'a> {
45    _path: &'a Path,
46    inner: UniquePtr<ffi::PathIterInner>,
47    p0: ffi::Point,
48    p1: ffi::Point,
49    p2: ffi::Point,
50    p3: ffi::Point,
51}
52
53impl<'a> PathIter<'a> {
54    pub(crate) fn new(path: &'a Path, force_close: bool) -> Self {
55        let inner = ffi::path_iter_new(path.as_raw(), force_close);
56        let z = ffi::Point { fX: 0.0, fY: 0.0 };
57        Self {
58            _path: path,
59            inner,
60            p0: z,
61            p1: z,
62            p2: z,
63            p3: z,
64        }
65    }
66}
67
68impl<'a> Iterator for PathIter<'a> {
69    type Item = PathVerbItem;
70
71    fn next(&mut self) -> Option<Self::Item> {
72        let v = ffi::path_iter_next(
73            self.inner.pin_mut(),
74            &mut self.p0,
75            &mut self.p1,
76            &mut self.p2,
77            &mut self.p3,
78        );
79        let item = match v {
80            PathVerb::Move => PathVerbItem::Move(self.p0.into()),
81            PathVerb::Line => PathVerbItem::Line(self.p0.into(), self.p1.into()),
82            PathVerb::Quad => PathVerbItem::Quad(self.p1.into(), self.p2.into()),
83            PathVerb::Conic => PathVerbItem::Conic(self.p1.into(), self.p2.into(), 1.0),
84            PathVerb::Cubic => PathVerbItem::Cubic(
85                self.p1.into(),
86                self.p2.into(),
87                self.p3.into(),
88            ),
89            PathVerb::Close => PathVerbItem::Close,
90            PathVerb::Done => return None,
91            _ => return None,
92        };
93        Some(item)
94    }
95}