Extract Range into its own file.

This commit is contained in:
Brian J. Burg 2012-10-18 14:19:46 -07:00
parent c9ec35fa2d
commit fcca6d6ada
10 changed files with 134 additions and 127 deletions

View file

@ -4,11 +4,12 @@ use geom::rect::Rect;
use image::base::Image;
use render_context::RenderContext;
use servo_text::text_run;
use text::text_run::SendableTextRun;
use util::range::Range;
use std::arc::ARC;
use clone_arc = std::arc::clone;
use dvec::DVec;
use text::text_run::{TextRange, SendableTextRun};
pub use layout::display_list_builder::DisplayListBuilder;
@ -24,7 +25,7 @@ pub enum DisplayItemData {
// TODO: need to provide spacing data for text run.
// (i.e, to support rendering of CSS 'word-spacing' and 'letter-spacing')
// TODO: don't copy text runs, ever.
TextData(~SendableTextRun, TextRange),
TextData(~SendableTextRun, Range),
ImageData(ARC<~image::base::Image>),
BorderData(au, u8, u8, u8)
}
@ -76,7 +77,7 @@ pub fn Border(bounds: Rect<au>, width: au, r: u8, g: u8, b: u8) -> DisplayItem {
}
}
pub fn Text(bounds: Rect<au>, run: ~SendableTextRun, range: TextRange) -> DisplayItem {
pub fn Text(bounds: Rect<au>, run: ~SendableTextRun, range: Range) -> DisplayItem {
DisplayItem {
draw: |self, ctx| draw_Text(self, ctx),
bounds: bounds,

View file

@ -2,10 +2,11 @@ use mod au = geometry;
use compositor::LayerBuffer;
use text::font::Font;
use text::text_run::{TextRun, TextRange};
use text::text_run::TextRun;
use text::font_cache::FontCache;
use image::base::Image;
use au = au::au;
use util::range::Range;
use core::libc::types::common::c99::uint16_t;
use core::ptr::to_unsafe_ptr;
@ -67,7 +68,7 @@ impl RenderContext {
draw_options);
}
pub fn draw_text(&self, bounds: Rect<au>, run: &TextRun, range: TextRange) {
pub fn draw_text(&self, bounds: Rect<au>, run: &TextRun, range: Range) {
use ptr::{null};
use vec::raw::to_ptr;
use libc::types::common::c99::{uint16_t, uint32_t};

View file

@ -22,10 +22,11 @@ use layout::debug::BoxedDebugMethods;
use layout::flow::FlowContext;
use layout::text::TextBoxData;
use servo_text::text_run;
use servo_text::text_run::{MutableTextRange, TextRange, TextRun};
use servo_text::text_run::TextRun;
use std::net::url::Url;
use task::spawn;
use util::color::Color;
use util::range::*;
use util::tree;
/**
@ -187,8 +188,8 @@ impl RenderBox : RenderBoxMethods {
let mut pieces_processed_count : uint = 0;
let mut remaining_width : au = max_width;
let left_range = MutableTextRange(data.range.begin(), 0);
let mut right_range : Option<TextRange> = None;
let left_range = MutableRange(data.range.begin(), 0);
let mut right_range : Option<Range> = None;
debug!("split_to_width: splitting text box (strlen=%u, range=%?, avail_width=%?)",
data.run.text.len(), data.range, max_width);
do data.run.iter_indivisible_pieces_for_range(data.range) |piece_range| {
@ -216,14 +217,14 @@ impl RenderBox : RenderBoxMethods {
// if there are still things after the trimmable whitespace, create right chunk
if piece_range.end() < data.range.end() {
debug!("split_to_width: case=skipping trimmable trailing whitespace, then split remainder");
right_range = Some(TextRange(piece_range.end(),
right_range = Some(Range(piece_range.end(),
data.range.end() - piece_range.end()));
} else {
debug!("split_to_width: case=skipping trimmable trailing whitespace");
}
} else if piece_range.begin() < data.range.end() {
// still things left, create right chunk
right_range = Some(TextRange(piece_range.begin(),
right_range = Some(Range(piece_range.begin(),
data.range.end() - piece_range.begin()));
debug!("split_to_width: case=splitting remainder with right range=%?",
right_range);
@ -237,7 +238,7 @@ impl RenderBox : RenderBoxMethods {
Some(layout::text::adapt_textbox_with_range(self.d(), data.run, left_range.as_immutable()))
} else { None };
let right_box = option::map_default(&right_range, None, |range: &TextRange| {
let right_box = option::map_default(&right_range, None, |range: &Range| {
Some(layout::text::adapt_textbox_with_range(self.d(), data.run, *range))
});

View file

@ -16,6 +16,7 @@ use num::Num;
use servo_text::text_run::TextRun;
use servo_text::util::*;
use std::arc;
use util::range::Range;
use util::tree;
/*
@ -169,7 +170,7 @@ impl TextRunScanner {
debug!("TextRunScanner: pushing single text box when start=%u,end=%u",
self.clump_start, self.clump_end);
let new_box = layout::text::adapt_textbox_with_range(in_boxes[self.clump_start].d(), run,
TextRange(0, run.text.len()));
Range(0, run.text.len()));
out_boxes.push(new_box);
},
(false, true) => {
@ -223,7 +224,7 @@ impl TextRunScanner {
debug!("TextRunScanner: pushing box(es) when start=%u,end=%u",
self.clump_start, self.clump_end);
let new_box = layout::text::adapt_textbox_with_range(in_boxes[self.clump_start].d(), run,
TextRange(0, run.text.len()));
Range(0, run.text.len()));
out_boxes.push(new_box);
}
} /* /match */

View file

@ -1,14 +1,15 @@
/** Text layout. */
use servo_text::text_run::{TextRange, TextRun};
use servo_text::text_run::TextRun;
use layout::box::{TextBox, RenderBox, RenderBoxData, UnscannedTextBox};
use util::range::Range;
pub struct TextBoxData {
run: @TextRun,
range: TextRange,
range: Range,
}
pub fn TextBoxData(run: @TextRun, range: TextRange) -> TextBoxData {
pub fn TextBoxData(run: @TextRun, range: Range) -> TextBoxData {
TextBoxData {
run: run,
range: range,
@ -16,7 +17,7 @@ pub fn TextBoxData(run: @TextRun, range: TextRange) -> TextBoxData {
}
pub fn adapt_textbox_with_range(box_data: &RenderBoxData, run: @TextRun,
range: TextRange) -> @RenderBox {
range: Range) -> @RenderBox {
debug!("Creating textbox with span: (strlen=%u, off=%u, len=%u) of textrun: %s",
run.text.len(), range.begin(), range.length(), run.text);
let new_box_data = copy *box_data;

View file

@ -129,6 +129,7 @@ pub mod util {
pub mod time;
pub mod url;
pub mod vec;
pub mod range;
}
pub mod opts;

View file

@ -9,8 +9,9 @@ use glyph::GlyphIndex;
use libc::{ c_int, c_double, c_ulong };
use native_font::NativeFont;
use ptr::{null, addr_of};
use text::text_run::{TextRun, TextRange};
use text::text_run::TextRun;
use vec_to_ptr = vec::raw::to_ptr;
use servo_util::range::Range;
// Used to abstract over the shaper's choice of fixed int representation.
type FractionalPixel = float;
@ -41,7 +42,7 @@ struct RunMetrics {
// Public API
pub trait FontMethods {
fn measure_text(&TextRun, TextRange) -> RunMetrics;
fn measure_text(&TextRun, Range) -> RunMetrics;
fn buf(&self) -> @~[u8];
// these are used to get glyphs and advances in the case that the
@ -51,7 +52,7 @@ pub trait FontMethods {
}
pub impl Font : FontMethods {
fn measure_text(run: &TextRun, range: TextRange) -> RunMetrics {
fn measure_text(run: &TextRun, range: Range) -> RunMetrics {
assert range.is_valid_for_string(run.text);
// TODO: alter advance direction for RTL

View file

@ -6,7 +6,7 @@ use core::u16;
use geom::point::Point2D;
use num::from_int;
use std::sort;
use servo_text::text_run::TextRange;
use servo_util::range::Range;
use servo_util::vec::*;
@ -545,7 +545,7 @@ impl GlyphStore {
}
}
fn iter_glyphs_for_range<T>(&self, range: TextRange, cb: fn&(uint, GlyphInfo/&) -> T) {
fn iter_glyphs_for_range<T>(&self, range: Range, cb: fn&(uint, GlyphInfo/&) -> T) {
assert range.begin() < self.entry_buffer.len();
assert range.end() <= self.entry_buffer.len();

View file

@ -12,6 +12,7 @@ use libc::{c_void};
use servo_util::color;
use shaper::shape_textrun;
use std::arc;
use servo_util::range::{Range, MutableRange};
pub struct TextRun {
text: ~str,
@ -19,98 +20,6 @@ pub struct TextRun {
priv glyphs: GlyphStore,
}
pub struct TextRange {
priv off: u16,
priv len: u16
}
pure fn TextRange(off: uint, len :uint) -> TextRange {
assert off <= u16::max_value as uint;
assert len <= u16::max_value as uint;
TextRange {
off: off as u16,
len: len as u16
}
}
impl TextRange {
pub pure fn begin() -> uint { self.off as uint }
pub pure fn length() -> uint { self.len as uint }
pub pure fn end() -> uint { (self.off as uint) + (self.len as uint) }
pub pure fn eachi(cb: fn&(uint) -> bool) {
do uint::range(self.off as uint,
(self.off as uint) + (self.len as uint)) |i| {
cb(i)
}
}
pub pure fn is_valid_for_string(s: &str) -> bool {
self.begin() < s.len() && self.end() <= s.len() && self.length() <= s.len()
}
pub pure fn shift_by(i: int) -> TextRange {
TextRange(((self.off as int) + i) as uint, self.len as uint)
}
pub pure fn extend_by(i: int) -> TextRange {
TextRange(self.off as uint, ((self.len as int) + i) as uint)
}
pub pure fn adjust_by(off_i: int, len_i: int) -> TextRange {
TextRange(((self.off as int) + off_i) as uint, ((self.len as int) + len_i) as uint)
}
}
pub struct MutableTextRange {
priv mut off: uint,
priv mut len: uint
}
pure fn MutableTextRange(off: uint, len :uint) -> MutableTextRange {
MutableTextRange { off: off, len: len }
}
impl MutableTextRange {
pub pure fn begin() -> uint { self.off }
pub pure fn length() -> uint { self.len }
pub pure fn end() -> uint { self.off + self.len }
pub pure fn eachi(cb: fn&(uint) -> bool) {
do uint::range(self.off, self.off + self.len) |i| { cb(i) }
}
pub pure fn as_immutable() -> TextRange {
TextRange(self.begin(), self.length())
}
pub pure fn is_valid_for_string(s: &str) -> bool {
self.begin() < s.len() && self.end() <= s.len() && self.length() <= s.len()
}
pub fn shift_by(i: int) {
self.off = ((self.off as int) + i) as uint;
}
pub fn extend_by(i: int) {
self.len = ((self.len as int) + i) as uint;
}
pub fn extend_to(i: uint) {
self.len = i - self.off;
}
pub fn adjust_by(off_i: int, len_i: int) {
self.off = ((self.off as int) + off_i) as uint;
self.len = ((self.len as int) + len_i) as uint;
}
pub fn reset(off_i: uint, len_i: uint) {
self.off = off_i;
self.len = len_i;
}
}
// This is a hack until TextRuns are normally sendable, or
// we instead use ARC<TextRun> everywhere.
pub struct SendableTextRun {
@ -139,20 +48,20 @@ pub fn deserialize(cache: @FontCache, run: &SendableTextRun) -> @TextRun {
trait TextRunMethods {
pure fn glyphs(&self) -> &self/GlyphStore;
fn iter_indivisible_pieces_for_range(&self, range: TextRange, f: fn&(TextRange) -> bool);
fn iter_indivisible_pieces_for_range(&self, range: Range, f: fn&(Range) -> bool);
// TODO: needs to take box style as argument, or move to TextBox.
// see Gecko's IsTrimmableSpace methods for details.
pure fn range_is_trimmable_whitespace(&self, range: TextRange) -> bool;
pure fn range_is_trimmable_whitespace(&self, range: Range) -> bool;
fn metrics_for_range(&self, range: TextRange) -> RunMetrics;
fn min_width_for_range(&self, range: TextRange) -> au;
fn iter_natural_lines_for_range(&self, range: TextRange, f: fn&(TextRange) -> bool);
fn metrics_for_range(&self, range: Range) -> RunMetrics;
fn min_width_for_range(&self, range: Range) -> au;
fn iter_natural_lines_for_range(&self, range: Range, f: fn&(Range) -> bool);
}
impl TextRun : TextRunMethods {
pure fn glyphs(&self) -> &self/GlyphStore { &self.glyphs }
pure fn range_is_trimmable_whitespace(&self, range: TextRange) -> bool {
pure fn range_is_trimmable_whitespace(&self, range: Range) -> bool {
let mut i = range.begin();
while i < range.end() {
// jump i to each new char
@ -166,11 +75,11 @@ impl TextRun : TextRunMethods {
return true;
}
fn metrics_for_range(&self, range: TextRange) -> RunMetrics {
fn metrics_for_range(&self, range: Range) -> RunMetrics {
self.font.measure_text(self, range)
}
fn min_width_for_range(&self, range: TextRange) -> au {
fn min_width_for_range(&self, range: Range) -> au {
assert range.is_valid_for_string(self.text);
let mut max_piece_width = au(0);
@ -181,10 +90,10 @@ impl TextRun : TextRunMethods {
return max_piece_width;
}
fn iter_natural_lines_for_range(&self, range: TextRange, f: fn(TextRange) -> bool) {
fn iter_natural_lines_for_range(&self, range: Range, f: fn(Range) -> bool) {
assert range.is_valid_for_string(self.text);
let clump = MutableTextRange(range.begin(), 0);
let clump = MutableRange(range.begin(), 0);
let mut in_clump = false;
// clump non-linebreaks of nonzero length
@ -209,10 +118,10 @@ impl TextRun : TextRunMethods {
}
}
fn iter_indivisible_pieces_for_range(&self, range: TextRange, f: fn(TextRange) -> bool) {
fn iter_indivisible_pieces_for_range(&self, range: Range, f: fn(Range) -> bool) {
assert range.is_valid_for_string(self.text);
let clump = MutableTextRange(range.begin(), 0);
let clump = MutableRange(range.begin(), 0);
loop {
// find next non-whitespace byte index, then clump all whitespace before it.
if clump.end() == range.end() { break }
@ -291,7 +200,7 @@ fn test_iter_indivisible_pieces() {
let font = flib.get_test_font();
let run = TextRun(font, copy text);
let mut slices : ~[~str] = ~[];
for run.iter_indivisible_pieces_for_range(TextRange(0, text.len())) |subrange| {
for run.iter_indivisible_pieces_for_range(Range(0, text.len())) |subrange| {
slices.push(str::slice(text, subrange.begin(), subrange.length()));
}
assert slices == res;

91
src/servo/util/range.rs Normal file
View file

@ -0,0 +1,91 @@
pub struct Range {
priv off: u16,
priv len: u16
}
pub pure fn Range(off: uint, len: uint) -> Range {
assert off <= u16::max_value as uint;
assert len <= u16::max_value as uint;
Range {
off: off as u16,
len: len as u16
}
}
pub impl Range {
pub pure fn begin() -> uint { self.off as uint }
pub pure fn length() -> uint { self.len as uint }
pub pure fn end() -> uint { (self.off as uint) + (self.len as uint) }
pub pure fn eachi(cb: fn&(uint) -> bool) {
do uint::range(self.off as uint,
(self.off as uint) + (self.len as uint)) |i| {
cb(i)
}
}
pub pure fn is_valid_for_string(s: &str) -> bool {
self.begin() < s.len() && self.end() <= s.len() && self.length() <= s.len()
}
pub pure fn shift_by(i: int) -> Range {
Range(((self.off as int) + i) as uint, self.len as uint)
}
pub pure fn extend_by(i: int) -> Range {
Range(self.off as uint, ((self.len as int) + i) as uint)
}
pub pure fn adjust_by(off_i: int, len_i: int) -> Range {
Range(((self.off as int) + off_i) as uint, ((self.len as int) + len_i) as uint)
}
}
pub struct MutableRange {
priv mut off: uint,
priv mut len: uint
}
pure fn MutableRange(off: uint, len :uint) -> MutableRange {
MutableRange { off: off, len: len }
}
impl MutableRange {
pub pure fn begin() -> uint { self.off }
pub pure fn length() -> uint { self.len }
pub pure fn end() -> uint { self.off + self.len }
pub pure fn eachi(cb: fn&(uint) -> bool) {
do uint::range(self.off, self.off + self.len) |i| { cb(i) }
}
pub pure fn as_immutable() -> Range {
Range(self.begin(), self.length())
}
pub pure fn is_valid_for_string(s: &str) -> bool {
self.begin() < s.len() && self.end() <= s.len() && self.length() <= s.len()
}
pub fn shift_by(i: int) {
self.off = ((self.off as int) + i) as uint;
}
pub fn extend_by(i: int) {
self.len = ((self.len as int) + i) as uint;
}
pub fn extend_to(i: uint) {
self.len = i - self.off;
}
pub fn adjust_by(off_i: int, len_i: int) {
self.off = ((self.off as int) + off_i) as uint;
self.len = ((self.len as int) + len_i) as uint;
}
pub fn reset(off_i: uint, len_i: uint) {
self.off = off_i;
self.len = len_i;
}
}