mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Another attempt at computing the minimum breaking width for TextRuns
This commit is contained in:
parent
ddcc11069e
commit
6859730f7a
2 changed files with 131 additions and 20 deletions
|
@ -28,6 +28,21 @@ impl au : cmp::Eq {
|
|||
}
|
||||
}
|
||||
|
||||
impl au : cmp::Ord {
|
||||
pure fn lt(&&other: au) -> bool {
|
||||
*self < *other
|
||||
}
|
||||
pure fn le(&&other: au) -> bool {
|
||||
*self <= *other
|
||||
}
|
||||
pure fn ge(&&other: au) -> bool {
|
||||
*self >= *other
|
||||
}
|
||||
pure fn gt(&&other: au) -> bool {
|
||||
*self > *other
|
||||
}
|
||||
}
|
||||
|
||||
fn box<A:Copy Num>(x: A, y: A, w: A, h: A) -> Rect<A> {
|
||||
Rect(Point2D(x, y), Size2D(w, h))
|
||||
}
|
||||
|
|
|
@ -11,28 +11,24 @@ use shaper::shape_text;
|
|||
struct TextRun {
|
||||
priv glyphs: ~[Glyph],
|
||||
priv size_: Size2D<au>,
|
||||
priv min_width_: au,
|
||||
priv min_break_width_: au,
|
||||
}
|
||||
|
||||
impl TextRun {
|
||||
/// The size of the entire TextRun
|
||||
fn size() -> Size2D<au> { self.size_ }
|
||||
fn preferred_width() -> au { self.size_.width }
|
||||
fn min_width() -> au { self.min_width_ }
|
||||
fn min_break_width() -> au { self.min_break_width_ }
|
||||
}
|
||||
|
||||
fn TextRun(font: Font, text: ~str) -> TextRun {
|
||||
let glyphs = shape_text(&font, text);
|
||||
let size = glyph_run_size(glyphs);
|
||||
|
||||
let min_width = match calc_min_width(&font, text) {
|
||||
Some(w) => w,
|
||||
None => size.width
|
||||
};
|
||||
let min_break_width = calc_min_break_width(&font, text);
|
||||
|
||||
TextRun {
|
||||
glyphs: shape_text(&font, text),
|
||||
size_: size,
|
||||
min_width_: min_width
|
||||
min_break_width_: min_break_width
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,31 +44,131 @@ fn glyph_run_size(glyphs: &[Glyph]) -> Size2D<au> {
|
|||
return Size2D(pen_end.x, pen_end.y);
|
||||
}
|
||||
|
||||
/// If there are breaking opportunities inside a string, then
|
||||
/// returns the width of the text up to the first break. Otherwise None.
|
||||
fn calc_min_width(font: &Font, text: &str) -> Option<au> {
|
||||
None
|
||||
/// Discovers the width of the largest indivisible substring
|
||||
fn calc_min_break_width(font: &Font, text: &str) -> au {
|
||||
let mut max_piece_width = au(0);
|
||||
do iter_indivisible_slices(font, text) |slice| {
|
||||
let glyphs = shape_text(font, slice);
|
||||
let size = glyph_run_size(glyphs);
|
||||
if size.width > max_piece_width {
|
||||
max_piece_width = size.width
|
||||
}
|
||||
}
|
||||
return max_piece_width;
|
||||
}
|
||||
|
||||
/// Iterates over all the indivisible substrings
|
||||
fn iter_indivisible_slices(font: &Font, text: &r/str,
|
||||
f: fn((&r/str))) {
|
||||
|
||||
let mut curr = text;
|
||||
loop {
|
||||
match str::find(curr, |c| !char::is_whitespace(c) ) {
|
||||
Some(idx) => {
|
||||
curr = str::view(curr, idx, curr.len());
|
||||
}
|
||||
None => {
|
||||
// Everything else is whitespace
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
match str::find(curr, |c| char::is_whitespace(c) ) {
|
||||
Some(idx) => {
|
||||
let piece = str::view(curr, 0, idx);
|
||||
f(piece);
|
||||
curr = str::view(curr, idx, curr.len());
|
||||
}
|
||||
None => {
|
||||
assert curr.is_not_empty();
|
||||
f(curr);
|
||||
// This is the end of the string
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_calc_min_width_with_breaking() {
|
||||
fn test_calc_min_break_width1() {
|
||||
let flib = FontLibrary();
|
||||
let font = flib.get_test_font();
|
||||
let actual = calc_min_width(font, ~"firecracker yumyum");
|
||||
let expected = Some(px_to_au(84));
|
||||
let actual = calc_min_break_width(font, ~"firecracker");
|
||||
let expected = px_to_au(84);
|
||||
assert expected == actual;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_calc_min_width_without_breaking() {
|
||||
fn test_calc_min_break_width2() {
|
||||
let flib = FontLibrary();
|
||||
let font = flib.get_test_font();
|
||||
let actual = calc_min_width(font, ~"firecracker_yumyum");
|
||||
let expected = None;
|
||||
let actual = calc_min_break_width(font, ~"firecracker yumyum");
|
||||
let expected = px_to_au(84);
|
||||
assert expected == actual;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_calc_min_break_width3() {
|
||||
let flib = FontLibrary();
|
||||
let font = flib.get_test_font();
|
||||
let actual = calc_min_break_width(font, ~"yumyum firecracker");
|
||||
let expected = px_to_au(84);
|
||||
assert expected == actual;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_calc_min_break_width4() {
|
||||
let flib = FontLibrary();
|
||||
let font = flib.get_test_font();
|
||||
let actual = calc_min_break_width(font, ~"yumyum firecracker yumyum");
|
||||
let expected = px_to_au(84);
|
||||
assert expected == actual;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iter_indivisible_slices() {
|
||||
let flib = FontLibrary();
|
||||
let font = flib.get_test_font();
|
||||
let mut slices = ~[];
|
||||
do iter_indivisible_slices(font, "firecracker yumyum woopwoop") |slice| {
|
||||
slices += [slice];
|
||||
}
|
||||
assert slices == ~["firecracker", "yumyum", "woopwoop"];
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iter_indivisible_slices_trailing_whitespace() {
|
||||
let flib = FontLibrary();
|
||||
let font = flib.get_test_font();
|
||||
let mut slices = ~[];
|
||||
do iter_indivisible_slices(font, "firecracker ") |slice| {
|
||||
slices += [slice];
|
||||
}
|
||||
assert slices == ~["firecracker"];
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iter_indivisible_slices_leading_whitespace() {
|
||||
let flib = FontLibrary();
|
||||
let font = flib.get_test_font();
|
||||
let mut slices = ~[];
|
||||
do iter_indivisible_slices(font, " firecracker") |slice| {
|
||||
slices += [slice];
|
||||
}
|
||||
assert slices == ~["firecracker"];
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iter_indivisible_slices_empty() {
|
||||
let flib = FontLibrary();
|
||||
let font = flib.get_test_font();
|
||||
let mut slices = ~[];
|
||||
do iter_indivisible_slices(font, "") |slice| {
|
||||
slices += [slice];
|
||||
}
|
||||
assert slices == ~[];
|
||||
}
|
||||
|
||||
fn should_calculate_the_total_size() {
|
||||
#[test];
|
||||
#[ignore(cfg(target_os = "macos"))];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue