path_offset/path/
subpath.rs

1use lyon::path::{Event, Iter as PathIter}; // 引入 lyon 的 Event 和迭代器类型 Iter,并重命名为 PathIter 以免混淆
2
3/// 一个迭代器,可以将一个包含多个图形的路径分解成单个的子路径。
4///
5/// 这个结构体及其 Iterator 实现,封装了从一个连续的路径事件流中
6/// 提取出独立子路径(从 Begin 到 End)的复杂状态管理逻辑。
7pub struct SubpathIter<'a> {
8    /// 持有对底层 lyon 路径事件流的迭代器。
9    iter: PathIter<'a>,
10}
11
12impl<'a> Iterator for SubpathIter<'a> {
13    // 每次迭代,我们都希望能产出一个完整的、我们自己的 Path 类型
14    type Item = super::Path;
15
16    /// 实现 next() 方法,这是迭代器的核心。
17    /// 每次调用,它会尝试构建并返回下一个完整的子路径。
18    fn next(&mut self) -> Option<Self::Item> {
19        // 这个 next() 方法的逻辑,是您提供的原始 for 循环的直接翻译。
20
21        // 1. 创建一个 Path Builder 来构建子路径。
22        //    我们从流中寻找下一个 `Begin` 事件来启动它。
23        let mut builder;
24        if let Some(event) = self.iter.find(|e| matches!(e, Event::Begin { .. })) {
25            if let Event::Begin { at } = event {
26                // 找到了起点,初始化 builder
27                let mut b = lyon::path::Path::builder();
28                b.begin(at);
29                builder = b;
30            } else {
31                // 理论上不可能发生,因为 find 已经保证了是 Begin
32                return None;
33            }
34        } else {
35            // 如果在整个事件流中再也找不到 Begin 事件,说明迭代结束了。
36            return None;
37        }
38
39        // 2. 既然已经有了启动的 builder,我们继续消耗事件流,
40        //    直到遇到对应的 `End` 事件。
41        for event in &mut self.iter {
42            match event {
43                Event::Line { to, .. } => {
44                    builder.line_to(to);
45                }
46                Event::Quadratic { ctrl, to, .. } => {
47                    builder.quadratic_bezier_to(ctrl, to);
48                }
49                Event::Cubic {
50                    ctrl1, ctrl2, to, ..
51                } => {
52                    builder.cubic_bezier_to(ctrl1, ctrl2, to);
53                }
54                Event::End { close, .. } => {
55                    // 遇到了 End,一个子路径构建完成。
56                    if close {
57                        builder.close();
58                    }
59                    // 构建出 lyon::path::Path,包装成我们自己的 Path,然后返回。
60                    // next() 方法的本次执行到此结束。
61                    return Some(super::Path {
62                        inner: builder.build(),
63                    });
64                }
65                Event::Begin { .. } => {
66                    // 如果在找到 End 之前又遇到了 Begin,
67                    // 这意味着上一个子路径没有正常结束。
68                    // 根据原始逻辑,我们应该结束当前构建并开始新的。
69                    // 在迭代器模式下,最简单的处理方式是就此打住,
70                    // 让下一次 next() 调用来处理这个新的 Begin 事件。
71                    // 但这意味着我们可能会丢失一个未闭合的路径。
72                    //
73                    // 为了忠实于您的原始代码(它会隐式地丢弃未完成的路径),
74                    // 我们在这里直接 break,然后返回 None。
75                    break;
76                }
77            }
78        }
79
80        // 如果 for 循环正常结束(意味着迭代器耗尽了),
81        // 但我们还没返回,说明最后一个子路径没有 End 事件。
82        // 您的原始代码会忽略这种情况,所以我们也返回 None。
83        None
84    }
85}
86
87/// 为我们自己的 Path 类型的引用实现 IntoIterator trait。
88/// 这使得可以直接在 for 循环中使用 `&Path`。
89impl<'a> IntoIterator for &'a super::Path {
90    type Item = super::Path;
91    type IntoIter = SubpathIter<'a>;
92
93    /// 定义如何从一个 `&Path` 创建出我们的 `SubpathIter` 迭代器。
94    fn into_iter(self) -> Self::IntoIter {
95        SubpathIter {
96            iter: self.inner.iter(),
97        }
98    }
99}