123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- use std::{borrow::Cow, cell::RefCell, rc::Rc};
- use held_core::view::{colors::Colors, style::CharStyle};
- use unicode_segmentation::UnicodeSegmentation;
- use held_core::utils::position::Position;
- #[derive(Debug, Clone, PartialEq)]
- pub struct Cell<'a> {
- pub content: Cow<'a, str>,
- pub colors: Colors,
- pub style: CharStyle,
- }
- impl<'c> Default for Cell<'c> {
- fn default() -> Self {
- Self {
- content: " ".into(),
- colors: Default::default(),
- style: Default::default(),
- }
- }
- }
- #[derive(Debug, Default, Clone)]
- pub struct CachedCell {
- pub content: String,
- pub colors: Colors,
- pub style: CharStyle,
- }
- #[derive(Debug)]
- pub struct CachedRenderBuffer {
- pub cells: Vec<Option<CachedCell>>,
- }
- impl CachedRenderBuffer {
- pub fn new(width: usize, height: usize) -> CachedRenderBuffer {
- CachedRenderBuffer {
- cells: vec![None; width * height],
- }
- }
- // 返回对应index是否与cell相等
- pub fn compare_and_update(&mut self, cell: &Cell, index: usize) -> bool {
- if index < self.cells.len() {
- let cache = &mut self.cells[index];
- let cell_content = String::from_iter(cell.content.chars());
- let equal = if let Some(cache) = cache {
- let equal = cache.colors == cell.colors
- && cache.style == cell.style
- && cache.content == cell_content;
- equal
- } else {
- false
- };
- if !equal {
- let mut cache_cell = CachedCell::default();
- let grapheme_count = cell.content.graphemes(true).count().max(1);
- cache_cell.colors = cell.colors;
- cache_cell.style = cell.style;
- cache_cell.content = cell_content;
- let end_index = (index + grapheme_count).min(self.cells.len());
- for i in (index + 1)..end_index {
- self.cells[i] = None
- }
- self.cells[index] = Some(cache_cell);
- }
- return equal;
- } else {
- return false;
- }
- }
- }
- #[derive(Debug)]
- pub struct RenderBuffer<'a> {
- width: usize,
- height: usize,
- cells: Vec<Cell<'a>>,
- cached: Rc<RefCell<CachedRenderBuffer>>,
- }
- impl<'a> RenderBuffer<'a> {
- pub fn new(
- width: usize,
- height: usize,
- cached: Rc<RefCell<CachedRenderBuffer>>,
- ) -> RenderBuffer<'a> {
- RenderBuffer {
- width,
- height,
- cells: vec![Cell::default(); width * height],
- cached,
- }
- }
- pub fn set_cell(&mut self, position: Position, cell: Cell<'a>) {
- if position.line >= self.height || position.offset >= self.width {
- return;
- }
- let index = position.line * self.width + position.offset;
- if index < self.cells.len() {
- self.cells[index] = cell;
- }
- }
- pub fn clear(&mut self) {
- self.cells = vec![Cell::default(); self.width * self.height];
- }
- pub fn iter(&self) -> RenderBufferIter {
- RenderBufferIter::new(self)
- }
- }
- pub struct RenderBufferIter<'a> {
- index: usize,
- width: usize,
- cells: &'a Vec<Cell<'a>>,
- cached: Rc<RefCell<CachedRenderBuffer>>,
- }
- impl<'a> RenderBufferIter<'a> {
- pub fn new(render_buffer: &'a RenderBuffer) -> RenderBufferIter<'a> {
- RenderBufferIter {
- index: 0,
- width: render_buffer.width,
- cells: &render_buffer.cells,
- cached: render_buffer.cached.clone(),
- }
- }
- }
- impl<'a> Iterator for RenderBufferIter<'a> {
- type Item = (Position, &'a Cell<'a>);
- fn next(&mut self) -> Option<Self::Item> {
- while self.index < self.cells.len() {
- let position = Position {
- line: self.index / self.width,
- offset: self.index % self.width,
- };
- let index = self.index;
- let cell = &self.cells[self.index];
- self.index += cell.content.graphemes(true).count().max(1);
- if !self.cached.borrow_mut().compare_and_update(cell, index) {
- return Some((position, cell));
- }
- }
- None
- }
- }
|