mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Compute and store line break information in the glyph storage when creating text runs.
This commit is contained in:
parent
2ad1c1564c
commit
751901d39e
3 changed files with 52 additions and 7 deletions
|
@ -375,6 +375,8 @@ pub trait FontMethods {
|
||||||
range: &Range,
|
range: &Range,
|
||||||
baseline_origin: Point2D<Au>,
|
baseline_origin: Point2D<Au>,
|
||||||
color: Color);
|
color: Color);
|
||||||
|
// This calculates run metrics for the specified character range
|
||||||
|
// within the provided textrun.
|
||||||
fn measure_text(&TextRun, &const Range) -> RunMetrics;
|
fn measure_text(&TextRun, &const Range) -> RunMetrics;
|
||||||
fn shape_text(@self, &str, &mut GlyphStore);
|
fn shape_text(@self, &str, &mut GlyphStore);
|
||||||
fn get_descriptor() -> FontDescriptor;
|
fn get_descriptor() -> FontDescriptor;
|
||||||
|
@ -448,12 +450,10 @@ pub impl Font : FontMethods {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn measure_text(run: &TextRun, range: &const Range) -> RunMetrics {
|
fn measure_text(run: &TextRun, range: &const Range) -> RunMetrics {
|
||||||
assert range.is_valid_for_string(run.text);
|
|
||||||
|
|
||||||
// TODO(Issue #199): alter advance direction for RTL
|
// TODO(Issue #199): alter advance direction for RTL
|
||||||
// TODO(Issue #98): using inter-char and inter-word spacing settings when measuring text
|
// TODO(Issue #98): using inter-char and inter-word spacing settings when measuring text
|
||||||
let mut advance = Au(0);
|
let mut advance = Au(0);
|
||||||
for run.glyphs.iter_glyphs_for_byte_range(range) |_i, glyph| {
|
for run.glyphs.iter_glyphs_for_char_range(range) |_i, glyph| {
|
||||||
advance += glyph.advance();
|
advance += glyph.advance();
|
||||||
}
|
}
|
||||||
let mut bounds = Rect(Point2D(Au(0), -self.metrics.ascent),
|
let mut bounds = Rect(Point2D(Au(0), -self.metrics.ascent),
|
||||||
|
|
|
@ -604,6 +604,7 @@ impl GlyphStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
pure fn iter_glyphs_for_byte_range(range: &const Range, cb: fn&(uint, GlyphInfo/&) -> bool) {
|
pure fn iter_glyphs_for_byte_range(range: &const Range, cb: fn&(uint, GlyphInfo/&) -> bool) {
|
||||||
|
warn!("Using deprecated iter_glyphs_for_byte_range API!");
|
||||||
if range.begin() >= self.entry_buffer.len() {
|
if range.begin() >= self.entry_buffer.len() {
|
||||||
error!("iter_glyphs_for_range: range.begin beyond length!");
|
error!("iter_glyphs_for_range: range.begin beyond length!");
|
||||||
return;
|
return;
|
||||||
|
@ -613,9 +614,11 @@ impl GlyphStore {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: actually compute char indexes from byte indexes.
|
self.iter_glyphs_for_char_range(range, cb)
|
||||||
let char_range = copy *range;
|
}
|
||||||
for char_range.eachi |i| {
|
|
||||||
|
pure fn iter_glyphs_for_char_range(range: &const Range, cb: fn&(uint, GlyphInfo/&) -> bool) {
|
||||||
|
for range.eachi |i| {
|
||||||
if !self.iter_glyphs_for_char_index(i, cb) { break; }
|
if !self.iter_glyphs_for_char_index(i, cb) { break; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use font_context::FontContext;
|
use font_context::FontContext;
|
||||||
use geometry::Au;
|
use geometry::Au;
|
||||||
use glyph::GlyphStore;
|
use glyph::{
|
||||||
|
BreakTypeNormal,
|
||||||
|
GlyphStore,
|
||||||
|
};
|
||||||
use servo_gfx_font::{Font, FontDescriptor, RunMetrics};
|
use servo_gfx_font::{Font, FontDescriptor, RunMetrics};
|
||||||
use servo_gfx_util::range::Range;
|
use servo_gfx_util::range::Range;
|
||||||
|
|
||||||
|
@ -42,6 +45,7 @@ impl SendableTextRun {
|
||||||
impl TextRun {
|
impl TextRun {
|
||||||
static fn new(font: @Font, text: ~str) -> TextRun {
|
static fn new(font: @Font, text: ~str) -> TextRun {
|
||||||
let mut glyph_store = GlyphStore::new(str::char_len(text));
|
let mut glyph_store = GlyphStore::new(str::char_len(text));
|
||||||
|
TextRun::compute_potential_breaks(text, &mut glyph_store);
|
||||||
font.shape_text(text, &mut glyph_store);
|
font.shape_text(text, &mut glyph_store);
|
||||||
|
|
||||||
let run = TextRun {
|
let run = TextRun {
|
||||||
|
@ -52,6 +56,44 @@ impl TextRun {
|
||||||
return move run;
|
return move run;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static fn compute_potential_breaks(text: &str, glyphs: &mut GlyphStore) {
|
||||||
|
// TODO(Issue #230): do a better job. See Gecko's LineBreaker.
|
||||||
|
|
||||||
|
let mut i = 0u;
|
||||||
|
let mut prev_is_whitespace = false;
|
||||||
|
while i < text.len() {
|
||||||
|
let {ch, next} = str::char_range_at(text, i);
|
||||||
|
// set char properties.
|
||||||
|
match ch {
|
||||||
|
' ' => { glyphs.set_char_is_space(i); },
|
||||||
|
'\t' => { glyphs.set_char_is_tab(i); },
|
||||||
|
'\n' => { glyphs.set_char_is_newline(i); },
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set line break opportunities at whitespace/non-whitespace boundaries.
|
||||||
|
if prev_is_whitespace {
|
||||||
|
match ch {
|
||||||
|
' ' | '\t' | '\n' => {},
|
||||||
|
_ => {
|
||||||
|
glyphs.set_can_break_before(i, BreakTypeNormal);
|
||||||
|
prev_is_whitespace = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match ch {
|
||||||
|
' ' | '\t' | '\n' => {
|
||||||
|
glyphs.set_can_break_before(i, BreakTypeNormal);
|
||||||
|
prev_is_whitespace = true;
|
||||||
|
},
|
||||||
|
_ => { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn serialize(&self) -> SendableTextRun {
|
pub fn serialize(&self) -> SendableTextRun {
|
||||||
SendableTextRun {
|
SendableTextRun {
|
||||||
text: copy self.text,
|
text: copy self.text,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue