mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +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::uint;
|
||||
use std::util;
|
||||
use std::iterator;
|
||||
use geom::point::Point2D;
|
||||
use extra::sort;
|
||||
|
||||
|
@ -599,62 +600,24 @@ impl<'self> GlyphStore {
|
|||
self.entry_buffer[i] = entry;
|
||||
}
|
||||
|
||||
pub fn iter_glyphs_for_char_index(&'self self,
|
||||
i: uint,
|
||||
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_index(&'self self, i: uint) -> GlyphIterator<'self> {
|
||||
self.iter_glyphs_for_char_range(&Range::new(i, 1))
|
||||
}
|
||||
|
||||
pub fn iter_glyphs_for_char_range(&'self self,
|
||||
range: &Range,
|
||||
callback: &fn(uint, &GlyphInfo<'self>) -> bool)
|
||||
-> bool {
|
||||
if range.begin() >= self.entry_buffer.len() {
|
||||
error!("iter_glyphs_for_range: range.begin beyond length!");
|
||||
return false
|
||||
pub fn iter_glyphs_for_char_range(&'self self, rang: &Range) -> GlyphIterator<'self> {
|
||||
if rang.begin() >= self.entry_buffer.len() {
|
||||
fail!("iter_glyphs_for_range: range.begin beyond length!");
|
||||
}
|
||||
if range.end() > self.entry_buffer.len() {
|
||||
error!("iter_glyphs_for_range: range.end beyond length!");
|
||||
return false
|
||||
if rang.end() > self.entry_buffer.len() {
|
||||
fail!("iter_glyphs_for_range: range.end beyond length!");
|
||||
}
|
||||
|
||||
for range.eachi |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
|
||||
}
|
||||
GlyphIterator {
|
||||
store: self,
|
||||
char_index: rang.begin(),
|
||||
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
|
||||
|
@ -713,3 +676,49 @@ impl<'self> GlyphStore {
|
|||
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
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::vec::VecIterator;
|
||||
|
||||
use font_context::FontContext;
|
||||
use geometry::Au;
|
||||
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 {
|
||||
pub fn new(font: @mut Font, text: ~str, underline: bool) -> TextRun {
|
||||
let glyphs = TextRun::break_and_shape(font, text);
|
||||
|
@ -156,53 +230,19 @@ impl<'self> TextRun {
|
|||
max_piece_width
|
||||
}
|
||||
|
||||
pub fn iter_slices_for_range(&self,
|
||||
range: &Range,
|
||||
f: &fn(&GlyphStore, uint, &Range) -> bool)
|
||||
-> bool {
|
||||
let mut 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();
|
||||
pub fn iter_slices_for_range(&'self self, range: &Range) -> SliceIterator<'self> {
|
||||
SliceIterator {
|
||||
glyph_iter: self.glyphs.iter(),
|
||||
range: *range,
|
||||
offset: 0,
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
pub fn iter_natural_lines_for_range(&self, range: &Range, f: &fn(&Range) -> bool) -> bool {
|
||||
let mut clump = Range::new(range.begin(), 0);
|
||||
let mut in_clump = false;
|
||||
|
||||
for self.iter_slices_for_range(range) |glyphs, offset, slice_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 }
|
||||
}
|
||||
}
|
||||
pub fn iter_natural_lines_for_range(&'self self, range: &Range) -> LineIterator<'self> {
|
||||
LineIterator {
|
||||
range: *range,
|
||||
clump: None,
|
||||
slices: self.iter_slices_for_range(range),
|
||||
}
|
||||
|
||||
// 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 {
|
||||
pub fn new(id: int, node: AbstractNode<LayoutView>) -> FlowData {
|
||||
FlowData {
|
||||
|
@ -408,43 +425,15 @@ impl<'self> FlowContext {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn iter_all_boxes(&self, cb: &fn(RenderBox) -> bool) -> bool {
|
||||
match *self {
|
||||
BlockFlow(block) => {
|
||||
let block = &mut *block;
|
||||
for block.box.iter().advance |box| {
|
||||
if !cb(*box) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
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))
|
||||
pub fn iter_all_boxes(&self) -> BoxIterator {
|
||||
BoxIterator {
|
||||
boxes: match *self {
|
||||
BlockFlow (block) => block.box.map_default(~[], |&x| ~[x]),
|
||||
InlineFlow(inline) => inline.boxes.clone(),
|
||||
_ => fail!(fmt!("Don't know how to iterate node's RenderBoxes for %?", self))
|
||||
},
|
||||
index: 0,
|
||||
}
|
||||
|
||||
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.
|
||||
|
|
|
@ -6,6 +6,9 @@ use layout::box::{RenderBox};
|
|||
use script::dom::node::{AbstractNode, LayoutView};
|
||||
use servo_util::range::Range;
|
||||
|
||||
use std::iterator::Enumerate;
|
||||
use std::vec::VecIterator;
|
||||
|
||||
pub struct NodeRange {
|
||||
node: AbstractNode<LayoutView>,
|
||||
range: Range,
|
||||
|
@ -39,22 +42,8 @@ impl ElementMapping {
|
|||
true
|
||||
}
|
||||
|
||||
pub fn eachi(&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 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 eachi<'a>(&'a self) -> Enumerate<VecIterator<'a, NodeRange>> {
|
||||
self.entries.iter().enumerate()
|
||||
}
|
||||
|
||||
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