Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use the whitespace flag in each glyph instead of going to the string for whitespace stripping. #8994

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -604,6 +604,10 @@ impl<'a> GlyphStore {
spaces
}

pub fn range_is_whitespace(&self, range: &Range<CharIndex>) -> bool {
range.each_index().all(|index| self.char_is_space(index))
}

pub fn distribute_extra_space_in_range(&mut self, range: &Range<CharIndex>, space: f64) {
debug_assert!(space >= 0.0);
if range.is_empty() {
@@ -115,7 +115,8 @@ impl<'a> Iterator for NaturalWordSliceIterator<'a> {
}

pub struct CharacterSliceIterator<'a> {
glyph_run: Option<&'a GlyphRun>,
next_glyph_run: Option<&'a GlyphRun>,
prev_glyph_run: Option<&'a GlyphRun>,
glyph_run_iter: Iter<'a, GlyphRun>,
range: Range<CharIndex>,
}
@@ -126,26 +127,59 @@ impl<'a> Iterator for CharacterSliceIterator<'a> {
// inline(always) due to the inefficient rt failures messing up inline heuristics, I think.
#[inline(always)]
fn next(&mut self) -> Option<TextRunSlice<'a>> {
let glyph_run = match self.glyph_run {
let next_glyph_run = match self.next_glyph_run {
None => return None,
Some(glyph_run) => glyph_run,
Some(next_glyph_run) => next_glyph_run,
};

debug_assert!(!self.range.is_empty());
let index_to_return = self.range.begin();
self.range.adjust_by(CharIndex(1), CharIndex(-1));
if self.range.is_empty() {
// We're done.
self.glyph_run = None
} else if self.range.intersect(&glyph_run.range).is_empty() {
self.next_glyph_run = None
} else if self.range.intersect(&next_glyph_run.range).is_empty() {
// Move on to the next glyph run.
self.glyph_run = self.glyph_run_iter.next();
self.next_glyph_run = match self.glyph_run_iter.next() {
Some(next_glyph_run) => Some(next_glyph_run),
None => self.prev_glyph_run.take(),
}
}

let index_within_glyph_run = index_to_return - next_glyph_run.range.begin();
Some(TextRunSlice {
glyphs: &*next_glyph_run.glyph_store,
offset: next_glyph_run.range.begin(),
range: Range::new(index_within_glyph_run, CharIndex(1)),
})
}
}

impl<'a> DoubleEndedIterator for CharacterSliceIterator<'a> {
fn next_back(&mut self) -> Option<TextRunSlice<'a>> {
let prev_glyph_run = match self.prev_glyph_run {
None => return None,
Some(prev_glyph_run) => prev_glyph_run,
};

debug_assert!(!self.range.is_empty());
let index_to_return = self.range.end() - CharIndex(1);
self.range.adjust_by(CharIndex(0), CharIndex(-1));
if self.range.is_empty() {
// We're done.
self.prev_glyph_run = None
} else if self.range.intersect(&prev_glyph_run.range).is_empty() {
// Move back to the previous glyph run.
self.prev_glyph_run = match self.glyph_run_iter.next_back() {
Some(prev_glyph_run) => Some(prev_glyph_run),
None => self.next_glyph_run.take(),
}
}

let index_within_glyph_run = index_to_return - glyph_run.range.begin();
let index_within_glyph_run = index_to_return - prev_glyph_run.range.begin();
Some(TextRunSlice {
glyphs: &*glyph_run.glyph_store,
offset: glyph_run.range.begin(),
glyphs: &*prev_glyph_run.glyph_store,
offset: prev_glyph_run.range.begin(),
range: Range::new(index_within_glyph_run, CharIndex(1)),
})
}
@@ -328,14 +362,30 @@ impl<'a> TextRun {
/// characters in the given range.
pub fn character_slices_in_range(&'a self, range: &Range<CharIndex>)
-> CharacterSliceIterator<'a> {
let index = match self.index_of_first_glyph_run_containing(range.begin()) {
if range.is_empty() {
return CharacterSliceIterator {
next_glyph_run: None,
prev_glyph_run: None,
glyph_run_iter: self.glyphs.iter(),
range: *range,
}
}

let first_index = match self.index_of_first_glyph_run_containing(range.begin()) {
None => self.glyphs.len(),
Some(index) => index,
};
let mut glyph_run_iter = self.glyphs[index..].iter();
let last_index =
match self.index_of_first_glyph_run_containing(range.end() - CharIndex(1)) {
None => 0,
Some(index) => index,
};
let mut glyph_run_iter = self.glyphs[first_index..(last_index + 1)].iter();
let first_glyph_run = glyph_run_iter.next();
let last_glyph_run = glyph_run_iter.next_back();
CharacterSliceIterator {
glyph_run: first_glyph_run,
next_glyph_run: first_glyph_run,
prev_glyph_run: last_glyph_run,
glyph_run_iter: glyph_run_iter,
range: *range,
}
@@ -2211,12 +2211,9 @@ impl Fragment {
SpecificFragmentInfo::ScannedText(ref mut scanned_text_fragment_info) => {
let mut leading_whitespace_character_count = 0;
{
let text = slice_chars(
&*scanned_text_fragment_info.run.text,
scanned_text_fragment_info.range.begin().to_usize(),
scanned_text_fragment_info.range.end().to_usize());
for character in text.chars() {
if util::str::char_is_whitespace(character) {
for slice in scanned_text_fragment_info.run.character_slices_in_range(
&scanned_text_fragment_info.range) {
if slice.glyphs.range_is_whitespace(&slice.range) {
leading_whitespace_character_count += 1
} else {
break
@@ -2272,18 +2269,15 @@ impl Fragment {

match self.specific {
SpecificFragmentInfo::ScannedText(ref mut scanned_text_fragment_info) => {
// FIXME(pcwalton): Is there a more clever (i.e. faster) way to do this?
debug!("stripping trailing whitespace: range={:?}, len={}",
scanned_text_fragment_info.range,
scanned_text_fragment_info.run.text.chars().count());
let mut trailing_whitespace_character_count = 0;
let text_bounds;
{
let text = slice_chars(&*scanned_text_fragment_info.run.text,
scanned_text_fragment_info.range.begin().to_usize(),
scanned_text_fragment_info.range.end().to_usize());
for ch in text.chars().rev() {
if util::str::char_is_whitespace(ch) {
for slice in scanned_text_fragment_info.run.character_slices_in_range(
&scanned_text_fragment_info.range).rev() {
if slice.glyphs.range_is_whitespace(&slice.range) {
trailing_whitespace_character_count += 1
} else {
break
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.