reimplement merge
This commit is contained in:
parent
6e0909ea95
commit
40f5492ba8
36
src/color.rs
36
src/color.rs
@ -1,4 +1,5 @@
|
|||||||
use gdk;
|
use gdk;
|
||||||
|
use ui_model::Cell;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub struct Color(pub f64, pub f64, pub f64);
|
pub struct Color(pub f64, pub f64, pub f64);
|
||||||
@ -17,3 +18,38 @@ impl <'a> Into<gdk::RGBA> for &'a Color {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ColorModel {
|
||||||
|
pub bg_color: Color,
|
||||||
|
pub fg_color: Color,
|
||||||
|
pub sp_color: Color,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ColorModel {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
ColorModel {
|
||||||
|
bg_color: COLOR_BLACK,
|
||||||
|
fg_color: COLOR_WHITE,
|
||||||
|
sp_color: COLOR_RED,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cell_colors<'a>(&'a self, cell: &'a Cell) -> (&'a Color, &'a Color) {
|
||||||
|
let bg = if let Some(ref bg) = cell.attrs.background {
|
||||||
|
bg
|
||||||
|
} else {
|
||||||
|
&self.bg_color
|
||||||
|
};
|
||||||
|
let fg = if let Some(ref fg) = cell.attrs.foreground {
|
||||||
|
fg
|
||||||
|
} else {
|
||||||
|
&self.fg_color
|
||||||
|
};
|
||||||
|
|
||||||
|
if cell.attrs.reverse {
|
||||||
|
(fg, bg)
|
||||||
|
} else {
|
||||||
|
(bg, fg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
mod context;
|
mod context;
|
||||||
|
|
||||||
|
pub use self::context::Context;
|
||||||
|
|
||||||
|
use color;
|
||||||
use sys::pango::*;
|
use sys::pango::*;
|
||||||
use pango;
|
use pango;
|
||||||
use cairo;
|
use cairo;
|
||||||
@ -8,25 +11,29 @@ use ui_model;
|
|||||||
|
|
||||||
pub fn render(
|
pub fn render(
|
||||||
ctx: &cairo::Context,
|
ctx: &cairo::Context,
|
||||||
font_desc: pango::FontDescription,
|
ui_model: &ui_model::UiModel,
|
||||||
|
color_model: &color::ColorModel,
|
||||||
line_height: f64,
|
line_height: f64,
|
||||||
char_width: f64,
|
char_width: f64,
|
||||||
ui_model: &mut ui_model::UiModel,
|
|
||||||
) {
|
) {
|
||||||
let font_ctx = context::Context::new(&font_desc);
|
ctx.set_source_rgb(
|
||||||
|
color_model.bg_color.0,
|
||||||
shape_dirty(&font_ctx, ui_model);
|
color_model.bg_color.1,
|
||||||
|
color_model.bg_color.2,
|
||||||
|
);
|
||||||
|
ctx.paint();
|
||||||
|
|
||||||
let mut line_y = line_height;
|
let mut line_y = line_height;
|
||||||
|
|
||||||
for line in ui_model.model_mut() {
|
for line in ui_model.model() {
|
||||||
let mut line_x = 0.0;
|
let mut line_x = 0.0;
|
||||||
|
|
||||||
for i in 0..line.line.len() {
|
for i in 0..line.line.len() {
|
||||||
ctx.move_to(line_x, line_y);
|
ctx.move_to(line_x, line_y);
|
||||||
let item = line.item_line[i].as_ref();
|
if let Some(item) = line.item_line[i].as_ref() {
|
||||||
if let Some(item) = item {
|
|
||||||
if let Some(ref glyphs) = item.glyphs {
|
if let Some(ref glyphs) = item.glyphs {
|
||||||
|
let (_, fg) = color_model.cell_colors(&line.line[i]);
|
||||||
|
ctx.set_source_rgb(fg.0, fg.1, fg.2);
|
||||||
ctx.show_glyph_string(item.font(), glyphs);
|
ctx.show_glyph_string(item.font(), glyphs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -36,7 +43,7 @@ pub fn render(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shape_dirty(ctx: &context::Context, ui_model: &mut ui_model::UiModel) {
|
pub fn shape_dirty(ctx: &context::Context, ui_model: &mut ui_model::UiModel) {
|
||||||
for line in ui_model.model_mut() {
|
for line in ui_model.model_mut() {
|
||||||
if line.dirty_line {
|
if line.dirty_line {
|
||||||
let styled_line = ui_model::StyledLine::from(line);
|
let styled_line = ui_model::StyledLine::from(line);
|
||||||
|
408
src/shell.rs
408
src/shell.rs
@ -19,8 +19,8 @@ use neovim_lib::{Neovim, NeovimApi, Value};
|
|||||||
use neovim_lib::neovim_api::Tabpage;
|
use neovim_lib::neovim_api::Tabpage;
|
||||||
|
|
||||||
use settings::{Settings, FontSource};
|
use settings::{Settings, FontSource};
|
||||||
use ui_model::{UiModel, Cell, Attrs, ModelRect};
|
use ui_model::{UiModel, Attrs, ModelRect};
|
||||||
use color::{Color, COLOR_BLACK, COLOR_WHITE, COLOR_RED};
|
use color::{ColorModel, Color, COLOR_BLACK, COLOR_WHITE, COLOR_RED};
|
||||||
use nvim;
|
use nvim;
|
||||||
use nvim::{RedrawEvents, GuiApi, RepaintMode, ErrorReport, NeovimClient};
|
use nvim::{RedrawEvents, GuiApi, RepaintMode, ErrorReport, NeovimClient};
|
||||||
use input;
|
use input;
|
||||||
@ -50,9 +50,7 @@ macro_rules! idle_cb_call {
|
|||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
pub model: UiModel,
|
pub model: UiModel,
|
||||||
bg_color: Color,
|
color_model: ColorModel,
|
||||||
fg_color: Color,
|
|
||||||
sp_color: Color,
|
|
||||||
cur_attrs: Option<Attrs>,
|
cur_attrs: Option<Attrs>,
|
||||||
mouse_enabled: bool,
|
mouse_enabled: bool,
|
||||||
nvim: Rc<RefCell<NeovimClient>>,
|
nvim: Rc<RefCell<NeovimClient>>,
|
||||||
@ -87,11 +85,9 @@ impl State {
|
|||||||
|
|
||||||
State {
|
State {
|
||||||
model: UiModel::new(1, 1),
|
model: UiModel::new(1, 1),
|
||||||
|
color_model: ColorModel::new(),
|
||||||
nvim: Rc::new(RefCell::new(NeovimClient::new())),
|
nvim: Rc::new(RefCell::new(NeovimClient::new())),
|
||||||
cur_attrs: None,
|
cur_attrs: None,
|
||||||
bg_color: COLOR_BLACK,
|
|
||||||
fg_color: COLOR_WHITE,
|
|
||||||
sp_color: COLOR_RED,
|
|
||||||
mouse_enabled: true,
|
mouse_enabled: true,
|
||||||
font_desc: FontDescription::from_string(DEFAULT_FONT_NAME),
|
font_desc: FontDescription::from_string(DEFAULT_FONT_NAME),
|
||||||
cursor: None,
|
cursor: None,
|
||||||
@ -120,11 +116,11 @@ impl State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_foreground(&self) -> &Color {
|
pub fn get_foreground(&self) -> &Color {
|
||||||
&self.fg_color
|
&self.color_model.fg_color
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_background(&self) -> &Color {
|
pub fn get_background(&self) -> &Color {
|
||||||
&self.bg_color
|
&self.color_model.bg_color
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nvim(&self) -> RefMut<Neovim> {
|
pub fn nvim(&self) -> RefMut<Neovim> {
|
||||||
@ -150,25 +146,6 @@ impl State {
|
|||||||
self.font_desc.clone()
|
self.font_desc.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn colors<'a>(&'a self, cell: &'a Cell) -> (&'a Color, &'a Color) {
|
|
||||||
let bg = if let Some(ref bg) = cell.attrs.background {
|
|
||||||
bg
|
|
||||||
} else {
|
|
||||||
&self.bg_color
|
|
||||||
};
|
|
||||||
let fg = if let Some(ref fg) = cell.attrs.foreground {
|
|
||||||
fg
|
|
||||||
} else {
|
|
||||||
&self.fg_color
|
|
||||||
};
|
|
||||||
|
|
||||||
if cell.attrs.reverse {
|
|
||||||
(fg, bg)
|
|
||||||
} else {
|
|
||||||
(bg, fg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_font_desc(&self) -> &FontDescription {
|
pub fn get_font_desc(&self) -> &FontDescription {
|
||||||
&self.font_desc
|
&self.font_desc
|
||||||
}
|
}
|
||||||
@ -646,7 +623,16 @@ fn render(state: &mut State, ctx: &cairo::Context) {
|
|||||||
let line_height = state.line_height.unwrap();
|
let line_height = state.line_height.unwrap();
|
||||||
let char_width = state.char_width.unwrap();
|
let char_width = state.char_width.unwrap();
|
||||||
|
|
||||||
render::render(ctx, font_desc, line_height, char_width, &mut state.model);
|
let font_ctx = render::Context::new(&font_desc);
|
||||||
|
|
||||||
|
render::shape_dirty(&font_ctx, &mut state.model);
|
||||||
|
render::render(
|
||||||
|
ctx,
|
||||||
|
&state.model,
|
||||||
|
&state.color_model,
|
||||||
|
line_height,
|
||||||
|
char_width,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_nvim_start_error(err: nvim::NvimInitError, state_arc: Arc<UiMutex<State>>) {
|
fn show_nvim_start_error(err: nvim::NvimInitError, state_arc: Arc<UiMutex<State>>) {
|
||||||
@ -756,40 +742,40 @@ fn get_model_clip(
|
|||||||
model_clip
|
model_clip
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
//#[inline]
|
||||||
fn draw_backgound(
|
//fn draw_backgound(
|
||||||
state: &State,
|
// state: &State,
|
||||||
draw_bitmap: &ModelBitamp,
|
// draw_bitmap: &ModelBitamp,
|
||||||
ctx: &cairo::Context,
|
// ctx: &cairo::Context,
|
||||||
line_height: f64,
|
// line_height: f64,
|
||||||
char_width: f64,
|
// char_width: f64,
|
||||||
model_clip: &ModelRect,
|
// model_clip: &ModelRect,
|
||||||
) {
|
//) {
|
||||||
let line_x = model_clip.left as f64 * char_width;
|
// let line_x = model_clip.left as f64 * char_width;
|
||||||
let mut line_y: f64 = model_clip.top as f64 * line_height;
|
// let mut line_y: f64 = model_clip.top as f64 * line_height;
|
||||||
|
//
|
||||||
for (line_idx, line) in state.model.clip_model(model_clip) {
|
// for (line_idx, line) in state.model.clip_model(model_clip) {
|
||||||
ctx.move_to(line_x, line_y);
|
// ctx.move_to(line_x, line_y);
|
||||||
|
//
|
||||||
for (col_idx, cell) in line.iter() {
|
// for (col_idx, cell) in line.iter() {
|
||||||
let current_point = ctx.get_current_point();
|
// let current_point = ctx.get_current_point();
|
||||||
|
//
|
||||||
if !draw_bitmap.get(col_idx, line_idx) {
|
// if !draw_bitmap.get(col_idx, line_idx) {
|
||||||
let (bg, _) = state.colors(cell);
|
// let (bg, _) = state.colors(cell);
|
||||||
|
//
|
||||||
if &state.bg_color != bg {
|
// if &state.bg_color != bg {
|
||||||
ctx.set_source_rgb(bg.0, bg.1, bg.2);
|
// ctx.set_source_rgb(bg.0, bg.1, bg.2);
|
||||||
ctx.rectangle(current_point.0, current_point.1, char_width, line_height);
|
// ctx.rectangle(current_point.0, current_point.1, char_width, line_height);
|
||||||
ctx.fill();
|
// ctx.fill();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
ctx.move_to(current_point.0 + char_width, current_point.1);
|
// ctx.move_to(current_point.0 + char_width, current_point.1);
|
||||||
}
|
// }
|
||||||
line_y += line_height;
|
// line_y += line_height;
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
fn draw_initializing(state: &State, ctx: &cairo::Context) {
|
fn draw_initializing(state: &State, ctx: &cairo::Context) {
|
||||||
let layout = ctx.create_pango_layout();
|
let layout = ctx.create_pango_layout();
|
||||||
@ -798,7 +784,11 @@ fn draw_initializing(state: &State, ctx: &cairo::Context) {
|
|||||||
let line_height = state.line_height.unwrap();
|
let line_height = state.line_height.unwrap();
|
||||||
let char_width = state.char_width.unwrap();
|
let char_width = state.char_width.unwrap();
|
||||||
|
|
||||||
ctx.set_source_rgb(state.bg_color.0, state.bg_color.1, state.bg_color.2);
|
ctx.set_source_rgb(
|
||||||
|
state.color_model.bg_color.0,
|
||||||
|
state.color_model.bg_color.1,
|
||||||
|
state.color_model.bg_color.2,
|
||||||
|
);
|
||||||
ctx.paint();
|
ctx.paint();
|
||||||
|
|
||||||
layout.set_font_description(&desc);
|
layout.set_font_description(&desc);
|
||||||
@ -809,7 +799,11 @@ fn draw_initializing(state: &State, ctx: &cairo::Context) {
|
|||||||
let y = alloc.height as f64 / 2.0 - height as f64 / 2.0;
|
let y = alloc.height as f64 / 2.0 - height as f64 / 2.0;
|
||||||
|
|
||||||
ctx.move_to(x, y);
|
ctx.move_to(x, y);
|
||||||
ctx.set_source_rgb(state.fg_color.0, state.fg_color.1, state.fg_color.2);
|
ctx.set_source_rgb(
|
||||||
|
state.color_model.fg_color.0,
|
||||||
|
state.color_model.fg_color.1,
|
||||||
|
state.color_model.fg_color.2,
|
||||||
|
);
|
||||||
ctx.update_pango_layout(&layout);
|
ctx.update_pango_layout(&layout);
|
||||||
ctx.show_pango_layout(&layout);
|
ctx.show_pango_layout(&layout);
|
||||||
|
|
||||||
@ -822,145 +816,145 @@ fn draw_initializing(state: &State, ctx: &cairo::Context) {
|
|||||||
line_height,
|
line_height,
|
||||||
y,
|
y,
|
||||||
false,
|
false,
|
||||||
&state.bg_color,
|
&state.color_model.bg_color,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(state: &State, ctx: &cairo::Context) {
|
//fn draw(state: &State, ctx: &cairo::Context) {
|
||||||
let layout = ctx.create_pango_layout();
|
// let layout = ctx.create_pango_layout();
|
||||||
let mut desc = state.create_pango_font();
|
// let mut desc = state.create_pango_font();
|
||||||
let mut buf = String::with_capacity(4);
|
// let mut buf = String::with_capacity(4);
|
||||||
|
//
|
||||||
|
// let (row, col) = state.model.get_cursor();
|
||||||
|
//
|
||||||
|
// let line_height = state.line_height.unwrap();
|
||||||
|
// let char_width = state.char_width.unwrap();
|
||||||
|
// let mut draw_bitmap = ModelBitamp::new(state.model.columns, state.model.rows);
|
||||||
|
//
|
||||||
|
// ctx.set_source_rgb(state.bg_color.0, state.bg_color.1, state.bg_color.2);
|
||||||
|
// ctx.paint();
|
||||||
|
//
|
||||||
|
// let clip_rects = &ctx.copy_clip_rectangle_list().rectangles;
|
||||||
|
// for clip_idx in 0..clip_rects.len() {
|
||||||
|
// let clip = clip_rects.get(clip_idx).unwrap();
|
||||||
|
//
|
||||||
|
// let model_clip = get_model_clip(state, line_height, char_width, (
|
||||||
|
// clip.x,
|
||||||
|
// clip.y,
|
||||||
|
// clip.x + clip.width,
|
||||||
|
// clip.y + clip.height,
|
||||||
|
// ));
|
||||||
|
//
|
||||||
|
// let line_x = model_clip.left as f64 * char_width;
|
||||||
|
// let mut line_y: f64 = model_clip.top as f64 * line_height;
|
||||||
|
//
|
||||||
|
// draw_backgound(
|
||||||
|
// state,
|
||||||
|
// &draw_bitmap,
|
||||||
|
// ctx,
|
||||||
|
// line_height,
|
||||||
|
// char_width,
|
||||||
|
// &model_clip,
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// for (line_idx, line) in state.model.clip_model(&model_clip) {
|
||||||
|
//
|
||||||
|
// ctx.move_to(line_x, line_y);
|
||||||
|
//
|
||||||
|
// for (col_idx, cell) in line.iter() {
|
||||||
|
// let current_point = ctx.get_current_point();
|
||||||
|
//
|
||||||
|
// if !draw_bitmap.get(col_idx, line_idx) {
|
||||||
|
// let double_width = line.is_double_width(col_idx);
|
||||||
|
//
|
||||||
|
// let (bg, fg) = state.colors(cell);
|
||||||
|
//
|
||||||
|
// if row == line_idx && col == col_idx {
|
||||||
|
// state.cursor.as_ref().unwrap().draw(
|
||||||
|
// ctx,
|
||||||
|
// state,
|
||||||
|
// char_width,
|
||||||
|
// line_height,
|
||||||
|
// line_y,
|
||||||
|
// double_width,
|
||||||
|
// bg,
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// ctx.move_to(current_point.0, current_point.1);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// if !cell.ch.is_whitespace() {
|
||||||
|
// update_font_description(&mut desc, &cell.attrs);
|
||||||
|
//
|
||||||
|
// layout.set_font_description(&desc);
|
||||||
|
// buf.clear();
|
||||||
|
// buf.push(cell.ch);
|
||||||
|
// layout.set_text(&buf);
|
||||||
|
//
|
||||||
|
// // correct layout for double_width chars
|
||||||
|
// if double_width {
|
||||||
|
// let (dw_width, dw_height) = layout.get_pixel_size();
|
||||||
|
// let x_offset = (char_width * 2.0 - dw_width as f64) / 2.0;
|
||||||
|
// let y_offset = (line_height - dw_height as f64) / 2.0;
|
||||||
|
// ctx.rel_move_to(x_offset, y_offset);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ctx.set_source_rgb(fg.0, fg.1, fg.2);
|
||||||
|
// ctx.update_pango_layout(&layout);
|
||||||
|
// ctx.show_pango_layout(&layout);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if cell.attrs.underline || cell.attrs.undercurl {
|
||||||
|
// // [TODO]: Current gtk-rs bindings does not provide fontmetrics access
|
||||||
|
// // so it is not possible to find right position for underline or undercurl position
|
||||||
|
// // > update_font_description(&mut desc, &cell.attrs);
|
||||||
|
// // > layout.get_context().unwrap().get_metrics();
|
||||||
|
// let top_offset = line_height * 0.9;
|
||||||
|
//
|
||||||
|
// if cell.attrs.undercurl {
|
||||||
|
// let sp = if let Some(ref sp) = cell.attrs.special {
|
||||||
|
// sp
|
||||||
|
// } else {
|
||||||
|
// &state.sp_color
|
||||||
|
// };
|
||||||
|
// ctx.set_source_rgba(sp.0, sp.1, sp.2, 0.7);
|
||||||
|
// ctx.set_dash(&[4.0, 2.0], 0.0);
|
||||||
|
// ctx.set_line_width(2.0);
|
||||||
|
// ctx.move_to(current_point.0, line_y + top_offset);
|
||||||
|
// ctx.line_to(current_point.0 + char_width, line_y + top_offset);
|
||||||
|
// ctx.stroke();
|
||||||
|
// ctx.set_dash(&[], 0.0);
|
||||||
|
// } else if cell.attrs.underline {
|
||||||
|
// ctx.set_source_rgb(fg.0, fg.1, fg.2);
|
||||||
|
// ctx.set_line_width(1.0);
|
||||||
|
// ctx.move_to(current_point.0, line_y + top_offset);
|
||||||
|
// ctx.line_to(current_point.0 + char_width, line_y + top_offset);
|
||||||
|
// ctx.stroke();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ctx.move_to(current_point.0 + char_width, current_point.1);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// line_y += line_height;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// draw_bitmap.fill_from_model(&model_clip);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
let (row, col) = state.model.get_cursor();
|
//#[inline]
|
||||||
|
//fn update_font_description(desc: &mut FontDescription, attrs: &Attrs) {
|
||||||
let line_height = state.line_height.unwrap();
|
// desc.unset_fields(pango::FONT_MASK_STYLE | pango::FONT_MASK_WEIGHT);
|
||||||
let char_width = state.char_width.unwrap();
|
// if attrs.italic {
|
||||||
let mut draw_bitmap = ModelBitamp::new(state.model.columns, state.model.rows);
|
// desc.set_style(pango::Style::Italic);
|
||||||
|
// }
|
||||||
ctx.set_source_rgb(state.bg_color.0, state.bg_color.1, state.bg_color.2);
|
// if attrs.bold {
|
||||||
ctx.paint();
|
// desc.set_weight(pango::Weight::Bold);
|
||||||
|
// }
|
||||||
let clip_rects = &ctx.copy_clip_rectangle_list().rectangles;
|
//}
|
||||||
for clip_idx in 0..clip_rects.len() {
|
|
||||||
let clip = clip_rects.get(clip_idx).unwrap();
|
|
||||||
|
|
||||||
let model_clip = get_model_clip(state, line_height, char_width, (
|
|
||||||
clip.x,
|
|
||||||
clip.y,
|
|
||||||
clip.x + clip.width,
|
|
||||||
clip.y + clip.height,
|
|
||||||
));
|
|
||||||
|
|
||||||
let line_x = model_clip.left as f64 * char_width;
|
|
||||||
let mut line_y: f64 = model_clip.top as f64 * line_height;
|
|
||||||
|
|
||||||
draw_backgound(
|
|
||||||
state,
|
|
||||||
&draw_bitmap,
|
|
||||||
ctx,
|
|
||||||
line_height,
|
|
||||||
char_width,
|
|
||||||
&model_clip,
|
|
||||||
);
|
|
||||||
|
|
||||||
for (line_idx, line) in state.model.clip_model(&model_clip) {
|
|
||||||
|
|
||||||
ctx.move_to(line_x, line_y);
|
|
||||||
|
|
||||||
for (col_idx, cell) in line.iter() {
|
|
||||||
let current_point = ctx.get_current_point();
|
|
||||||
|
|
||||||
if !draw_bitmap.get(col_idx, line_idx) {
|
|
||||||
let double_width = line.is_double_width(col_idx);
|
|
||||||
|
|
||||||
let (bg, fg) = state.colors(cell);
|
|
||||||
|
|
||||||
if row == line_idx && col == col_idx {
|
|
||||||
state.cursor.as_ref().unwrap().draw(
|
|
||||||
ctx,
|
|
||||||
state,
|
|
||||||
char_width,
|
|
||||||
line_height,
|
|
||||||
line_y,
|
|
||||||
double_width,
|
|
||||||
bg,
|
|
||||||
);
|
|
||||||
|
|
||||||
ctx.move_to(current_point.0, current_point.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if !cell.ch.is_whitespace() {
|
|
||||||
update_font_description(&mut desc, &cell.attrs);
|
|
||||||
|
|
||||||
layout.set_font_description(&desc);
|
|
||||||
buf.clear();
|
|
||||||
buf.push(cell.ch);
|
|
||||||
layout.set_text(&buf);
|
|
||||||
|
|
||||||
// correct layout for double_width chars
|
|
||||||
if double_width {
|
|
||||||
let (dw_width, dw_height) = layout.get_pixel_size();
|
|
||||||
let x_offset = (char_width * 2.0 - dw_width as f64) / 2.0;
|
|
||||||
let y_offset = (line_height - dw_height as f64) / 2.0;
|
|
||||||
ctx.rel_move_to(x_offset, y_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.set_source_rgb(fg.0, fg.1, fg.2);
|
|
||||||
ctx.update_pango_layout(&layout);
|
|
||||||
ctx.show_pango_layout(&layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if cell.attrs.underline || cell.attrs.undercurl {
|
|
||||||
// [TODO]: Current gtk-rs bindings does not provide fontmetrics access
|
|
||||||
// so it is not possible to find right position for underline or undercurl position
|
|
||||||
// > update_font_description(&mut desc, &cell.attrs);
|
|
||||||
// > layout.get_context().unwrap().get_metrics();
|
|
||||||
let top_offset = line_height * 0.9;
|
|
||||||
|
|
||||||
if cell.attrs.undercurl {
|
|
||||||
let sp = if let Some(ref sp) = cell.attrs.special {
|
|
||||||
sp
|
|
||||||
} else {
|
|
||||||
&state.sp_color
|
|
||||||
};
|
|
||||||
ctx.set_source_rgba(sp.0, sp.1, sp.2, 0.7);
|
|
||||||
ctx.set_dash(&[4.0, 2.0], 0.0);
|
|
||||||
ctx.set_line_width(2.0);
|
|
||||||
ctx.move_to(current_point.0, line_y + top_offset);
|
|
||||||
ctx.line_to(current_point.0 + char_width, line_y + top_offset);
|
|
||||||
ctx.stroke();
|
|
||||||
ctx.set_dash(&[], 0.0);
|
|
||||||
} else if cell.attrs.underline {
|
|
||||||
ctx.set_source_rgb(fg.0, fg.1, fg.2);
|
|
||||||
ctx.set_line_width(1.0);
|
|
||||||
ctx.move_to(current_point.0, line_y + top_offset);
|
|
||||||
ctx.line_to(current_point.0 + char_width, line_y + top_offset);
|
|
||||||
ctx.stroke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.move_to(current_point.0 + char_width, current_point.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
line_y += line_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
draw_bitmap.fill_from_model(&model_clip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn update_font_description(desc: &mut FontDescription, attrs: &Attrs) {
|
|
||||||
desc.unset_fields(pango::FONT_MASK_STYLE | pango::FONT_MASK_WEIGHT);
|
|
||||||
if attrs.italic {
|
|
||||||
desc.set_style(pango::Style::Italic);
|
|
||||||
}
|
|
||||||
if attrs.bold {
|
|
||||||
desc.set_weight(pango::Weight::Bold);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn request_window_resize(state: &mut State) {
|
fn request_window_resize(state: &mut State) {
|
||||||
if !state.request_resize {
|
if !state.request_resize {
|
||||||
@ -1111,27 +1105,27 @@ impl RedrawEvents for State {
|
|||||||
|
|
||||||
fn on_update_bg(&mut self, bg: i64) -> RepaintMode {
|
fn on_update_bg(&mut self, bg: i64) -> RepaintMode {
|
||||||
if bg >= 0 {
|
if bg >= 0 {
|
||||||
self.bg_color = split_color(bg as u64);
|
self.color_model.bg_color = split_color(bg as u64);
|
||||||
} else {
|
} else {
|
||||||
self.bg_color = COLOR_BLACK;
|
self.color_model.bg_color = COLOR_BLACK;
|
||||||
}
|
}
|
||||||
RepaintMode::Nothing
|
RepaintMode::Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_update_fg(&mut self, fg: i64) -> RepaintMode {
|
fn on_update_fg(&mut self, fg: i64) -> RepaintMode {
|
||||||
if fg >= 0 {
|
if fg >= 0 {
|
||||||
self.fg_color = split_color(fg as u64);
|
self.color_model.fg_color = split_color(fg as u64);
|
||||||
} else {
|
} else {
|
||||||
self.fg_color = COLOR_WHITE;
|
self.color_model.fg_color = COLOR_WHITE;
|
||||||
}
|
}
|
||||||
RepaintMode::Nothing
|
RepaintMode::Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_update_sp(&mut self, sp: i64) -> RepaintMode {
|
fn on_update_sp(&mut self, sp: i64) -> RepaintMode {
|
||||||
if sp >= 0 {
|
if sp >= 0 {
|
||||||
self.sp_color = split_color(sp as u64);
|
self.color_model.sp_color = split_color(sp as u64);
|
||||||
} else {
|
} else {
|
||||||
self.sp_color = COLOR_RED;
|
self.color_model.sp_color = COLOR_RED;
|
||||||
}
|
}
|
||||||
RepaintMode::Nothing
|
RepaintMode::Nothing
|
||||||
}
|
}
|
||||||
|
@ -53,13 +53,14 @@ impl Cell {
|
|||||||
Cell {
|
Cell {
|
||||||
attrs: Attrs::new(),
|
attrs: Attrs::new(),
|
||||||
ch: ch,
|
ch: ch,
|
||||||
dirty: false,
|
dirty: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
self.ch = ' ';
|
self.ch = ' ';
|
||||||
self.attrs.clear();
|
self.attrs.clear();
|
||||||
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,6 @@ pub struct Line {
|
|||||||
pub item_line: Box<[Option<Item>]>,
|
pub item_line: Box<[Option<Item>]>,
|
||||||
cell_to_item: Box<[i32]>,
|
cell_to_item: Box<[i32]>,
|
||||||
|
|
||||||
item_line_empty: bool,
|
|
||||||
pub dirty_line: bool,
|
pub dirty_line: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,8 +71,7 @@ impl Line {
|
|||||||
line: line.into_boxed_slice(),
|
line: line.into_boxed_slice(),
|
||||||
item_line: item_line.into_boxed_slice(),
|
item_line: item_line.into_boxed_slice(),
|
||||||
cell_to_item: vec![-1; columns].into_boxed_slice(),
|
cell_to_item: vec![-1; columns].into_boxed_slice(),
|
||||||
dirty_line: false,
|
dirty_line: true,
|
||||||
item_line_empty: true,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,36 +79,85 @@ impl Line {
|
|||||||
for cell in &mut self.line[left..right + 1] {
|
for cell in &mut self.line[left..right + 1] {
|
||||||
cell.clear();
|
cell.clear();
|
||||||
}
|
}
|
||||||
|
self.dirty_line = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn merge(&mut self, old_items: &StyledLine, new_items: &[sys_pango::Item]) {
|
fn set_cell_to_empty(&mut self, cell_idx: usize) -> bool {
|
||||||
for new_item in new_items {
|
if self.item_line[cell_idx].is_some() {
|
||||||
//FIXME: clear empty cells
|
self.item_line[cell_idx] = None;
|
||||||
let (offset, length, _) = new_item.offset();
|
self.cell_to_item[cell_idx] = -1;
|
||||||
let start_cell = old_items.cell_to_byte[offset];
|
self.line[cell_idx].dirty = true;
|
||||||
let end_cell = old_items.cell_to_byte[offset + length - 1];
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// first time initialization
|
fn set_cell_to_item(&mut self, pango_item: &PangoItemPosition) -> bool {
|
||||||
// as cell_to_item points to wrong values
|
let start_item = self.cell_to_item(pango_item.start_cell);
|
||||||
if !self.item_line_empty {
|
let end_item = self.cell_to_item(pango_item.end_cell);
|
||||||
let start_item = self.cell_to_item(start_cell);
|
//FIXME: check start cell
|
||||||
let end_item = self.cell_to_item(end_cell);
|
//FIXME: check length
|
||||||
|
//FIXME: don't check start_item != end_item
|
||||||
|
|
||||||
// in case different item length was in previous iteration
|
// in case different item length was in previous iteration
|
||||||
// mark all item as dirty
|
// mark all item as dirty
|
||||||
if start_item != end_item {
|
if start_item != end_item || start_item == -1 || end_item == -1 {
|
||||||
self.initialize_cell_item(start_cell, end_cell, new_item);
|
self.initialize_cell_item(pango_item.start_cell, pango_item.end_cell, pango_item.item);
|
||||||
|
true
|
||||||
} else {
|
} else {
|
||||||
self.item_line[start_cell].as_mut().unwrap().update(
|
// update only if cell marked as dirty
|
||||||
new_item.clone(),
|
if self.line[pango_item.start_cell..pango_item.end_cell + 1]
|
||||||
);
|
.iter()
|
||||||
|
.find(|c| c.dirty)
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
self.item_line[pango_item.start_cell]
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.update(pango_item.item.clone());
|
||||||
|
self.line[pango_item.start_cell].dirty = true;
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
self.initialize_cell_item(start_cell, end_cell, new_item);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.item_line_empty = false;
|
pub fn merge(&mut self, old_items: &StyledLine, pango_items: &[sys_pango::Item]) {
|
||||||
|
let mut pango_item_iter = pango_items.iter().map(|item| {
|
||||||
|
PangoItemPosition::new(old_items, item)
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut next_item = pango_item_iter.next();
|
||||||
|
let mut move_to_next_item = false;
|
||||||
|
|
||||||
|
let mut cell_idx = 0;
|
||||||
|
while cell_idx < self.line.len() {
|
||||||
|
let dirty = match next_item {
|
||||||
|
None => self.set_cell_to_empty(cell_idx),
|
||||||
|
Some(ref pango_item) => {
|
||||||
|
if cell_idx < pango_item.start_cell {
|
||||||
|
self.set_cell_to_empty(cell_idx)
|
||||||
|
} else if cell_idx == pango_item.start_cell {
|
||||||
|
move_to_next_item = true;
|
||||||
|
self.set_cell_to_item(pango_item)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.dirty_line = self.dirty_line || dirty;
|
||||||
|
if move_to_next_item {
|
||||||
|
let pango_item = next_item.unwrap();
|
||||||
|
cell_idx += pango_item.end_cell - pango_item.start_cell + 1;
|
||||||
|
next_item = pango_item_iter.next();
|
||||||
|
move_to_next_item = false;
|
||||||
|
} else {
|
||||||
|
cell_idx += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize_cell_item(
|
fn initialize_cell_item(
|
||||||
@ -161,6 +208,26 @@ impl IndexMut<usize> for Line {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct PangoItemPosition<'a> {
|
||||||
|
item: &'a sys_pango::Item,
|
||||||
|
start_cell: usize,
|
||||||
|
end_cell: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> PangoItemPosition<'a> {
|
||||||
|
pub fn new(styled_line: &StyledLine, item: &'a sys_pango::Item) -> Self {
|
||||||
|
let (offset, length, _) = item.offset();
|
||||||
|
let start_cell = styled_line.cell_to_byte[offset];
|
||||||
|
let end_cell = styled_line.cell_to_byte[offset + length - 1];
|
||||||
|
|
||||||
|
PangoItemPosition {
|
||||||
|
item,
|
||||||
|
start_cell,
|
||||||
|
end_cell,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct StyledLine {
|
pub struct StyledLine {
|
||||||
pub line_str: String,
|
pub line_str: String,
|
||||||
cell_to_byte: Box<[usize]>,
|
cell_to_byte: Box<[usize]>,
|
||||||
|
Loading…
Reference in New Issue
Block a user