From 8216cfb2b1b6a3b3caa178fcdc0999cde9c920c3 Mon Sep 17 00:00:00 2001 From: daa Date: Sat, 5 May 2018 22:41:38 +0300 Subject: [PATCH] Set cursor color from theme and xor it with text --- src/cmd_line.rs | 5 +- src/color.rs | 16 +++---- src/cursor.rs | 12 +++-- src/render/mod.rs | 80 +++++++++++++++++++------------ src/render/model_clip_iterator.rs | 2 - src/shell.rs | 8 ++-- src/theme.rs | 22 +++++++++ 7 files changed, 95 insertions(+), 50 deletions(-) diff --git a/src/cmd_line.rs b/src/cmd_line.rs index 94277dd..3cf1ded 100644 --- a/src/cmd_line.rs +++ b/src/cmd_line.rs @@ -536,7 +536,7 @@ fn gtk_draw(ctx: &cairo::Context, state: &Arc>) -> Inhibit { ctx.translate(0.0, (gap / 2) as f64); } - render::clear(ctx, &render_state.color_model); + render::clear(ctx); if let Some(block) = block { render::render( @@ -559,6 +559,9 @@ fn gtk_draw(ctx: &cairo::Context, state: &Arc>) -> Inhibit { &render_state.color_model, ); } + + render::fill_background(ctx, &render_state.color_model); + Inhibit(false) } diff --git a/src/color.rs b/src/color.rs index 76ec34a..89630eb 100644 --- a/src/color.rs +++ b/src/color.rs @@ -90,14 +90,6 @@ impl ColorModel { } } - pub fn actual_cell_bg<'a>(&'a self, cell: &'a Cell) -> &'a Color { - if !cell.attrs.reverse { - cell.attrs.background.as_ref().unwrap_or(&self.bg_color) - } else { - cell.attrs.foreground.as_ref().unwrap_or(&self.fg_color) - } - } - #[inline] pub fn actual_cell_sp<'a>(&'a self, cell: &'a Cell) -> &'a Color { cell.attrs.special.as_ref().unwrap_or(&self.sp_color) @@ -134,6 +126,14 @@ impl ColorModel { .clone() .unwrap_or_else(|| self.fg_color.clone()) } + + pub fn cursor_bg(&self) -> Color { + self.theme + .cursor() + .bg + .clone() + .unwrap_or_else(|| self.bg_color.clone()) + } } #[cfg(test)] diff --git a/src/cursor.rs b/src/cursor.rs index 8410099..1cb5d13 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -1,5 +1,5 @@ use cairo; -use color::Color; +use color; use ui::UiMutex; use mode; use std::sync::{Arc, Weak}; @@ -75,7 +75,7 @@ pub trait Cursor { font_ctx: &render::Context, line_y: f64, double_width: bool, - bg: &Color, + color: &color::ColorModel, ); } @@ -94,7 +94,7 @@ impl Cursor for EmptyCursor { _font_ctx: &render::Context, _line_y: f64, _double_width: bool, - _bg: &Color, + _color: &color::ColorModel, ) { } } @@ -165,7 +165,7 @@ impl Cursor for BlinkCursor { font_ctx: &render::Context, line_y: f64, double_width: bool, - bg: &Color, + color: &color::ColorModel, ) { let state = self.state.borrow(); @@ -174,7 +174,9 @@ impl Cursor for BlinkCursor { } let current_point = ctx.get_current_point(); - ctx.set_source_rgba(1.0 - bg.0, 1.0 - bg.1, 1.0 - bg.2, 0.6 * state.alpha.0); + + let bg = color.cursor_bg(); + ctx.set_source_rgba(bg.0, bg.1, bg.2, state.alpha.0); let (y, width, height) = cursor_rect( self.mode_info.as_ref(), diff --git a/src/render/mod.rs b/src/render/mod.rs index de74b38..19fecbb 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -16,7 +16,14 @@ use pangocairo; use cursor::Cursor; use ui_model; -pub fn clear(ctx: &cairo::Context, color_model: &color::ColorModel) { +pub fn clear(ctx: &cairo::Context) { + ctx.set_operator(cairo::Operator::Clear); + ctx.paint(); +} + +pub fn fill_background(ctx: &cairo::Context, color_model: &color::ColorModel) { + // must be dest over here + //ctx.set_operator(cairo::Operator::DestOver); ctx.set_source_rgb( color_model.bg_color.0, color_model.bg_color.1, @@ -36,6 +43,40 @@ pub fn render( let &CellMetrics { char_width, .. } = cell_metrics; let (cursor_row, cursor_col) = ui_model.get_cursor(); + // draw text + ctx.set_operator(cairo::Operator::Source); + + for cell_view in ui_model.get_clip_iterator(ctx, cell_metrics) { + let mut line_x = 0.0; + + for (col, cell) in cell_view.line.line.iter().enumerate() { + draw_cell(&cell_view, color_model, cell, col, line_x); + draw_underline(&cell_view, color_model, cell, line_x); + + line_x += char_width; + } + } + + + // draw cursor + ctx.set_operator(cairo::Operator::Xor); + let (_x1, _y1, x2, y2) = ctx.clip_extents(); + let line_x = cursor_col as f64 * cell_metrics.char_width; + let line_y = cursor_row as f64 * cell_metrics.line_height; + + if line_x < x2 && line_y < y2 { + if let Some(cursor_line) = ui_model.model().get(cursor_row) { + let double_width = cursor_line + .line + .get(cursor_col + 1) + .map_or(false, |c| c.attrs.double_width); + ctx.move_to(line_x, line_y); + cursor.draw(ctx, font_ctx, line_y, double_width, &color_model); + } + } + + // draw background + ctx.set_operator(cairo::Operator::DestOver); for cell_view in ui_model.get_clip_iterator(ctx, cell_metrics) { let mut line_x = 0.0; @@ -44,35 +85,6 @@ pub fn render( line_x += char_width; } } - - for cell_view in ui_model.get_clip_iterator(ctx, cell_metrics) { - let mut line_x = 0.0; - let RowView { - line, row, line_y, .. - } = cell_view; - - for (col, cell) in line.line.iter().enumerate() { - draw_cell(&cell_view, color_model, cell, col, line_x); - - draw_underline(&cell_view, color_model, cell, line_x); - - if row == cursor_row && col == cursor_col { - let double_width = line.line - .get(col + 1) - .map_or(false, |c| c.attrs.double_width); - ctx.move_to(line_x, line_y); - cursor.draw( - ctx, - font_ctx, - line_y, - double_width, - color_model.actual_cell_bg(cell), - ); - } - - line_x += char_width; - } - } } fn draw_underline( @@ -104,7 +116,13 @@ fn draw_underline( let undercurl_height = (underline_thickness * 4.0).min(max_undercurl_height); let undercurl_y = line_y + underline_position - undercurl_height / 2.0; - pangocairo::functions::show_error_underline(ctx, line_x, undercurl_y, char_width, undercurl_height); + pangocairo::functions::show_error_underline( + ctx, + line_x, + undercurl_y, + char_width, + undercurl_height, + ); } else if cell.attrs.underline { let fg = color_model.actual_cell_fg(cell); ctx.set_source_rgb(fg.0, fg.1, fg.2); diff --git a/src/render/model_clip_iterator.rs b/src/render/model_clip_iterator.rs index 452cb1f..132e9e2 100644 --- a/src/render/model_clip_iterator.rs +++ b/src/render/model_clip_iterator.rs @@ -7,7 +7,6 @@ use super::context::CellMetrics; use ui_model; pub struct RowView<'a> { - pub row: usize, pub line: &'a ui_model::Line, pub cell_metrics: &'a CellMetrics, pub line_y: f64, @@ -24,7 +23,6 @@ impl<'a> RowView<'a> { RowView { line, line_y: row as f64 * cell_metrics.line_height, - row, cell_metrics, ctx, } diff --git a/src/shell.rs b/src/shell.rs index 933fa79..7101d95 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -957,7 +957,7 @@ fn gtk_draw_double_buffer(state: &State, ctx: &cairo::Context) { buf_ctx.clip(); let render_state = state.render_state.borrow(); - render::clear(buf_ctx, &render_state.color_model); + render::clear(buf_ctx); render::render( &buf_ctx, state.cursor.as_ref().unwrap(), @@ -965,6 +965,7 @@ fn gtk_draw_double_buffer(state: &State, ctx: &cairo::Context) { &state.model, &render_state.color_model, ); + render::fill_background(buf_ctx, &render_state.color_model); ctx.set_source_surface(&surface.surface, 0.0, 0.0); ctx.paint(); @@ -973,7 +974,7 @@ fn gtk_draw_double_buffer(state: &State, ctx: &cairo::Context) { fn gtk_draw_direct(state: &State, ctx: &cairo::Context) { let render_state = state.render_state.borrow(); - render::clear(ctx, &render_state.color_model); + render::clear(ctx); render::render( ctx, state.cursor.as_ref().unwrap(), @@ -981,6 +982,7 @@ fn gtk_draw_direct(state: &State, ctx: &cairo::Context) { &state.model, &render_state.color_model, ); + render::fill_background(ctx, &render_state.color_model); } fn gtk_draw(state_arc: &Arc>, ctx: &cairo::Context) -> Inhibit { @@ -1153,7 +1155,7 @@ fn draw_initializing(state: &State, ctx: &cairo::Context) { &render_state.font_ctx, y, false, - &color_model.bg_color, + &color_model, ); } diff --git a/src/theme.rs b/src/theme.rs index 4a08f2b..6a66912 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -13,12 +13,14 @@ use value::ValueMapExt; struct State { pmenu: Pmenu, + cursor: Cursor, } impl State { fn new() -> Self { State { pmenu: Pmenu::new(), + cursor: Cursor::new(), } } } @@ -38,7 +40,15 @@ impl Theme { Ref::map(self.state.borrow(), |s| &s.pmenu) } + pub fn cursor(&self) -> Ref { + Ref::map(self.state.borrow(), |s| &s.cursor) + } + pub fn queue_update(&self, nvim: &mut Neovim) { + self.get_hl(nvim, "Cursor", |state, bg, _fg| { + state.cursor.bg = bg; + }); + self.get_hl(nvim, "Pmenu", |state, bg, fg| { state.pmenu.bg = bg; state.pmenu.fg = fg; @@ -70,6 +80,18 @@ impl Theme { } } +pub struct Cursor { + pub bg: Option, +} + +impl Cursor { + pub fn new() -> Self { + Cursor { + bg: None, + } + } +} + pub struct Pmenu { pub bg: Option, pub fg: Option,