Support double_width chars
This commit is contained in:
parent
31a0fea819
commit
dc8d6d5a70
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1,6 +1,6 @@
|
|||||||
[root]
|
[root]
|
||||||
name = "nvim-gtk"
|
name = "nvim-gtk"
|
||||||
version = "0.1.2"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cairo-rs 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cairo-rs 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nvim-gtk"
|
name = "nvim-gtk"
|
||||||
version = "0.1.2"
|
version = "0.2.0"
|
||||||
authors = ["daa84 <daa84@inbox.ru>"]
|
authors = ["daa84 <daa84@inbox.ru>"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ mod model_clip_iterator;
|
|||||||
|
|
||||||
pub use self::context::Context;
|
pub use self::context::Context;
|
||||||
pub use self::context::CellMetrics;
|
pub use self::context::CellMetrics;
|
||||||
use self::model_clip_iterator::ModelClipIteratorFactory;
|
use self::model_clip_iterator::{RowView, ModelClipIteratorFactory};
|
||||||
|
|
||||||
use mode;
|
use mode;
|
||||||
use color;
|
use color;
|
||||||
@ -31,62 +31,34 @@ pub fn render(
|
|||||||
ctx.paint();
|
ctx.paint();
|
||||||
|
|
||||||
let cell_metrics = font_ctx.cell_metrics();
|
let cell_metrics = font_ctx.cell_metrics();
|
||||||
let &CellMetrics {
|
let &CellMetrics { char_width, .. } = cell_metrics;
|
||||||
line_height,
|
|
||||||
char_width,
|
|
||||||
underline_position,
|
|
||||||
underline_thickness,
|
|
||||||
..
|
|
||||||
} = cell_metrics;
|
|
||||||
let (cursor_row, cursor_col) = ui_model.get_cursor();
|
let (cursor_row, cursor_col) = ui_model.get_cursor();
|
||||||
|
|
||||||
for (row, line) in ui_model.get_clip_iterator(ctx, cell_metrics) {
|
for cell_view in ui_model.get_clip_iterator(ctx, cell_metrics) {
|
||||||
let line_y = row as f64 * line_height;
|
|
||||||
let mut line_x = 0.0;
|
let mut line_x = 0.0;
|
||||||
|
let RowView { line, row, line_y, .. } = cell_view;
|
||||||
|
|
||||||
for col in 0..line.line.len() {
|
for col in 0..line.line.len() {
|
||||||
let cell = &line.line[col];
|
let cell = &line.line[col];
|
||||||
|
|
||||||
|
|
||||||
draw_cell(
|
draw_cell(&cell_view, color_model, cell, col, line_x);
|
||||||
ctx,
|
|
||||||
cell_metrics,
|
|
||||||
color_model,
|
|
||||||
line,
|
|
||||||
cell,
|
|
||||||
col,
|
|
||||||
line_x,
|
|
||||||
line_y,
|
|
||||||
);
|
|
||||||
|
|
||||||
if cell.attrs.underline || cell.attrs.undercurl {
|
draw_underline(&cell_view, color_model, cell, line_x);
|
||||||
if cell.attrs.undercurl {
|
|
||||||
let sp = color_model.actual_cell_sp(cell);
|
|
||||||
ctx.set_source_rgba(sp.0, sp.1, sp.2, 0.7);
|
|
||||||
|
|
||||||
let max_undercurl_height = (line_height - underline_position) * 2.0;
|
|
||||||
let undercurl_height = (underline_thickness * 4.0).min(max_undercurl_height);
|
|
||||||
let undercurl_y = line_y + underline_position - undercurl_height / 2.0;
|
|
||||||
|
|
||||||
ctx.show_error_underline(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);
|
|
||||||
ctx.set_line_width(underline_thickness);
|
|
||||||
ctx.move_to(line_x, line_y + underline_position);
|
|
||||||
ctx.line_to(line_x + char_width, line_y + underline_position);
|
|
||||||
ctx.stroke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if row == cursor_row && col == cursor_col {
|
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);
|
ctx.move_to(line_x, line_y);
|
||||||
cursor.draw(
|
cursor.draw(
|
||||||
ctx,
|
ctx,
|
||||||
font_ctx,
|
font_ctx,
|
||||||
mode,
|
mode,
|
||||||
line_y,
|
line_y,
|
||||||
false, //TODO: double_width,
|
double_width,
|
||||||
color_model.actual_cell_bg(cell),
|
color_model.actual_cell_bg(cell),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -96,23 +68,68 @@ pub fn render(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_cell(
|
fn draw_underline(
|
||||||
ctx: &cairo::Context,
|
cell_view: &RowView,
|
||||||
cell_metrics: &CellMetrics,
|
color_model: &color::ColorModel,
|
||||||
|
cell: &ui_model::Cell,
|
||||||
|
line_x: f64,
|
||||||
|
) {
|
||||||
|
|
||||||
|
if cell.attrs.underline || cell.attrs.undercurl {
|
||||||
|
|
||||||
|
let &RowView {
|
||||||
|
ctx,
|
||||||
|
line_y,
|
||||||
|
cell_metrics: &CellMetrics {
|
||||||
|
line_height,
|
||||||
|
char_width,
|
||||||
|
underline_position,
|
||||||
|
underline_thickness,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
..
|
||||||
|
} = cell_view;
|
||||||
|
|
||||||
|
if cell.attrs.undercurl {
|
||||||
|
let sp = color_model.actual_cell_sp(cell);
|
||||||
|
ctx.set_source_rgba(sp.0, sp.1, sp.2, 0.7);
|
||||||
|
|
||||||
|
let max_undercurl_height = (line_height - underline_position) * 2.0;
|
||||||
|
let undercurl_height = (underline_thickness * 4.0).min(max_undercurl_height);
|
||||||
|
let undercurl_y = line_y + underline_position - undercurl_height / 2.0;
|
||||||
|
|
||||||
|
ctx.show_error_underline(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);
|
||||||
|
ctx.set_line_width(underline_thickness);
|
||||||
|
ctx.move_to(line_x, line_y + underline_position);
|
||||||
|
ctx.line_to(line_x + char_width, line_y + underline_position);
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_cell(
|
||||||
|
cell_view: &RowView,
|
||||||
color_model: &color::ColorModel,
|
color_model: &color::ColorModel,
|
||||||
line: &ui_model::Line,
|
|
||||||
cell: &ui_model::Cell,
|
cell: &ui_model::Cell,
|
||||||
col: usize,
|
col: usize,
|
||||||
line_x: f64,
|
line_x: f64,
|
||||||
line_y: f64,
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
let &CellMetrics {
|
let &RowView {
|
||||||
char_width,
|
ctx,
|
||||||
line_height,
|
line,
|
||||||
ascent,
|
line_y,
|
||||||
|
cell_metrics: &CellMetrics {
|
||||||
|
char_width,
|
||||||
|
line_height,
|
||||||
|
ascent,
|
||||||
|
..
|
||||||
|
},
|
||||||
..
|
..
|
||||||
} = cell_metrics;
|
} = cell_view;
|
||||||
|
|
||||||
let (bg, fg) = color_model.cell_colors(cell);
|
let (bg, fg) = color_model.cell_colors(cell);
|
||||||
|
|
||||||
|
@ -4,25 +4,57 @@ use cairo;
|
|||||||
use super::context::CellMetrics;
|
use super::context::CellMetrics;
|
||||||
use ui_model;
|
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,
|
||||||
|
pub ctx: &'a cairo::Context,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> RowView<'a> {
|
||||||
|
pub fn new(
|
||||||
|
row: usize,
|
||||||
|
ctx: &'a cairo::Context,
|
||||||
|
cell_metrics: &'a CellMetrics,
|
||||||
|
line: &'a ui_model::Line,
|
||||||
|
) -> Self {
|
||||||
|
RowView {
|
||||||
|
line,
|
||||||
|
line_y: row as f64 * cell_metrics.line_height,
|
||||||
|
row,
|
||||||
|
cell_metrics,
|
||||||
|
ctx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ModelClipIterator<'a> {
|
pub struct ModelClipIterator<'a> {
|
||||||
model_idx: usize,
|
model_idx: usize,
|
||||||
model_iter: Iter<'a, ui_model::Line>,
|
model_iter: Iter<'a, ui_model::Line>,
|
||||||
|
cell_metrics: &'a CellMetrics,
|
||||||
|
ctx: &'a cairo::Context,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ModelClipIteratorFactory {
|
pub trait ModelClipIteratorFactory {
|
||||||
fn get_clip_iterator(
|
fn get_clip_iterator<'a>(
|
||||||
&self,
|
&'a self,
|
||||||
ctx: &cairo::Context,
|
ctx: &'a cairo::Context,
|
||||||
cell_metrics: &CellMetrics,
|
cell_metrics: &'a CellMetrics,
|
||||||
) -> ModelClipIterator;
|
) -> ModelClipIterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for ModelClipIterator<'a> {
|
impl<'a> Iterator for ModelClipIterator<'a> {
|
||||||
type Item = (usize, &'a ui_model::Line);
|
type Item = RowView<'a>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<(usize, &'a ui_model::Line)> {
|
fn next(&mut self) -> Option<RowView<'a>> {
|
||||||
let next = if let Some(line) = self.model_iter.next() {
|
let next = if let Some(line) = self.model_iter.next() {
|
||||||
Some((self.model_idx, line))
|
Some(RowView::new(
|
||||||
|
self.model_idx,
|
||||||
|
self.ctx,
|
||||||
|
self.cell_metrics,
|
||||||
|
line,
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -36,11 +68,11 @@ impl<'a> Iterator for ModelClipIterator<'a> {
|
|||||||
/// this is because in some cases(like 'g' character) drawing character does not fit to calculated bounds
|
/// this is because in some cases(like 'g' character) drawing character does not fit to calculated bounds
|
||||||
/// and if one line must be repainted - also previous and next line must be repainted to
|
/// and if one line must be repainted - also previous and next line must be repainted to
|
||||||
impl ModelClipIteratorFactory for ui_model::UiModel {
|
impl ModelClipIteratorFactory for ui_model::UiModel {
|
||||||
fn get_clip_iterator(
|
fn get_clip_iterator<'a>(
|
||||||
&self,
|
&'a self,
|
||||||
ctx: &cairo::Context,
|
ctx: &'a cairo::Context,
|
||||||
cell_metrics: &CellMetrics,
|
cell_metrics: &'a CellMetrics,
|
||||||
) -> ModelClipIterator {
|
) -> ModelClipIterator<'a> {
|
||||||
let model = self.model();
|
let model = self.model();
|
||||||
|
|
||||||
let (x1, y1, x2, y2) = ctx.clip_extents();
|
let (x1, y1, x2, y2) = ctx.clip_extents();
|
||||||
@ -59,6 +91,8 @@ impl ModelClipIteratorFactory for ui_model::UiModel {
|
|||||||
ModelClipIterator {
|
ModelClipIterator {
|
||||||
model_idx: model_clip_top,
|
model_idx: model_clip_top,
|
||||||
model_iter: model[model_clip_top..model_clip_bot + 1].iter(),
|
model_iter: model[model_clip_top..model_clip_bot + 1].iter(),
|
||||||
|
ctx,
|
||||||
|
cell_metrics,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,6 +108,24 @@ impl ModelRect {
|
|||||||
if right < self.right + len_since_right {
|
if right < self.right + len_since_right {
|
||||||
right = self.right + len_since_right;
|
right = self.right + len_since_right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extend also double_width chars
|
||||||
|
let cell = &line.line[self.left];
|
||||||
|
if self.left > 0 && cell.attrs.double_width {
|
||||||
|
let dw_char_idx = self.left - 1;
|
||||||
|
if dw_char_idx < left {
|
||||||
|
left = dw_char_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let dw_char_idx = self.right + 1;
|
||||||
|
if let Some(cell) = line.line.get(dw_char_idx) {
|
||||||
|
if cell.attrs.double_width {
|
||||||
|
if right < dw_char_idx {
|
||||||
|
right = dw_char_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.left = left;
|
self.left = left;
|
||||||
|
Loading…
Reference in New Issue
Block a user