support font setting and changing

macos-click-through
keith 5 years ago
parent 9ed5bbcdde
commit 6f04e9e7e0

@ -10,7 +10,7 @@ mod command_line;
pub use cursor::{Cursor, CursorShape, CursorMode};
pub use style::{Colors, Style};
use command_line::CommandLine;
use crate::events::{GridLineCell, RedrawEvent};
use crate::events::{GridLineCell, GuiOption, RedrawEvent};
pub type GridCell = Option<(char, Option<Style>)>;
@ -47,6 +47,8 @@ pub struct Editor {
pub command_line: CommandLine,
pub title: String,
pub size: (u64, u64),
pub font_name: Option<String>,
pub font_size: Option<f32>,
pub cursor: Cursor,
pub default_colors: Colors,
pub defined_styles: HashMap<u64, Style>,
@ -66,6 +68,8 @@ impl Editor {
title: "Neovide".to_string(),
cursor: Cursor::new(),
size: (width, height),
font_name: None,
font_size: None,
default_colors: Colors::new(Some(colors::WHITE), Some(colors::BLACK), Some(colors::GREY)),
defined_styles: HashMap::new(),
previous_style: None
@ -79,6 +83,7 @@ impl Editor {
match event {
RedrawEvent::SetTitle { title } => self.title = title,
RedrawEvent::ModeInfoSet { cursor_modes } => self.cursor.mode_list = cursor_modes,
RedrawEvent::OptionSet { gui_option } => self.set_option(gui_option),
RedrawEvent::ModeChange { mode_index } => self.cursor.change_mode(mode_index, &self.defined_styles),
RedrawEvent::BusyStart => self.cursor.enabled = false,
RedrawEvent::BusyStop => self.cursor.enabled = true,
@ -255,4 +260,19 @@ impl Editor {
self.dirty = vec![vec![true; width as usize]; height as usize];
self.should_clear = true;
}
fn set_option(&mut self, gui_option: GuiOption) {
match gui_option {
GuiOption::GuiFont(font_description) => {
let parts: Vec<&str> = font_description.split(":").collect();
self.font_name = Some(parts[0].to_string());
for part in parts.iter().skip(1) {
if part.starts_with("h") && part.len() > 1 {
self.font_size = part[1..].parse::<f32>().ok();
}
}
},
_ => {}
}
}
}

@ -28,8 +28,7 @@ impl CachingShaper {
self.cache.get(&key).unwrap()
}
// Re-enable once fonts change
// pub fn clear(&mut self) {
// self.cache.clear();
// }
pub fn clear(&mut self) {
self.cache.clear();
}
}

@ -1,5 +1,5 @@
use std::collections::HashMap;
use skulpin::skia_safe::{Typeface, Font, FontStyle};
use skulpin::skia_safe::{Typeface, Font, FontStyle, Paint};
use crate::editor::Style;
pub struct Fonts {
@ -69,4 +69,19 @@ impl FontLookup {
Fonts::new(&name, base_size * size_multiplier as f32)
})
}
pub fn font_base_dimensions(&mut self, paint: &Paint) -> (f32, f32) {
let base_fonts = self.size(1);
let (_, metrics) = base_fonts.normal.metrics();
let font_width = if metrics.avg_char_width > 0.0 {
metrics.avg_char_width
} else {
let (_, bounds) = base_fonts.normal.measure_str("x", Some(&paint));
bounds.width()
};
let font_height = metrics.descent - metrics.ascent;
(font_width, font_height)
}
}

@ -16,6 +16,12 @@ use crate::editor::{Editor, Style, Colors};
const FONT_NAME: &str = "Delugia Nerd Font";
const FONT_SIZE: f32 = 14.0;
#[derive(new)]
pub struct DrawResult {
pub is_animating: bool,
pub font_changed: bool
}
pub struct Renderer {
editor: Arc<Mutex<Editor>>,
@ -35,19 +41,23 @@ impl Renderer {
let mut paint = Paint::new(colors::WHITE, None);
paint.set_anti_alias(false);
let mut fonts_lookup = FontLookup::new(FONT_NAME, FONT_SIZE);
let shaper = CachingShaper::new();
let base_fonts = fonts_lookup.size(1);
let (_, bounds) = base_fonts.normal.measure_str("_", Some(&paint));
let font_width = bounds.width();
let (_, metrics) = base_fonts.normal.metrics();
let font_height = metrics.descent - metrics.ascent;
let mut fonts_lookup = FontLookup::new(FONT_NAME, FONT_SIZE);
let (font_width, font_height) = fonts_lookup.font_base_dimensions(&paint);
let cursor_renderer = CursorRenderer::new();
Renderer { editor, surface, paint, fonts_lookup, shaper, font_width, font_height, cursor_renderer }
}
fn set_font(&mut self, name: &str, size: f32) {
self.fonts_lookup = FontLookup::new(name, size);
let (font_width, font_height) = self.fonts_lookup.font_base_dimensions(&self.paint);
self.font_width = font_width;
self.font_height = font_height;
self.shaper.clear();
}
fn compute_text_region(&self, text: &str, grid_pos: (u64, u64), size: u16) -> Rect {
let (grid_x, grid_y) = grid_pos;
let x = grid_x as f32 * self.font_width;
@ -97,16 +107,25 @@ impl Renderer {
canvas.restore();
}
pub fn draw(&mut self, gpu_canvas: &mut Canvas, coordinate_system_helper: &CoordinateSystemHelper) -> bool {
let ((draw_commands, should_clear), default_colors, cursor) = {
pub fn draw(&mut self, gpu_canvas: &mut Canvas, coordinate_system_helper: &CoordinateSystemHelper) -> DrawResult {
let ((draw_commands, should_clear), default_colors, cursor, font_name, font_size) = {
let mut editor = self.editor.lock().unwrap();
(
editor.build_draw_commands(),
editor.default_colors.clone(),
editor.cursor.clone()
editor.cursor.clone(),
editor.font_name.clone(),
editor.font_size.clone()
)
};
let font_changed =
font_name.clone().map(|new_name| new_name != self.fonts_lookup.name).unwrap_or(false) ||
font_size.map(|new_size| new_size != self.fonts_lookup.base_size).unwrap_or(false);
if font_changed {
self.set_font(&font_name.unwrap(), font_size.unwrap());
}
if should_clear {
self.surface = None;
}
@ -146,6 +165,6 @@ impl Renderer {
&mut self.shaper, &mut self.fonts_lookup,
gpu_canvas);
draw_commands.len() > 0 || cursor_animating
DrawResult::new(draw_commands.len() > 0 || cursor_animating, font_changed)
}
}

@ -13,6 +13,15 @@ use crate::renderer::Renderer;
const EXTRA_LIVE_FRAMES: usize = 10;
fn handle_new_grid_size(new_size: LogicalSize, renderer: &Renderer, nvim: &mut Neovim) {
if new_size.width > 0.0 && new_size.height > 0.0 {
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).max(10), (new_height as i64).max(3)).expect("Resize failed");
}
}
pub fn ui_loop(editor: Arc<Mutex<Editor>>, nvim: Neovim, initial_size: (u64, u64)) {
let mut nvim = nvim;
let mut renderer = Renderer::new(editor.clone());
@ -66,12 +75,7 @@ pub fn ui_loop(editor: Arc<Mutex<Editor>>, nvim: Neovim, initial_size: (u64, u64
event: WindowEvent::Resized(new_size),
..
} => {
if new_size.width > 0.0 && new_size.height > 0.0 {
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).max(10), (new_height as i64).max(3)).expect("Resize failed");
}
handle_new_grid_size(new_size, &renderer, &mut nvim)
},
Event::WindowEvent {
@ -162,7 +166,8 @@ pub fn ui_loop(editor: Arc<Mutex<Editor>>, nvim: Neovim, initial_size: (u64, u64
} => {
frame_start = Instant::now();
if let Err(e) = skulpin_renderer.draw(&window.clone(), |canvas, coordinate_system_helper| {
if renderer.draw(canvas, coordinate_system_helper) {
let draw_result = renderer.draw(canvas, coordinate_system_helper);
if draw_result.is_animating {
live_frames = EXTRA_LIVE_FRAMES;
} else {
if live_frames > 0 {
@ -170,6 +175,10 @@ pub fn ui_loop(editor: Arc<Mutex<Editor>>, nvim: Neovim, initial_size: (u64, u64
}
}
if draw_result.font_changed {
handle_new_grid_size(window.inner_size(), &renderer, &mut nvim)
}
if live_frames > 0 {
*control_flow = ControlFlow::WaitUntil(frame_start + Duration::from_secs_f32(1.0 / 60.0));
} else {

Loading…
Cancel
Save