mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Extract Range into its own file.
This commit is contained in:
parent
c9ec35fa2d
commit
fcca6d6ada
10 changed files with 134 additions and 127 deletions
|
@ -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,
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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))
|
||||
});
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -129,6 +129,7 @@ pub mod util {
|
|||
pub mod time;
|
||||
pub mod url;
|
||||
pub mod vec;
|
||||
pub mod range;
|
||||
}
|
||||
|
||||
pub mod opts;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
91
src/servo/util/range.rs
Normal 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;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue