render_buffer.rs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. use std::{borrow::Cow, cell::RefCell, rc::Rc};
  2. use held_core::view::{colors::Colors, style::CharStyle};
  3. use unicode_segmentation::UnicodeSegmentation;
  4. use held_core::utils::position::Position;
  5. #[derive(Debug, Clone, PartialEq)]
  6. pub struct Cell<'a> {
  7. pub content: Cow<'a, str>,
  8. pub colors: Colors,
  9. pub style: CharStyle,
  10. }
  11. impl<'c> Default for Cell<'c> {
  12. fn default() -> Self {
  13. Self {
  14. content: " ".into(),
  15. colors: Default::default(),
  16. style: Default::default(),
  17. }
  18. }
  19. }
  20. #[derive(Debug, Default, Clone)]
  21. pub struct CachedCell {
  22. pub content: String,
  23. pub colors: Colors,
  24. pub style: CharStyle,
  25. }
  26. #[derive(Debug)]
  27. pub struct CachedRenderBuffer {
  28. pub cells: Vec<Option<CachedCell>>,
  29. }
  30. impl CachedRenderBuffer {
  31. pub fn new(width: usize, height: usize) -> CachedRenderBuffer {
  32. CachedRenderBuffer {
  33. cells: vec![None; width * height],
  34. }
  35. }
  36. // 返回对应index是否与cell相等
  37. pub fn compare_and_update(&mut self, cell: &Cell, index: usize) -> bool {
  38. if index < self.cells.len() {
  39. let cache = &mut self.cells[index];
  40. let cell_content = String::from_iter(cell.content.chars());
  41. let equal = if let Some(cache) = cache {
  42. let equal = cache.colors == cell.colors
  43. && cache.style == cell.style
  44. && cache.content == cell_content;
  45. equal
  46. } else {
  47. false
  48. };
  49. if !equal {
  50. let mut cache_cell = CachedCell::default();
  51. let grapheme_count = cell.content.graphemes(true).count().max(1);
  52. cache_cell.colors = cell.colors;
  53. cache_cell.style = cell.style;
  54. cache_cell.content = cell_content;
  55. let end_index = (index + grapheme_count).min(self.cells.len());
  56. for i in (index + 1)..end_index {
  57. self.cells[i] = None
  58. }
  59. self.cells[index] = Some(cache_cell);
  60. }
  61. return equal;
  62. } else {
  63. return false;
  64. }
  65. }
  66. }
  67. #[derive(Debug)]
  68. pub struct RenderBuffer<'a> {
  69. width: usize,
  70. height: usize,
  71. cells: Vec<Cell<'a>>,
  72. cached: Rc<RefCell<CachedRenderBuffer>>,
  73. }
  74. impl<'a> RenderBuffer<'a> {
  75. pub fn new(
  76. width: usize,
  77. height: usize,
  78. cached: Rc<RefCell<CachedRenderBuffer>>,
  79. ) -> RenderBuffer<'a> {
  80. RenderBuffer {
  81. width,
  82. height,
  83. cells: vec![Cell::default(); width * height],
  84. cached,
  85. }
  86. }
  87. pub fn set_cell(&mut self, position: Position, cell: Cell<'a>) {
  88. if position.line >= self.height || position.offset >= self.width {
  89. return;
  90. }
  91. let index = position.line * self.width + position.offset;
  92. if index < self.cells.len() {
  93. self.cells[index] = cell;
  94. }
  95. }
  96. pub fn clear(&mut self) {
  97. self.cells = vec![Cell::default(); self.width * self.height];
  98. }
  99. pub fn iter(&self) -> RenderBufferIter {
  100. RenderBufferIter::new(self)
  101. }
  102. }
  103. pub struct RenderBufferIter<'a> {
  104. index: usize,
  105. width: usize,
  106. cells: &'a Vec<Cell<'a>>,
  107. cached: Rc<RefCell<CachedRenderBuffer>>,
  108. }
  109. impl<'a> RenderBufferIter<'a> {
  110. pub fn new(render_buffer: &'a RenderBuffer) -> RenderBufferIter<'a> {
  111. RenderBufferIter {
  112. index: 0,
  113. width: render_buffer.width,
  114. cells: &render_buffer.cells,
  115. cached: render_buffer.cached.clone(),
  116. }
  117. }
  118. }
  119. impl<'a> Iterator for RenderBufferIter<'a> {
  120. type Item = (Position, &'a Cell<'a>);
  121. fn next(&mut self) -> Option<Self::Item> {
  122. while self.index < self.cells.len() {
  123. let position = Position {
  124. line: self.index / self.width,
  125. offset: self.index % self.width,
  126. };
  127. let index = self.index;
  128. let cell = &self.cells[self.index];
  129. self.index += cell.content.graphemes(true).count().max(1);
  130. if !self.cached.borrow_mut().compare_and_update(cell, index) {
  131. return Some((position, cell));
  132. }
  133. }
  134. None
  135. }
  136. }