Fix cursor only showing up over left half of wide characters

This commit is contained in:
Elaina Martineau 2019-05-11 09:57:22 -06:00 committed by Christian Duerr
parent bdae9f0f28
commit ca9724a5ef
4 changed files with 35 additions and 35 deletions

View File

@ -23,6 +23,13 @@ use crate::ansi::CursorStyle;
/// Width/Height of the cursor relative to the font width /// Width/Height of the cursor relative to the font width
pub const CURSOR_WIDTH_PERCENTAGE: i32 = 15; pub const CURSOR_WIDTH_PERCENTAGE: i32 = 15;
/// A key for caching cursor glyphs
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash, Deserialize)]
pub struct CursorKey {
pub style: CursorStyle,
pub is_wide: bool,
}
pub fn get_cursor_glyph( pub fn get_cursor_glyph(
cursor: CursorStyle, cursor: CursorStyle,
metrics: Metrics, metrics: Metrics,

View File

@ -438,7 +438,7 @@ impl Display {
let window_focused = self.window.is_focused; let window_focused = self.window.is_focused;
let grid_cells: Vec<RenderableCell> = let grid_cells: Vec<RenderableCell> =
terminal.renderable_cells(config, window_focused, metrics).collect(); terminal.renderable_cells(config, window_focused).collect();
// Get message from terminal to ignore modifications after lock is dropped // Get message from terminal to ignore modifications after lock is dropped
let message_buffer = terminal.message_buffer_mut().message(); let message_buffer = terminal.message_buffer_mut().message();

View File

@ -26,8 +26,8 @@ use font::{self, FontDesc, FontKey, GlyphKey, Rasterize, RasterizedGlyph, Raster
use glutin::dpi::PhysicalSize; use glutin::dpi::PhysicalSize;
use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher}; use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher};
use crate::ansi::CursorStyle;
use crate::config::{self, Config, Delta}; use crate::config::{self, Config, Delta};
use crate::cursor::{get_cursor_glyph, CursorKey};
use crate::gl; use crate::gl;
use crate::gl::types::*; use crate::gl::types::*;
use crate::index::{Column, Line}; use crate::index::{Column, Line};
@ -160,7 +160,7 @@ pub struct GlyphCache {
cache: HashMap<GlyphKey, Glyph, BuildHasherDefault<FnvHasher>>, cache: HashMap<GlyphKey, Glyph, BuildHasherDefault<FnvHasher>>,
/// Cache of buffered cursor glyphs /// Cache of buffered cursor glyphs
cursor_cache: HashMap<CursorStyle, Glyph, BuildHasherDefault<FnvHasher>>, cursor_cache: HashMap<CursorKey, Glyph, BuildHasherDefault<FnvHasher>>,
/// Rasterizer for loading new glyphs /// Rasterizer for loading new glyphs
rasterizer: Rasterizer, rasterizer: Rasterizer,
@ -994,12 +994,21 @@ impl<'a> RenderApi<'a> {
pub fn render_cell(&mut self, cell: RenderableCell, glyph_cache: &mut GlyphCache) { pub fn render_cell(&mut self, cell: RenderableCell, glyph_cache: &mut GlyphCache) {
let chars = match cell.inner { let chars = match cell.inner {
RenderableCellContent::Cursor((cursor_style, ref raw)) => { RenderableCellContent::Cursor(cursor_key) => {
// Raw cell pixel buffers like cursors don't need to go through font lookup // Raw cell pixel buffers like cursors don't need to go through font lookup
let glyph = glyph_cache let metrics = glyph_cache.metrics;
.cursor_cache let glyph = glyph_cache.cursor_cache.entry(cursor_key).or_insert_with(|| {
.entry(cursor_style) let offset_x = self.config.font.offset.x;
.or_insert_with(|| self.load_glyph(raw)); let offset_y = self.config.font.offset.y;
self.load_glyph(&get_cursor_glyph(
cursor_key.style,
metrics,
offset_x,
offset_y,
cursor_key.is_wide,
))
});
self.add_render_item(&cell, &glyph); self.add_render_item(&cell, &glyph);
return; return;
}, },

View File

@ -18,7 +18,7 @@ use std::ops::{Index, IndexMut, Range, RangeInclusive};
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use std::{io, mem, ptr}; use std::{io, mem, ptr};
use font::{self, RasterizedGlyph, Size}; use font::{self, Size};
use glutin::MouseCursor; use glutin::MouseCursor;
use unicode_width::UnicodeWidthChar; use unicode_width::UnicodeWidthChar;
@ -27,7 +27,7 @@ use crate::ansi::{
}; };
use crate::clipboard::{Clipboard, ClipboardType}; use crate::clipboard::{Clipboard, ClipboardType};
use crate::config::{Config, VisualBellAnimation}; use crate::config::{Config, VisualBellAnimation};
use crate::cursor; use crate::cursor::CursorKey;
use crate::grid::{ use crate::grid::{
BidirectionalIterator, DisplayIter, Grid, GridCell, IndexRegion, Indexed, Scroll, BidirectionalIterator, DisplayIter, Grid, GridCell, IndexRegion, Indexed, Scroll,
ViewportPosition, ViewportPosition,
@ -158,7 +158,7 @@ pub struct RenderableCellsIter<'a> {
grid: &'a Grid<Cell>, grid: &'a Grid<Cell>,
cursor: &'a Point, cursor: &'a Point,
cursor_offset: usize, cursor_offset: usize,
cursor_cell: Option<RasterizedGlyph>, cursor_key: Option<CursorKey>,
cursor_style: CursorStyle, cursor_style: CursorStyle,
config: &'a Config, config: &'a Config,
colors: &'a color::List, colors: &'a color::List,
@ -176,7 +176,6 @@ impl<'a> RenderableCellsIter<'a> {
config: &'b Config, config: &'b Config,
selection: Option<Span>, selection: Option<Span>,
mut cursor_style: CursorStyle, mut cursor_style: CursorStyle,
metrics: font::Metrics,
) -> RenderableCellsIter<'b> { ) -> RenderableCellsIter<'b> {
let grid = &term.grid; let grid = &term.grid;
@ -226,13 +225,10 @@ impl<'a> RenderableCellsIter<'a> {
// Load cursor glyph // Load cursor glyph
let cursor = &term.cursor.point; let cursor = &term.cursor.point;
let cursor_visible = term.mode.contains(TermMode::SHOW_CURSOR) && grid.contains(cursor); let cursor_visible = term.mode.contains(TermMode::SHOW_CURSOR) && grid.contains(cursor);
let cursor_cell = if cursor_visible { let cursor_key = if cursor_visible {
let offset_x = config.font.offset.x;
let offset_y = config.font.offset.y;
let is_wide = grid[cursor].flags.contains(cell::Flags::WIDE_CHAR) let is_wide = grid[cursor].flags.contains(cell::Flags::WIDE_CHAR)
&& (cursor.col + 1) < grid.num_cols(); && (cursor.col + 1) < grid.num_cols();
Some(cursor::get_cursor_glyph(cursor_style, metrics, offset_x, offset_y, is_wide)) Some(CursorKey { style: cursor_style, is_wide })
} else { } else {
// Use hidden cursor so text will not get inverted // Use hidden cursor so text will not get inverted
cursor_style = CursorStyle::Hidden; cursor_style = CursorStyle::Hidden;
@ -248,7 +244,7 @@ impl<'a> RenderableCellsIter<'a> {
url_highlight: &grid.url_highlight, url_highlight: &grid.url_highlight,
config, config,
colors: &term.colors, colors: &term.colors,
cursor_cell, cursor_key,
cursor_style, cursor_style,
} }
} }
@ -257,7 +253,7 @@ impl<'a> RenderableCellsIter<'a> {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum RenderableCellContent { pub enum RenderableCellContent {
Chars([char; cell::MAX_ZEROWIDTH_CHARS + 1]), Chars([char; cell::MAX_ZEROWIDTH_CHARS + 1]),
Cursor((CursorStyle, RasterizedGlyph)), Cursor(CursorKey),
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -377,7 +373,7 @@ impl<'a> Iterator for RenderableCellsIter<'a> {
loop { loop {
if self.cursor_offset == self.inner.offset() && self.inner.column() == self.cursor.col { if self.cursor_offset == self.inner.offset() && self.inner.column() == self.cursor.col {
// Handle cursor // Handle cursor
if let Some(cursor_cell) = self.cursor_cell.take() { if let Some(cursor_key) = self.cursor_key.take() {
let cell = Indexed { let cell = Indexed {
inner: self.grid[self.cursor], inner: self.grid[self.cursor],
column: self.cursor.col, column: self.cursor.col,
@ -386,8 +382,7 @@ impl<'a> Iterator for RenderableCellsIter<'a> {
let mut renderable_cell = let mut renderable_cell =
RenderableCell::new(self.config, self.colors, cell, false); RenderableCell::new(self.config, self.colors, cell, false);
renderable_cell.inner = renderable_cell.inner = RenderableCellContent::Cursor(cursor_key);
RenderableCellContent::Cursor((self.cursor_style, cursor_cell));
if let Some(color) = self.config.colors.cursor.cursor { if let Some(color) = self.config.colors.cursor.cursor {
renderable_cell.fg = color; renderable_cell.fg = color;
@ -1102,7 +1097,6 @@ impl Term {
&'b self, &'b self,
config: &'b Config, config: &'b Config,
window_focused: bool, window_focused: bool,
metrics: font::Metrics,
) -> RenderableCellsIter<'_> { ) -> RenderableCellsIter<'_> {
let alt_screen = self.mode.contains(TermMode::ALT_SCREEN); let alt_screen = self.mode.contains(TermMode::ALT_SCREEN);
let selection = self.grid.selection.as_ref().and_then(|s| s.to_span(self, alt_screen)); let selection = self.grid.selection.as_ref().and_then(|s| s.to_span(self, alt_screen));
@ -1113,7 +1107,7 @@ impl Term {
CursorStyle::HollowBlock CursorStyle::HollowBlock
}; };
RenderableCellsIter::new(&self, config, selection, cursor, metrics) RenderableCellsIter::new(&self, config, selection, cursor)
} }
/// Resize terminal to new dimensions /// Resize terminal to new dimensions
@ -2424,18 +2418,8 @@ mod benches {
let mut terminal = Term::new(&config, size, MessageBuffer::new(), Clipboard::new_nop()); let mut terminal = Term::new(&config, size, MessageBuffer::new(), Clipboard::new_nop());
mem::swap(&mut terminal.grid, &mut grid); mem::swap(&mut terminal.grid, &mut grid);
let metrics = font::Metrics {
descent: 0.,
line_height: 0.,
average_advance: 0.,
underline_position: 0.,
underline_thickness: 0.,
strikeout_position: 0.,
strikeout_thickness: 0.,
};
b.iter(|| { b.iter(|| {
let iter = terminal.renderable_cells(&config, false, metrics); let iter = terminal.renderable_cells(&config, false);
for cell in iter { for cell in iter {
test::black_box(cell); test::black_box(cell);
} }