aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/gfx/Cargo.toml1
-rw-r--r--components/gfx/lib.rs1
-rw-r--r--components/gfx/text/text_run.rs87
-rw-r--r--components/servo/Cargo.lock6
4 files changed, 36 insertions, 59 deletions
diff --git a/components/gfx/Cargo.toml b/components/gfx/Cargo.toml
index 865f313cf96..d02445d606f 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 daae5d70eec..553f32d446e 100644
--- a/components/servo/Cargo.lock
+++ b/components/servo/Cargo.lock
@@ -739,6 +739,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]]
@@ -2526,6 +2527,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"