Finish area readrawing optimization
This commit is contained in:
parent
778cbd0af2
commit
e676af8f91
12
src/shell.rs
12
src/shell.rs
@ -277,8 +277,9 @@ fn draw(shell: &Shell, ctx: &cairo::Context) {
|
|||||||
let line_height = shell.line_height.unwrap();
|
let line_height = shell.line_height.unwrap();
|
||||||
let char_width = shell.char_width.unwrap();
|
let char_width = shell.char_width.unwrap();
|
||||||
let clip = ctx.clip_extents();
|
let clip = ctx.clip_extents();
|
||||||
let model_clip = ModelRect::from_area(line_height, char_width,
|
let mut model_clip = ModelRect::from_area(line_height, char_width,
|
||||||
clip.0, clip.1, clip.2, clip.3);
|
clip.0, clip.1, clip.2, clip.3);
|
||||||
|
shell.model.limit_to_model(&mut model_clip);
|
||||||
|
|
||||||
let line_x = model_clip.left as f64 * char_width;
|
let line_x = model_clip.left as f64 * char_width;
|
||||||
let mut line_y: f64 = model_clip.top as f64 * line_height;
|
let mut line_y: f64 = model_clip.top as f64 * line_height;
|
||||||
@ -291,16 +292,15 @@ fn draw(shell: &Shell, ctx: &cairo::Context) {
|
|||||||
let layout = pc::create_layout(ctx);
|
let layout = pc::create_layout(ctx);
|
||||||
let mut desc = shell.create_pango_font();
|
let mut desc = shell.create_pango_font();
|
||||||
|
|
||||||
// FIXME: col_idx is wrong
|
|
||||||
for (line_idx, line) in shell.model.clip_model(&model_clip) {
|
for (line_idx, line) in shell.model.clip_model(&model_clip) {
|
||||||
ctx.move_to(line_x, line_y);
|
ctx.move_to(line_x, line_y);
|
||||||
|
|
||||||
// first draw background
|
// first draw background
|
||||||
// here we join same bg color for given line
|
// here we join same bg color for given line
|
||||||
// this gives less drawing primitives
|
// this gives less drawing primitives
|
||||||
let mut from_col_idx = 0;
|
let mut from_col_idx = model_clip.left;
|
||||||
let mut from_bg = None;
|
let mut from_bg = None;
|
||||||
for (col_idx, cell) in line.iter().enumerate() {
|
for (col_idx, cell) in line.iter() {
|
||||||
let (bg, _) = shell.colors(cell);
|
let (bg, _) = shell.colors(cell);
|
||||||
|
|
||||||
if from_bg.is_none() {
|
if from_bg.is_none() {
|
||||||
@ -321,14 +321,14 @@ fn draw(shell: &Shell, ctx: &cairo::Context) {
|
|||||||
draw_joined_rect(shell,
|
draw_joined_rect(shell,
|
||||||
ctx,
|
ctx,
|
||||||
from_col_idx,
|
from_col_idx,
|
||||||
line.len(),
|
model_clip.right + 1,
|
||||||
char_width,
|
char_width,
|
||||||
line_height,
|
line_height,
|
||||||
from_bg.take().unwrap());
|
from_bg.take().unwrap());
|
||||||
|
|
||||||
ctx.move_to(line_x, line_y);
|
ctx.move_to(line_x, line_y);
|
||||||
|
|
||||||
for (col_idx, cell) in line.iter().enumerate() {
|
for (col_idx, cell) in line.iter() {
|
||||||
let double_width = line.get(col_idx + 1).map(|c| c.attrs.double_width).unwrap_or(false);
|
let double_width = line.get(col_idx + 1).map(|c| c.attrs.double_width).unwrap_or(false);
|
||||||
let current_point = ctx.get_current_point();
|
let current_point = ctx.get_current_point();
|
||||||
|
|
||||||
|
103
src/ui_model.rs
103
src/ui_model.rs
@ -121,6 +121,29 @@ impl UiModel {
|
|||||||
&self.model
|
&self.model
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn limit_to_model(&self, clip: &mut ModelRect) {
|
||||||
|
clip.left = if clip.left >= self.columns {
|
||||||
|
self.columns - 1
|
||||||
|
} else {
|
||||||
|
clip.left
|
||||||
|
};
|
||||||
|
clip.right = if clip.right >= self.columns {
|
||||||
|
self.columns - 1
|
||||||
|
} else {
|
||||||
|
clip.right
|
||||||
|
};
|
||||||
|
clip.top = if clip.top >= self.rows {
|
||||||
|
self.rows - 1
|
||||||
|
} else {
|
||||||
|
clip.top
|
||||||
|
};
|
||||||
|
clip.bot = if clip.bot >= self.rows {
|
||||||
|
self.rows - 1
|
||||||
|
} else {
|
||||||
|
clip.bot
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn clip_model<'a> (&'a self, clip: &'a ModelRect) -> ClipRowIterator<'a> {
|
pub fn clip_model<'a> (&'a self, clip: &'a ModelRect) -> ClipRowIterator<'a> {
|
||||||
ClipRowIterator::new(self, clip)
|
ClipRowIterator::new(self, clip)
|
||||||
}
|
}
|
||||||
@ -275,8 +298,8 @@ impl ModelRect {
|
|||||||
pub fn to_area(&self, line_height: f64, char_width: f64) -> (i32, i32, i32, i32) {
|
pub fn to_area(&self, line_height: f64, char_width: f64) -> (i32, i32, i32, i32) {
|
||||||
(self.left as i32 * char_width as i32,
|
(self.left as i32 * char_width as i32,
|
||||||
self.top as i32 * line_height as i32,
|
self.top as i32 * line_height as i32,
|
||||||
(self.right - self.left + 1) as i32 * char_width as i32,
|
(self.right - self.left + 1) as i32 * char_width as i32- 1,
|
||||||
(self.bot - self.top + 1) as i32 * line_height as i32)
|
(self.bot - self.top + 1) as i32 * line_height as i32 - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_area(line_height: f64, char_width: f64, x1: f64, y1: f64, x2: f64, y2: f64) -> ModelRect {
|
pub fn from_area(line_height: f64, char_width: f64, x1: f64, y1: f64, x2: f64, y2: f64) -> ModelRect {
|
||||||
@ -306,20 +329,40 @@ impl <'a> ClipRowIterator<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl <'a> Iterator for ClipRowIterator<'a> {
|
impl <'a> Iterator for ClipRowIterator<'a> {
|
||||||
type Item = (usize, ClipColIterator<'a>);
|
type Item = (usize, ClipLine<'a>);
|
||||||
|
|
||||||
fn next(&mut self) -> Option<(usize, ClipColIterator<'a>)> {
|
fn next(&mut self) -> Option<(usize, ClipLine<'a>)> {
|
||||||
self.pos += 1;
|
self.pos += 1;
|
||||||
self.iter.next().map(|line| {
|
self.iter.next().map(|line| {
|
||||||
(self.rect.top + self.pos, ClipColIterator::new(line, self.rect))
|
(self.rect.top + self.pos - 1, ClipLine::new(line, self.rect))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ClipLine <'a> {
|
||||||
|
rect: &'a ModelRect,
|
||||||
|
line: &'a Vec<Cell>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <'a> ClipLine<'a> {
|
||||||
|
pub fn new(model: &'a Vec<Cell>, rect: &'a ModelRect) -> ClipLine<'a> {
|
||||||
|
ClipLine {
|
||||||
|
line: model,
|
||||||
|
rect: rect,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, idx: usize) -> Option<&Cell> {
|
||||||
|
self.line.get(idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> ClipColIterator<'a> {
|
||||||
|
ClipColIterator::new(self.line, self.rect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ClipColIterator<'a> {
|
pub struct ClipColIterator<'a> {
|
||||||
rect: &'a ModelRect,
|
rect: &'a ModelRect,
|
||||||
len: usize,
|
|
||||||
line: &'a Vec<Cell>,
|
|
||||||
pos: usize,
|
pos: usize,
|
||||||
iter: Iter<'a, Cell>,
|
iter: Iter<'a, Cell>,
|
||||||
}
|
}
|
||||||
@ -327,21 +370,12 @@ pub struct ClipColIterator<'a> {
|
|||||||
impl <'a> ClipColIterator<'a> {
|
impl <'a> ClipColIterator<'a> {
|
||||||
pub fn new(model: &'a Vec<Cell>, rect: &'a ModelRect) -> ClipColIterator<'a> {
|
pub fn new(model: &'a Vec<Cell>, rect: &'a ModelRect) -> ClipColIterator<'a> {
|
||||||
ClipColIterator {
|
ClipColIterator {
|
||||||
len: rect.right - rect.left + 1,
|
|
||||||
line: model,
|
|
||||||
rect: rect,
|
rect: rect,
|
||||||
pos: 0,
|
pos: 0,
|
||||||
iter: model[rect.left..rect.right + 1].iter(),
|
iter: model[rect.left..rect.right + 1].iter(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
self.len
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get(&self, idx: usize) -> Option<&Cell> {
|
|
||||||
self.line.get(idx)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a>Iterator for ClipColIterator<'a> {
|
impl <'a>Iterator for ClipColIterator<'a> {
|
||||||
@ -350,7 +384,7 @@ impl <'a>Iterator for ClipColIterator<'a> {
|
|||||||
fn next(&mut self) -> Option<(usize, &'a Cell)> {
|
fn next(&mut self) -> Option<(usize, &'a Cell)> {
|
||||||
self.pos += 1;
|
self.pos += 1;
|
||||||
self.iter.next().map(|line| {
|
self.iter.next().map(|line| {
|
||||||
(self.rect.left + self.pos, line)
|
(self.rect.left + self.pos - 1, line)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -359,13 +393,32 @@ impl <'a>Iterator for ClipColIterator<'a> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_iterator_border() {
|
||||||
|
let model = UiModel::new(10, 20);
|
||||||
|
let rect = ModelRect::new(0, 9, 0, 19);
|
||||||
|
|
||||||
|
assert_eq!(10, model.clip_model(&rect).count());
|
||||||
|
let (_, first_line) = model.clip_model(&rect).nth(0).unwrap();
|
||||||
|
assert_eq!(20, first_line.iter().count());
|
||||||
|
|
||||||
|
let (idx, _) = first_line.iter().nth(19).unwrap();
|
||||||
|
assert_eq!(19, idx);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_iterator() {
|
fn test_iterator() {
|
||||||
let model = UiModel::new(10, 20);
|
let model = UiModel::new(10, 20);
|
||||||
let rect = ModelRect::new(1, 2, 1, 2);
|
let rect = ModelRect::new(1, 2, 1, 2);
|
||||||
|
|
||||||
assert_eq!(2, model.clip_model(&rect).count());
|
assert_eq!(2, model.clip_model(&rect).count());
|
||||||
assert_eq!(2, model.clip_model(&rect).nth(0).unwrap().count());
|
let (idx, first_line) = model.clip_model(&rect).nth(0).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(1, idx);
|
||||||
|
assert_eq!(2, first_line.iter().count());
|
||||||
|
|
||||||
|
let (idx, _) = first_line.iter().nth(0).unwrap();
|
||||||
|
assert_eq!(1, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -376,6 +429,14 @@ mod tests {
|
|||||||
assert_eq!(0, rect.left);
|
assert_eq!(0, rect.left);
|
||||||
assert_eq!(1, rect.bot);
|
assert_eq!(1, rect.bot);
|
||||||
assert_eq!(1, rect.right);
|
assert_eq!(1, rect.right);
|
||||||
|
|
||||||
|
|
||||||
|
let rect = ModelRect::from_area(10.0, 5.0, 0.0, 0.0, 9.0, 19.0);
|
||||||
|
|
||||||
|
assert_eq!(0, rect.top);
|
||||||
|
assert_eq!(0, rect.left);
|
||||||
|
assert_eq!(1, rect.bot);
|
||||||
|
assert_eq!(1, rect.right);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -409,12 +470,12 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_repaint_rect() {
|
fn test_repaint_rect() {
|
||||||
let rect = ModelRect::point(1, 1);
|
let rect = ModelRect::point(1, 1);
|
||||||
let (x, y, width, height) = rect.to_area(10, 5);
|
let (x, y, width, height) = rect.to_area(10.0, 5.0);
|
||||||
|
|
||||||
assert_eq!(5, x);
|
assert_eq!(5, x);
|
||||||
assert_eq!(10, y);
|
assert_eq!(10, y);
|
||||||
assert_eq!(5, width);
|
assert_eq!(4, width);
|
||||||
assert_eq!(10, height);
|
assert_eq!(9, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
Reference in New Issue
Block a user