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());
}
}