reimplement merge

This commit is contained in:
daa84
2017-08-31 18:37:55 +03:00
parent 6e0909ea95
commit 40f5492ba8
5 changed files with 348 additions and 243 deletions

View File

@@ -53,13 +53,14 @@ impl Cell {
Cell {
attrs: Attrs::new(),
ch: ch,
dirty: false,
dirty: true,
}
}
pub fn clear(&mut self) {
self.ch = ' ';
self.attrs.clear();
self.dirty = true;
}
}

View File

@@ -53,7 +53,6 @@ pub struct Line {
pub item_line: Box<[Option<Item>]>,
cell_to_item: Box<[i32]>,
item_line_empty: bool,
pub dirty_line: bool,
}
@@ -72,8 +71,7 @@ impl Line {
line: line.into_boxed_slice(),
item_line: item_line.into_boxed_slice(),
cell_to_item: vec![-1; columns].into_boxed_slice(),
dirty_line: false,
item_line_empty: true,
dirty_line: true,
}
}
@@ -81,36 +79,85 @@ impl Line {
for cell in &mut self.line[left..right + 1] {
cell.clear();
}
self.dirty_line = true;
}
pub fn merge(&mut self, old_items: &StyledLine, new_items: &[sys_pango::Item]) {
for new_item in new_items {
//FIXME: clear empty cells
let (offset, length, _) = new_item.offset();
let start_cell = old_items.cell_to_byte[offset];
let end_cell = old_items.cell_to_byte[offset + length - 1];
fn set_cell_to_empty(&mut self, cell_idx: usize) -> bool {
if self.item_line[cell_idx].is_some() {
self.item_line[cell_idx] = None;
self.cell_to_item[cell_idx] = -1;
self.line[cell_idx].dirty = true;
true
} else {
false
}
}
// first time initialization
// as cell_to_item points to wrong values
if !self.item_line_empty {
let start_item = self.cell_to_item(start_cell);
let end_item = self.cell_to_item(end_cell);
fn set_cell_to_item(&mut self, pango_item: &PangoItemPosition) -> bool {
let start_item = self.cell_to_item(pango_item.start_cell);
let end_item = self.cell_to_item(pango_item.end_cell);
//FIXME: check start cell
//FIXME: check length
//FIXME: don't check start_item != end_item
// in case different item length was in previous iteration
// mark all item as dirty
if start_item != end_item {
self.initialize_cell_item(start_cell, end_cell, new_item);
} else {
self.item_line[start_cell].as_mut().unwrap().update(
new_item.clone(),
);
}
// in case different item length was in previous iteration
// mark all item as dirty
if start_item != end_item || start_item == -1 || end_item == -1 {
self.initialize_cell_item(pango_item.start_cell, pango_item.end_cell, pango_item.item);
true
} else {
// update only if cell marked as dirty
if self.line[pango_item.start_cell..pango_item.end_cell + 1]
.iter()
.find(|c| c.dirty)
.is_some()
{
self.item_line[pango_item.start_cell]
.as_mut()
.unwrap()
.update(pango_item.item.clone());
self.line[pango_item.start_cell].dirty = true;
true
} else {
self.initialize_cell_item(start_cell, end_cell, new_item);
false
}
}
}
self.item_line_empty = false;
pub fn merge(&mut self, old_items: &StyledLine, pango_items: &[sys_pango::Item]) {
let mut pango_item_iter = pango_items.iter().map(|item| {
PangoItemPosition::new(old_items, item)
});
let mut next_item = pango_item_iter.next();
let mut move_to_next_item = false;
let mut cell_idx = 0;
while cell_idx < self.line.len() {
let dirty = match next_item {
None => self.set_cell_to_empty(cell_idx),
Some(ref pango_item) => {
if cell_idx < pango_item.start_cell {
self.set_cell_to_empty(cell_idx)
} else if cell_idx == pango_item.start_cell {
move_to_next_item = true;
self.set_cell_to_item(pango_item)
} else {
false
}
}
};
self.dirty_line = self.dirty_line || dirty;
if move_to_next_item {
let pango_item = next_item.unwrap();
cell_idx += pango_item.end_cell - pango_item.start_cell + 1;
next_item = pango_item_iter.next();
move_to_next_item = false;
} else {
cell_idx += 1;
}
}
}
fn initialize_cell_item(
@@ -161,6 +208,26 @@ impl IndexMut<usize> for Line {
}
}
struct PangoItemPosition<'a> {
item: &'a sys_pango::Item,
start_cell: usize,
end_cell: usize,
}
impl<'a> PangoItemPosition<'a> {
pub fn new(styled_line: &StyledLine, item: &'a sys_pango::Item) -> Self {
let (offset, length, _) = item.offset();
let start_cell = styled_line.cell_to_byte[offset];
let end_cell = styled_line.cell_to_byte[offset + length - 1];
PangoItemPosition {
item,
start_cell,
end_cell,
}
}
}
pub struct StyledLine {
pub line_str: String,
cell_to_byte: Box<[usize]>,