Registry / RepositoryTypeScriptRustPython
Rollpie
ReadmeFiles
Versions
Info
Download
0.2.0579.9 KB2026-09-150.1.1576.6 KB2026-09-12
Version
0.2.0
Copyright
Rollpie, Irohabook
Publisher
math
Published
2026-09-15
Size
579.9 KB
Downloads
2
Checksum
58312d92e63a92784e82a974317afd849e59d143a6320c3cc62faa0980834a7b
Dependencies
None

metric.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
//! 組み上げた式の寸法
//!
//! 書き出さずに大きさだけ知りたいとき、たとえば置き場所を先に空けておきたいときに使う。
//! 単位は em で、まわりの文字サイズを 1 とする。

use crate::error::Error;
use crate::font::Font;
use crate::layout;
use crate::node::{Node, Style};
use crate::parse;


/// 式が占める大きさ
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Size {
    /// 送り幅
    pub width: f64,
    /// ベースラインから上
    pub height: f64,
    /// ベースラインから下
    pub depth: f64,
}


/// 構文木の寸法
pub fn size_of(node: &Node, font: &Font, display: bool) -> Size {
    let placed = layout::layout(node, font, 1.0, Style::Auto, display);

    Size {width: placed.width, height: placed.height, depth: placed.depth}
}


/// LaTeX の文字列の寸法。囲みが付いていればそれが組み方を決める
pub fn size_of_source(source: &str, font: &Font, display: bool) -> Result<Size, Error> {
    let (node, wrapper) = parse::parse_wrapped(source)?;

    Ok(size_of(&node, font, parse::display_of(wrapper, display)))
}


#[cfg(test)]
mod tests {
    use super::*;
    use crate::font;

    fn sample() -> Font {
        let data = std::fs::read("font/latinmodern-math.otf").expect("試験用のフォントを読めません");

        font::load(data).unwrap()
    }

    #[test]
    fn a_longer_formula_is_wider() {
        let font = sample();
        let short = size_of_source("x", &font, false).unwrap();
        let long = size_of_source("x + y + z", &font, false).unwrap();
        assert!(long.width > short.width);
    }

    #[test]
    fn a_fraction_has_height_and_depth() {
        let font = sample();
        let found = size_of_source(r"\frac{a}{b}", &font, false).unwrap();
        assert!(found.height > 0.4);
        assert!(found.depth > 0.1);
    }

    #[test]
    fn a_wrapper_changes_the_size() {
        let font = sample();
        let inline = size_of_source(r"\sum_{k=1}^{n}", &font, false).unwrap();
        let wrapped = size_of_source(r"$$\sum_{k=1}^{n}$$", &font, false).unwrap();
        assert!(wrapped.height > inline.height, "囲みが効いていません");
    }

    #[test]
    fn a_broken_formula_reports_its_place() {
        let font = sample();
        assert!(size_of_source("{x", &font, false).is_err());
    }
}