Implement font features (#94)

This commit is contained in:
daa 2018-05-06 15:22:38 +03:00
parent 2dc10aa611
commit ad0ea04f93
9 changed files with 94 additions and 22 deletions

View File

@ -6,7 +6,6 @@ build = "build.rs"
[dependencies]
cairo-rs = "0.4"
pango = "0.4"
pango-sys = "0.6"
pangocairo = "0.5"
pangocairo-sys = "0.7"
@ -51,6 +50,10 @@ atty = "0.2"
[build-dependencies]
phf_codegen = "0.7"
[dependencies.pango]
features = ["v1_38"]
version = "0.4"
[dependencies.gtk]
version = "0.4"
features = ["v3_22"]

View File

@ -52,8 +52,10 @@ function s:GuiFontCommand(fname, bang) abort
call GuiFont(a:fname, a:bang ==# '!')
endif
endfunction
command! -nargs=? -bang Guifont call s:GuiFontCommand("<args>", "<bang>")
command! -nargs=? -bang GuiFont call s:GuiFontCommand("<args>", "<bang>")
command! -nargs=1 -bang Guifont call s:GuiFontCommand("<args>", "<bang>")
command! -nargs=1 -bang GuiFont call s:GuiFontCommand("<args>", "<bang>")
command! -nargs=? GuiFontFeatures call rpcnotify(1, 'Gui', 'FontFeatures', <q-args>)
command! NGToggleSidebar call rpcnotify(1, 'Gui', 'Command', 'ToggleSidebar')

View File

@ -86,6 +86,7 @@ pub fn call_gui_event(
) -> result::Result<(), String> {
match method {
"Font" => call!(ui->set_font(args: str)),
"FontFeatures" => call!(ui->set_font_features(args: str)),
"Clipboard" => match try_str!(args[0]) {
"Set" => match try_str!(args[1]) {
"*" => ui.clipboard_primary_set(try_str!(args[2])),

View File

@ -8,18 +8,24 @@ use ui_model::StyledLine;
use super::itemize::ItemizeIterator;
pub struct Context {
state: ContextState,
font_metrics: FontMetrix,
font_features: FontFeatures,
}
impl Context {
pub fn new(pango_context: pango::Context) -> Self {
Context {
state: ContextState::new(pango_context),
font_metrics: FontMetrix::new(pango_context),
font_features: FontFeatures::new(),
}
}
pub fn update(&mut self, pango_context: pango::Context) {
self.state = ContextState::new(pango_context);
self.font_metrics = FontMetrix::new(pango_context);
}
pub fn update_font_features(&mut self, font_features: FontFeatures) {
self.font_features = font_features;
}
pub fn itemize(&self, line: &StyledLine) -> Vec<sys_pango::Item> {
@ -28,7 +34,7 @@ impl Context {
ItemizeIterator::new(&line.line_str)
.flat_map(|(offset, len)| {
sys_pango::pango_itemize(
&self.state.pango_context,
&self.font_metrics.pango_context,
&line.line_str,
offset,
len,
@ -40,32 +46,34 @@ impl Context {
}
pub fn create_layout(&self) -> pango::Layout {
pango::Layout::new(&self.state.pango_context)
pango::Layout::new(&self.font_metrics.pango_context)
}
#[inline]
pub fn font_description(&self) -> &pango::FontDescription {
&self.state.font_desc
&self.font_metrics.font_desc
}
#[inline]
pub fn cell_metrics(&self) -> &CellMetrics {
&self.state.cell_metrics
&self.font_metrics.cell_metrics
}
pub fn font_features(&self) -> &FontFeatures {
&self.font_features
}
}
struct ContextState {
struct FontMetrix {
pango_context: pango::Context,
cell_metrics: CellMetrics,
font_desc: pango::FontDescription,
}
impl ContextState {
impl FontMetrix {
pub fn new(pango_context: pango::Context) -> Self {
let font_metrics = pango_context.get_metrics(None, None).unwrap();
let font_desc = pango_context.get_font_description().unwrap();
ContextState {
FontMetrix {
pango_context,
cell_metrics: CellMetrics::new(&font_metrics),
font_desc,
@ -115,3 +123,34 @@ impl CellMetrics {
}
}
}
pub struct FontFeatures {
features: Option<String>,
}
impl FontFeatures {
pub fn new() -> Self {
FontFeatures {
features: None,
}
}
pub fn from(font_features: String) -> Self {
if font_features.trim().is_empty() {
return Self::new();
}
FontFeatures {
features: Some(font_features)
}
}
pub fn insert_attr(&self, attr_list: &pango::AttrList, end_idx: usize) {
if let Some(ref features) = self.features {
let mut attr = sys_pango::attribute::new_features(features).unwrap();
attr.set_start_index(0);
attr.set_end_index(end_idx as u32);
attr_list.insert(attr);
}
}
}

View File

@ -2,7 +2,7 @@ mod context;
mod itemize;
mod model_clip_iterator;
pub use self::context::Context;
pub use self::context::{Context, FontFeatures};
pub use self::context::CellMetrics;
use self::model_clip_iterator::{ModelClipIteratorFactory, RowView};
@ -210,7 +210,7 @@ pub fn shape_dirty(
) {
for line in ui_model.model_mut() {
if line.dirty_line {
let styled_line = ui_model::StyledLine::from(line, color_model);
let styled_line = ui_model::StyledLine::from(line, color_model, ctx.font_features());
let items = ctx.itemize(&styled_line);
line.merge(&styled_line, &items);

View File

@ -276,6 +276,17 @@ impl State {
self.on_redraw(&RepaintMode::All);
}
pub fn set_font_features(&mut self, font_features: String) {
let font_features = render::FontFeatures::from(font_features);
self.render_state
.borrow_mut()
.font_ctx
.update_font_features(font_features);
self.model.clear_glyphs();
self.on_redraw(&RepaintMode::All);
}
pub fn open_file(&self, path: &str) {
if let Some(mut nvim) = self.nvim() {
nvim.command_async(&format!("e {}", path))

View File

@ -0,0 +1,12 @@
use pango_sys;
use pango;
use glib::translate::*;
pub fn new_features(features: &str) -> Option<pango::Attribute> {
unsafe {
from_glib_full(pango_sys::pango_attr_font_features_new(
features.to_glib_none().0,
))
}
}

View File

@ -2,6 +2,8 @@ mod item;
mod analysis;
mod attr_iterator;
pub mod attribute;
pub use self::item::Item;
pub use self::analysis::Analysis;
pub use self::attr_iterator::{AttrIterator, AttrIteratorFactory};

View File

@ -1,10 +1,12 @@
use std::ops::{Index, IndexMut};
use sys::pango as sys_pango;
use pango;
use render;
use color;
use super::cell::Cell;
use super::item::Item;
use sys::pango as sys_pango;
use pango;
pub struct Line {
pub line: Box<[Cell]>,
@ -242,8 +244,7 @@ pub struct StyledLine {
}
impl StyledLine {
pub fn from(line: &Line, color_model: &color::ColorModel) -> Self {
pub fn from(line: &Line, color_model: &color::ColorModel, font_features: &render::FontFeatures) -> Self {
let average_capacity = line.line.len() * 4 * 2; // code bytes * grapheme cluster
let mut line_str = String::with_capacity(average_capacity);
@ -278,6 +279,7 @@ impl StyledLine {
}
style_attr.insert(&attr_list);
font_features.insert_attr(&attr_list, line_str.len());
StyledLine {
line_str,
@ -410,7 +412,7 @@ mod tests {
line[1].ch = "b".to_owned();
line[2].ch = "c".to_owned();
let styled_line = StyledLine::from(&line, &color::ColorModel::new());
let styled_line = StyledLine::from(&line, &color::ColorModel::new(), &render::FontFeatures::new());
assert_eq!("abc", styled_line.line_str);
assert_eq!(3, styled_line.cell_to_byte.len());
assert_eq!(0, styled_line.cell_to_byte[0]);