diff options
Diffstat (limited to 'components')
-rw-r--r-- | components/gfx/Cargo.toml | 1 | ||||
-rw-r--r-- | components/gfx/lib.rs | 1 | ||||
-rw-r--r-- | components/gfx/text/text_run.rs | 87 | ||||
-rw-r--r-- | components/servo/Cargo.lock | 6 |
4 files changed, 36 insertions, 59 deletions
diff --git a/components/gfx/Cargo.toml b/components/gfx/Cargo.toml index 1e927e18b89..93d510c62d9 100644 --- a/components/gfx/Cargo.toml +++ b/components/gfx/Cargo.toml @@ -44,6 +44,7 @@ azure = {git = "https://github.com/servo/rust-azure", features = ["plugins"]} layers = {git = "https://github.com/servo/rust-layers", features = ["plugins"]} ipc-channel = {git = "https://github.com/servo/ipc-channel"} webrender_traits = {git = "https://github.com/servo/webrender_traits"} +xi-unicode = "0.0.1" [target.'cfg(target_os = "macos")'.dependencies] core-foundation = "0.2" diff --git a/components/gfx/lib.rs b/components/gfx/lib.rs index af04ce3476b..c5be037e694 100644 --- a/components/gfx/lib.rs +++ b/components/gfx/lib.rs @@ -80,6 +80,7 @@ extern crate unicode_script; extern crate url; extern crate util; extern crate webrender_traits; +extern crate xi_unicode; pub use paint_context::PaintContext; diff --git a/components/gfx/text/text_run.rs b/components/gfx/text/text_run.rs index 45215799eed..10cced11166 100644 --- a/components/gfx/text/text_run.rs +++ b/components/gfx/text/text_run.rs @@ -12,7 +12,9 @@ use std::cmp::{Ordering, max}; use std::slice::Iter; use std::sync::Arc; use text::glyph::{ByteIndex, GlyphStore}; +use util::str::char_is_whitespace; use webrender_traits; +use xi_unicode::LineBreakIterator; thread_local! { static INDEX_OF_FIRST_GLYPH_RUN_CACHE: Cell<Option<(*const TextRun, ByteIndex, usize)>> = @@ -191,73 +193,40 @@ impl<'a> TextRun { pub fn break_and_shape(font: &mut Font, text: &str, options: &ShapingOptions) -> Vec<GlyphRun> { - // TODO(Issue #230): do a better job. See Gecko's LineBreaker. let mut glyphs = vec!(); - let mut byte_i = 0; - let mut cur_slice_is_whitespace = false; - let mut byte_last_boundary = 0; - - for ch in text.chars() { - // Slices alternate between whitespace and non-whitespace, - // representing line break opportunities. - let can_break_before = if cur_slice_is_whitespace { - match ch { - ' ' | '\t' | '\n' => false, - _ => { - cur_slice_is_whitespace = false; - true - } - } - } else { - match ch { - ' ' | '\t' | '\n' => { - cur_slice_is_whitespace = true; - true - }, - _ => false - } - }; - - // Create a glyph store for this slice if it's nonempty. - if can_break_before && byte_i > byte_last_boundary { - let slice = &text[byte_last_boundary .. byte_i]; - debug!("creating glyph store for slice {} (ws? {}), {} - {} in run {}", - slice, !cur_slice_is_whitespace, byte_last_boundary, byte_i, text); - - let mut options = *options; - if !cur_slice_is_whitespace { - options.flags.insert(IS_WHITESPACE_SHAPING_FLAG); - } + let mut slice = 0..0; + + for (idx, _is_hard_break) in LineBreakIterator::new(text) { + // Extend the slice to the next UAX#14 line break opportunity. + slice.end = idx; + let word = &text[slice.clone()]; + + // Split off any trailing whitespace into a separate glyph run. + let mut whitespace = slice.end..slice.end; + if let Some((i, _)) = word.char_indices().rev() + .take_while(|&(_, c)| char_is_whitespace(c)).last() { + whitespace.start = slice.start + i; + slice.end = whitespace.start; + } + if slice.len() > 0 { glyphs.push(GlyphRun { - glyph_store: font.shape_text(slice, &options), - range: Range::new(ByteIndex(byte_last_boundary as isize), - ByteIndex((byte_i - byte_last_boundary) as isize)), + glyph_store: font.shape_text(&text[slice.clone()], options), + range: Range::new(ByteIndex(slice.start as isize), + ByteIndex(slice.len() as isize)), }); - byte_last_boundary = byte_i; } - - byte_i = byte_i + ch.len_utf8(); - } - - // Create a glyph store for the final slice if it's nonempty. - if byte_i > byte_last_boundary { - let slice = &text[byte_last_boundary..]; - debug!("creating glyph store for final slice {} (ws? {}), {} - {} in run {}", - slice, cur_slice_is_whitespace, byte_last_boundary, text.len(), text); - - let mut options = *options; - if cur_slice_is_whitespace { + if whitespace.len() > 0 { + let mut options = options.clone(); options.flags.insert(IS_WHITESPACE_SHAPING_FLAG); + glyphs.push(GlyphRun { + glyph_store: font.shape_text(&text[whitespace.clone()], &options), + range: Range::new(ByteIndex(whitespace.start as isize), + ByteIndex(whitespace.len() as isize)), + }); } - - glyphs.push(GlyphRun { - glyph_store: font.shape_text(slice, &options), - range: Range::new(ByteIndex(byte_last_boundary as isize), - ByteIndex((byte_i - byte_last_boundary) as isize)), - }); + slice.start = whitespace.end; } - glyphs } diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 72d2d8949df..9b683c2dd5d 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -740,6 +740,7 @@ dependencies = [ "url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", "webrender_traits 0.1.0 (git+https://github.com/servo/webrender_traits)", + "xi-unicode 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2511,6 +2512,11 @@ dependencies = [ ] [[package]] +name = "xi-unicode" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "xml-rs" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" |