Draw optimization
This commit is contained in:
parent
39db875b6f
commit
531c900d66
@ -1,8 +1,10 @@
|
|||||||
mod context;
|
mod context;
|
||||||
mod itemize;
|
mod itemize;
|
||||||
|
mod model_clip_iterator;
|
||||||
|
|
||||||
pub use self::context::Context;
|
pub use self::context::Context;
|
||||||
pub use self::context::CellMetrics;
|
pub use self::context::CellMetrics;
|
||||||
|
use self::model_clip_iterator::ModelClipIteratorFactory;
|
||||||
|
|
||||||
use mode;
|
use mode;
|
||||||
use color;
|
use color;
|
||||||
@ -36,10 +38,10 @@ pub fn render(
|
|||||||
ascent,
|
ascent,
|
||||||
..
|
..
|
||||||
} = font_ctx.cell_metrics();
|
} = font_ctx.cell_metrics();
|
||||||
let mut line_y = 0.0;
|
|
||||||
let (cursor_row, cursor_col) = ui_model.get_cursor();
|
let (cursor_row, cursor_col) = ui_model.get_cursor();
|
||||||
|
|
||||||
for (row, line) in ui_model.model().iter().enumerate() {
|
for (row, line) in ui_model.get_clip_iterator(ctx, font_ctx.cell_metrics()) {
|
||||||
|
let line_y = row as f64 * line_height;
|
||||||
let mut line_x = 0.0;
|
let mut line_x = 0.0;
|
||||||
|
|
||||||
for col in 0..line.line.len() {
|
for col in 0..line.line.len() {
|
||||||
@ -78,7 +80,7 @@ pub fn render(
|
|||||||
|
|
||||||
if cell.attrs.underline || cell.attrs.undercurl {
|
if cell.attrs.underline || cell.attrs.undercurl {
|
||||||
if cell.attrs.undercurl {
|
if cell.attrs.undercurl {
|
||||||
//FIXME: don't repaint all lines on changes
|
//FIXME: sometime we don't repaint all undercurl lines
|
||||||
let sp = color_model.actual_cell_sp(cell);
|
let sp = color_model.actual_cell_sp(cell);
|
||||||
ctx.set_source_rgba(sp.0, sp.1, sp.2, 0.7);
|
ctx.set_source_rgba(sp.0, sp.1, sp.2, 0.7);
|
||||||
|
|
||||||
@ -115,7 +117,6 @@ pub fn render(
|
|||||||
|
|
||||||
line_x += char_width;
|
line_x += char_width;
|
||||||
}
|
}
|
||||||
line_y += line_height;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
64
src/render/model_clip_iterator.rs
Normal file
64
src/render/model_clip_iterator.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
use std::slice::Iter;
|
||||||
|
use cairo;
|
||||||
|
|
||||||
|
use super::context::CellMetrics;
|
||||||
|
use ui_model;
|
||||||
|
|
||||||
|
pub struct ModelClipIterator<'a> {
|
||||||
|
model_idx: usize,
|
||||||
|
model_iter: Iter<'a, ui_model::Line>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ModelClipIteratorFactory {
|
||||||
|
fn get_clip_iterator(
|
||||||
|
&self,
|
||||||
|
ctx: &cairo::Context,
|
||||||
|
cell_metrics: &CellMetrics,
|
||||||
|
) -> ModelClipIterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for ModelClipIterator<'a> {
|
||||||
|
type Item = (usize, &'a ui_model::Line);
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<(usize, &'a ui_model::Line)> {
|
||||||
|
let next = if let Some(line) = self.model_iter.next() {
|
||||||
|
Some((self.model_idx, line))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
self.model_idx += 1;
|
||||||
|
|
||||||
|
next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clip implemented as top - 1/bot + 1
|
||||||
|
/// this is because in some cases(like 'g' character) drawing character does not fit to calculated bounds
|
||||||
|
/// and if one line must be repainted - also previous and next line must be repainted to
|
||||||
|
impl ModelClipIteratorFactory for ui_model::UiModel {
|
||||||
|
fn get_clip_iterator(
|
||||||
|
&self,
|
||||||
|
ctx: &cairo::Context,
|
||||||
|
cell_metrics: &CellMetrics,
|
||||||
|
) -> ModelClipIterator {
|
||||||
|
let model = self.model();
|
||||||
|
|
||||||
|
let (x1, y1, x2, y2) = ctx.clip_extents();
|
||||||
|
let model_clip = ui_model::ModelRect::from_area(cell_metrics, x1, y1, x2, y2);
|
||||||
|
let model_clip_top = if model_clip.top <= 0 {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
model_clip.top - 1
|
||||||
|
};
|
||||||
|
let model_clip_bot = if model_clip.bot >= model.len() - 1 {
|
||||||
|
model.len() - 1
|
||||||
|
} else {
|
||||||
|
model_clip.bot + 1
|
||||||
|
};
|
||||||
|
|
||||||
|
ModelClipIterator {
|
||||||
|
model_idx: model_clip_top,
|
||||||
|
model_iter: model[model_clip_top..model_clip_bot + 1].iter(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,10 +4,9 @@ mod item;
|
|||||||
mod model_rect;
|
mod model_rect;
|
||||||
|
|
||||||
pub use self::cell::{Cell, Attrs};
|
pub use self::cell::{Cell, Attrs};
|
||||||
pub use self::line::StyledLine;
|
pub use self::line::{Line, StyledLine};
|
||||||
pub use self::item::Item;
|
pub use self::item::Item;
|
||||||
pub use self::model_rect::{ModelRect, ModelRectVec};
|
pub use self::model_rect::{ModelRect, ModelRectVec};
|
||||||
use self::line::Line;
|
|
||||||
|
|
||||||
|
|
||||||
pub struct UiModel {
|
pub struct UiModel {
|
||||||
@ -42,10 +41,12 @@ impl UiModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn model(&self) -> &[Line] {
|
pub fn model(&self) -> &[Line] {
|
||||||
&self.model
|
&self.model
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn model_mut(&mut self) -> &mut [Line] {
|
pub fn model_mut(&mut self) -> &mut [Line] {
|
||||||
&mut self.model
|
&mut self.model
|
||||||
}
|
}
|
||||||
|
@ -240,13 +240,18 @@ impl ModelRect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_area(
|
pub fn from_area(
|
||||||
line_height: f64,
|
cell_metrics: &CellMetrics,
|
||||||
char_width: f64,
|
|
||||||
x1: f64,
|
x1: f64,
|
||||||
y1: f64,
|
y1: f64,
|
||||||
x2: f64,
|
x2: f64,
|
||||||
y2: f64,
|
y2: f64,
|
||||||
) -> ModelRect {
|
) -> ModelRect {
|
||||||
|
let &CellMetrics {
|
||||||
|
char_width,
|
||||||
|
line_height,
|
||||||
|
..
|
||||||
|
} = cell_metrics;
|
||||||
|
|
||||||
let x2 = if x2 > 0.0 { x2 - 1.0 } else { x2 };
|
let x2 = if x2 > 0.0 { x2 - 1.0 } else { x2 };
|
||||||
let y2 = if y2 > 0.0 { y2 - 1.0 } else { y2 };
|
let y2 = if y2 > 0.0 { y2 - 1.0 } else { y2 };
|
||||||
let left = (x1 / char_width) as usize;
|
let left = (x1 / char_width) as usize;
|
||||||
|
Loading…
Reference in New Issue
Block a user