rework draw commands to send whole line at once and draw background before foreground

macos-click-through
Keith Simmons 3 years ago committed by Keith Simmons
parent 8bade3667d
commit 3cc0d5c173

@ -9,20 +9,23 @@ use super::style::Style;
use super::{AnchorInfo, DrawCommand, DrawCommandBatcher}; use super::{AnchorInfo, DrawCommand, DrawCommandBatcher};
use crate::bridge::GridLineCell; use crate::bridge::GridLineCell;
#[derive(new, Clone, Debug)] #[derive(Clone, Debug)]
pub struct LineFragment {
pub text: String,
pub window_left: u64,
pub window_top: u64,
pub width: u64,
pub style: Option<Arc<Style>>,
}
#[derive(Clone, Debug)]
pub enum WindowDrawCommand { pub enum WindowDrawCommand {
Position { Position {
grid_position: (f64, f64), grid_position: (f64, f64),
grid_size: (u64, u64), grid_size: (u64, u64),
floating_order: Option<u64>, floating_order: Option<u64>,
}, },
Cells { DrawLine(Vec<LineFragment>),
cells: Vec<String>,
window_left: u64,
window_top: u64,
width: u64,
style: Option<Arc<Style>>,
},
Scroll { Scroll {
top: u64, top: u64,
bottom: u64, bottom: u64,
@ -179,14 +182,14 @@ impl Window {
*previous_style = style; *previous_style = style;
} }
// Send a draw command for the given row starting from current_start up until the next style // Build a line fragment for the given row starting from current_start up until the next style
// change or double width character. // change or double width character.
fn send_draw_command(&self, row_index: u64, start: u64) -> Option<u64> { fn build_line_fragment(&self, row_index: u64, start: u64) -> (u64, LineFragment) {
let row = self.grid.row(row_index).unwrap(); let row = self.grid.row(row_index).unwrap();
let (_, style) = &row[start as usize]; let (_, style) = &row[start as usize];
let mut cells = Vec::new(); let mut text = String::new();
let mut width = 0; let mut width = 0;
for possible_end_index in start..self.grid.width { for possible_end_index in start..self.grid.width {
let (character, possible_end_style) = &row[possible_end_index as usize]; let (character, possible_end_style) = &row[possible_end_index as usize];
@ -203,19 +206,35 @@ impl Window {
} }
// Add the grid cell to the cells to render // Add the grid cell to the cells to render
cells.push(character.clone()); text.push_str(character);
} }
// Send a window draw command to the current window. let line_fragment = LineFragment {
self.send_command(WindowDrawCommand::Cells { text,
cells,
window_left: start, window_left: start,
window_top: row_index, window_top: row_index,
width, width,
style: style.clone(), style: style.clone(),
}); };
Some(start + width) (start + width, line_fragment)
}
// Redraw line by calling build_line_fragment starting at 0
// until current_start is greater than the grid width and sending the resulting
// fragments as a batch
fn redraw_line(&self, row: u64) {
// until current_start is greater than the grid width and sending the resulting
// fragments as a batch
let mut current_start = 0;
let mut line_fragments = Vec::new();
while current_start < self.grid.width {
let (next_start, line_fragment) = self.build_line_fragment(row, current_start);
current_start = next_start;
line_fragments.push(line_fragment);
}
self.send_command(WindowDrawCommand::DrawLine(line_fragments));
} }
pub fn draw_grid_line( pub fn draw_grid_line(
@ -238,16 +257,7 @@ impl Window {
); );
} }
// Redraw the participating line by calling send_draw_command starting at 0 self.redraw_line(row);
// until current_start is greater than the grid width
let mut current_start = 0;
while current_start < self.grid.width {
if let Some(next_start) = self.send_draw_command(row, current_start) {
current_start = next_start;
} else {
break;
}
}
} else { } else {
warn!("Draw command out of bounds"); warn!("Draw command out of bounds");
} }
@ -312,14 +322,7 @@ impl Window {
pub fn redraw(&self) { pub fn redraw(&self) {
self.send_command(WindowDrawCommand::Clear); self.send_command(WindowDrawCommand::Clear);
for row in 0..self.grid.height { for row in 0..self.grid.height {
let mut current_start = 0; self.redraw_line(row);
while current_start < self.grid.width {
if let Some(next_start) = self.send_draw_command(row, current_start) {
current_start = next_start;
} else {
break;
}
}
} }
} }

@ -373,7 +373,7 @@ impl CursorRenderer {
let y_adjustment = grid_renderer.shaper.y_adjustment(); let y_adjustment = grid_renderer.shaper.y_adjustment();
let blobs = &grid_renderer let blobs = &grid_renderer
.shaper .shaper
.shape_cached(&[character], false, false); .shape_cached(character, false, false);
for blob in blobs.iter() { for blob in blobs.iter() {
canvas.draw_text_blob( canvas.draw_text_blob(

@ -14,7 +14,7 @@ use super::font_options::*;
#[derive(new, Clone, Hash, PartialEq, Eq, Debug)] #[derive(new, Clone, Hash, PartialEq, Eq, Debug)]
struct ShapeKey { struct ShapeKey {
pub cells: Vec<String>, pub text: String,
pub bold: bool, pub bold: bool,
pub italic: bool, pub italic: bool,
} }
@ -229,13 +229,12 @@ impl CachingShaper {
grouped_results grouped_results
} }
pub fn shape(&mut self, cells: &[String], bold: bool, italic: bool) -> Vec<TextBlob> { pub fn shape(&mut self, text: String, bold: bool, italic: bool) -> Vec<TextBlob> {
let current_size = self.current_size(); let current_size = self.current_size();
let (glyph_width, ..) = self.font_base_dimensions(); let (glyph_width, ..) = self.font_base_dimensions();
let mut resulting_blobs = Vec::new(); let mut resulting_blobs = Vec::new();
let text = cells.concat();
trace!("Shaping text: {}", text); trace!("Shaping text: {}", text);
for (cluster_group, font_pair) in self.build_clusters(&text, bold, italic) { for (cluster_group, font_pair) in self.build_clusters(&text, bold, italic) {
@ -279,11 +278,11 @@ impl CachingShaper {
resulting_blobs resulting_blobs
} }
pub fn shape_cached(&mut self, cells: &[String], bold: bool, italic: bool) -> &Vec<TextBlob> { pub fn shape_cached(&mut self, text: String, bold: bool, italic: bool) -> &Vec<TextBlob> {
let key = ShapeKey::new(cells.to_vec(), bold, italic); let key = ShapeKey::new(text.clone(), bold, italic);
if !self.blob_cache.contains(&key) { if !self.blob_cache.contains(&key) {
let blobs = self.shape(cells, bold, italic); let blobs = self.shape(text, bold, italic);
self.blob_cache.put(key.clone(), blobs); self.blob_cache.put(key.clone(), blobs);
} }

@ -103,7 +103,7 @@ impl GridRenderer {
pub fn draw_foreground( pub fn draw_foreground(
&mut self, &mut self,
canvas: &mut Canvas, canvas: &mut Canvas,
cells: &[String], text: String,
grid_position: (u64, u64), grid_position: (u64, u64),
cell_width: u64, cell_width: u64,
style: &Option<Arc<Style>>, style: &Option<Arc<Style>>,
@ -163,7 +163,7 @@ impl GridRenderer {
for blob in self for blob in self
.shaper .shaper
.shape_cached(cells, style.bold, style.italic) .shape_cached(text, style.bold, style.italic)
.iter() .iter()
{ {
canvas.draw_text_blob(blob, (x as f32, (y + y_adjustment) as f32), &self.paint); canvas.draw_text_blob(blob, (x as f32, (y + y_adjustment) as f32), &self.paint);

@ -9,7 +9,7 @@ use skia_safe::{
use super::animation_utils::*; use super::animation_utils::*;
use super::{GridRenderer, RendererSettings}; use super::{GridRenderer, RendererSettings};
use crate::editor::WindowDrawCommand; use crate::editor::{WindowDrawCommand, LineFragment};
use crate::redraw_scheduler::REDRAW_SCHEDULER; use crate::redraw_scheduler::REDRAW_SCHEDULER;
use crate::utils::Dimensions; use crate::utils::Dimensions;
@ -335,19 +335,33 @@ impl RenderedWindow {
self.grid_destination = new_destination; self.grid_destination = new_destination;
} }
} }
WindowDrawCommand::Cells { WindowDrawCommand::DrawLine(line_fragments) => {
cells,
window_left,
window_top,
width,
style,
} => {
let grid_position = (window_left, window_top);
let canvas = self.current_surface.surface.canvas(); let canvas = self.current_surface.surface.canvas();
canvas.save(); canvas.save();
grid_renderer.draw_background(canvas, grid_position, width, &style); for line_fragment in line_fragments.iter() {
grid_renderer.draw_foreground(canvas, &cells, grid_position, width, &style); let LineFragment {
window_left,
window_top,
width,
style,
..
} = line_fragment;
let grid_position = (*window_left, *window_top);
grid_renderer.draw_background(canvas, grid_position, *width, &style);
}
for line_fragment in line_fragments.into_iter() {
let LineFragment {
text,
window_left,
window_top,
width,
style
} = line_fragment;
let grid_position = (window_left, window_top);
grid_renderer.draw_foreground(canvas, text, grid_position, width, &style);
}
canvas.restore(); canvas.restore();
} }
WindowDrawCommand::Scroll { WindowDrawCommand::Scroll {

Loading…
Cancel
Save