Skip to content
Permalink
Browse files

Move away from using non-freezable Range.

  • Loading branch information
Brian J. Burg
Brian J. Burg committed Nov 19, 2012
1 parent a706a57 commit da17edee9230c8c5cadb2bde322c552f8ddf104a
@@ -3,7 +3,7 @@ use geometry::Au;
use image::base::Image;
use render_context::RenderContext;
use text::SendableTextRun;
use util::range::Range;
use util::range::MutableRange;

use azure::azure_hl::DrawTarget;
use core::dvec::DVec;
@@ -27,7 +27,7 @@ pub enum DisplayItem {
// 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.
Text(DisplayItemData, ~SendableTextRun, Range, Color),
Text(DisplayItemData, ~SendableTextRun, MutableRange, Color),
Image(DisplayItemData, ARC<~image::base::Image>),
Border(DisplayItemData, Au, Color)
}
@@ -45,7 +45,7 @@ impl DisplayItem {
fn draw_into_context(&self, ctx: &RenderContext) {
match *self {
SolidColor(_, color) => ctx.draw_solid_color(&self.d().bounds, color),
Text(_, run, range, color) => {
Text(_, run, ref range, color) => {
let new_run = @run.deserialize(ctx.font_ctx);
let font = new_run.font;
let origin = self.d().bounds.origin;
@@ -71,9 +71,9 @@ impl DisplayItem {

static pure fn new_Text(bounds: &Rect<Au>,
run: ~SendableTextRun,
range: Range,
range: MutableRange,
color: Color) -> DisplayItem {
Text(DisplayItemData::new(bounds), move run, range, color)
Text(DisplayItemData::new(bounds), move run, move range, color)
}

// ARC should be cloned into ImageData, but Images are not sendable
@@ -2,7 +2,7 @@ use color::Color;
use font_context::FontContext;
use geometry::Au;
use render_context::RenderContext;
use util::range::Range;
use util::range::{Range, MutableRange};
use text::glyph::{GlyphStore, GlyphIndex};
use text::{Shaper, TextRun};

@@ -372,10 +372,10 @@ impl Font {
pub trait FontMethods {
fn draw_text_into_context(rctx: &RenderContext,
run: &TextRun,
range: Range,
range: &MutableRange,
baseline_origin: Point2D<Au>,
color: Color);
fn measure_text(&TextRun, Range) -> RunMetrics;
fn measure_text(&TextRun, &const MutableRange) -> RunMetrics;
fn shape_text(@self, &str) -> GlyphStore;
fn get_descriptor() -> FontDescriptor;

@@ -388,7 +388,7 @@ pub trait FontMethods {
pub impl Font : FontMethods {
fn draw_text_into_context(rctx: &RenderContext,
run: &TextRun,
range: Range,
range: &const MutableRange,
baseline_origin: Point2D<Au>,
color: Color) {
use libc::types::common::c99::{uint16_t, uint32_t};
@@ -445,7 +445,7 @@ pub impl Font : FontMethods {
ptr::null());
}

fn measure_text(run: &TextRun, range: Range) -> RunMetrics {
fn measure_text(run: &TextRun, range: &const MutableRange) -> RunMetrics {
assert range.is_valid_for_string(run.text);

// TODO(Issue #199): alter advance direction for RTL
@@ -1,6 +1,6 @@
use au = geometry;
use au::Au;
use servo_gfx_util::range::Range;
use servo_gfx_util::range::MutableRange;
use servo_gfx_util::vec::*;

use core::cmp::{Ord, Eq};
@@ -582,7 +582,7 @@ impl GlyphStore {
return true;
}

fn iter_glyphs_for_range(&self, range: Range, cb: fn&(uint, GlyphInfo/&) -> bool) {
fn iter_glyphs_for_range(&self, range: &const MutableRange, cb: fn&(uint, GlyphInfo/&) -> bool) {
assert range.begin() < self.entry_buffer.len();
assert range.end() <= self.entry_buffer.len();

@@ -60,7 +60,7 @@ impl TextRun {

pure fn glyphs(&self) -> &self/GlyphStore { &self.glyphs }

pure fn range_is_trimmable_whitespace(&self, range: Range) -> bool {
pure fn range_is_trimmable_whitespace(&self, range: &const MutableRange) -> bool {
let mut i = range.begin();
while i < range.end() {
// jump i to each new char
@@ -74,11 +74,11 @@ impl TextRun {
return true;
}

fn metrics_for_range(&self, range: Range) -> RunMetrics {
fn metrics_for_range(&self, range: &const MutableRange) -> RunMetrics {
self.font.measure_text(self, range)
}

fn min_width_for_range(&self, range: Range) -> Au {
fn min_width_for_range(&self, range: &const MutableRange) -> Au {
assert range.is_valid_for_string(self.text);

let mut max_piece_width = Au(0);
@@ -89,7 +89,7 @@ impl TextRun {
return max_piece_width;
}

fn iter_natural_lines_for_range(&self, range: Range, f: fn(Range) -> bool) {
fn iter_natural_lines_for_range(&self, range: &const MutableRange, f: fn(&const MutableRange) -> bool) {
assert range.is_valid_for_string(self.text);

let mut clump = MutableRange::new(range.begin(), 0);
@@ -105,19 +105,19 @@ impl TextRun {
in_clump = false;
// don't include the linebreak 'glyph'
// (we assume there's one GlyphEntry for a newline, and no actual glyphs)
if !f(clump.as_immutable()) { break }
if !f(&const clump) { break }
}
}
}

// flush any remaining chars as a line
if in_clump {
clump.extend_to(range.end());
f(clump.as_immutable());
f(&const clump);
}
}

fn iter_indivisible_pieces_for_range(&self, range: Range, f: fn(Range) -> bool) {
fn iter_indivisible_pieces_for_range(&self, range: &const MutableRange, f: fn(&const MutableRange) -> bool) {
assert range.is_valid_for_string(self.text);

let mut clump = MutableRange::new(range.begin(), 0);
@@ -126,14 +126,14 @@ impl TextRun {
match str::find_between(self.text, clump.begin(), range.end(), |c| !char::is_whitespace(c)) {
Some(nonws_char_offset) => {
clump.extend_to(nonws_char_offset);
if !f(clump.as_immutable()) { break }
if !f(&const clump) { break }
clump.reset(clump.end(), 0);
},
None => {
// nothing left, flush last piece containing only whitespace
if clump.end() < range.end() {
clump.extend_to(range.end());
f(clump.as_immutable());
f(&const clump);
break;
}
}
@@ -143,14 +143,14 @@ impl TextRun {
match str::find_between(self.text, clump.begin(), range.end(), |c| char::is_whitespace(c)) {
Some(ws_char_offset) => {
clump.extend_to(ws_char_offset);
if !f(clump.as_immutable()) { break }
if !f(&const clump) { break }
clump.reset(clump.end(), 0);
}
None => {
// nothing left, flush last piece containing only non-whitespaces
if clump.end() < range.end() {
clump.extend_to(range.end());
f(clump.as_immutable());
f(&const clump);
break;
}
}
@@ -83,10 +83,6 @@ pub impl MutableRange {
i >= self.begin() && i < self.end()
}

pure fn as_immutable(&const self) -> Range {
Range(self.begin(), self.length())
}

pure fn is_valid_for_string(&const self, s: &str) -> bool {
self.begin() < s.len() && self.end() <= s.len() && self.length() <= s.len()
}
@@ -190,10 +190,10 @@ impl RenderBox : RenderBoxMethods {
let mut pieces_processed_count : uint = 0;
let mut remaining_width : Au = max_width;
let mut left_range = MutableRange::new(data.range.begin(), 0);
let mut right_range : Option<Range> = None;
let mut right_range : Option<MutableRange> = 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| {
do data.run.iter_indivisible_pieces_for_range(&const data.range) |piece_range| {
debug!("split_to_width: considering piece (range=%?, remain_width=%?)",
piece_range, remaining_width);
let metrics = data.run.metrics_for_range(piece_range);
@@ -218,15 +218,15 @@ 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(Range(piece_range.end(),
data.range.end() - piece_range.end()));
right_range = Some(MutableRange::new(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(Range(piece_range.begin(),
data.range.end() - piece_range.begin()));
right_range = Some(MutableRange::new(piece_range.begin(),
data.range.end() - piece_range.begin()));
debug!("split_to_width: case=splitting remainder with right range=%?",
right_range);
}
@@ -236,11 +236,11 @@ impl RenderBox : RenderBoxMethods {
}

let left_box = if left_range.length() > 0 {
Some(layout::text::adapt_textbox_with_range(self.d(), data.run, left_range.as_immutable()))
Some(layout::text::adapt_textbox_with_range(self.d(), data.run, &const left_range))
} else { None };

let right_box = option::map_default(&right_range, None, |range: &Range| {
Some(layout::text::adapt_textbox_with_range(self.d(), data.run, *range))
let right_box = option::map_default(&right_range, None, |range: &const MutableRange| {
Some(layout::text::adapt_textbox_with_range(self.d(), data.run, range))
});

return if pieces_processed_count == 1 || left_box.is_none() {
@@ -267,7 +267,7 @@ impl RenderBox : RenderBoxMethods {
// TODO: consult CSS 'width', margin, border.
// TODO: If image isn't available, consult 'width'.
ImageBox(_,i) => Au::from_px(i.get_size().get_default(Size2D(0,0)).width),
TextBox(_,d) => d.run.min_width_for_range(d.range),
TextBox(_,d) => d.run.min_width_for_range(&const d.range),
UnscannedTextBox(*) => fail ~"Shouldn't see unscanned boxes here."
}
}
@@ -290,7 +290,7 @@ impl RenderBox : RenderBoxMethods {
// factor in min/pref widths of any text runs that it owns.
TextBox(_,d) => {
let mut max_line_width: Au = Au(0);
for d.run.iter_natural_lines_for_range(d.range) |line_range| {
for d.run.iter_natural_lines_for_range(&const d.range) |line_range| {
let mut line_width: Au = Au(0);
for d.run.glyphs.iter_glyphs_for_range(line_range) |_char_i, glyph| {
line_width += glyph.advance()
@@ -156,7 +156,7 @@ impl BoxGenerator {
assert node_range.length() > 0;

debug!("BoxGenerator: adding element range=%?", node_range);
self.flow.inline().elems.add_mapping(node, node_range.as_immutable());
self.flow.inline().elems.add_mapping(node, &const node_range);
},
@BlockFlow(*) | @RootFlow(*) => {
assert self.range_stack.len() == 0;
@@ -41,12 +41,12 @@ hard to try out that alternative.

struct NodeRange {
node: Node,
mut range: Range,
range: MutableRange,
}

impl NodeRange {
static pure fn new(node: Node, range: Range) -> NodeRange {
NodeRange { node: node, range: range }
static pure fn new(node: Node, range: &const MutableRange) -> NodeRange {
NodeRange { node: node, range: copy *range }
}
}

@@ -59,7 +59,7 @@ impl ElementMapping {
ElementMapping { entries: DVec() }
}

fn add_mapping(node: Node, range: Range) {
fn add_mapping(node: Node, range: &const MutableRange) {
self.entries.push(NodeRange::new(node, range))
}

@@ -103,7 +103,7 @@ impl ElementMapping {
};
let repair_stack : DVec<WorkItem> = DVec();

do self.entries.borrow |entries: &[NodeRange]| {
do self.entries.borrow_mut |entries: &[mut NodeRange]| {
// index into entries
let mut entries_k = 0;

@@ -133,7 +133,7 @@ impl ElementMapping {
let item = repair_stack.pop();
debug!("repair_for_box_changes: Set range for %u to %?",
item.entry_idx, Range(item.begin_idx, new_j - item.begin_idx));
entries[item.entry_idx].range = Range(item.begin_idx, new_j - item.begin_idx);
entries[item.entry_idx].range = MutableRange::new(item.begin_idx, new_j - item.begin_idx);
}
}
}
@@ -249,7 +249,7 @@ priv impl TextRunScanner {
debug!("TextRunScanner: pushing single text box in range: %?", self.clump);
let new_box = layout::text::adapt_textbox_with_range(old_box.d(),
run,
Range(0, run.text.len()));
&const MutableRange::new(0, run.text.len()));
out_boxes.push(new_box);
},
(false, true) => {
@@ -270,9 +270,9 @@ priv impl TextRunScanner {

// TODO(Issue #118): use a rope, simply give ownership of nonzero strs to rope
let mut run_str : ~str = ~"";
let new_ranges : DVec<Range> = DVec();
let new_ranges : DVec<MutableRange> = DVec();
for uint::range(0, transformed_strs.len()) |i| {
new_ranges.push(Range(run_str.len(), transformed_strs[i].len()));
new_ranges.push(MutableRange::new(run_str.len(), transformed_strs[i].len()));
str::push_str(&mut run_str, transformed_strs[i]);
}

@@ -289,7 +289,7 @@ priv impl TextRunScanner {
debug!("TextRunScanner: pushing box(es) in range: %?", self.clump);
let clump = self.clump;
for clump.eachi |i| {
let range = new_ranges[i - self.clump.begin()];
let range = &const new_ranges[i - self.clump.begin()];
if range.length() == 0 {
error!("Elided an UnscannedTextbox because it was zero-length after compression; %s",
in_boxes[i].debug_str());
@@ -328,7 +328,7 @@ struct LineboxScanner {
new_boxes: DVec<@RenderBox>,
work_list: DList<@RenderBox>,
pending_line: {mut range: MutableRange, mut width: Au},
line_spans: DVec<Range>,
line_spans: DVec<MutableRange>,
}

fn LineboxScanner(inline: @FlowContext) -> LineboxScanner {
@@ -415,7 +415,7 @@ impl LineboxScanner {
debug!("LineboxScanner: Flushing line %u: %?",
self.line_spans.len(), self.pending_line);
// set box horizontal offsets
let line_range = self.pending_line.range.as_immutable();
let line_range = self.pending_line.range;
let mut offset_x = Au(0);
// TODO(Issue #199): interpretation of CSS 'direction' will change how boxes are positioned.
debug!("LineboxScanner: Setting horizontal offsets for boxes in line %u range: %?",
@@ -566,7 +566,7 @@ struct InlineFlowData {
boxes: DVec<@RenderBox>,
// vec of ranges into boxes that represents line positions.
// these ranges are disjoint, and are the result of inline layout.
lines: DVec<Range>,
lines: DVec<MutableRange>,
// vec of ranges into boxes that represent elements. These ranges
// must be well-nested, and are only related to the content of
// boxes (not lines). Ranges are only kept for non-leaf elements.
@@ -681,7 +681,7 @@ impl FlowContext : InlineLayout {
// adjust bounding box metric to box's horizontal offset
// TODO: can we trust the leading provided by font metrics?
@TextBox(_, data) => {
let text_bounds = data.run.metrics_for_range(data.range).bounding_box;
let text_bounds = data.run.metrics_for_range(&const data.range).bounding_box;
text_bounds.translate(&Point2D(cur_box.d().position.origin.x, Au(0)))
},
_ => fail fmt!("Tried to compute bounding box of unknown Box variant: %s", cur_box.debug_str())

0 comments on commit da17ede

Please sign in to comment.
You can’t perform that action at this time.