updated readme

macos-click-through
Keith Simmons 4 years ago
parent 5da81b4f26
commit 62d2ca407d

@ -1,146 +1,159 @@
# Neovide [![Gitter](https://badges.gitter.im/neovide/community.svg)](https://gitter.im/neovide/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) # Neovide [![Gitter](https://badges.gitter.im/neovide/community.svg)](https://gitter.im/neovide/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
This is a simple graphical user interface for Neovim. Where possible there are some graphical improvements, but it should act This is a simple graphical user interface for Neovim. Where possible there are some graphical improvements, but it should act
functionally like the terminal UI. functionally like the terminal UI.
![Basic Screen Cap](./assets/BasicScreenCap.png) ![Basic Screen Cap](./assets/BasicScreenCap.png)
I've been using this as my daily driver since November 2019. It should be relatively stable, but I'm still working out some kinks I've been using this as my daily driver since November 2019. It should be relatively stable, but I'm still working out some kinks
and ironing out some cross platform issues. In general it should be usable at this point, and if it isn't I consider that a bug and and ironing out some cross platform issues. In general it should be usable at this point, and if it isn't I consider that a bug and
appreciate a report in the issues! Any help and ideas are also greatly appreciated. appreciate a report in the issues! Any help and ideas are also greatly appreciated.
I'm also very interested in suggestions code quality/style wise when it comes to Rust. I'm pretty new to the language and appreciate I'm also very interested in suggestions code quality/style wise when it comes to Rust. I'm pretty new to the language and appreciate
any critiques that you might have to offer. I won't take all of them, but I promise to consider anything you might have to offer. any critiques that you might have to offer. I won't take all of them, but I promise to consider anything you might have to offer.
## Features ## Features
Should be a standard full features Neovim GUI. Beyond that there are some visual niceties: Should be a standard full features Neovim GUI. Beyond that there are some visual niceties:
### Ligatures ### Ligatures
Supports ligatures and full [HarfBuzz](https://www.freedesktop.org/wiki/Software/HarfBuzz/) backed font shaping. Supports ligatures and full [HarfBuzz](https://www.freedesktop.org/wiki/Software/HarfBuzz/) backed font shaping.
![Ligatures](./assets/Ligatures.png) ![Ligatures](./assets/Ligatures.png)
### Animated Cursor ### Animated Cursor
Cursor animates into position with a smear effect to improve tracking of cursor position. Cursor animates into position with a smear effect to improve tracking of cursor position.
![Animated Cursor](./assets/AnimatedCursor.gif) ![Animated Cursor](./assets/AnimatedCursor.gif)
### Emoji Support ### Animated Windows
Font fallback supports rendering of emoji not contained in the configured font. Windows animate into position when they are moved making it easier to see how layout changes happen.
![Emoji](./assets/Emoji.png) ![Animated Windows](./assets/AnimatedWindows.gif)
### Some Nonsense ;) ### Blurred Floating Windows
``` The backgrounds of floating windows are blurred improving the visual separation between foreground and background from
let g:neovide_cursor_vfx_mode = "railgun" built in window transparency.
```
![Blurred Floating Windows](./assets/BlurredFloatingWindows.png)
![Railgun](./assets/Railgun.gif)
### Emoji Support
### More to Come
Font fallback supports rendering of emoji not contained in the configured font.
I've got more ideas for simple unobtrusive improvements. More to come.
![Emoji](./assets/Emoji.png)
## Configuration
### Some Nonsense ;)
Configuration is done almost completely via global neovide variables in your vim config and can be manipulated live at runtime. Details can be found [here](https://github.com/Kethku/neovide/wiki/Configuration).
```
## Install let g:neovide_cursor_vfx_mode = "railgun"
```
Relatively recent binaries can be found in the [project releases](https://github.com/Kethku/neovide/releases). But if you want the latest and greatest you should clone it and build yourself.
![Railgun](./assets/Railgun.gif)
Installing should be as simple as downloading the binary, making sure `nvim.exe` with version 0.4 or greater is on your path, and running it. Everything should be self contained.
### More to Come
## Building
I've got more ideas for simple unobtrusive improvements. More to come.
Building instructions are somewhat limited at the moment. All the libraries I use are cross platform and should have
support for Windows, Mac, and Linux. The rendering however is Vulkan-based, so driver support for Vulkan will be ## Configuration
necessary. On Windows this should be enabled by default if you have a relatively recent system.
Configuration is done almost completely via global neovide variables in your vim config and can be manipulated live at runtime. Details can be found [here](https://github.com/Kethku/neovide/wiki/Configuration).
Note: Neovide requires neovim version 0.4 or greater.
## Install
### Windows
Relatively recent binaries can be found in the [project releases](https://github.com/Kethku/neovide/releases). But if you want the latest and greatest you should clone it and build yourself.
1. Install the latest version of Rust. I recommend <https://rustup.rs/>
2. Install CMake. I use chocolatey: `choco install cmake --installargs '"ADD_CMAKE_TO_PATH=System"' -y` Installing should be as simple as downloading the binary, making sure `nvim.exe` with version 0.4 or greater is on your path, and running it. Everything should be self contained.
3. Install LLVM. I use chocolatey: `choco install llvm -y`
4. Ensure graphics libraries are up to date. ## Building
5. `git clone https://github.com/Kethku/neovide`
6. `cd neovide` Building instructions are somewhat limited at the moment. All the libraries I use are cross platform and should have
7. `cargo build --release` support for Windows, Mac, and Linux. The rendering however is Vulkan-based, so driver support for Vulkan will be
8. Copy `./target/release/neovide.exe` to a known location and enjoy. necessary. On Windows this should be enabled by default if you have a relatively recent system.
### Mac Note: Neovide requires neovim version 0.4 or greater.
1. Install the latest version of Rust. I recommend <https://rustup.rs/> ### Windows
2. Install CMake. Using homebrew: `brew install cmake`
3. Install the Vulkan SDK. I'm told `brew cask install apenngrace/vulkan/vulkan-sdk` works, but I can't test locally to find out. 1. Install the latest version of Rust. I recommend <https://rustup.rs/>
4. `git clone https://github.com/Kethku/neovide` 2. Install CMake. I use chocolatey: `choco install cmake --installargs '"ADD_CMAKE_TO_PATH=System"' -y`
5. `cd neovide` 3. Install LLVM. I use chocolatey: `choco install llvm -y`
6. `cargo build --release` 4. Ensure graphics libraries are up to date.
7. Copy `./target/release/neovide` to a known location and enjoy. 5. `git clone https://github.com/Kethku/neovide`
6. `cd neovide`
Note: If you run into issues with the vulkan libraries being reported as not verified, this issue thread may help: https://github.com/Kethku/neovide/issues/167#issuecomment-593314579 7. `cargo build --release`
8. Copy `./target/release/neovide.exe` to a known location and enjoy.
### Linux
### Mac
#### Arch Linux
1. Install the latest version of Rust. I recommend <https://rustup.rs/>
There is an [AUR package for neovide](https://aur.archlinux.org/packages/neovide-git/). 2. Install CMake. Using homebrew: `brew install cmake`
3. Install the Vulkan SDK. I'm told `brew cask install apenngrace/vulkan/vulkan-sdk` works, but I can't test locally to find out.
```sh 4. `git clone https://github.com/Kethku/neovide`
git clone https://aur.archlinux.org/neovide-git.git 5. `cd neovide`
cd neovide 6. `cargo build --release`
makepkg -si 7. Copy `./target/release/neovide` to a known location and enjoy.
```
Note: If you run into issues with the vulkan libraries being reported as not verified, this issue thread may help: https://github.com/Kethku/neovide/issues/167#issuecomment-593314579
#### Debian/Ubuntu
### Linux
Note: Neovide has been successfully built on other destros but this reportedly works on ubuntu.
#### Arch Linux
1. Install necessary dependencies
There is an [AUR package for neovide](https://aur.archlinux.org/packages/neovide-git/).
```sh
sudo apt-get install -y curl \ ```sh
gnupg ca-certificates git \ git clone https://aur.archlinux.org/neovide-git.git
gcc-multilib g++-multilib cmake libssl-dev pkg-config \ cd neovide
libfreetype6-dev libasound2-dev libexpat1-dev libxcb-composite0-dev \ makepkg -si
libbz2-dev libsndio-dev freeglut3-dev libxmu-dev libxi-dev ```
```
#### Debian/Ubuntu
2. Install Vulkan SDK
Note: Neovide has been successfully built on other destros but this reportedly works on ubuntu.
```sh
curl -sL "http://packages.lunarg.com/lunarg-signing-key-pub.asc" | sudo apt-key add - 1. Install necessary dependencies
sudo curl -sLo "/etc/apt/sources.list.d/lunarg-vulkan-1.2.131-bionic.list" "http://packages.lunarg.com/vulkan/1.2.131/lunarg-vulkan-1.2.131-bionic.list"
sudo apt-get update -y ```sh
sudo apt-get install -y vulkan-sdk sudo apt-get install -y curl \
``` gnupg ca-certificates git \
gcc-multilib g++-multilib cmake libssl-dev pkg-config \
Alternatively if you are running an amd graphics card you may have more success by installing amdvlk. libfreetype6-dev libasound2-dev libexpat1-dev libxcb-composite0-dev \
https://github.com/Kethku/neovide/issues/209 libbz2-dev libsndio-dev freeglut3-dev libxmu-dev libxi-dev
```
3. Install Rust
2. Install Vulkan SDK
`curl --proto '=https' --tlsv1.2 -sSf "https://sh.rustup.rs" | sh`
```sh
4. Clone the repository curl -sL "http://packages.lunarg.com/lunarg-signing-key-pub.asc" | sudo apt-key add -
sudo curl -sLo "/etc/apt/sources.list.d/lunarg-vulkan-1.2.131-bionic.list" "http://packages.lunarg.com/vulkan/1.2.131/lunarg-vulkan-1.2.131-bionic.list"
`git clone "https://github.com/Kethku/neovide"` sudo apt-get update -y
sudo apt-get install -y vulkan-sdk
5. Build ```
`cd neovide && ~/.cargo/bin/cargo build --release` Alternatively if you are running an amd graphics card you may have more success by installing amdvlk.
https://github.com/Kethku/neovide/issues/209
6. Copy `./target/release/neovide` to a known location and enjoy.
3. Install Rust
If you see an error complaining about DRI3 settings, links in this issue may help:
<https://github.com/Kethku/neovide/issues/44#issuecomment-578618052>. `curl --proto '=https' --tlsv1.2 -sSf "https://sh.rustup.rs" | sh`
Note: If you run into libsndio errors, try building without default features which will disable static linking of the SDL 4. Clone the repository
library.
`git clone "https://github.com/Kethku/neovide"`
5. Build
`cd neovide && ~/.cargo/bin/cargo build --release`
6. Copy `./target/release/neovide` to a known location and enjoy.
If you see an error complaining about DRI3 settings, links in this issue may help:
<https://github.com/Kethku/neovide/issues/44#issuecomment-578618052>.
Note: If you run into libsndio errors, try building without default features which will disable static linking of the SDL
library.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 KiB

@ -1,335 +1,335 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::mpsc::Receiver; use std::sync::mpsc::Receiver;
use std::sync::Arc; use std::sync::Arc;
use log::{error, trace, warn}; use log::{error, trace, warn};
use skulpin::skia_safe::{colors, dash_path_effect, BlendMode, Canvas, Color, Paint, Rect}; use skulpin::skia_safe::{colors, dash_path_effect, BlendMode, Canvas, Color, Paint, Rect};
use skulpin::CoordinateSystemHelper; use skulpin::CoordinateSystemHelper;
pub mod animation_utils; pub mod animation_utils;
mod caching_shaper; mod caching_shaper;
pub mod cursor_renderer; pub mod cursor_renderer;
pub mod font_options; pub mod font_options;
mod rendered_window; mod rendered_window;
pub use caching_shaper::CachingShaper; pub use caching_shaper::CachingShaper;
pub use font_options::*; pub use font_options::*;
pub use rendered_window::{RenderedWindow, WindowDrawDetails}; pub use rendered_window::{RenderedWindow, WindowDrawDetails};
use crate::editor::{Colors, DrawCommand, Style, WindowDrawCommand}; use crate::editor::{Colors, DrawCommand, Style, WindowDrawCommand};
use crate::settings::*; use crate::settings::*;
use cursor_renderer::CursorRenderer; use cursor_renderer::CursorRenderer;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#[derive(Clone)] #[derive(Clone)]
pub struct RendererSettings { pub struct RendererSettings {
animation_length: f32, animation_length: f32,
floating_opacity: f32, floating_opacity: f32,
floating_blur: bool, floating_blur: bool,
} }
pub fn initialize_settings() { pub fn initialize_settings() {
SETTINGS.set(&RendererSettings { SETTINGS.set(&RendererSettings {
animation_length: 0.15, animation_length: 0.15,
floating_opacity: 0.7, floating_opacity: 0.7,
floating_blur: true, floating_blur: true,
}); });
register_nvim_setting!( register_nvim_setting!(
"window_animation_length", "window_animation_length",
RendererSettings::animation_length RendererSettings::animation_length
); );
register_nvim_setting!( register_nvim_setting!(
"floating_window_opacity", "floating_window_opacity",
RendererSettings::floating_opacity RendererSettings::floating_opacity
); );
register_nvim_setting!("floating_window_blur", RendererSettings::floating_blur); register_nvim_setting!("floating_window_blur", RendererSettings::floating_blur);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
pub struct Renderer { pub struct Renderer {
rendered_windows: HashMap<u64, RenderedWindow>, rendered_windows: HashMap<u64, RenderedWindow>,
cursor_renderer: CursorRenderer, cursor_renderer: CursorRenderer,
pub paint: Paint, pub paint: Paint,
pub shaper: CachingShaper, pub shaper: CachingShaper,
pub default_style: Arc<Style>, pub default_style: Arc<Style>,
pub font_width: f32, pub font_width: f32,
pub font_height: f32, pub font_height: f32,
pub window_regions: Vec<WindowDrawDetails>, pub window_regions: Vec<WindowDrawDetails>,
pub batched_draw_command_receiver: Receiver<Vec<DrawCommand>>, pub batched_draw_command_receiver: Receiver<Vec<DrawCommand>>,
} }
impl Renderer { impl Renderer {
pub fn new(batched_draw_command_receiver: Receiver<Vec<DrawCommand>>) -> Renderer { pub fn new(batched_draw_command_receiver: Receiver<Vec<DrawCommand>>) -> Renderer {
let rendered_windows = HashMap::new(); let rendered_windows = HashMap::new();
let cursor_renderer = CursorRenderer::new(); let cursor_renderer = CursorRenderer::new();
let mut paint = Paint::new(colors::WHITE, None); let mut paint = Paint::new(colors::WHITE, None);
paint.set_anti_alias(false); paint.set_anti_alias(false);
let mut shaper = CachingShaper::new(); let mut shaper = CachingShaper::new();
let (font_width, font_height) = shaper.font_base_dimensions(); let (font_width, font_height) = shaper.font_base_dimensions();
let default_style = Arc::new(Style::new(Colors::new( let default_style = Arc::new(Style::new(Colors::new(
Some(colors::WHITE), Some(colors::WHITE),
Some(colors::BLACK), Some(colors::BLACK),
Some(colors::GREY), Some(colors::GREY),
))); )));
let window_regions = Vec::new(); let window_regions = Vec::new();
Renderer { Renderer {
rendered_windows, rendered_windows,
cursor_renderer, cursor_renderer,
paint, paint,
shaper, shaper,
default_style, default_style,
font_width, font_width,
font_height, font_height,
window_regions, window_regions,
batched_draw_command_receiver, batched_draw_command_receiver,
} }
} }
fn update_font(&mut self, guifont_setting: &str) -> bool { fn update_font(&mut self, guifont_setting: &str) -> bool {
let updated = self.shaper.update_font(guifont_setting); let updated = self.shaper.update_font(guifont_setting);
if updated { if updated {
let (font_width, font_height) = self.shaper.font_base_dimensions(); let (font_width, font_height) = self.shaper.font_base_dimensions();
self.font_width = font_width; self.font_width = font_width;
self.font_height = font_height.ceil(); self.font_height = font_height.ceil();
} }
updated updated
} }
fn compute_text_region(&self, grid_pos: (u64, u64), cell_width: u64) -> Rect { fn compute_text_region(&self, grid_pos: (u64, u64), cell_width: u64) -> Rect {
let (grid_x, grid_y) = grid_pos; let (grid_x, grid_y) = grid_pos;
let x = grid_x as f32 * self.font_width; let x = grid_x as f32 * self.font_width;
let y = grid_y as f32 * self.font_height; let y = grid_y as f32 * self.font_height;
let width = cell_width as f32 * self.font_width as f32; let width = cell_width as f32 * self.font_width as f32;
let height = self.font_height as f32; let height = self.font_height as f32;
Rect::new(x, y, x + width, y + height) Rect::new(x, y, x + width, y + height)
} }
fn draw_background( fn draw_background(
&mut self, &mut self,
canvas: &mut Canvas, canvas: &mut Canvas,
grid_pos: (u64, u64), grid_pos: (u64, u64),
cell_width: u64, cell_width: u64,
style: &Option<Arc<Style>>, style: &Option<Arc<Style>>,
) { ) {
self.paint.set_blend_mode(BlendMode::Src); self.paint.set_blend_mode(BlendMode::Src);
let region = self.compute_text_region(grid_pos, cell_width); let region = self.compute_text_region(grid_pos, cell_width);
let style = style.as_ref().unwrap_or(&self.default_style); let style = style.as_ref().unwrap_or(&self.default_style);
self.paint self.paint
.set_color(style.background(&self.default_style.colors).to_color()); .set_color(style.background(&self.default_style.colors).to_color());
canvas.draw_rect(region, &self.paint); canvas.draw_rect(region, &self.paint);
} }
fn draw_foreground( fn draw_foreground(
&mut self, &mut self,
canvas: &mut Canvas, canvas: &mut Canvas,
text: &str, text: &str,
grid_pos: (u64, u64), grid_pos: (u64, u64),
cell_width: u64, cell_width: u64,
style: &Option<Arc<Style>>, style: &Option<Arc<Style>>,
) { ) {
let (grid_x, grid_y) = grid_pos; let (grid_x, grid_y) = grid_pos;
let x = grid_x as f32 * self.font_width; let x = grid_x as f32 * self.font_width;
let y = grid_y as f32 * self.font_height; let y = grid_y as f32 * self.font_height;
let width = cell_width as f32 * self.font_width; let width = cell_width as f32 * self.font_width;
let style = style.as_ref().unwrap_or(&self.default_style); let style = style.as_ref().unwrap_or(&self.default_style);
canvas.save(); canvas.save();
let region = self.compute_text_region(grid_pos, cell_width); let region = self.compute_text_region(grid_pos, cell_width);
canvas.clip_rect(region, None, Some(false)); canvas.clip_rect(region, None, Some(false));
self.paint.set_blend_mode(BlendMode::Src); self.paint.set_blend_mode(BlendMode::Src);
let transparent = Color::from_argb(0, 0, 0, 0); let transparent = Color::from_argb(0, 0, 0, 0);
self.paint.set_color(transparent); self.paint.set_color(transparent);
canvas.draw_rect(region, &self.paint); canvas.draw_rect(region, &self.paint);
if style.underline || style.undercurl { if style.underline || style.undercurl {
let line_position = self.shaper.underline_position(); let line_position = self.shaper.underline_position();
let stroke_width = self.shaper.options.size / 10.0; let stroke_width = self.shaper.options.size / 10.0;
self.paint self.paint
.set_color(style.special(&self.default_style.colors).to_color()); .set_color(style.special(&self.default_style.colors).to_color());
self.paint.set_stroke_width(stroke_width); self.paint.set_stroke_width(stroke_width);
if style.undercurl { if style.undercurl {
self.paint.set_path_effect(dash_path_effect::new( self.paint.set_path_effect(dash_path_effect::new(
&[stroke_width * 2.0, stroke_width * 2.0], &[stroke_width * 2.0, stroke_width * 2.0],
0.0, 0.0,
)); ));
} else { } else {
self.paint.set_path_effect(None); self.paint.set_path_effect(None);
} }
canvas.draw_line( canvas.draw_line(
(x, y - line_position + self.font_height), (x, y - line_position + self.font_height),
(x + width, y - line_position + self.font_height), (x + width, y - line_position + self.font_height),
&self.paint, &self.paint,
); );
} }
self.paint self.paint
.set_color(style.foreground(&self.default_style.colors).to_color()); .set_color(style.foreground(&self.default_style.colors).to_color());
let text = text.trim_end(); let text = text.trim_end();
if !text.is_empty() { if !text.is_empty() {
for blob in self for blob in self
.shaper .shaper
.shape_cached(text, style.bold, style.italic) .shape_cached(text, style.bold, style.italic)
.iter() .iter()
{ {
canvas.draw_text_blob(blob, (x, y), &self.paint); canvas.draw_text_blob(blob, (x, y), &self.paint);
} }
} }
if style.strikethrough { if style.strikethrough {
let line_position = region.center_y(); let line_position = region.center_y();
self.paint self.paint
.set_color(style.special(&self.default_style.colors).to_color()); .set_color(style.special(&self.default_style.colors).to_color());
canvas.draw_line((x, line_position), (x + width, line_position), &self.paint); canvas.draw_line((x, line_position), (x + width, line_position), &self.paint);
} }
canvas.restore(); canvas.restore();
} }
pub fn handle_draw_command(&mut self, root_canvas: &mut Canvas, draw_command: DrawCommand) { pub fn handle_draw_command(&mut self, root_canvas: &mut Canvas, draw_command: DrawCommand) {
warn!("{:?}", &draw_command); warn!("{:?}", &draw_command);
match draw_command { match draw_command {
DrawCommand::Window { DrawCommand::Window {
grid_id, grid_id,
command: WindowDrawCommand::Close, command: WindowDrawCommand::Close,
} => { } => {
self.rendered_windows.remove(&grid_id); self.rendered_windows.remove(&grid_id);
} }
DrawCommand::Window { grid_id, command } => { DrawCommand::Window { grid_id, command } => {
if let Some(rendered_window) = self.rendered_windows.remove(&grid_id) { if let Some(rendered_window) = self.rendered_windows.remove(&grid_id) {
warn!("Window positioned {}", grid_id); warn!("Window positioned {}", grid_id);
let rendered_window = rendered_window.handle_window_draw_command(self, command); let rendered_window = rendered_window.handle_window_draw_command(self, command);
self.rendered_windows.insert(grid_id, rendered_window); self.rendered_windows.insert(grid_id, rendered_window);
} else if let WindowDrawCommand::Position { } else if let WindowDrawCommand::Position {
grid_left, grid_left,
grid_top, grid_top,
width, width,
height, height,
.. ..
} = command } = command
{ {
warn!("Created window {}", grid_id); warn!("Created window {}", grid_id);
let new_window = RenderedWindow::new( let new_window = RenderedWindow::new(
root_canvas, root_canvas,
&self, &self,
grid_id, grid_id,
(grid_left as f32, grid_top as f32).into(), (grid_left as f32, grid_top as f32).into(),
width, width,
height, height,
); );
self.rendered_windows.insert(grid_id, new_window); self.rendered_windows.insert(grid_id, new_window);
} else { } else {
error!("WindowDrawCommand sent for uninitialized grid {}", grid_id); error!("WindowDrawCommand sent for uninitialized grid {}", grid_id);
} }
} }
DrawCommand::UpdateCursor(new_cursor) => { DrawCommand::UpdateCursor(new_cursor) => {
self.cursor_renderer.update_cursor(new_cursor); self.cursor_renderer.update_cursor(new_cursor);
} }
DrawCommand::FontChanged(new_font) => { DrawCommand::FontChanged(new_font) => {
if self.update_font(&new_font) { if self.update_font(&new_font) {
// Resize all the grids // Resize all the grids
} }
} }
DrawCommand::DefaultStyleChanged(new_style) => { DrawCommand::DefaultStyleChanged(new_style) => {
self.default_style = Arc::new(new_style); self.default_style = Arc::new(new_style);
} }
_ => {} _ => {}
} }
} }
pub fn draw_frame( pub fn draw_frame(
&mut self, &mut self,
root_canvas: &mut Canvas, root_canvas: &mut Canvas,
coordinate_system_helper: &CoordinateSystemHelper, coordinate_system_helper: &CoordinateSystemHelper,
dt: f32, dt: f32,
) -> bool { ) -> bool {
trace!("Rendering"); trace!("Rendering");
let mut font_changed = false; let mut font_changed = false;
let draw_commands: Vec<DrawCommand> = self let draw_commands: Vec<DrawCommand> = self
.batched_draw_command_receiver .batched_draw_command_receiver
.try_iter() // Iterator of Vec of DrawCommand .try_iter() // Iterator of Vec of DrawCommand
.map(|batch| batch.into_iter()) // Iterator of Iterator of DrawCommand .map(|batch| batch.into_iter()) // Iterator of Iterator of DrawCommand
.flatten() // Iterator of DrawCommand .flatten() // Iterator of DrawCommand
.collect(); // Vec of DrawCommand .collect(); // Vec of DrawCommand
for draw_command in draw_commands.into_iter() { for draw_command in draw_commands.into_iter() {
if let DrawCommand::FontChanged(_) = draw_command { if let DrawCommand::FontChanged(_) = draw_command {
font_changed = true; font_changed = true;
} }
self.handle_draw_command(root_canvas, draw_command); self.handle_draw_command(root_canvas, draw_command);
} }
root_canvas.clear( root_canvas.clear(
self.default_style self.default_style
.colors .colors
.background .background
.clone() .clone()
.unwrap() .unwrap()
.to_color(), .to_color(),
); );
root_canvas.save(); root_canvas.save();
if let Some(root_window) = self.rendered_windows.get(&1) { if let Some(root_window) = self.rendered_windows.get(&1) {
let clip_rect = root_window.pixel_region(self.font_width, self.font_height); let clip_rect = root_window.pixel_region(self.font_width, self.font_height);
root_canvas.clip_rect(&clip_rect, None, Some(false)); root_canvas.clip_rect(&clip_rect, None, Some(false));
} }
coordinate_system_helper.use_logical_coordinates(root_canvas); coordinate_system_helper.use_logical_coordinates(root_canvas);
let windows: Vec<&mut RenderedWindow> = { let windows: Vec<&mut RenderedWindow> = {
let (mut root_windows, mut floating_windows): ( let (mut root_windows, mut floating_windows): (
Vec<&mut RenderedWindow>, Vec<&mut RenderedWindow>,
Vec<&mut RenderedWindow>, Vec<&mut RenderedWindow>,
) = self ) = self
.rendered_windows .rendered_windows
.values_mut() .values_mut()
.filter(|window| !window.hidden) .filter(|window| !window.hidden)
.partition(|window| !window.floating); .partition(|window| !window.floating);
root_windows root_windows
.sort_by(|window_a, window_b| window_a.id.partial_cmp(&window_b.id).unwrap()); .sort_by(|window_a, window_b| window_a.id.partial_cmp(&window_b.id).unwrap());
floating_windows floating_windows
.sort_by(|window_a, window_b| window_a.id.partial_cmp(&window_b.id).unwrap()); .sort_by(|window_a, window_b| window_a.id.partial_cmp(&window_b.id).unwrap());
root_windows root_windows
.into_iter() .into_iter()
.chain(floating_windows.into_iter()) .chain(floating_windows.into_iter())
.collect() .collect()
}; };
let settings = SETTINGS.get::<RendererSettings>(); let settings = SETTINGS.get::<RendererSettings>();
let font_width = self.font_width; let font_width = self.font_width;
let font_height = self.font_height; let font_height = self.font_height;
self.window_regions = windows self.window_regions = windows
.into_iter() .into_iter()
.map(|window| window.draw(root_canvas, &settings, font_width, font_height, dt)) .map(|window| window.draw(root_canvas, &settings, font_width, font_height, dt))
.collect(); .collect();
self.cursor_renderer.draw( self.cursor_renderer.draw(
&self.default_style.colors, &self.default_style.colors,
(self.font_width, self.font_height), (self.font_width, self.font_height),
&mut self.shaper, &mut self.shaper,
root_canvas, root_canvas,
dt, dt,
); );
root_canvas.restore(); root_canvas.restore();
font_changed font_changed
} }
} }

Loading…
Cancel
Save