refactor grid_renderer out of renderer and clean up window draw command handling

macos-click-through
Keith Simmons 3 years ago
parent c52a6e356a
commit 3bba418c1c

@ -2,8 +2,8 @@ use log::error;
use skia_safe::{paint::Style, BlendMode, Canvas, Color, Paint, Point, Rect};
use super::CursorSettings;
use crate::editor::{Colors, Cursor};
use crate::renderer::animation_utils::*;
use crate::editor::Cursor;
use crate::renderer::{animation_utils::*, grid_renderer::GridRenderer};
use crate::settings::*;
pub trait CursorVfx {
@ -11,7 +11,7 @@ pub trait CursorVfx {
&mut self,
settings: &CursorSettings,
current_cursor_destination: Point,
font_size: (u64, u64),
cursor_dimensions: Point,
dt: f32,
) -> bool;
fn restart(&mut self, position: Point);
@ -19,9 +19,8 @@ pub trait CursorVfx {
&self,
settings: &CursorSettings,
canvas: &mut Canvas,
grid_renderer: &mut GridRenderer,
cursor: &Cursor,
colors: &Colors,
font_size: (u64, u64),
);
}
@ -111,7 +110,7 @@ impl CursorVfx for PointHighlight {
&mut self,
_settings: &CursorSettings,
_current_cursor_destination: Point,
_font_size: (u64, u64),
_cursor_dimensions: Point,
dt: f32,
) -> bool {
self.t = (self.t + dt * 5.0).min(1.0); // TODO - speed config
@ -127,9 +126,8 @@ impl CursorVfx for PointHighlight {
&self,
settings: &CursorSettings,
canvas: &mut Canvas,
grid_renderer: &mut GridRenderer,
cursor: &Cursor,
colors: &Colors,
font_size: (u64, u64),
) {
if (self.t - 1.0).abs() < std::f32::EPSILON {
return;
@ -138,13 +136,15 @@ impl CursorVfx for PointHighlight {
let mut paint = Paint::new(skia_safe::colors::WHITE, None);
paint.set_blend_mode(BlendMode::SrcOver);
let colors = &grid_renderer.default_style.colors;
let base_color: Color = cursor.background(colors).to_color();
let alpha = ease(ease_in_quad, settings.vfx_opacity, 0.0, self.t) as u8;
let color = Color::from_argb(alpha, base_color.r(), base_color.g(), base_color.b());
paint.set_color(color);
let size = 3 * font_size.1;
let cursor_height = grid_renderer.font_dimensions.height;
let size = 3 * cursor_height;
let radius = self.t * size as f32;
let hr = radius * 0.5;
let rect = Rect::from_xywh(
@ -160,12 +160,12 @@ impl CursorVfx for PointHighlight {
}
HighlightMode::Ripple => {
paint.set_style(Style::Stroke);
paint.set_stroke_width(font_size.1 as f32 * 0.2);
paint.set_stroke_width(cursor_height as f32 * 0.2);
canvas.draw_oval(&rect, &paint);
}
HighlightMode::Wireframe => {
paint.set_style(Style::Stroke);
paint.set_stroke_width(font_size.1 as f32 * 0.2);
paint.set_stroke_width(cursor_height as f32 * 0.2);
canvas.draw_rect(&rect, &paint);
}
}
@ -218,7 +218,7 @@ impl CursorVfx for ParticleTrail {
&mut self,
settings: &CursorSettings,
current_cursor_dest: Point,
font_size: (u64, u64),
cursor_dimensions: Point,
dt: f32,
) -> bool {
// Update lifetimes and remove dead particles
@ -246,7 +246,7 @@ impl CursorVfx for ParticleTrail {
let travel_distance = travel.length();
// Increase amount of particles when cursor travels further
let particle_count = ((travel_distance / font_size.0 as f32).powf(1.5)
let particle_count = ((travel_distance / cursor_dimensions.y as f32).powf(1.5)
* settings.vfx_particle_density
* 0.01) as usize;
@ -259,7 +259,7 @@ impl CursorVfx for ParticleTrail {
TrailMode::Railgun => {
let phase = t / std::f32::consts::PI
* settings.vfx_particle_phase
* (travel_distance / font_size.0 as f32);
* (travel_distance / cursor_dimensions.y as f32);
Point::new(phase.sin(), phase.cos()) * 2.0 * settings.vfx_particle_speed
}
TrailMode::Torpedo => {
@ -282,7 +282,7 @@ impl CursorVfx for ParticleTrail {
TrailMode::PixieDust | TrailMode::Torpedo => {
prev_p
+ travel * self.rng.next_f32()
+ Point::new(0.0, font_size.1 as f32 * 0.5)
+ Point::new(0.0, cursor_dimensions.y as f32 * 0.5)
}
};
@ -316,19 +316,20 @@ impl CursorVfx for ParticleTrail {
&self,
settings: &CursorSettings,
canvas: &mut Canvas,
grid_renderer: &mut GridRenderer,
cursor: &Cursor,
colors: &Colors,
font_size: (u64, u64),
) {
let mut paint = Paint::new(skia_safe::colors::WHITE, None);
let font_dimensions = grid_renderer.font_dimensions;
match self.trail_mode {
TrailMode::Torpedo | TrailMode::Railgun => {
paint.set_style(Style::Stroke);
paint.set_stroke_width(font_size.1 as f32 * 0.2);
paint.set_stroke_width(font_dimensions.height as f32 * 0.2);
}
_ => {}
}
let colors = &grid_renderer.default_style.colors;
let base_color: Color = cursor.background(colors).to_color();
paint.set_blend_mode(BlendMode::SrcOver);
@ -340,8 +341,10 @@ impl CursorVfx for ParticleTrail {
paint.set_color(color);
let radius = match self.trail_mode {
TrailMode::Torpedo | TrailMode::Railgun => font_size.0 as f32 * 0.5 * lifetime,
TrailMode::PixieDust => font_size.0 as f32 * 0.2,
TrailMode::Torpedo | TrailMode::Railgun => {
font_dimensions.width as f32 * 0.5 * lifetime
}
TrailMode::PixieDust => font_dimensions.width as f32 * 0.2,
};
let hr = radius * 0.5;

@ -6,12 +6,11 @@ use std::collections::HashMap;
// use neovide_derive::SettingGroup;
use skia_safe::{Canvas, Paint, Path, Point};
use super::RenderedWindow;
use super::{GridRenderer, RenderedWindow};
use crate::bridge::EditorMode;
use crate::editor::{Colors, Cursor, CursorShape};
use crate::editor::{Cursor, CursorShape};
use crate::redraw_scheduler::REDRAW_SCHEDULER;
use crate::renderer::animation_utils::*;
use crate::renderer::CachingShaper;
use crate::settings::{FromValue, SETTINGS};
use blink::*;
@ -257,10 +256,8 @@ impl CursorRenderer {
pub fn draw(
&mut self,
default_colors: &Colors,
(font_width, font_height): (u64, u64),
grid_renderer: &mut GridRenderer,
current_mode: &EditorMode,
shaper: &mut CachingShaper,
canvas: &mut Canvas,
dt: f32,
) {
@ -277,19 +274,23 @@ impl CursorRenderer {
let character = self.cursor.character.clone();
let font_width = match (self.cursor.double_width, &self.cursor.shape) {
(true, CursorShape::Block) => font_width * 2,
_ => font_width,
};
let mut cursor_width = grid_renderer.font_dimensions.width;
if self.cursor.double_width && self.cursor.shape == CursorShape::Block {
cursor_width *= 2;
}
let font_dimensions: Point = (font_width as f32, font_height as f32).into();
let cursor_dimensions: Point = (
cursor_width as f32,
grid_renderer.font_dimensions.height as f32,
)
.into();
let in_insert_mode = matches!(current_mode, EditorMode::Insert);
let changed_to_from_cmdline = !matches!(self.previous_editor_mode, EditorMode::CmdLine)
^ matches!(current_mode, EditorMode::CmdLine);
let center_destination = self.destination + font_dimensions * 0.5;
let center_destination = self.destination + cursor_dimensions * 0.5;
let new_cursor = Some(self.cursor.shape.clone());
if self.previous_cursor_shape != new_cursor {
@ -315,7 +316,7 @@ impl CursorRenderer {
let corner_animating = corner.update(
&settings,
font_dimensions,
cursor_dimensions,
center_destination,
dt,
immediate_movement,
@ -325,7 +326,7 @@ impl CursorRenderer {
}
let vfx_animating = if let Some(vfx) = self.cursor_vfx.as_mut() {
vfx.update(&settings, center_destination, (font_width, font_height), dt)
vfx.update(&settings, center_destination, cursor_dimensions, dt)
} else {
false
};
@ -341,7 +342,11 @@ impl CursorRenderer {
if self.cursor.enabled && render {
// Draw Background
paint.set_color(self.cursor.background(default_colors).to_color());
let background_color = self
.cursor
.background(&grid_renderer.default_style.colors)
.to_color();
paint.set_color(background_color);
// The cursor is made up of four points, so I create a path with each of the four
// corners.
@ -356,13 +361,19 @@ impl CursorRenderer {
canvas.draw_path(&path, &paint);
// Draw foreground
paint.set_color(self.cursor.foreground(default_colors).to_color());
let foreground_color = self
.cursor
.foreground(&grid_renderer.default_style.colors)
.to_color();
paint.set_color(foreground_color);
canvas.save();
canvas.clip_path(&path, None, Some(false));
let y_adjustment = shaper.y_adjustment();
let blobs = &shaper.shape_cached(&[character], false, false);
let y_adjustment = grid_renderer.shaper.y_adjustment();
let blobs = &grid_renderer
.shaper
.shape_cached(&[character], false, false);
for blob in blobs.iter() {
canvas.draw_text_blob(
@ -375,13 +386,7 @@ impl CursorRenderer {
canvas.restore();
if let Some(vfx) = self.cursor_vfx.as_ref() {
vfx.render(
&settings,
canvas,
&self.cursor,
default_colors,
(font_width, font_height),
);
vfx.render(&settings, canvas, grid_renderer, &self.cursor);
}
}
}

@ -0,0 +1,185 @@
use std::sync::Arc;
use glutin::dpi::PhysicalSize;
use log::trace;
use skia_safe::{colors, dash_path_effect, BlendMode, Canvas, Color, Paint, Rect, HSV};
use super::{CachingShaper, RendererSettings};
use crate::editor::{Colors, Style};
use crate::settings::*;
use crate::utils::Dimensions;
pub struct GridRenderer {
pub shaper: CachingShaper,
pub paint: Paint,
pub default_style: Arc<Style>,
pub font_dimensions: Dimensions,
pub scale_factor: f64,
pub is_ready: bool,
}
impl GridRenderer {
pub fn new(scale_factor: f64) -> Self {
let mut shaper = CachingShaper::new(scale_factor as f32);
let mut paint = Paint::new(colors::WHITE, None);
paint.set_anti_alias(false);
let default_style = Arc::new(Style::new(Colors::new(
Some(colors::WHITE),
Some(colors::BLACK),
Some(colors::GREY),
)));
let font_dimensions: Dimensions = shaper.font_base_dimensions().into();
GridRenderer {
shaper,
paint,
default_style,
font_dimensions,
scale_factor,
is_ready: false,
}
}
/// Convert PhysicalSize to grid size
pub fn convert_physical_to_grid(&self, physical: PhysicalSize<u32>) -> Dimensions {
Dimensions::from(physical) / self.font_dimensions
}
/// Convert grid size to PhysicalSize
pub fn convert_grid_to_physical(&self, grid: Dimensions) -> PhysicalSize<u32> {
(grid * self.font_dimensions).into()
}
pub fn handle_scale_factor_update(&mut self, scale_factor: f64) {
self.shaper.update_scale_factor(scale_factor as f32);
self.update_font_dimensions();
}
pub fn update_font(&mut self, guifont_setting: &str) {
self.shaper.update_font(guifont_setting);
self.update_font_dimensions();
}
fn update_font_dimensions(&mut self) {
self.font_dimensions = self.shaper.font_base_dimensions().into();
self.is_ready = true;
trace!("Updated font dimensions: {:?}", self.font_dimensions,);
}
fn compute_text_region(&self, grid_position: (u64, u64), cell_width: u64) -> Rect {
let (x, y) = grid_position * self.font_dimensions;
let width = cell_width * self.font_dimensions.width;
let height = self.font_dimensions.height;
Rect::new(x as f32, y as f32, (x + width) as f32, (y + height) as f32)
}
pub fn get_default_background(&self) -> Color {
self.default_style.colors.background.unwrap().to_color()
}
pub fn draw_background(
&mut self,
canvas: &mut Canvas,
grid_position: (u64, u64),
cell_width: u64,
style: &Option<Arc<Style>>,
) {
self.paint.set_blend_mode(BlendMode::Src);
let region = self.compute_text_region(grid_position, cell_width);
let style = style.as_ref().unwrap_or(&self.default_style);
if SETTINGS.get::<RendererSettings>().debug_renderer {
let random_hsv: HSV = (rand::random::<f32>() * 360.0, 0.3, 0.3).into();
let random_color = random_hsv.to_color(255);
self.paint.set_color(random_color);
} else {
self.paint
.set_color(style.background(&self.default_style.colors).to_color());
}
canvas.draw_rect(region, &self.paint);
}
pub fn draw_foreground(
&mut self,
canvas: &mut Canvas,
cells: &[String],
grid_position: (u64, u64),
cell_width: u64,
style: &Option<Arc<Style>>,
) {
let (x, y) = grid_position * self.font_dimensions;
let width = cell_width * self.font_dimensions.width;
let style = style.as_ref().unwrap_or(&self.default_style);
canvas.save();
let region = self.compute_text_region(grid_position, cell_width);
canvas.clip_rect(region, None, Some(false));
if style.underline || style.undercurl {
let line_position = self.shaper.underline_position();
let stroke_width = self.shaper.current_size() / 10.0;
self.paint
.set_color(style.special(&self.default_style.colors).to_color());
self.paint.set_stroke_width(stroke_width);
if style.undercurl {
self.paint.set_path_effect(dash_path_effect::new(
&[stroke_width * 2.0, stroke_width * 2.0],
0.0,
));
} else {
self.paint.set_path_effect(None);
}
canvas.draw_line(
(
x as f32,
(y - line_position + self.font_dimensions.height) as f32,
),
(
(x + width) as f32,
(y - line_position + self.font_dimensions.height) as f32,
),
&self.paint,
);
}
let y_adjustment = self.shaper.y_adjustment();
if SETTINGS.get::<RendererSettings>().debug_renderer {
let random_hsv: HSV = (rand::random::<f32>() * 360.0, 1.0, 1.0).into();
let random_color = random_hsv.to_color(255);
self.paint.set_color(random_color);
} else {
self.paint
.set_color(style.foreground(&self.default_style.colors).to_color());
}
self.paint.set_anti_alias(false);
for blob in self
.shaper
.shape_cached(cells, style.bold, style.italic)
.iter()
{
canvas.draw_text_blob(blob, (x as f32, (y + y_adjustment) as f32), &self.paint);
}
if style.strikethrough {
let line_position = region.center_y();
self.paint
.set_color(style.special(&self.default_style.colors).to_color());
canvas.draw_line(
(x as f32, line_position),
((x + width) as f32, line_position),
&self.paint,
);
}
canvas.restore();
}
}

@ -1,22 +1,22 @@
pub mod animation_utils;
pub mod cursor_renderer;
mod fonts;
pub mod grid_renderer;
mod rendered_window;
use std::collections::HashMap;
use std::collections::{hash_map::Entry, HashMap};
use std::sync::mpsc::Receiver;
use std::sync::Arc;
use glutin::dpi::PhysicalSize;
use log::{error, trace};
use skia_safe::{colors, dash_path_effect, BlendMode, Canvas, Color, Paint, Rect, HSV};
use log::error;
use skia_safe::Canvas;
use crate::bridge::EditorMode;
use crate::editor::{Colors, DrawCommand, Style, WindowDrawCommand};
use crate::editor::{DrawCommand, WindowDrawCommand};
use crate::settings::*;
use crate::utils::Dimensions;
use cursor_renderer::CursorRenderer;
pub use fonts::caching_shaper::CachingShaper;
pub use grid_renderer::GridRenderer;
pub use rendered_window::{RenderedWindow, WindowDrawDetails};
#[derive(SettingGroup, Clone)]
@ -41,238 +41,35 @@ impl Default for RendererSettings {
}
pub struct Renderer {
rendered_windows: HashMap<u64, RenderedWindow>,
cursor_renderer: CursorRenderer,
pub grid_renderer: GridRenderer,
current_mode: EditorMode,
pub paint: Paint,
pub shaper: CachingShaper,
pub default_style: Arc<Style>,
pub font_dimensions: Dimensions,
rendered_windows: HashMap<u64, RenderedWindow>,
pub window_regions: Vec<WindowDrawDetails>,
pub batched_draw_command_receiver: Receiver<Vec<DrawCommand>>,
pub is_ready: bool,
}
impl Renderer {
pub fn new(
batched_draw_command_receiver: Receiver<Vec<DrawCommand>>,
scale_factor: f64,
) -> Renderer {
let rendered_windows = HashMap::new();
) -> Self {
let cursor_renderer = CursorRenderer::new();
let grid_renderer = GridRenderer::new(scale_factor);
let current_mode = EditorMode::Unknown(String::from(""));
let mut paint = Paint::new(colors::WHITE, None);
paint.set_anti_alias(false);
let mut shaper = CachingShaper::new(scale_factor as f32);
let font_dimensions: Dimensions = shaper.font_base_dimensions().into();
let default_style = Arc::new(Style::new(Colors::new(
Some(colors::WHITE),
Some(colors::BLACK),
Some(colors::GREY),
)));
let rendered_windows = HashMap::new();
let window_regions = Vec::new();
Renderer {
rendered_windows,
cursor_renderer,
grid_renderer,
current_mode,
paint,
shaper,
default_style,
font_dimensions,
window_regions,
batched_draw_command_receiver,
is_ready: false,
}
}
/// Convert PhysicalSize to grid size
pub fn convert_physical_to_grid(&self, physical: PhysicalSize<u32>) -> Dimensions {
Dimensions::from(physical) / self.font_dimensions
}
/// Convert grid size to PhysicalSize
pub fn convert_grid_to_physical(&self, grid: Dimensions) -> PhysicalSize<u32> {
(grid * self.font_dimensions).into()
}
pub fn handle_scale_factor_update(&mut self, scale_factor: f64) {
self.shaper.update_scale_factor(scale_factor as f32);
self.update_font_dimensions();
}
fn update_font(&mut self, guifont_setting: &str) {
self.shaper.update_font(guifont_setting);
self.update_font_dimensions();
}
fn update_font_dimensions(&mut self) {
self.font_dimensions = self.shaper.font_base_dimensions().into();
self.is_ready = true;
trace!("Updated font dimensions: {:?}", self.font_dimensions,);
}
fn compute_text_region(&self, grid_position: (u64, u64), cell_width: u64) -> Rect {
let (x, y) = grid_position * self.font_dimensions;
let width = cell_width * self.font_dimensions.width;
let height = self.font_dimensions.height;
Rect::new(x as f32, y as f32, (x + width) as f32, (y + height) as f32)
}
fn get_default_background(&self) -> Color {
self.default_style.colors.background.unwrap().to_color()
}
fn draw_background(
&mut self,
canvas: &mut Canvas,
grid_position: (u64, u64),
cell_width: u64,
style: &Option<Arc<Style>>,
) {
self.paint.set_blend_mode(BlendMode::Src);
let region = self.compute_text_region(grid_position, cell_width);
let style = style.as_ref().unwrap_or(&self.default_style);
if SETTINGS.get::<RendererSettings>().debug_renderer {
let random_hsv: HSV = (rand::random::<f32>() * 360.0, 0.3, 0.3).into();
let random_color = random_hsv.to_color(255);
self.paint.set_color(random_color);
} else {
self.paint
.set_color(style.background(&self.default_style.colors).to_color());
}
canvas.draw_rect(region, &self.paint);
}
fn draw_foreground(
&mut self,
canvas: &mut Canvas,
cells: &[String],
grid_position: (u64, u64),
cell_width: u64,
style: &Option<Arc<Style>>,
) {
let (x, y) = grid_position * self.font_dimensions;
let width = cell_width * self.font_dimensions.width;
let style = style.as_ref().unwrap_or(&self.default_style);
canvas.save();
let region = self.compute_text_region(grid_position, cell_width);
canvas.clip_rect(region, None, Some(false));
if style.underline || style.undercurl {
let line_position = self.shaper.underline_position();
let stroke_width = self.shaper.current_size() / 10.0;
self.paint
.set_color(style.special(&self.default_style.colors).to_color());
self.paint.set_stroke_width(stroke_width);
if style.undercurl {
self.paint.set_path_effect(dash_path_effect::new(
&[stroke_width * 2.0, stroke_width * 2.0],
0.0,
));
} else {
self.paint.set_path_effect(None);
}
canvas.draw_line(
(
x as f32,
(y - line_position + self.font_dimensions.height) as f32,
),
(
(x + width) as f32,
(y - line_position + self.font_dimensions.height) as f32,
),
&self.paint,
);
}
let y_adjustment = self.shaper.y_adjustment();
if SETTINGS.get::<RendererSettings>().debug_renderer {
let random_hsv: HSV = (rand::random::<f32>() * 360.0, 1.0, 1.0).into();
let random_color = random_hsv.to_color(255);
self.paint.set_color(random_color);
} else {
self.paint
.set_color(style.foreground(&self.default_style.colors).to_color());
}
self.paint.set_anti_alias(false);
for blob in self
.shaper
.shape_cached(cells, style.bold, style.italic)
.iter()
{
canvas.draw_text_blob(blob, (x as f32, (y + y_adjustment) as f32), &self.paint);
}
if style.strikethrough {
let line_position = region.center_y();
self.paint
.set_color(style.special(&self.default_style.colors).to_color());
canvas.draw_line(
(x as f32, line_position),
((x + width) as f32, line_position),
&self.paint,
);
}
canvas.restore();
}
fn handle_draw_command(&mut self, root_canvas: &mut Canvas, draw_command: DrawCommand) {
match draw_command {
DrawCommand::Window {
grid_id,
command: WindowDrawCommand::Close,
} => {
self.rendered_windows.remove(&grid_id);
}
DrawCommand::Window { grid_id, command } => {
if let Some(rendered_window) = self.rendered_windows.remove(&grid_id) {
let rendered_window = rendered_window.handle_window_draw_command(self, command);
self.rendered_windows.insert(grid_id, rendered_window);
} else if let WindowDrawCommand::Position {
grid_position: (grid_left, grid_top),
grid_size: (width, height),
..
} = command
{
let new_window = RenderedWindow::new(
root_canvas,
self,
grid_id,
(grid_left as f32, grid_top as f32).into(),
(width, height).into(),
);
self.rendered_windows.insert(grid_id, new_window);
} else {
error!("WindowDrawCommand sent for uninitialized grid {}", grid_id);
}
}
DrawCommand::UpdateCursor(new_cursor) => {
self.cursor_renderer.update_cursor(new_cursor);
}
DrawCommand::FontChanged(new_font) => {
self.update_font(&new_font);
}
DrawCommand::DefaultStyleChanged(new_style) => {
self.default_style = Arc::new(new_style);
}
DrawCommand::ModeChanged(new_mode) => {
self.current_mode = new_mode;
}
_ => {}
}
}
@ -297,17 +94,18 @@ impl Renderer {
self.handle_draw_command(root_canvas, draw_command);
}
root_canvas.clear(self.default_style.colors.background.unwrap().to_color());
let default_background = self.grid_renderer.get_default_background();
let font_dimensions = self.grid_renderer.font_dimensions;
root_canvas.clear(default_background);
root_canvas.save();
root_canvas.reset_matrix();
if let Some(root_window) = self.rendered_windows.get(&1) {
let clip_rect = root_window.pixel_region(self.font_dimensions);
let clip_rect = root_window.pixel_region(font_dimensions);
root_canvas.clip_rect(&clip_rect, None, Some(false));
}
let default_background = self.get_default_background();
let windows: Vec<&mut RenderedWindow> = {
let (mut root_windows, mut floating_windows): (
Vec<&mut RenderedWindow>,
@ -335,7 +133,6 @@ impl Renderer {
};
let settings = SETTINGS.get::<RendererSettings>();
let font_dimensions = self.font_dimensions;
self.window_regions = windows
.into_iter()
.map(|window| {
@ -353,17 +150,63 @@ impl Renderer {
self.cursor_renderer
.update_cursor_destination(font_dimensions.into(), windows);
self.cursor_renderer.draw(
&self.default_style.colors,
font_dimensions.into(),
&self.current_mode,
&mut self.shaper,
root_canvas,
dt,
);
self.cursor_renderer
.draw(&mut self.grid_renderer, &self.current_mode, root_canvas, dt);
root_canvas.restore();
font_changed
}
fn handle_draw_command(&mut self, root_canvas: &mut Canvas, draw_command: DrawCommand) {
match draw_command {
DrawCommand::Window {
grid_id,
command: WindowDrawCommand::Close,
} => {
self.rendered_windows.remove(&grid_id);
}
DrawCommand::Window { grid_id, command } => {
match self.rendered_windows.entry(grid_id) {
Entry::Occupied(mut occupied_entry) => {
let rendered_window = occupied_entry.get_mut();
rendered_window
.handle_window_draw_command(&mut self.grid_renderer, command);
}
Entry::Vacant(vacant_entry) => {
if let WindowDrawCommand::Position {
grid_position: (grid_left, grid_top),
grid_size: (width, height),
..
} = command
{
let new_window = RenderedWindow::new(
root_canvas,
&self.grid_renderer,
grid_id,
(grid_left as f32, grid_top as f32).into(),
(width, height).into(),
);
vacant_entry.insert(new_window);
} else {
error!("WindowDrawCommand sent for uninitialized grid {}", grid_id);
}
}
}
}
DrawCommand::UpdateCursor(new_cursor) => {
self.cursor_renderer.update_cursor(new_cursor);
}
DrawCommand::FontChanged(new_font) => {
self.grid_renderer.update_font(&new_font);
}
DrawCommand::DefaultStyleChanged(new_style) => {
self.grid_renderer.default_style = Arc::new(new_style);
}
DrawCommand::ModeChanged(new_mode) => {
self.current_mode = new_mode;
}
_ => {}
}
}
}

@ -8,7 +8,7 @@ use skia_safe::{
};
use super::animation_utils::*;
use super::{Renderer, RendererSettings};
use super::{GridRenderer, RendererSettings};
use crate::editor::WindowDrawCommand;
use crate::redraw_scheduler::REDRAW_SCHEDULER;
use crate::utils::Dimensions;
@ -40,14 +40,16 @@ fn build_window_surface(parent_canvas: &mut Canvas, pixel_size: (i32, i32)) -> S
fn build_window_surface_with_grid_size(
parent_canvas: &mut Canvas,
renderer: &Renderer,
grid_renderer: &GridRenderer,
grid_size: Dimensions,
) -> Surface {
let mut surface =
build_window_surface(parent_canvas, (grid_size * renderer.font_dimensions).into());
let mut surface = build_window_surface(
parent_canvas,
(grid_size * grid_renderer.font_dimensions).into(),
);
let canvas = surface.canvas();
canvas.clear(renderer.get_default_background());
canvas.clear(grid_renderer.get_default_background());
surface
}
@ -64,11 +66,11 @@ pub struct LocatedSurface {
impl LocatedSurface {
fn new(
parent_canvas: &mut Canvas,
renderer: &Renderer,
grid_renderer: &GridRenderer,
grid_size: Dimensions,
top_line: u64,
) -> LocatedSurface {
let surface = build_window_surface_with_grid_size(parent_canvas, renderer, grid_size);
let surface = build_window_surface_with_grid_size(parent_canvas, grid_renderer, grid_size);
LocatedSurface { surface, top_line }
}
@ -113,12 +115,12 @@ pub struct WindowDrawDetails {
impl RenderedWindow {
pub fn new(
parent_canvas: &mut Canvas,
renderer: &Renderer,
grid_renderer: &GridRenderer,
id: u64,
grid_position: Point,
grid_size: Dimensions,
) -> RenderedWindow {
let current_surface = LocatedSurface::new(parent_canvas, renderer, grid_size, 0);
let current_surface = LocatedSurface::new(parent_canvas, grid_renderer, grid_size, 0);
RenderedWindow {
snapshots: VecDeque::new(),
@ -279,10 +281,10 @@ impl RenderedWindow {
}
pub fn handle_window_draw_command(
mut self,
renderer: &mut Renderer,
&mut self,
grid_renderer: &mut GridRenderer,
draw_command: WindowDrawCommand,
) -> Self {
) {
match draw_command {
WindowDrawCommand::Position {
grid_position: (grid_left, grid_top),
@ -308,19 +310,19 @@ impl RenderedWindow {
}
if self.grid_size != new_grid_size {
let mut old_surface = self.current_surface.surface;
self.current_surface.surface = build_window_surface_with_grid_size(
old_surface.canvas(),
renderer,
let mut new_surface = build_window_surface_with_grid_size(
self.current_surface.surface.canvas(),
grid_renderer,
new_grid_size,
);
old_surface.draw(
self.current_surface.surface.canvas(),
self.current_surface.surface.draw(
new_surface.canvas(),
(0.0, 0.0),
SamplingOptions::default(),
None,
);
self.current_surface.surface = new_surface;
self.grid_size = new_grid_size;
}
@ -344,8 +346,8 @@ impl RenderedWindow {
let canvas = self.current_surface.surface.canvas();
canvas.save();
renderer.draw_background(canvas, grid_position, width, &style);
renderer.draw_foreground(canvas, &cells, grid_position, width, &style);
grid_renderer.draw_background(canvas, grid_position, width, &style);
grid_renderer.draw_foreground(canvas, &cells, grid_position, width, &style);
canvas.restore();
}
WindowDrawCommand::Scroll {
@ -359,7 +361,7 @@ impl RenderedWindow {
let Dimensions {
width: font_width,
height: font_height,
} = renderer.font_dimensions;
} = grid_renderer.font_dimensions;
let scrolled_region = Rect::new(
(left * font_width) as f32,
(top * font_height) as f32,
@ -383,7 +385,7 @@ impl RenderedWindow {
snapshot,
Some((&scrolled_region, SrcRectConstraint::Fast)),
translated_region,
&renderer.paint,
&grid_renderer.paint,
);
canvas.restore();
@ -391,7 +393,7 @@ impl RenderedWindow {
WindowDrawCommand::Clear => {
self.current_surface.surface = build_window_surface_with_grid_size(
self.current_surface.surface.canvas(),
renderer,
grid_renderer,
self.grid_size,
);
@ -424,7 +426,5 @@ impl RenderedWindow {
}
_ => {}
};
self
}
}

@ -22,6 +22,9 @@ macro_rules! impl_from_tuple_to_dimensions {
};
}
impl_from_tuple_to_dimensions!(u64);
impl_from_tuple_to_dimensions!(f32);
macro_rules! impl_from_dimensions_to_tuple {
($type:ty) => {
impl From<Dimensions> for ($type, $type) {
@ -32,9 +35,6 @@ macro_rules! impl_from_dimensions_to_tuple {
};
}
impl_from_tuple_to_dimensions!(u64);
impl_from_tuple_to_dimensions!(f32);
impl_from_dimensions_to_tuple!(u64);
impl_from_dimensions_to_tuple!(u32);
impl_from_dimensions_to_tuple!(i32);

@ -171,13 +171,13 @@ impl GlutinWindowWrapper {
}
// Wait until fonts are loaded, so we can set proper window size.
if !self.renderer.is_ready {
if !self.renderer.grid_renderer.is_ready {
return;
}
if self.saved_grid_size.is_none() && !window.is_maximized() {
let size = SETTINGS.get::<CmdLineSettings>().geometry;
window.set_inner_size(self.renderer.convert_grid_to_physical(size));
window.set_inner_size(self.renderer.grid_renderer.convert_grid_to_physical(size));
self.saved_grid_size = Some(size);
// Font change at startup is ignored, so grid size (and startup screen) could be preserved.
font_changed = false;
@ -193,7 +193,10 @@ impl GlutinWindowWrapper {
}
fn handle_new_grid_size(&mut self, new_size: PhysicalSize<u32>) {
let grid_size = self.renderer.convert_physical_to_grid(new_size);
let grid_size = self
.renderer
.grid_renderer
.convert_physical_to_grid(new_size);
if self.saved_grid_size == Some(grid_size) {
trace!("Grid matched saved size, skip update.");
return;
@ -208,7 +211,9 @@ impl GlutinWindowWrapper {
}
fn handle_scale_factor_update(&mut self, scale_factor: f64) {
self.renderer.handle_scale_factor_update(scale_factor);
self.renderer
.grid_renderer
.handle_scale_factor_update(scale_factor);
}
}
@ -265,7 +270,7 @@ pub fn create_window(
log::info!(
"window created (scale_factor: {:.4}, font_dimensions: {:?})",
scale_factor,
renderer.font_dimensions,
renderer.grid_renderer.font_dimensions,
);
let mut window_wrapper = GlutinWindowWrapper {

@ -113,18 +113,26 @@ impl MouseManager {
let global_bounds = relevant_window_details
.map(|details| details.region)
.unwrap_or_else(|| Rect::from_wh(size.width as f32, size.height as f32));
let clamped_position =
clamp_position(position, global_bounds, renderer.font_dimensions.into());
let clamped_position = clamp_position(
position,
global_bounds,
renderer.grid_renderer.font_dimensions.into(),
);
self.position = to_grid_coords(clamped_position, renderer.font_dimensions.into());
self.position = to_grid_coords(
clamped_position,
renderer.grid_renderer.font_dimensions.into(),
);
if let Some(relevant_window_details) = relevant_window_details {
let relative_position = PhysicalPosition::new(
clamped_position.x - relevant_window_details.region.left,
clamped_position.y - relevant_window_details.region.top,
);
self.relative_position =
to_grid_coords(relative_position, renderer.font_dimensions.into());
self.relative_position = to_grid_coords(
relative_position,
renderer.grid_renderer.font_dimensions.into(),
);
let previous_position = self.drag_position;
// Until https://github.com/neovim/neovim/pull/12667 is merged, we have to special
@ -288,7 +296,7 @@ impl MouseManager {
},
..
} => self.handle_pixel_scroll(
renderer.font_dimensions.into(),
renderer.grid_renderer.font_dimensions.into(),
(delta.x as f32, delta.y as f32),
),
Event::WindowEvent {

Loading…
Cancel
Save