mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Convert our iterators to external iterators
Except util/tree.rs (see next commit).
This commit is contained in:
parent
be061a9aa0
commit
abaeb58203
4 changed files with 173 additions and 146 deletions
|
@ -14,6 +14,7 @@ use std::u16;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
use std::uint;
|
use std::uint;
|
||||||
use std::util;
|
use std::util;
|
||||||
|
use std::iterator;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use extra::sort;
|
use extra::sort;
|
||||||
|
|
||||||
|
@ -599,62 +600,24 @@ impl<'self> GlyphStore {
|
||||||
self.entry_buffer[i] = entry;
|
self.entry_buffer[i] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_glyphs_for_char_index(&'self self,
|
pub fn iter_glyphs_for_char_index(&'self self, i: uint) -> GlyphIterator<'self> {
|
||||||
i: uint,
|
self.iter_glyphs_for_char_range(&Range::new(i, 1))
|
||||||
cb: &fn(uint, &GlyphInfo<'self>) -> bool)
|
|
||||||
-> bool {
|
|
||||||
assert!(i < self.entry_buffer.len());
|
|
||||||
|
|
||||||
let entry = &self.entry_buffer[i];
|
|
||||||
match entry.is_simple() {
|
|
||||||
true => {
|
|
||||||
let proxy = &SimpleGlyphInfo(self, i);
|
|
||||||
cb(i, proxy);
|
|
||||||
},
|
|
||||||
false => {
|
|
||||||
let glyphs = self.detail_store.get_detailed_glyphs_for_entry(i,
|
|
||||||
entry.glyph_count());
|
|
||||||
for uint::range(0, glyphs.len()) |j| {
|
|
||||||
let proxy = &DetailGlyphInfo(self, i, j as u16);
|
|
||||||
cb(i, proxy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_glyphs_for_char_range(&'self self,
|
pub fn iter_glyphs_for_char_range(&'self self, rang: &Range) -> GlyphIterator<'self> {
|
||||||
range: &Range,
|
if rang.begin() >= self.entry_buffer.len() {
|
||||||
callback: &fn(uint, &GlyphInfo<'self>) -> bool)
|
fail!("iter_glyphs_for_range: range.begin beyond length!");
|
||||||
-> bool {
|
|
||||||
if range.begin() >= self.entry_buffer.len() {
|
|
||||||
error!("iter_glyphs_for_range: range.begin beyond length!");
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
if range.end() > self.entry_buffer.len() {
|
if rang.end() > self.entry_buffer.len() {
|
||||||
error!("iter_glyphs_for_range: range.end beyond length!");
|
fail!("iter_glyphs_for_range: range.end beyond length!");
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for range.eachi |i| {
|
GlyphIterator {
|
||||||
// FIXME: Work around rust#2202. We should be able to pass the callback directly.
|
store: self,
|
||||||
if !self.iter_glyphs_for_char_index(i, |a, b| callback(a, b)) {
|
char_index: rang.begin(),
|
||||||
break
|
char_range: rang.eachi(),
|
||||||
}
|
glyph_range: None
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iter_all_glyphs(&'self self, callback: &fn(uint, &GlyphInfo<'self>) -> bool) -> bool {
|
|
||||||
for uint::range(0, self.entry_buffer.len()) |i| {
|
|
||||||
// FIXME: Work around rust#2202. We should be able to pass the callback directly.
|
|
||||||
if !self.iter_glyphs_for_char_index(i, |a, b| callback(a, b)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getter methods
|
// getter methods
|
||||||
|
@ -713,3 +676,49 @@ impl<'self> GlyphStore {
|
||||||
self.entry_buffer[i] = entry.set_can_break_before(t);
|
self.entry_buffer[i] = entry.set_can_break_before(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct GlyphIterator<'self> {
|
||||||
|
priv store: &'self GlyphStore,
|
||||||
|
priv char_index: uint,
|
||||||
|
priv char_range: iterator::Range<uint>,
|
||||||
|
priv glyph_range: Option<iterator::Range<uint>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'self> Iterator<(uint, GlyphInfo<'self>)> for GlyphIterator<'self> {
|
||||||
|
// I tried to start with something simpler and apply FlatMap, but the
|
||||||
|
// inability to store free variables in the FlatMap struct was problematic.
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<(uint, GlyphInfo<'self>)> {
|
||||||
|
// Would use 'match' here but it borrows contents in a way that
|
||||||
|
// interferes with mutation.
|
||||||
|
if self.glyph_range.is_some() {
|
||||||
|
match self.glyph_range.unwrap().next() {
|
||||||
|
Some(j) => Some((self.char_index,
|
||||||
|
DetailGlyphInfo(self.store, self.char_index, j as u16))),
|
||||||
|
None => {
|
||||||
|
// No more glyphs for current character. Try to get another.
|
||||||
|
self.glyph_range = None;
|
||||||
|
self.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No glyph range. Look at next character.
|
||||||
|
match self.char_range.next() {
|
||||||
|
Some(i) => {
|
||||||
|
self.char_index = i;
|
||||||
|
assert!(i < self.store.entry_buffer.len());
|
||||||
|
let entry = &self.store.entry_buffer[i];
|
||||||
|
if entry.is_simple() {
|
||||||
|
Some((self.char_index, SimpleGlyphInfo(self.store, i)))
|
||||||
|
} else {
|
||||||
|
let glyphs = self.store.detail_store
|
||||||
|
.get_detailed_glyphs_for_entry(i, entry.glyph_count());
|
||||||
|
self.glyph_range = Some(range(0, glyphs.len()));
|
||||||
|
self.next()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::vec::VecIterator;
|
||||||
|
|
||||||
use font_context::FontContext;
|
use font_context::FontContext;
|
||||||
use geometry::Au;
|
use geometry::Au;
|
||||||
use text::glyph::GlyphStore;
|
use text::glyph::GlyphStore;
|
||||||
|
@ -41,6 +43,78 @@ impl SendableTextRun {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct SliceIterator<'self> {
|
||||||
|
priv glyph_iter: VecIterator<'self, Arc<GlyphStore>>,
|
||||||
|
priv range: Range,
|
||||||
|
priv offset: uint,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'self> Iterator<(&'self GlyphStore, uint, Range)> for SliceIterator<'self> {
|
||||||
|
fn next(&mut self) -> Option<(&'self GlyphStore, uint, Range)> {
|
||||||
|
loop {
|
||||||
|
let slice_glyphs = self.glyph_iter.next();
|
||||||
|
if slice_glyphs.is_none() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let slice_glyphs = slice_glyphs.unwrap().get();
|
||||||
|
|
||||||
|
let slice_range = Range::new(self.offset, slice_glyphs.char_len());
|
||||||
|
let mut char_range = self.range.intersect(&slice_range);
|
||||||
|
char_range.shift_by(-(self.offset.to_int()));
|
||||||
|
|
||||||
|
let old_offset = self.offset;
|
||||||
|
self.offset += slice_glyphs.char_len();
|
||||||
|
if !char_range.is_empty() {
|
||||||
|
return Some((slice_glyphs, old_offset, char_range))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LineIterator<'self> {
|
||||||
|
priv range: Range,
|
||||||
|
priv clump: Option<Range>,
|
||||||
|
priv slices: SliceIterator<'self>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'self> Iterator<Range> for LineIterator<'self> {
|
||||||
|
fn next(&mut self) -> Option<Range> {
|
||||||
|
// Loop until we hit whitespace and are in a clump.
|
||||||
|
loop {
|
||||||
|
match self.slices.next() {
|
||||||
|
Some((glyphs, offset, slice_range)) => {
|
||||||
|
match (glyphs.is_whitespace(), self.clump) {
|
||||||
|
(false, Some(ref mut c)) => {
|
||||||
|
c.extend_by(slice_range.length().to_int());
|
||||||
|
}
|
||||||
|
(false, None) => {
|
||||||
|
let mut c = slice_range;
|
||||||
|
c.shift_by(offset.to_int());
|
||||||
|
self.clump = Some(c);
|
||||||
|
}
|
||||||
|
(true, None) => { /* chomp whitespace */ }
|
||||||
|
(true, Some(c)) => {
|
||||||
|
self.clump = None;
|
||||||
|
// The final whitespace clump is not included.
|
||||||
|
return Some(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
// flush any remaining chars as a line
|
||||||
|
if self.clump.is_some() {
|
||||||
|
let mut c = self.clump.take_unwrap();
|
||||||
|
c.extend_to(self.range.end());
|
||||||
|
return Some(c);
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'self> TextRun {
|
impl<'self> TextRun {
|
||||||
pub fn new(font: @mut Font, text: ~str, underline: bool) -> TextRun {
|
pub fn new(font: @mut Font, text: ~str, underline: bool) -> TextRun {
|
||||||
let glyphs = TextRun::break_and_shape(font, text);
|
let glyphs = TextRun::break_and_shape(font, text);
|
||||||
|
@ -156,53 +230,19 @@ impl<'self> TextRun {
|
||||||
max_piece_width
|
max_piece_width
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_slices_for_range(&self,
|
pub fn iter_slices_for_range(&'self self, range: &Range) -> SliceIterator<'self> {
|
||||||
range: &Range,
|
SliceIterator {
|
||||||
f: &fn(&GlyphStore, uint, &Range) -> bool)
|
glyph_iter: self.glyphs.iter(),
|
||||||
-> bool {
|
range: *range,
|
||||||
let mut offset = 0;
|
offset: 0,
|
||||||
for self.glyphs.iter().advance |slice_glyphs| {
|
|
||||||
// Determine the range of this slice that we need.
|
|
||||||
let slice_range = Range::new(offset, slice_glyphs.get().char_len());
|
|
||||||
let mut char_range = range.intersect(&slice_range);
|
|
||||||
char_range.shift_by(-(offset.to_int()));
|
|
||||||
|
|
||||||
let unwrapped_glyphs = slice_glyphs.get();
|
|
||||||
if !char_range.is_empty() {
|
|
||||||
if !f(unwrapped_glyphs, offset, &char_range) { break }
|
|
||||||
}
|
|
||||||
offset += unwrapped_glyphs.char_len();
|
|
||||||
}
|
}
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_natural_lines_for_range(&self, range: &Range, f: &fn(&Range) -> bool) -> bool {
|
pub fn iter_natural_lines_for_range(&'self self, range: &Range) -> LineIterator<'self> {
|
||||||
let mut clump = Range::new(range.begin(), 0);
|
LineIterator {
|
||||||
let mut in_clump = false;
|
range: *range,
|
||||||
|
clump: None,
|
||||||
for self.iter_slices_for_range(range) |glyphs, offset, slice_range| {
|
slices: self.iter_slices_for_range(range),
|
||||||
match (glyphs.is_whitespace(), in_clump) {
|
|
||||||
(false, true) => { clump.extend_by(slice_range.length().to_int()); }
|
|
||||||
(false, false) => {
|
|
||||||
in_clump = true;
|
|
||||||
clump = *slice_range;
|
|
||||||
clump.shift_by(offset.to_int());
|
|
||||||
}
|
|
||||||
(true, false) => { /* chomp whitespace */ }
|
|
||||||
(true, true) => {
|
|
||||||
in_clump = false;
|
|
||||||
// The final whitespace clump is not included.
|
|
||||||
if !f(&clump) { break }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// flush any remaining chars as a line
|
|
||||||
if in_clump {
|
|
||||||
clump.extend_to(range.end());
|
|
||||||
f(&clump);
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,6 +238,23 @@ impl TreeNode<FlowContext> for FlowData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct BoxIterator {
|
||||||
|
priv boxes: ~[RenderBox],
|
||||||
|
priv index: uint,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator<RenderBox> for BoxIterator {
|
||||||
|
fn next(&mut self) -> Option<RenderBox> {
|
||||||
|
if self.index >= self.boxes.len() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let v = self.boxes[self.index].clone();
|
||||||
|
self.index += 1;
|
||||||
|
Some(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FlowData {
|
impl FlowData {
|
||||||
pub fn new(id: int, node: AbstractNode<LayoutView>) -> FlowData {
|
pub fn new(id: int, node: AbstractNode<LayoutView>) -> FlowData {
|
||||||
FlowData {
|
FlowData {
|
||||||
|
@ -408,43 +425,15 @@ impl<'self> FlowContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_all_boxes(&self, cb: &fn(RenderBox) -> bool) -> bool {
|
pub fn iter_all_boxes(&self) -> BoxIterator {
|
||||||
match *self {
|
BoxIterator {
|
||||||
BlockFlow(block) => {
|
boxes: match *self {
|
||||||
let block = &mut *block;
|
BlockFlow (block) => block.box.map_default(~[], |&x| ~[x]),
|
||||||
for block.box.iter().advance |box| {
|
InlineFlow(inline) => inline.boxes.clone(),
|
||||||
if !cb(*box) {
|
_ => fail!(fmt!("Don't know how to iterate node's RenderBoxes for %?", self))
|
||||||
break;
|
},
|
||||||
}
|
index: 0,
|
||||||
}
|
|
||||||
}
|
|
||||||
InlineFlow(inline) => {
|
|
||||||
let inline = &mut *inline;
|
|
||||||
for inline.boxes.iter().advance |box| {
|
|
||||||
if !cb(*box) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => fail!(fmt!("Don't know how to iterate node's RenderBoxes for %?", self))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iter_boxes_for_node(&self,
|
|
||||||
node: AbstractNode<LayoutView>,
|
|
||||||
callback: &fn(RenderBox) -> bool)
|
|
||||||
-> bool {
|
|
||||||
for self.iter_all_boxes |box| {
|
|
||||||
if box.node() == node {
|
|
||||||
if !callback(box) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dumps the flow tree for debugging.
|
/// Dumps the flow tree for debugging.
|
||||||
|
|
|
@ -6,6 +6,9 @@ use layout::box::{RenderBox};
|
||||||
use script::dom::node::{AbstractNode, LayoutView};
|
use script::dom::node::{AbstractNode, LayoutView};
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
|
|
||||||
|
use std::iterator::Enumerate;
|
||||||
|
use std::vec::VecIterator;
|
||||||
|
|
||||||
pub struct NodeRange {
|
pub struct NodeRange {
|
||||||
node: AbstractNode<LayoutView>,
|
node: AbstractNode<LayoutView>,
|
||||||
range: Range,
|
range: Range,
|
||||||
|
@ -39,22 +42,8 @@ impl ElementMapping {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eachi(&self, callback: &fn(i: uint, nr: &NodeRange) -> bool) -> bool {
|
pub fn eachi<'a>(&'a self) -> Enumerate<VecIterator<'a, NodeRange>> {
|
||||||
for self.entries.iter().enumerate().advance |(i, nr)| {
|
self.entries.iter().enumerate()
|
||||||
if !callback(i, nr) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn eachi_mut(&self, callback: &fn(i: uint, nr: &NodeRange) -> bool) -> bool {
|
|
||||||
for self.entries.iter().enumerate().advance |(i, nr)| {
|
|
||||||
if !callback(i, nr) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn repair_for_box_changes(&mut self, old_boxes: &[RenderBox], new_boxes: &[RenderBox]) {
|
pub fn repair_for_box_changes(&mut self, old_boxes: &[RenderBox], new_boxes: &[RenderBox]) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue