Skip to main content

path_kit/
path_iter.rs

1//! 路径迭代器。Path iterator over verbs and points.
2
3use crate::path::Path;
4use crate::point::Point;
5use crate::pathkit;
6
7/// 路径动词,描述路径中的每个图元。Path verb - describes each element in the path.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum PathVerb {
10    /// 移动到新轮廓起点 / Move to start new contour
11    Move,
12    /// 直线 / Line segment
13    Line,
14    /// 二次贝塞尔 / Quadratic bezier
15    Quad,
16    /// 圆锥曲线(有理二次)/ Conic (rational quadratic)
17    Conic,
18    /// 三次贝塞尔 / Cubic bezier
19    Cubic,
20    /// 闭合轮廓 / Close contour
21    Close,
22    /// 迭代结束 / Iteration done
23    Done,
24}
25
26/// 单步迭代结果,含动词与关联点。Single iteration result with verb and points.
27#[derive(Debug, Clone)]
28pub enum PathVerbItem {
29    /// 移动到新起点 / Move to new contour start
30    Move(Point),
31    /// 直线段 (from, to),from 为上一端点 / Line segment (from, to), from is previous point
32    Line(Point, Point),
33    /// 二次贝塞尔 (control, to) / Quadratic bezier (control, to)
34    Quad(Point, Point),
35    /// 圆锥曲线 (control, to, weight) / Conic (control, to, weight)
36    Conic(Point, Point, f32),
37    /// 三次贝塞尔 (ctrl1, ctrl2, to) / Cubic bezier (ctrl1, ctrl2, to)
38    Cubic(Point, Point, Point),
39    /// 闭合轮廓 / Close contour
40    Close,
41}
42
43impl PathVerbItem {
44    /// 返回动词类型。Returns the verb kind.
45    pub fn verb(&self) -> PathVerb {
46        match self {
47            PathVerbItem::Move(_) => PathVerb::Move,
48            PathVerbItem::Line(_, _) => PathVerb::Line,
49            PathVerbItem::Quad(_, _) => PathVerb::Quad,
50            PathVerbItem::Conic(_, _, _) => PathVerb::Conic,
51            PathVerbItem::Cubic(_, _, _) => PathVerb::Cubic,
52            PathVerbItem::Close => PathVerb::Close,
53        }
54    }
55}
56
57/// 路径迭代器,按动词顺序遍历路径。Path iterator over verbs and points.
58pub struct PathIter<'a> {
59    _path: &'a Path,
60    inner: pathkit::SkPath_Iter,
61    pts: [pathkit::SkPoint; 4],
62}
63
64impl<'a> PathIter<'a> {
65    pub(crate) fn new(path: &'a Path, force_close: bool) -> Self {
66        let inner = unsafe {
67            pathkit::SkPath_Iter::new1(path.as_raw() as *const _, force_close)
68        };
69        let pts = [
70            pathkit::SkPoint { fX: 0.0, fY: 0.0 },
71            pathkit::SkPoint { fX: 0.0, fY: 0.0 },
72            pathkit::SkPoint { fX: 0.0, fY: 0.0 },
73            pathkit::SkPoint { fX: 0.0, fY: 0.0 },
74        ];
75        Self {
76            _path: path,
77            inner,
78            pts,
79        }
80    }
81}
82
83impl<'a> Iterator for PathIter<'a> {
84    type Item = PathVerbItem;
85
86    fn next(&mut self) -> Option<Self::Item> {
87        let verb = unsafe {
88            self.inner.next(self.pts.as_mut_ptr())
89        };
90        let v = verb as u32;
91        let item = match v {
92            pathkit::SkPath_Verb::kMove_Verb => PathVerbItem::Move(self.pts[0].into()),
93            pathkit::SkPath_Verb::kLine_Verb => {
94                PathVerbItem::Line(self.pts[0].into(), self.pts[1].into())
95            }
96            pathkit::SkPath_Verb::kQuad_Verb => {
97                PathVerbItem::Quad(self.pts[1].into(), self.pts[2].into())
98            }
99            pathkit::SkPath_Verb::kConic_Verb => {
100                // SkPath::Iter 不暴露 conicWeight,用 1.0 近似(椭圆/圆多为 0.5,此处简化)
101                // SkPath::Iter does not expose conicWeight; using 1.0 as approx (ellipse/circle often 0.5)
102                PathVerbItem::Conic(self.pts[1].into(), self.pts[2].into(), 1.0)
103            }
104            pathkit::SkPath_Verb::kCubic_Verb => PathVerbItem::Cubic(
105                self.pts[1].into(),
106                self.pts[2].into(),
107                self.pts[3].into(),
108            ),
109            pathkit::SkPath_Verb::kClose_Verb => PathVerbItem::Close,
110            pathkit::SkPath_Verb::kDone_Verb => return None,
111            _ => return None,
112        };
113        Some(item)
114    }
115}