From c154553aad9398621986e55de9019d63bb30adf9 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Fri, 12 Apr 2024 23:28:51 +0300 Subject: [PATCH] Use typesafe grid and pixel units --- src/bridge/mod.rs | 10 +- src/dimensions.rs | 19 --- src/main.rs | 1 + src/renderer/animation_utils.rs | 68 ++++---- src/renderer/cursor_renderer/cursor_vfx.rs | 96 +++++------ src/renderer/cursor_renderer/mod.rs | 115 ++++++-------- src/renderer/fonts/caching_shaper.rs | 34 ++-- src/renderer/grid_renderer.rs | 107 +++++-------- src/renderer/mod.rs | 43 +++-- src/renderer/rendered_window.rs | 164 +++++++++---------- src/settings/mod.rs | 4 +- src/settings/window_size.rs | 25 ++- src/units.rs | 109 +++++++++++++ src/window/mod.rs | 13 +- src/window/mouse_manager.rs | 176 ++++++++------------- src/window/window_wrapper.rs | 139 ++++++++-------- 16 files changed, 555 insertions(+), 568 deletions(-) create mode 100644 src/units.rs diff --git a/src/bridge/mod.rs b/src/bridge/mod.rs index 894f991d9f..1038e36a69 100644 --- a/src/bridge/mod.rs +++ b/src/bridge/mod.rs @@ -17,8 +17,8 @@ use tokio::runtime::{Builder, Runtime}; use winit::event_loop::EventLoopProxy; use crate::{ - cmd_line::CmdLineSettings, dimensions::Dimensions, editor::start_editor, running_tracker::*, - settings::*, window::UserEvent, + cmd_line::CmdLineSettings, editor::start_editor, running_tracker::*, settings::*, + units::GridSize, window::UserEvent, }; pub use handler::NeovimHandler; use session::{NeovimInstance, NeovimSession}; @@ -169,7 +169,7 @@ pub async fn show_error_message( nvim.echo(prepared_lines, true, vec![]).await } -async fn launch(handler: NeovimHandler, grid_size: Option) -> Result { +async fn launch(handler: NeovimHandler, grid_size: Option>) -> Result { let neovim_instance = neovim_instance()?; let session = NeovimSession::new(neovim_instance, handler) @@ -215,7 +215,7 @@ async fn launch(handler: NeovimHandler, grid_size: Option) -> Result // Triggers loading the user config - let grid_size = grid_size.map_or(DEFAULT_GRID_SIZE, |v| v.clamped_grid_size()); + let grid_size = grid_size.map_or(DEFAULT_GRID_SIZE, |v| clamped_grid_size(&v)); let res = session .neovim .ui_attach(grid_size.width as i64, grid_size.height as i64, &options) @@ -251,7 +251,7 @@ impl NeovimRuntime { pub fn launch( &mut self, event_loop_proxy: EventLoopProxy, - grid_size: Option, + grid_size: Option>, ) -> Result<()> { let handler = start_editor(event_loop_proxy); let runtime = self.runtime.as_ref().unwrap(); diff --git a/src/dimensions.rs b/src/dimensions.rs index 8a236cab72..8509e6d926 100644 --- a/src/dimensions.rs +++ b/src/dimensions.rs @@ -7,8 +7,6 @@ use std::{ use serde::{Deserialize, Serialize}; use winit::dpi::PhysicalSize; -use crate::settings; - // Maybe this should be independent from serialization? #[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)] pub struct Dimensions { @@ -16,23 +14,6 @@ pub struct Dimensions { pub height: u64, } -impl Dimensions { - pub fn clamped_grid_size(&self) -> Self { - let min = settings::MIN_GRID_SIZE; - let max = settings::MAX_GRID_SIZE; - Dimensions { - width: self.width.clamp(min.width, max.width), - height: self.height.clamp(min.height, max.height), - } - } -} - -impl Default for Dimensions { - fn default() -> Self { - settings::DEFAULT_GRID_SIZE - } -} - impl FromStr for Dimensions { type Err = String; fn from_str(s: &str) -> Result { diff --git a/src/main.rs b/src/main.rs index 38cce3211e..8aaf5dedc7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,7 @@ mod profiling; mod renderer; mod running_tracker; mod settings; +mod units; mod utils; mod window; diff --git a/src/renderer/animation_utils.rs b/src/renderer/animation_utils.rs index 7c633ccc6f..8f1edfcf7c 100644 --- a/src/renderer/animation_utils.rs +++ b/src/renderer/animation_utils.rs @@ -1,4 +1,4 @@ -use skia_safe::Point; +use crate::units::PixelPos; #[allow(dead_code)] pub fn ease_linear(t: f32) -> f32 { @@ -73,11 +73,16 @@ pub fn ease(ease_func: fn(f32) -> f32, start: f32, end: f32, t: f32) -> f32 { lerp(start, end, ease_func(t)) } -pub fn ease_point(ease_func: fn(f32) -> f32, start: Point, end: Point, t: f32) -> Point { - Point { - x: ease(ease_func, start.x, end.x, t), - y: ease(ease_func, start.y, end.y, t), - } +pub fn ease_point( + ease_func: fn(f32) -> f32, + start: PixelPos, + end: PixelPos, + t: f32, +) -> PixelPos { + PixelPos::new( + ease(ease_func, start.x, end.x, t), + ease(ease_func, start.y, end.y, t), + ) } pub struct CriticallyDampedSpringAnimation { @@ -205,79 +210,70 @@ mod test { #[test] fn test_ease_point_linear() { - let start = Point { x: 0.0, y: 0.0 }; - let end = Point { x: 1.0, y: 1.0 }; + let start = PixelPos::new(0.0, 0.0); + let end = PixelPos::new(1.0, 1.0); assert_eq!(ease_point(ease_linear, start, end, 1.0), end); } #[test] fn test_ease_point_in_quad() { - let start = Point { x: 0.0, y: 0.0 }; - let end = Point { x: 1.0, y: 1.0 }; + let start = PixelPos::new(0.0, 0.0); + let end = PixelPos::new(1.0, 1.0); assert_eq!(ease_point(ease_in_quad, start, end, 1.0), end); } #[test] fn test_ease_point_out_quad() { - let start = Point { x: 0.0, y: 0.0 }; - let end = Point { x: 1.0, y: 1.0 }; + let start = PixelPos::new(0.0, 0.0); + let end = PixelPos::new(1.0, 1.0); assert_eq!(ease_point(ease_out_quad, start, end, 1.0), end); } #[test] fn test_ease_point_in_out_quad() { - let start = Point { x: 0.0, y: 0.0 }; - let end = Point { x: 1.0, y: 1.0 }; - let expected = Point { - x: 0.68000007, - y: 0.68000007, - }; + let start = PixelPos::new(0.0, 0.0); + let end = PixelPos::new(1.0, 1.0); + let expected = PixelPos::new(0.68000007, 0.68000007); assert_eq!(ease_point(ease_in_out_quad, start, end, 1.0), end); assert_eq!(ease_point(ease_in_out_quad, start, end, 1.4), expected); } #[test] fn test_ease_point_in_cubic() { - let start = Point { x: 0.0, y: 0.0 }; - let end = Point { x: 1.0, y: 1.0 }; + let start = PixelPos::new(0.0, 0.0); + let end = PixelPos::new(1.0, 1.0); assert_eq!(ease_point(ease_in_cubic, start, end, 1.0), end); } #[test] fn test_ease_point_out_cubic() { - let start = Point { x: 0.0, y: 0.0 }; - let end = Point { x: 1.0, y: 1.0 }; + let start = PixelPos::new(0.0, 0.0); + let end = PixelPos::new(1.0, 1.0); assert_eq!(ease_point(ease_out_cubic, start, end, 1.0), end); } #[test] fn test_ease_point_in_out_cubic() { - let start = Point { x: 0.0, y: 0.0 }; - let end = Point { x: 1.0, y: 1.0 }; - let expected = Point { - x: 0.0625, - y: 0.0625, - }; + let start = PixelPos::new(0.0, 0.0); + let end = PixelPos::new(1.0, 1.0); + let expected = PixelPos::new(0.0625, 0.0625); assert_eq!(ease_point(ease_in_out_cubic, start, end, 1.0), end); assert_eq!(ease_point(ease_in_out_cubic, start, end, 0.25), expected); } #[test] fn test_ease_point_in_expo() { - let start = Point { x: 0.0, y: 0.0 }; - let end = Point { x: 1.0, y: 1.0 }; + let start = PixelPos::new(0.0, 0.0); + let end = PixelPos::new(1.0, 1.0); assert_eq!(ease_point(ease_in_expo, start, end, 1.0), end); assert_eq!(ease_point(ease_in_expo, start, end, 0.0), start); } #[test] fn test_ease_point_out_expo() { - let start = Point { x: 0.0, y: 0.0 }; - let end = Point { x: 1.0, y: 1.0 }; - let expected = Point { - x: 0.9995117, - y: 0.9995117, - }; + let start = PixelPos::new(0.0, 0.0); + let end = PixelPos::new(1.0, 1.0); + let expected = PixelPos::new(0.9995117, 0.9995117); assert_eq!(ease_point(ease_out_expo, start, end, 1.0), end); assert_eq!(ease_point(ease_out_expo, start, end, 1.1), expected); } diff --git a/src/renderer/cursor_renderer/cursor_vfx.rs b/src/renderer/cursor_renderer/cursor_vfx.rs index e18c45f50f..fa22b5bed0 100644 --- a/src/renderer/cursor_renderer/cursor_vfx.rs +++ b/src/renderer/cursor_renderer/cursor_vfx.rs @@ -1,24 +1,25 @@ use log::error; use nvim_rs::Value; -use skia_safe::{paint::Style, BlendMode, Canvas, Color, Paint, Point, Rect}; +use skia_safe::{paint::Style, BlendMode, Canvas, Color, Paint, Rect}; use crate::{ editor::Cursor, renderer::cursor_renderer::CursorSettings, renderer::{animation_utils::*, grid_renderer::GridRenderer}, settings::*, + units::{PixelPos, PixelSize, PixelVec}, }; pub trait CursorVfx { fn update( &mut self, settings: &CursorSettings, - current_cursor_destination: Point, - cursor_dimensions: Point, + current_cursor_destination: PixelPos, + cursor_dimensions: PixelSize, immediate_movement: bool, dt: f32, ) -> bool; - fn restart(&mut self, position: Point); + fn restart(&mut self, position: PixelPos); fn render( &self, settings: &CursorSettings, @@ -95,7 +96,7 @@ pub fn new_cursor_vfx(mode: &VfxMode) -> Option> { pub struct PointHighlight { t: f32, - center_position: Point, + center_position: PixelPos, mode: HighlightMode, } @@ -103,7 +104,7 @@ impl PointHighlight { pub fn new(mode: &HighlightMode) -> PointHighlight { PointHighlight { t: 0.0, - center_position: Point::new(0.0, 0.0), + center_position: PixelPos::new(0.0, 0.0), mode: mode.clone(), } } @@ -113,8 +114,8 @@ impl CursorVfx for PointHighlight { fn update( &mut self, _settings: &CursorSettings, - _current_cursor_destination: Point, - _cursor_dimensions: Point, + _current_cursor_destination: PixelPos, + _cursor_dimensions: PixelSize, _immediate_movement: bool, dt: f32, ) -> bool { @@ -122,7 +123,7 @@ impl CursorVfx for PointHighlight { self.t < 1.0 } - fn restart(&mut self, position: Point) { + fn restart(&mut self, position: PixelPos) { self.t = 0.0; self.center_position = position; } @@ -148,9 +149,9 @@ impl CursorVfx for PointHighlight { paint.set_color(color); - let cursor_height = grid_renderer.font_dimensions.height; - let size = 3 * cursor_height; - let radius = self.t * size as f32; + let cursor_height = grid_renderer.grid_scale.0.height; + let size = 3.0 * cursor_height; + let radius = self.t * size; let hr = radius * 0.5; let rect = Rect::from_xywh( self.center_position.x - hr, @@ -165,12 +166,12 @@ impl CursorVfx for PointHighlight { } HighlightMode::Ripple => { paint.set_style(Style::Stroke); - paint.set_stroke_width(cursor_height as f32 * 0.2); + paint.set_stroke_width(cursor_height * 0.2); canvas.draw_oval(rect, &paint); } HighlightMode::Wireframe => { paint.set_style(Style::Stroke); - paint.set_stroke_width(cursor_height as f32 * 0.2); + paint.set_stroke_width(cursor_height * 0.2); canvas.draw_rect(rect, &paint); } } @@ -179,15 +180,15 @@ impl CursorVfx for PointHighlight { #[derive(Clone)] struct ParticleData { - pos: Point, - speed: Point, + pos: PixelPos, + speed: PixelVec, rotation_speed: f32, lifetime: f32, } pub struct ParticleTrail { particles: Vec, - previous_cursor_dest: Point, + previous_cursor_dest: PixelPos, trail_mode: TrailMode, rng: RngState, } @@ -196,13 +197,19 @@ impl ParticleTrail { pub fn new(trail_mode: &TrailMode) -> ParticleTrail { ParticleTrail { particles: vec![], - previous_cursor_dest: Point::new(0.0, 0.0), + previous_cursor_dest: PixelPos::new(0.0, 0.0), trail_mode: trail_mode.clone(), rng: RngState::new(), } } - fn add_particle(&mut self, pos: Point, speed: Point, rotation_speed: f32, lifetime: f32) { + fn add_particle( + &mut self, + pos: PixelPos, + speed: PixelVec, + rotation_speed: f32, + lifetime: f32, + ) { self.particles.push(ParticleData { pos, speed, @@ -222,8 +229,8 @@ impl CursorVfx for ParticleTrail { fn update( &mut self, settings: &CursorSettings, - current_cursor_dest: Point, - cursor_dimensions: Point, + current_cursor_dest: PixelPos, + cursor_dimensions: PixelSize, immediate_movement: bool, dt: f32, ) -> bool { @@ -253,7 +260,7 @@ impl CursorVfx for ParticleTrail { let travel_distance = travel.length(); // Increase amount of particles when cursor travels further - let particle_count = ((travel_distance / cursor_dimensions.y).powf(1.5) + let particle_count = ((travel_distance / cursor_dimensions.height).powf(1.5) * settings.vfx_particle_density * 0.01) as usize; @@ -266,20 +273,19 @@ impl CursorVfx for ParticleTrail { TrailMode::Railgun => { let phase = t / std::f32::consts::PI * settings.vfx_particle_phase - * (travel_distance / cursor_dimensions.y); - Point::new(phase.sin(), phase.cos()) * 2.0 * settings.vfx_particle_speed + * (travel_distance / cursor_dimensions.height); + PixelVec::new(phase.sin(), phase.cos()) + * 2.0 + * settings.vfx_particle_speed } TrailMode::Torpedo => { - let mut travel_dir = travel; - travel_dir.normalize(); - let mut particle_dir = - self.rng.rand_dir_normalized() - travel_dir * 1.5; - particle_dir.normalize(); - particle_dir * settings.vfx_particle_speed + let travel_dir = travel.normalize(); + let particle_dir = self.rng.rand_dir_normalized() - travel_dir * 1.5; + particle_dir.normalize() * settings.vfx_particle_speed } TrailMode::PixieDust => { let base_dir = self.rng.rand_dir_normalized(); - let dir = Point::new(base_dir.x * 0.5, 0.4 + base_dir.y.abs()); + let dir = PixelVec::new(base_dir.x * 0.5, 0.4 + base_dir.y.abs()); dir * 3.0 * settings.vfx_particle_speed } }; @@ -290,7 +296,7 @@ impl CursorVfx for ParticleTrail { TrailMode::PixieDust | TrailMode::Torpedo => { prev_p + travel * self.rng.next_f32() - + Point::new(0.0, cursor_dimensions.y * 0.5) + + PixelVec::new(0.0, cursor_dimensions.height * 0.5) } }; @@ -319,7 +325,7 @@ impl CursorVfx for ParticleTrail { !self.particles.is_empty() } - fn restart(&mut self, _position: Point) {} + fn restart(&mut self, _position: PixelPos) {} fn render( &self, @@ -329,11 +335,11 @@ impl CursorVfx for ParticleTrail { cursor: &Cursor, ) { let mut paint = Paint::new(skia_safe::colors::WHITE, None); - let font_dimensions = grid_renderer.font_dimensions; + let font_dimensions = grid_renderer.grid_scale.0; match self.trail_mode { TrailMode::Torpedo | TrailMode::Railgun => { paint.set_style(Style::Stroke); - paint.set_stroke_width(font_dimensions.height as f32 * 0.2); + paint.set_stroke_width(font_dimensions.height * 0.2); } _ => {} } @@ -350,10 +356,8 @@ impl CursorVfx for ParticleTrail { paint.set_color(color); let radius = match self.trail_mode { - TrailMode::Torpedo | TrailMode::Railgun => { - font_dimensions.width as f32 * 0.5 * lifetime - } - TrailMode::PixieDust => font_dimensions.width as f32 * 0.2, + TrailMode::Torpedo | TrailMode::Railgun => font_dimensions.width * 0.5 * lifetime, + TrailMode::PixieDust => font_dimensions.width * 0.2, }; let hr = radius * 0.5; @@ -426,23 +430,21 @@ impl RngState { // Produces a random vector with x and y in the [-1,1) range // Note: Vector is not normalized. - fn rand_dir(&mut self) -> Point { + fn rand_dir(&mut self) -> PixelVec { let x = self.next_f32(); let y = self.next_f32(); - Point::new(x * 2.0 - 1.0, y * 2.0 - 1.0) + PixelVec::new(x * 2.0 - 1.0, y * 2.0 - 1.0) } - fn rand_dir_normalized(&mut self) -> Point { - let mut v = self.rand_dir(); - v.normalize(); - v + fn rand_dir_normalized(&mut self) -> PixelVec { + self.rand_dir().normalize() } } -fn rotate_vec(v: Point, rot: f32) -> Point { +fn rotate_vec(v: PixelVec, rot: f32) -> PixelVec { let sin = rot.sin(); let cos = rot.cos(); - Point::new(v.x * cos - v.y * sin, v.x * sin + v.y * cos) + PixelVec::new(v.x * cos - v.y * sin, v.x * sin + v.y * cos) } diff --git a/src/renderer/cursor_renderer/mod.rs b/src/renderer/cursor_renderer/mod.rs index be689393ba..8f86d22d8b 100644 --- a/src/renderer/cursor_renderer/mod.rs +++ b/src/renderer/cursor_renderer/mod.rs @@ -3,16 +3,16 @@ mod cursor_vfx; use std::collections::HashMap; -use skia_safe::{op, Canvas, Paint, Path, Point}; +use skia_safe::{op, Canvas, Paint, Path}; use winit::event::{Event, WindowEvent}; use crate::{ bridge::EditorMode, editor::{Cursor, CursorShape}, profiling::{tracy_plot, tracy_zone}, - renderer::animation_utils::*, - renderer::{GridRenderer, RenderedWindow}, + renderer::{animation_utils::*, GridRenderer, RenderedWindow}, settings::{ParseFromValue, SETTINGS}, + units::{to_skia_point, GridPos, GridScale, PixelPos, PixelSize, PixelVec}, window::{ShouldRender, UserEvent}, }; @@ -68,10 +68,10 @@ impl Default for CursorSettings { #[derive(Debug, Clone)] pub struct Corner { - start_position: Point, - current_position: Point, - relative_position: Point, - previous_destination: Point, + start_position: PixelPos, + current_position: PixelPos, + relative_position: GridPos, + previous_destination: PixelPos, length_multiplier: f32, t: f32, } @@ -79,10 +79,10 @@ pub struct Corner { impl Corner { pub fn new() -> Corner { Corner { - start_position: Point::new(0.0, 0.0), - current_position: Point::new(0.0, 0.0), - relative_position: Point::new(0.0, 0.0), - previous_destination: Point::new(-1000.0, -1000.0), + start_position: PixelPos::origin(), + current_position: PixelPos::origin(), + relative_position: GridPos::::origin(), + previous_destination: PixelPos::new(-1000.0, -1000.0), length_multiplier: 1.0, t: 0.0, } @@ -91,8 +91,8 @@ impl Corner { pub fn update( &mut self, settings: &CursorSettings, - font_dimensions: Point, - destination: Point, + cursor_dimensions: GridScale, + destination: PixelPos, dt: f32, immediate_movement: bool, ) -> bool { @@ -116,13 +116,9 @@ impl Corner { } // Calculate window-space destination for corner - let relative_scaled_position: Point = ( - self.relative_position.x * font_dimensions.x, - self.relative_position.y * font_dimensions.y, - ) - .into(); + let relative_scaled_position = self.relative_position * cursor_dimensions; - let corner_destination = destination + relative_scaled_position; + let corner_destination = destination + relative_scaled_position.to_vector(); if immediate_movement { self.t = 1.0; @@ -134,16 +130,11 @@ impl Corner { // with the direction of motion. Corners in front will move faster than corners in the // back let travel_direction = { - let mut d = destination - self.current_position; - d.normalize(); - d + let d = destination - self.current_position; + d.normalize() }; - let corner_direction = { - let mut d = self.relative_position; - d.normalize(); - d - }; + let corner_direction = self.relative_position.to_vector().normalize().cast_unit(); let direction_alignment = travel_direction.dot(corner_direction); @@ -175,7 +166,7 @@ impl Corner { pub struct CursorRenderer { pub corners: Vec, cursor: Cursor, - destination: Point, + destination: PixelPos, blink_status: BlinkStatus, previous_cursor_shape: Option, previous_editor_mode: EditorMode, @@ -250,15 +241,15 @@ impl CursorRenderer { pub fn update_cursor_destination( &mut self, - (font_width, font_height): (u64, u64), + grid_scale: GridScale, windows: &HashMap, ) { - let (cursor_grid_x, cursor_grid_y) = self.cursor.grid_position; - + let cursor_grid_position = GridPos::::from(self.cursor.grid_position) + .try_cast() + .unwrap(); if let Some(window) = windows.get(&self.cursor.parent_window_id) { - let grid_x = cursor_grid_x as f32 + window.grid_current_position.x; - let mut grid_y = cursor_grid_y as f32 + window.grid_current_position.y - - window.scroll_animation.position; + let mut grid = cursor_grid_position + window.grid_current_position.to_vector(); + grid.y -= window.scroll_animation.position; let top_border = window.viewport_margins.top as f32; let bottom_border = window.viewport_margins.bottom as f32; @@ -266,19 +257,15 @@ impl CursorRenderer { // Prevent the cursor from targeting a position outside its current window. Since only // the vertical direction is effected by scrolling, we only have to clamp the vertical // grid position. - grid_y = grid_y.max(window.grid_current_position.y + top_border).min( + grid.y = grid.y.max(window.grid_current_position.y + top_border).min( window.grid_current_position.y + window.grid_size.height as f32 - 1.0 - bottom_border, ); - self.destination = (grid_x * font_width as f32, grid_y * font_height as f32).into(); + self.destination = grid * grid_scale; } else { - self.destination = ( - (cursor_grid_x * font_width) as f32, - (cursor_grid_y * font_height) as f32, - ) - .into(); + self.destination = cursor_grid_position * grid_scale; } } @@ -339,7 +326,7 @@ impl CursorRenderer { for blob in blobs.iter() { canvas.draw_text_blob( blob, - (self.destination.x, self.destination.y + y_adjustment as f32), + (self.destination.x, self.destination.y + y_adjustment), &paint, ); } @@ -365,23 +352,19 @@ impl CursorRenderer { self.previous_vfx_mode = settings.vfx_mode.clone(); } - let mut cursor_width = grid_renderer.font_dimensions.width; + let mut cursor_width = grid_renderer.grid_scale.0.width; if self.cursor.double_width && self.cursor.shape == CursorShape::Block { - cursor_width *= 2; + cursor_width *= 2.0; } - let cursor_dimensions: Point = ( - cursor_width as f32, - grid_renderer.font_dimensions.height as f32, - ) - .into(); + let cursor_dimensions = PixelSize::new(cursor_width, grid_renderer.grid_scale.0.height); 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 + cursor_dimensions * 0.5; + let center_destination = self.destination + cursor_dimensions.to_vector() * 0.5; if self.previous_cursor_shape.as_ref() != Some(&self.cursor.shape) { self.previous_cursor_shape = Some(self.cursor.shape.clone()); @@ -399,13 +382,13 @@ impl CursorRenderer { let mut animating = false; - if !center_destination.is_zero() { + if center_destination != PixelPos::origin() { let immediate_movement = !settings.animate_in_insert_mode && in_insert_mode || !settings.animate_command_line && !changed_to_from_cmdline; for corner in self.corners.iter_mut() { let corner_animating = corner.update( &settings, - cursor_dimensions, + GridScale(cursor_dimensions), center_destination, dt, immediate_movement, @@ -445,10 +428,10 @@ impl CursorRenderer { // corners. let mut path = Path::new(); - path.move_to(self.corners[0].current_position); - path.line_to(self.corners[1].current_position); - path.line_to(self.corners[2].current_position); - path.line_to(self.corners[3].current_position); + path.move_to(to_skia_point(self.corners[0].current_position)); + path.line_to(to_skia_point(self.corners[1].current_position)); + path.line_to(to_skia_point(self.corners[2].current_position)); + path.line_to(to_skia_point(self.corners[3].current_position)); path.close(); canvas.draw_path(&path, paint); @@ -457,13 +440,13 @@ impl CursorRenderer { fn draw_rectangular_outline(&self, canvas: &Canvas, paint: &Paint, outline_width: f32) -> Path { let mut rectangle = Path::new(); - rectangle.move_to(self.corners[0].current_position); - rectangle.line_to(self.corners[1].current_position); - rectangle.line_to(self.corners[2].current_position); - rectangle.line_to(self.corners[3].current_position); + rectangle.move_to(to_skia_point(self.corners[0].current_position)); + rectangle.line_to(to_skia_point(self.corners[1].current_position)); + rectangle.line_to(to_skia_point(self.corners[2].current_position)); + rectangle.line_to(to_skia_point(self.corners[3].current_position)); rectangle.close(); - let offsets: [Point; 4] = [ + let offsets: [PixelVec; 4] = [ (outline_width, outline_width).into(), (-outline_width, outline_width).into(), (-outline_width, -outline_width).into(), @@ -471,10 +454,10 @@ impl CursorRenderer { ]; let mut subtract = Path::new(); - subtract.move_to(self.corners[0].current_position + offsets[0]); - subtract.line_to(self.corners[1].current_position + offsets[1]); - subtract.line_to(self.corners[2].current_position + offsets[2]); - subtract.line_to(self.corners[3].current_position + offsets[3]); + subtract.move_to(to_skia_point(self.corners[0].current_position + offsets[0])); + subtract.line_to(to_skia_point(self.corners[1].current_position + offsets[1])); + subtract.line_to(to_skia_point(self.corners[2].current_position + offsets[2])); + subtract.line_to(to_skia_point(self.corners[3].current_position + offsets[3])); subtract.close(); // We have two "rectangles"; create an outline path by subtracting the smaller rectangle @@ -485,7 +468,7 @@ impl CursorRenderer { path } - pub fn get_current_position(&self) -> Point { + pub fn get_destination(&self) -> PixelPos { self.destination } } diff --git a/src/renderer/fonts/caching_shaper.rs b/src/renderer/fonts/caching_shaper.rs index d3108d753b..c75305d68c 100644 --- a/src/renderer/fonts/caching_shaper.rs +++ b/src/renderer/fonts/caching_shaper.rs @@ -21,6 +21,7 @@ use crate::{ error_msg, profiling::tracy_zone, renderer::fonts::{font_loader::*, font_options::*}, + units::PixelSize, }; #[derive(new, Clone, Hash, PartialEq, Eq, Debug)] @@ -36,7 +37,7 @@ pub struct CachingShaper { shape_context: ShapeContext, scale_factor: f32, fudge_factor: f32, - linespace: i64, + linespace: f32, font_info: Option<(Metrics, f32)>, } @@ -51,7 +52,7 @@ impl CachingShaper { shape_context: ShapeContext::new(), scale_factor, fudge_factor: 1.0, - linespace: 0, + linespace: 0.0, font_info: None, }; shaper.reset_font_loader(); @@ -132,11 +133,11 @@ impl CachingShaper { } } - pub fn update_linespace(&mut self, linespace: i64) { + pub fn update_linespace(&mut self, linespace: f32) { debug!("Updating linespace: {}", linespace); - let font_height = self.font_base_dimensions().1; - let impossible_linespace = font_height as i64 + linespace <= 0; + let font_height = self.font_base_dimensions().height; + let impossible_linespace = font_height + linespace <= 0.0; if !impossible_linespace { debug!("Linespace updated to: {linespace}"); @@ -215,27 +216,28 @@ impl CachingShaper { self.info().0 } - pub fn font_base_dimensions(&mut self) -> (u64, u64) { + pub fn font_base_dimensions(&mut self) -> PixelSize { let (metrics, glyph_advance) = self.info(); let bare_font_height = (metrics.ascent + metrics.descent + metrics.leading).ceil(); - let font_height = bare_font_height as i64 + self.linespace; - let font_width = (glyph_advance + self.options.width + 0.5).floor() as u64; + let font_height = bare_font_height + self.linespace; + let font_width = (glyph_advance + self.options.width + 0.5).floor(); ( font_width, - font_height as u64, // assuming that linespace is checked on receive for - // validity + font_height, // assuming that linespace is checked on receive for + // validity ) + .into() } - pub fn underline_position(&mut self) -> u64 { - self.metrics().underline_offset as u64 + pub fn underline_position(&mut self) -> f32 { + self.metrics().underline_offset } - pub fn y_adjustment(&mut self) -> u64 { + pub fn y_adjustment(&mut self) -> f32 { let metrics = self.metrics(); - (metrics.ascent + metrics.leading + self.linespace as f32 / 2.).ceil() as u64 + (metrics.ascent + metrics.leading + self.linespace / 2.).ceil() } fn build_clusters( @@ -385,7 +387,7 @@ impl CachingShaper { pub fn shape(&mut self, text: String, style: CoarseStyle) -> Vec { let current_size = self.current_size(); - let (glyph_width, ..) = self.font_base_dimensions(); + let glyph_width = self.font_base_dimensions().width; let mut resulting_blobs = Vec::new(); @@ -418,7 +420,7 @@ impl CachingShaper { shaper.shape_with(|glyph_cluster| { for glyph in glyph_cluster.glyphs { - let position = ((glyph.data as u64 * glyph_width) as f32, glyph.y); + let position = ((glyph.data as f32 * glyph_width), glyph.y); glyph_data.push((glyph.id, position)); } }); diff --git a/src/renderer/grid_renderer.rs b/src/renderer/grid_renderer.rs index 756c88eccf..ab91eefd3f 100644 --- a/src/renderer/grid_renderer.rs +++ b/src/renderer/grid_renderer.rs @@ -1,17 +1,16 @@ use std::sync::Arc; use log::trace; -use skia_safe::{ - colors, dash_path_effect, BlendMode, Canvas, Color, Paint, Path, Point, Rect, HSV, -}; -use winit::dpi::PhysicalSize; +use skia_safe::{colors, dash_path_effect, BlendMode, Canvas, Color, Paint, Path, HSV}; use crate::{ - dimensions::Dimensions, editor::{Colors, Style, UnderlineStyle}, profiling::tracy_zone, renderer::{CachingShaper, RendererSettings}, settings::*, + units::{ + to_skia_point, to_skia_rect, GridPos, GridScale, GridSize, PixelPos, PixelRect, PixelVec, + }, }; use super::fonts::font_options::FontOptions; @@ -20,7 +19,7 @@ pub struct GridRenderer { pub shaper: CachingShaper, pub default_style: Arc