nvim_gtk/ui_model/
item.rs

1use crate::render;
2
3use pango;
4
5#[derive(Clone)]
6pub struct Item {
7    pub item: pango::Item,
8    pub cells_count: usize,
9    pub glyphs: Option<pango::GlyphString>,
10    pub ink_overflow: Option<InkOverflow>,
11    font: pango::Font,
12}
13
14impl Item {
15    pub fn new(item: pango::Item, cells_count: usize) -> Self {
16        debug_assert!(cells_count > 0);
17
18        Item {
19            font: item.analysis().font(),
20            item,
21            cells_count,
22            glyphs: None,
23            ink_overflow: None,
24        }
25    }
26
27    pub fn update(&mut self, item: pango::Item) {
28        self.font = item.analysis().font();
29        self.item = item;
30        self.glyphs = None;
31        self.ink_overflow = None;
32    }
33
34    pub fn set_glyphs(&mut self, ctx: &render::Context, glyphs: pango::GlyphString) {
35        let mut glyphs = glyphs;
36        let (ink_rect, _) = glyphs.extents(&self.font);
37        self.ink_overflow = InkOverflow::from(ctx, &ink_rect, self.cells_count as i32);
38        self.glyphs = Some(glyphs);
39    }
40
41    pub fn font(&self) -> &pango::Font {
42        &self.font
43    }
44
45    pub fn analysis(&self) -> &pango::Analysis {
46        self.item.analysis()
47    }
48}
49
50#[derive(Clone)]
51pub struct InkOverflow {
52    pub left: f64,
53    pub right: f64,
54    pub top: f64,
55    pub bot: f64,
56}
57
58impl InkOverflow {
59    pub fn from(
60        ctx: &render::Context,
61        ink_rect: &pango::Rectangle,
62        cells_count: i32,
63    ) -> Option<Self> {
64        let cell_metrix = ctx.cell_metrics();
65
66        let ink_descent = ink_rect.y + ink_rect.height;
67        let ink_ascent = ink_rect.y.abs();
68
69        let mut top = ink_ascent - cell_metrix.pango_ascent;
70        if top < 0 {
71            top = 0;
72        }
73
74        let mut bot = ink_descent - cell_metrix.pango_descent;
75        if bot < 0 {
76            bot = 0;
77        }
78
79        let left = if ink_rect.x < 0 { ink_rect.x.abs() } else { 0 };
80
81        let mut right = ink_rect.width - cells_count * cell_metrix.pango_char_width;
82        if right < 0 {
83            right = 0;
84        }
85
86        if left == 0 && right == 0 && top == 0 && bot == 0 {
87            None
88        } else {
89            Some(InkOverflow {
90                left: left as f64 / pango::SCALE as f64,
91                right: right as f64 / pango::SCALE as f64,
92                top: top as f64 / pango::SCALE as f64,
93                bot: bot as f64 / pango::SCALE as f64,
94            })
95        }
96    }
97}