slint/internal/core/textlayout/linebreak_simple.rs
Simon Hausmann f1fb451791 Make the line break iterators implement Clone
This is needed in the future to be able to roll back state within the
line breaking when we can't fit even a single word into the line and
have to go back to fitting glyph by glyph.

For the unicode line break iterator the clone is a little more complicated.
The iterator is clone, but the type is anonymous. I first had an
implementation to moved the iterator into a closure, which was cloned
via another control closure. But that's complicated and still involves
allocating the various bits & pieces the closure captures.

So instead the simpler solution used here is to allocate the breaks
into a shared vector.
2022-05-13 17:33:01 +02:00

42 lines
1.3 KiB
Rust

// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum BreakOpportunity {
Allowed,
Mandatory,
}
#[derive(Clone)]
pub struct LineBreakIterator<'a> {
it: core::str::CharIndices<'a>,
leading_whitespace: bool,
}
impl<'a> LineBreakIterator<'a> {
pub fn new(text: &'a str) -> Self {
Self { it: text.char_indices(), leading_whitespace: false }
}
}
impl<'a> Iterator for LineBreakIterator<'a> {
type Item = (usize, BreakOpportunity);
fn next(&mut self) -> Option<Self::Item> {
while let Some((byte_offset, char)) = self.it.next() {
let maybe_opportunity = match char {
'\u{2028}' | '\u{2029}' => Some(BreakOpportunity::Mandatory), // unicode line- and paragraph separators
'\n' => Some(BreakOpportunity::Mandatory), // ascii line break
_ if self.leading_whitespace => Some(BreakOpportunity::Allowed),
_ => None,
};
self.leading_whitespace = char.is_ascii_whitespace();
if let Some(opportunity) = maybe_opportunity {
return Some((byte_offset, opportunity));
}
}
None
}
}