filled in more parsers

macos-click-through
keith 5 years ago
parent 8b633986de
commit 86b2e0df7d

@ -1,6 +1,5 @@
use std::collections::HashMap;
use neovim_lib::{Neovim, NeovimApi};
use skulpin::skia_safe::{colors, Color4f};
use crate::events::{GridLineCell, RedrawEvent};
@ -90,6 +89,7 @@ impl CursorType {
pub struct Editor {
pub grid: Vec<Vec<GridCell>>,
pub title: String,
pub cursor_pos: (u64, u64),
pub cursor_type: CursorType,
pub cursor_style: Option<Style>,
@ -105,6 +105,7 @@ impl Editor {
pub fn new(width: u64, height: u64) -> Editor {
let mut editor = Editor {
grid: Vec::new(),
title: "".to_string(),
cursor_pos: (0, 0),
cursor_type: CursorType::Block,
cursor_style: None,
@ -182,6 +183,7 @@ impl Editor {
pub fn handle_redraw_event(&mut self, event: RedrawEvent) {
match event {
RedrawEvent::SetTitle { title } => self.set_title(title),
RedrawEvent::ModeInfoSet { mode_list } => self.set_mode_list(mode_list),
RedrawEvent::ModeChange { mode_index } => self.change_mode(mode_index),
RedrawEvent::BusyStart => self.set_cursor_enabled(false),
@ -196,6 +198,10 @@ impl Editor {
}
}
pub fn set_title(&mut self, title: String) {
self.title = title;
}
pub fn set_mode_list(&mut self, mode_list: Vec<ModeInfo>) {
self.mode_list = mode_list;
}
@ -292,9 +298,6 @@ impl Editor {
(left as i64, right as i64)
};
let width = right - left;
let height = bot - top;
let mut region = Vec::new();
for y in top..bot {
let row = &self.grid[y as usize];
@ -312,7 +315,7 @@ impl Editor {
for (x, cell) in row_section.into_iter().enumerate() {
let y = new_top + y as i64;
if y >= 0 && y < self.grid.len() as i64 {
let mut row = &mut self.grid[y as usize];
let row = &mut self.grid[y as usize];
let x = new_left + x as i64;
if x >= 0 && x < row.len() as i64 {
row[x as usize] = cell;

@ -45,6 +45,7 @@ pub struct GridLineCell {
#[derive(Debug)]
pub enum RedrawEvent {
SetTitle { title: String },
ModeInfoSet { mode_list: Vec<ModeInfo> },
ModeChange { mode_index: u64 },
BusyStart,
@ -111,6 +112,16 @@ fn parse_i64(i64_value: &Value) -> Result<i64> {
}
}
fn parse_set_title(set_title_arguments: Vec<Value>) -> Result<RedrawEvent> {
if let [title] = set_title_arguments.as_slice() {
Ok(RedrawEvent::SetTitle {
title: parse_string(&title)?
})
} else {
Err(EventParseError::InvalidEventFormat)
}
}
fn parse_mode_info_set(mode_info_set_arguments: Vec<Value>) -> Result<RedrawEvent> {
if let [_cursor_style_enabled, mode_info] = mode_info_set_arguments.as_slice() {
let mode_info_values = parse_array(&mode_info)?;
@ -186,8 +197,12 @@ fn parse_hl_attr_define(hl_attr_define_arguments: Vec<Value>) -> Result<RedrawEv
("background", Value::Integer(packed_color)) => style.colors.background = Some(unpack_color(packed_color.as_u64().unwrap())),
("special", Value::Integer(packed_color)) => style.colors.special = Some(unpack_color(packed_color.as_u64().unwrap())),
("reverse", Value::Boolean(reverse)) => style.reverse = *reverse,
("italic", Value::Boolean(italic)) => style.italic = *italic,
("bold", Value::Boolean(bold)) => style.bold = *bold,
("strikethrough", Value::Boolean(strikethrough)) => style.strikethrough = *strikethrough,
("underline", Value::Boolean(underline)) => style.underline = *underline,
("undercurl", Value::Boolean(undercurl)) => style.undercurl = *undercurl,
("blend", Value::Integer(blend)) => style.blend = blend.as_u64().unwrap() as u8,
_ => println!("Ignored style attribute: {}", name)
}
} else {
@ -266,7 +281,7 @@ pub fn parse_redraw_event(event_value: Value) -> Result<Vec<RedrawEvent>> {
for event in &events[1..] {
let event_parameters = parse_array(&event)?;
let possible_parsed_event = match event_name.clone().as_ref() {
"set_title" => None, // Ignore set title for now
"set_title" => Some(parse_set_title(event_parameters)?),
"set_icon" => None, // Ignore set icon for now
"mode_info_set" => Some(parse_mode_info_set(event_parameters)?),
"option_set" => None, // Ignore option set for now

@ -1,6 +1,5 @@
use std::borrow::Cow;
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
use std::time::Instant;
use lru::LruCache;
@ -10,7 +9,7 @@ use skulpin::skia_safe::icu;
use skulpin::winit::dpi::LogicalSize;
use skulpin::winit::event::{ElementState, Event, MouseScrollDelta, WindowEvent};
use skulpin::winit::event_loop::{ControlFlow, EventLoop};
use skulpin::winit::window::WindowBuilder;
use skulpin::winit::window::{Window, WindowBuilder};
use neovim_lib::{Neovim, NeovimApi};
@ -34,7 +33,7 @@ impl CachingShaper {
}
pub fn shape(&self, text: &str, font: &Font) -> TextBlob {
let (blob, _) = self.shaper.shape_text_blob(text, font, true, 1000.0, Point::default()).unwrap();
let (blob, _) = self.shaper.shape_text_blob(text, font, true, 1000000.0, Point::default()).unwrap();
blob
}
@ -47,9 +46,38 @@ impl CachingShaper {
}
}
struct FpsTracker {
last_record_time: Instant,
frame_count: usize,
fps: usize
}
impl FpsTracker {
pub fn new() -> FpsTracker {
FpsTracker {
fps: 0,
last_record_time: Instant::now(),
frame_count: 0
}
}
pub fn record_frame(&mut self) {
self.frame_count = self.frame_count + 1;
let now = Instant::now();
let time_since = (now - self.last_record_time).as_secs_f32();
if time_since > 1.0 {
self.fps = self.frame_count;
self.last_record_time = now;
self.frame_count = 0;
}
}
}
struct Renderer {
editor: Arc<Mutex<Editor>>,
title: String,
paint: Paint,
font: Font,
shaper: CachingShaper,
@ -58,11 +86,13 @@ struct Renderer {
font_height: f32,
cursor_pos: (f32, f32),
previous_frame_instant: Instant
fps_tracker: FpsTracker
}
impl Renderer {
pub fn new(editor: Arc<Mutex<Editor>>) -> Renderer {
let title = "".to_string();
let paint = Paint::new(colors::WHITE, None);
let typeface = Typeface::new(FONT_NAME, FontStyle::default()).expect("Could not load font file.");
let font = Font::from_typeface(typeface, FONT_SIZE);
@ -70,40 +100,35 @@ impl Renderer {
let (_, bounds) = font.measure_str("0", Some(&paint));
let font_width = bounds.width();
let (_, metrics) = font.metrics();
let font_height = metrics.descent - metrics.ascent; // bounds.height() * 1.68;
let font_height = metrics.descent - metrics.ascent;
let cursor_pos = (0.0, 0.0);
let previous_frame_instant = Instant::now();
let fps_tracker = FpsTracker::new();
Renderer { editor, paint, font, shaper, font_width, font_height, cursor_pos, previous_frame_instant }
Renderer { editor, title, paint, font, shaper, font_width, font_height, cursor_pos, fps_tracker }
}
fn draw_text(&mut self, canvas: &mut Canvas, text: &str, grid_pos: (u64, u64), style: &Style, default_colors: &Colors, update_cache: bool) {
let (grid_x, grid_y) = grid_pos;
let x = grid_x as f32 * self.font_width;
let y = grid_y as f32 * self.font_height + self.font_height - self.font_height * 0.2;
let top = y - self.font_height * 0.8;
let y = grid_y as f32 * self.font_height;
let width = text.chars().count() as f32 * self.font_width;
let height = self.font_height;
let region = Rect::new(x, top, x + width, top + height);
let region = Rect::new(x, y, x + width, y + height);
self.paint.set_color(style.background(default_colors).to_color());
canvas.draw_rect(region, &self.paint);
if style.underline || style.undercurl {
let (_, metrics) = self.font.metrics();
let width = text.chars().count() as f32 * self.font_width;
let underline_position = metrics.underline_position().unwrap();
let line_position = metrics.underline_position().unwrap();
self.paint.set_color(style.special(&default_colors).to_color());
canvas.draw_line((x, y + underline_position), (x + width, y + underline_position), &self.paint);
canvas.draw_line((x, y - line_position + self.font_height), (x + width, y - line_position + self.font_height), &self.paint);
}
self.paint.set_color(style.foreground(&default_colors).to_color());
let text = text.trim_end();
//canvas.draw_str(text, (x, y), &font, &paint);
if text.len() > 0 {
let reference;
let blob = if update_cache {
@ -112,16 +137,18 @@ impl Renderer {
reference = self.shaper.shape(text, &self.font);
&reference
};
canvas.draw_text_blob(blob, (x, top), &self.paint);
canvas.draw_text_blob(blob, (x, y), &self.paint);
}
}
pub fn draw(&mut self, canvas: &mut Canvas) {
let (draw_commands, default_colors, cursor_grid_pos, cursor_type, cursor_foreground, cursor_background, cursor_enabled) = {
pub fn draw(&mut self, window: &Window, canvas: &mut Canvas) {
let (draw_commands, title, default_colors, (width, height), cursor_grid_pos, cursor_type, cursor_foreground, cursor_background, cursor_enabled) = {
let editor = self.editor.lock().unwrap();
(
editor.build_draw_commands().clone(),
editor.title.clone(),
editor.default_colors.clone(),
editor.size.clone(),
editor.cursor_pos.clone(),
editor.cursor_type.clone(),
editor.cursor_foreground(),
@ -136,6 +163,9 @@ impl Renderer {
self.draw_text(canvas, &command.text, command.grid_position, &command.style, &default_colors, true);
}
self.fps_tracker.record_frame();
self.draw_text(canvas, &self.fps_tracker.fps.to_string(), (width - 2, height - 1), &Style::new(default_colors.clone()), &default_colors, false);
let (cursor_grid_x, cursor_grid_y) = cursor_grid_pos;
let target_cursor_x = cursor_grid_x as f32 * self.font_width;
let target_cursor_y = cursor_grid_y as f32 * self.font_height;
@ -164,12 +194,16 @@ impl Renderer {
let character = editor.grid[cursor_grid_y as usize][cursor_grid_x as usize].clone()
.map(|(character, _)| character)
.unwrap_or(' ');
let text_y = cursor_y + self.font_height - self.font_height * 0.2;
canvas.draw_text_blob(
self.shaper.shape_cached(character.to_string(), &self.font),
(cursor_x, text_y), &self.paint);
(cursor_x, cursor_y), &self.paint);
}
}
if self.title != title {
window.set_title(&title);
self.title = title;
}
}
}
@ -181,7 +215,6 @@ pub fn ui_loop(editor: Arc<Mutex<Editor>>, nvim: Neovim, initial_size: (u64, u64
let (width, height) = initial_size;
let logical_size = LogicalSize::new(
(width as f32 * renderer.font_width) as f64,
// Add 1.0 here to make sure resizing horizontally doesn't change the grid height
(height as f32 * renderer.font_height + 1.0) as f64
);
@ -213,8 +246,9 @@ pub fn ui_loop(editor: Arc<Mutex<Editor>>, nvim: Neovim, initial_size: (u64, u64
..
} => {
if new_size.width > 0.0 && new_size.height > 0.0 {
let new_width = (new_size.width as f32 / renderer.font_width) as u64;
let new_height = (new_size.height as f32 / renderer.font_height) as u64;
let new_width = ((new_size.width + 1.0) as f32 / renderer.font_width) as u64;
let new_height = ((new_size.height + 1.0) as f32 / renderer.font_height) as u64;
// Add 1 here to make sure resizing doesn't change the grid size on startup
nvim.ui_try_resize(new_width as i64, new_height as i64).expect("Resize failed");
}
},
@ -292,7 +326,7 @@ pub fn ui_loop(editor: Arc<Mutex<Editor>>, nvim: Neovim, initial_size: (u64, u64
..
} => {
if let Err(e) = skulpin_renderer.draw(&window, |canvas, _coordinate_system_helper| {
renderer.draw(canvas);
renderer.draw(&window, canvas);
}) {
println!("Error during draw: {:?}", e);
*control_flow = ControlFlow::Exit

Loading…
Cancel
Save