Another attempt at computing the minimum breaking width for TextRuns

This commit is contained in:
Brian Anderson 2012-09-14 15:29:32 -07:00
parent ddcc11069e
commit 6859730f7a
2 changed files with 131 additions and 20 deletions

View file

@ -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))
}

View file

@ -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"))];