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

Optimize `TextRun::advance_for_range`. #8990

Merged
merged 3 commits into from Dec 17, 2015
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Prev

gfx: Cache the last result of

`TextRun::index_of_first_glyph_run_containing` in TLS.

This achieves a 40% or so hit rate on Wikipedia.
  • Loading branch information
pcwalton committed Dec 16, 2015
commit 520c561d3d70dfeacd4b7b0f0a580e37f0702e35
@@ -6,13 +6,19 @@ use app_units::Au;
use font::{Font, FontHandleMethods, FontMetrics, IS_WHITESPACE_SHAPING_FLAG, RunMetrics};
use font::{ShapingOptions};
use platform::font_template::FontTemplateData;
use std::cell::Cell;
use std::cmp::{Ordering, max};
use std::slice::Iter;
use std::sync::Arc;
use text::glyph::{CharIndex, GlyphStore};
use util::range::Range;
use util::vec::{Comparator, FullBinarySearchMethods};

thread_local! {
static INDEX_OF_FIRST_GLYPH_RUN_CACHE: Cell<Option<(*const TextRun, CharIndex, usize)>> =
Cell::new(None)
}

/// A single "paragraph" of text in one font size and style.
#[derive(Clone, Deserialize, Serialize)]
pub struct TextRun {
@@ -26,6 +32,19 @@ pub struct TextRun {
pub bidi_level: u8,
}

impl Drop for TextRun {
fn drop(&mut self) {
// Invalidate the glyph run cache if it was our text run that got freed.
INDEX_OF_FIRST_GLYPH_RUN_CACHE.with(|index_of_first_glyph_run_cache| {
if let Some((text_run_ptr, _, _)) = index_of_first_glyph_run_cache.get() {
if text_run_ptr == (self as *const TextRun) {
index_of_first_glyph_run_cache.set(None);
}
}
})
}
}

/// A single series of glyphs within a text run.
#[derive(Clone, Deserialize, Serialize)]
pub struct GlyphRun {
@@ -248,6 +267,10 @@ impl<'a> TextRun {
}

pub fn advance_for_range(&self, range: &Range<CharIndex>) -> Au {
if range.is_empty() {
return Au(0)
}

// TODO(Issue #199): alter advance direction for RTL
// TODO(Issue #98): using inter-char and inter-word spacing settings when measuring text
self.natural_word_slices_in_range(range)
@@ -279,7 +302,21 @@ impl<'a> TextRun {

/// Returns the index of the first glyph run containing the given character index.
fn index_of_first_glyph_run_containing(&self, index: CharIndex) -> Option<usize> {
(&**self.glyphs).binary_search_index_by(&index, CharIndexComparator)
let self_ptr = self as *const TextRun;
INDEX_OF_FIRST_GLYPH_RUN_CACHE.with(|index_of_first_glyph_run_cache| {
if let Some((last_text_run, last_index, last_result)) =
index_of_first_glyph_run_cache.get() {
if last_text_run == self_ptr && last_index == index {
return Some(last_result)
}
}

let result = (&**self.glyphs).binary_search_index_by(&index, CharIndexComparator);
if let Some(result) = result {
index_of_first_glyph_run_cache.set(Some((self_ptr, index, result)));
}
result
})
}

/// Returns an iterator that will iterate over all slices of glyphs that represent natural
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.