From 8aeac2b819f55a3c6750657ba4c69be0e5d33470 Mon Sep 17 00:00:00 2001 From: daa Date: Sat, 26 Aug 2017 23:17:09 +0300 Subject: [PATCH] Render fixes --- src/render/context.rs | 6 +++--- src/render/mod.rs | 16 +++++++++------- src/shell.rs | 4 +++- src/sys/pango/item.rs | 12 ++++++++++++ src/sys/pango/mod.rs | 9 ++++++--- src/ui_model/line.rs | 41 +++++++++++++++++++++++++++++++++++++++-- 6 files changed, 72 insertions(+), 16 deletions(-) diff --git a/src/render/context.rs b/src/render/context.rs index 7691847..f5ff9ca 100644 --- a/src/render/context.rs +++ b/src/render/context.rs @@ -4,7 +4,7 @@ use pangocairo::FontMap; use pango::prelude::*; use pango; -use sys::pango::*; +use sys::pango as sys_pango; use ui_model::StyledLine; @@ -21,8 +21,8 @@ impl Context { self.pango_context = create_pango_context(font_desc); } - pub fn itemize(&self, line: &StyledLine) -> Vec { - pango_itemize(&self.pango_context, &line.line_str, &line.attr_list) + pub fn itemize(&self, line: &StyledLine) -> Vec { + sys_pango::pango_itemize(&self.pango_context, &line.line_str, &line.attr_list) } } diff --git a/src/render/mod.rs b/src/render/mod.rs index 83b3a6a..2f7281f 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -2,15 +2,15 @@ mod context; use sys::pango::*; use pango; -use pango::prelude::*; use cairo; -use pangocairo::{CairoContextExt, FontMap}; -use std::ffi::CString; +use pangocairo::CairoContextExt; use ui_model; pub fn render( ctx: &cairo::Context, font_desc: pango::FontDescription, + line_height: f64, + char_width: f64, ui_model: &mut ui_model::UiModel, ) { let font_ctx = context::Context::new(&font_desc); @@ -18,17 +18,19 @@ pub fn render( shape_dirty(&font_ctx, ui_model); + let mut line_y = line_height; + for line in ui_model.model_mut() { + ctx.move_to(0.0, line_y); for i in 0..line.line.len() { let item = line.item_line[i].as_ref(); if let Some(item) = item { if let Some(ref glyphs) = item.glyphs { - let analysis = item.item.analysis(); - let font = analysis.font(); - ctx.show_glyph_string(&font, glyphs); + ctx.show_glyph_string(item.font(), glyphs); } } } + line_y += line_height; } } @@ -44,7 +46,7 @@ fn shape_dirty(ctx: &context::Context, ui_model: &mut ui_model::UiModel) { let mut item = line.get_item_mut(i).unwrap(); let mut glyphs = pango::GlyphString::new(); { - let analysis = item.item.analysis(); + let analysis = item.analysis(); let (offset, length, _) = item.item.offset(); pango_shape( &styled_line.line_str, diff --git a/src/shell.rs b/src/shell.rs index c950232..e2e388c 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -643,8 +643,10 @@ fn gtk_draw(state_arc: &Arc>, ctx: &cairo::Context) -> Inhibit { fn render(state: &mut State, ctx: &cairo::Context) { let font_desc = state.create_pango_font(); + let line_height = state.line_height.unwrap(); + let char_width = state.char_width.unwrap(); - render::render(ctx, font_desc, &mut state.model); + render::render(ctx, font_desc, line_height, char_width, &mut state.model); } fn show_nvim_start_error(err: nvim::NvimInitError, state_arc: Arc>) { diff --git a/src/sys/pango/item.rs b/src/sys/pango/item.rs index a98b35d..015cd88 100644 --- a/src/sys/pango/item.rs +++ b/src/sys/pango/item.rs @@ -20,6 +20,18 @@ glib_wrapper! { } impl Item { + pub fn new() -> Self { + unsafe { + from_glib_none(pango_sys::pango_item_new()) + } + } + + pub fn set_offset(&mut self, offset: i32, length: i32, num_chars: i32) { + self.0.offset = offset; + self.0.length = length; + self.0.num_chars = num_chars; + } + pub fn analysis(&self) -> analysis::Analysis { analysis::Analysis::from(&self.0.analysis) } diff --git a/src/sys/pango/mod.rs b/src/sys/pango/mod.rs index 65952c3..f5dc4a5 100644 --- a/src/sys/pango/mod.rs +++ b/src/sys/pango/mod.rs @@ -1,6 +1,9 @@ -pub mod item; +mod item; mod analysis; +pub use self::item::Item; +pub use self::analysis::Analysis; + use std::ptr; use pango; @@ -12,7 +15,7 @@ pub fn pango_itemize( context: &pango::Context, text: &String, attrs: &pango::AttrList -) -> Vec { +) -> Vec { unsafe { FromGlibPtrContainer::from_glib_container(pango_sys::pango_itemize( context.to_glib_none().0, @@ -29,7 +32,7 @@ pub fn pango_shape( text: &String, offset: usize, length: usize, - analysis: &analysis::Analysis, + analysis: &Analysis, glyphs: &mut pango::GlyphString, ) { debug_assert!(offset + length <= text.len()); diff --git a/src/ui_model/line.rs b/src/ui_model/line.rs index 7d8dde1..8454da4 100644 --- a/src/ui_model/line.rs +++ b/src/ui_model/line.rs @@ -1,30 +1,47 @@ use std::ops::{Index, IndexMut}; use super::cell::Cell; -use sys::pango::item as sys_pango; +use sys::pango as sys_pango; use pango; pub struct Item { pub item: sys_pango::Item, pub glyphs: Option, + pub ink_rect: Option, + font: pango::Font, } impl Item { pub fn new(item: sys_pango::Item) -> Self { Item { + font: item.analysis().font(), item, glyphs: None, + ink_rect: None, } } pub fn update(&mut self, item: sys_pango::Item) { + self.font = item.analysis().font(); self.item = item; self.glyphs = None; + self.ink_rect = None; } pub fn set_glyphs(&mut self, glyphs: pango::GlyphString) { + let mut glyphs = glyphs; + let (ink_rect, _) = glyphs.extents(&self.font); + self.ink_rect = Some(ink_rect); self.glyphs = Some(glyphs); } + + pub fn font(&self) -> &pango::Font { + &self.font + } + + pub fn analysis(&self) -> sys_pango::Analysis { + self.item.analysis() + } } pub struct Line { @@ -112,7 +129,7 @@ impl Line { } fn cell_to_item(&self, cell_idx: usize) -> usize { - for i in (cell_idx..0).rev() { + for i in (0..cell_idx + 1).rev() { if self.item_line[i].is_some() { return i; } @@ -212,4 +229,24 @@ mod tests { assert_eq!(1, styled_line.cell_to_byte[1]); assert_eq!(2, styled_line.cell_to_byte[2]); } + + #[test] + fn test_line_merge() { + let mut line = Line::new(2); + line[0].ch = 'a'; + line[1].ch = 'b'; + let styled_line = StyledLine::from(&line); + + let mut item1 = sys_pango::Item::new(); + item1.set_offset(0, 1, 1); + let mut item2 = sys_pango::Item::new(); + item2.set_offset(1, 1, 1); + + let new_items = [item1, item2]; + line.merge(&styled_line, &new_items); + + assert_eq!(2, line.item_line.len()); + assert!(line.item_line[0].is_some()); + assert!(line.item_line[1].is_some()); + } }