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 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 {
Position {
grid_position: (f64, f64),
grid_size: (u64, u64),
floating_order: Option<u64>,
},
Cells {
cells: Vec<String>,
window_left: u64,
window_top: u64,
width: u64,
style: Option<Arc<Style>>,
},
DrawLine(Vec<LineFragment>),
Scroll {
top: u64,
bottom: u64,
@ -179,14 +182,14 @@ impl Window {
*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.
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 (_, style) = &row[start as usize];
let mut cells = Vec::new();
let mut text = String::new();
let mut width = 0;
for possible_end_index in start..self.grid.width {
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
cells.push(character.clone());
text.push_str(character);
}
// Send a window draw command to the current window.
self.send_command(WindowDrawCommand::Cells {
cells,
let line_fragment = LineFragment {
text,
window_left: start,
window_top: row_index,
width,
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(
@ -238,16 +257,7 @@ impl Window {
);
}
// Redraw the participating line by calling send_draw_command starting at 0
// 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;
}
}
self.redraw_line(row);
} else {
warn!("Draw command out of bounds");
}
@ -312,14 +322,7 @@ impl Window {
pub fn redraw(&self) {
self.send_command(WindowDrawCommand::Clear);
for row in 0..self.grid.height {
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;
}
}
self.redraw_line(row);
}
}

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

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

@ -103,7 +103,7 @@ impl GridRenderer {
pub fn draw_foreground(
&mut self,
canvas: &mut Canvas,
cells: &[String],
text: String,
grid_position: (u64, u64),
cell_width: u64,
style: &Option<Arc<Style>>,
@ -163,7 +163,7 @@ impl GridRenderer {
for blob in self
.shaper
.shape_cached(cells, style.bold, style.italic)
.shape_cached(text, style.bold, style.italic)
.iter()
{
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::{GridRenderer, RendererSettings};
use crate::editor::WindowDrawCommand;
use crate::editor::{WindowDrawCommand, LineFragment};
use crate::redraw_scheduler::REDRAW_SCHEDULER;
use crate::utils::Dimensions;
@ -335,19 +335,33 @@ impl RenderedWindow {
self.grid_destination = new_destination;
}
}
WindowDrawCommand::Cells {
cells,
window_left,
window_top,
width,
style,
} => {
let grid_position = (window_left, window_top);
WindowDrawCommand::DrawLine(line_fragments) => {
let canvas = self.current_surface.surface.canvas();
canvas.save();
grid_renderer.draw_background(canvas, grid_position, width, &style);
grid_renderer.draw_foreground(canvas, &cells, grid_position, width, &style);
for line_fragment in line_fragments.iter() {
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();
}
WindowDrawCommand::Scroll {

Loading…
Cancel
Save