Registry / RepositoryTypeScriptRustPython
Rollpie
ReadmeFiles
Versions
Info
Download
0.2.3555.5 KB2026-10-160.2.2572.8 KB2026-10-150.2.1580.5 KB2026-10-150.2.0579.9 KB2026-09-150.1.1576.6 KB2026-09-12
Version
0.2.2
Copyright
Rollpie, Irohabook
Publisher
math
Published
2026-10-15
Size
572.8 KB
Downloads
28
Checksum
ce26f898ba26eb49c71ebc68597f62f268b83e41bb265b1b5a01688966054588
Dependencies
None

geometry.rs

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
98
99
100
101
//! Compares the vertical positions of delimiters and their content as numbers

use suki::font::{self, Font};
use suki::layout::{Content, Placed};
use suki::node::Style;
use suki::{layout, parse};

fn main() {
    let loaded = font::load(std::fs::read("font/latinmodern-math.otf").unwrap()).unwrap();
    let units = font::units_per_em(&loaded);

    println!("Where each delimiter glyph puts its ink within its advance");

    for character in ['(', ')', '[', '{'] {
        let base = font::glyph_of(&loaded, character).unwrap();
        let mut glyphs = vec![base];

        if let Some(growth) = font::vertical_growth(&loaded, base) {
            glyphs.extend(growth.variant.iter().take(4).map(|variant| variant.glyph));
        }

        for glyph in glyphs {
            let drawn = font::outline_of(&loaded, glyph);
            let (left, _, right, _) = suki::outline::bounds(&drawn);
            let advance = font::advance(&loaded, glyph);
            println!(
                "  {character} glyph {glyph} advance {advance:.3} ink {:.3}..{:.3} \
left bearing {:.3} right bearing {:.3}",
                left / units,
                right / units,
                left / units,
                advance - right / units
            );
        }
    }

    for source in [
        r"\left( \frac{a}{b} \right)",
        r"\begin{pmatrix} a & b \\ c & d \end{pmatrix}",
        r"\begin{bmatrix} 12 & 3 \\ 4 & 56 \end{bmatrix}",
    ] {
        let node = parse(source).unwrap();
        let placed = layout::layout(&node, &loaded, 1.0, Style::Auto, true);
        let Content::Group(row) = &placed.content else {continue};
        let Content::Group(parts) = &row[0].layout.content else {continue};
        println!("\n{source}");
        println!("  math axis {:.3}", font::constant(&loaded).axis_height);

        for (index, part) in parts.iter().enumerate() {
            let name = match index {
                0 => "left delimiter",
                1 => "content",
                _ => "right delimiter",
            };
            report(name, part, &loaded);

            if index == 1 {
                if let Content::Group(cells) = &part.layout.content {
                    for cell in cells.iter().take(4) {
                        let ink = leftmost(&cell.layout, &loaded);
                        println!(
                            "      cell x {:.3} width {:.3} left edge of ink {:.3}",
                            part.x + cell.x,
                            cell.layout.width,
                            part.x + cell.x + ink
                        );
                    }
                }
            }
        }
    }
}

/// The leftmost position of ink within a group
fn leftmost(placed: &suki::layout::Layout, loaded: &Font) -> f64 {
    match &placed.content {
        Content::Glyph {glyph, size, ..} => font::bearing(loaded, *glyph).0 * size,
        Content::Group(children) => children
            .first()
            .map_or(0.0, |child| child.x + leftmost(&child.layout, loaded)),
        Content::Rule => 0.0,
    }
}


fn report(name: &str, part: &Placed, loaded: &Font) {
    let top = part.y - part.layout.height;
    let bottom = part.y + part.layout.depth;
    let middle = (top + bottom) / 2.0;
    let ink = match &part.layout.content {
        Content::Glyph {glyph, ..} => {
            let (height, depth) = font::extent(loaded, *glyph);
            format!(" glyph {glyph} ink {:.3}..{:.3}", -height, depth)
        }
        _ => String::new(),
    };
    println!(
        "  {name} x {:.3} width {:.3} top {top:.3} bottom {bottom:.3} middle {middle:.3}{ink}",
        part.x, part.layout.width
    );
}