1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use crate::render;

use pango;

#[derive(Clone)]
pub struct Item {
    pub item: pango::Item,
    pub cells_count: usize,
    pub glyphs: Option<pango::GlyphString>,
    pub ink_overflow: Option<InkOverflow>,
    font: pango::Font,
}

impl Item {
    pub fn new(item: pango::Item, cells_count: usize) -> Self {
        debug_assert!(cells_count > 0);

        Item {
            font: item.analysis().font(),
            item,
            cells_count,
            glyphs: None,
            ink_overflow: None,
        }
    }

    pub fn update(&mut self, item: pango::Item) {
        self.font = item.analysis().font();
        self.item = item;
        self.glyphs = None;
        self.ink_overflow = None;
    }

    pub fn set_glyphs(&mut self, ctx: &render::Context, glyphs: pango::GlyphString) {
        let mut glyphs = glyphs;
        let (ink_rect, _) = glyphs.extents(&self.font);
        self.ink_overflow = InkOverflow::from(ctx, &ink_rect, self.cells_count as i32);
        self.glyphs = Some(glyphs);
    }

    pub fn font(&self) -> &pango::Font {
        &self.font
    }

    pub fn analysis(&self) -> &pango::Analysis {
        self.item.analysis()
    }
}

#[derive(Clone)]
pub struct InkOverflow {
    pub left: f64,
    pub right: f64,
    pub top: f64,
    pub bot: f64,
}

impl InkOverflow {
    pub fn from(
        ctx: &render::Context,
        ink_rect: &pango::Rectangle,
        cells_count: i32,
    ) -> Option<Self> {
        let cell_metrix = ctx.cell_metrics();

        let ink_descent = ink_rect.y + ink_rect.height;
        let ink_ascent = ink_rect.y.abs();

        let mut top = ink_ascent - cell_metrix.pango_ascent;
        if top < 0 {
            top = 0;
        }

        let mut bot = ink_descent - cell_metrix.pango_descent;
        if bot < 0 {
            bot = 0;
        }

        let left = if ink_rect.x < 0 { ink_rect.x.abs() } else { 0 };

        let mut right = ink_rect.width - cells_count * cell_metrix.pango_char_width;
        if right < 0 {
            right = 0;
        }

        if left == 0 && right == 0 && top == 0 && right == 0 {
            None
        } else {
            Some(InkOverflow {
                left: left as f64 / pango::SCALE as f64,
                right: right as f64 / pango::SCALE as f64,
                top: top as f64 / pango::SCALE as f64,
                bot: bot as f64 / pango::SCALE as f64,
            })
        }
    }
}