| 1 | // Copyright © SixtyFPS GmbH <info@slint.dev> |
| 2 | // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 |
| 3 | |
| 4 | use core::marker::PhantomData; |
| 5 | |
| 6 | pub use unicode_linebreak::BreakOpportunity; |
| 7 | |
| 8 | use crate::SharedVector; |
| 9 | |
| 10 | #[derive (Clone)] |
| 11 | pub struct LineBreakIterator<'a> { |
| 12 | breaks: SharedVector<(usize, unicode_linebreak::BreakOpportunity)>, |
| 13 | pos: usize, |
| 14 | phantom: PhantomData<&'a str>, |
| 15 | } |
| 16 | |
| 17 | impl LineBreakIterator<'_> { |
| 18 | pub fn new(text: &str) -> Self { |
| 19 | let iterator: impl Iterator = unicode_linebreak::linebreaks(text).filter(|(offset: &usize, opportunity: &BreakOpportunity)| { |
| 20 | // unicode-linebreaks emits a mandatory break at the end of the text. We're not interested |
| 21 | // in that. |
| 22 | *offset != text.len() || !matches!(opportunity, BreakOpportunity::Mandatory) |
| 23 | }); |
| 24 | |
| 25 | Self { breaks: iterator.collect(), pos: 0, phantom: Default::default() } |
| 26 | } |
| 27 | } |
| 28 | |
| 29 | impl Iterator for LineBreakIterator<'_> { |
| 30 | type Item = (usize, unicode_linebreak::BreakOpportunity); |
| 31 | |
| 32 | fn next(&mut self) -> Option<Self::Item> { |
| 33 | if self.pos < self.breaks.len() { |
| 34 | let i: usize = self.pos; |
| 35 | self.pos += 1; |
| 36 | Some(self.breaks[i]) |
| 37 | } else { |
| 38 | None |
| 39 | } |
| 40 | } |
| 41 | } |
| 42 | |