1use crate::units::{Emu, HalfPoint, Twips};
4
5#[derive(Debug, Clone, Copy, PartialEq)]
7pub struct Length {
8 emu: i64,
9}
10
11impl Length {
12 pub fn inches(val: f64) -> Self {
14 Length {
15 emu: (val * 914400.0) as i64,
16 }
17 }
18
19 pub fn cm(val: f64) -> Self {
21 Length {
22 emu: (val * 360000.0) as i64,
23 }
24 }
25
26 pub fn mm(val: f64) -> Self {
28 Length {
29 emu: (val * 36000.0) as i64,
30 }
31 }
32
33 pub fn pt(val: f64) -> Self {
35 Length {
36 emu: (val * 12700.0) as i64,
37 }
38 }
39
40 pub fn emu(val: i64) -> Self {
42 Length { emu: val }
43 }
44
45 pub fn twips(val: i32) -> Self {
47 Length {
48 emu: val as i64 * 635,
49 }
50 }
51
52 pub fn to_inches(self) -> f64 {
54 self.emu as f64 / 914400.0
55 }
56
57 pub fn to_cm(self) -> f64 {
59 self.emu as f64 / 360000.0
60 }
61
62 pub fn to_pt(self) -> f64 {
64 self.emu as f64 / 12700.0
65 }
66
67 pub fn to_emu(self) -> i64 {
69 self.emu
70 }
71
72 pub fn to_twips(self) -> i32 {
74 (self.emu / 635) as i32
75 }
76
77 pub fn as_twips(self) -> Twips {
79 Twips(self.to_twips())
80 }
81
82 pub fn as_emu(self) -> Emu {
84 Emu(self.emu)
85 }
86
87 pub fn as_half_points(self) -> HalfPoint {
89 HalfPoint((self.to_pt() * 2.0) as u32)
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96
97 #[test]
98 fn length_conversions() {
99 let one_inch = Length::inches(1.0);
100 assert!((one_inch.to_inches() - 1.0).abs() < 0.001);
101 assert!((one_inch.to_cm() - 2.54).abs() < 0.01);
102 assert!((one_inch.to_pt() - 72.0).abs() < 0.01);
103 assert_eq!(one_inch.to_twips(), 1440);
104 }
105
106 #[test]
107 fn length_from_pt() {
108 let twelve_pt = Length::pt(12.0);
109 assert_eq!(twelve_pt.as_half_points().0, 24);
110 }
111
112 #[test]
113 fn length_float_constructors_truncate_toward_zero() {
114 assert_eq!(Length::inches(1.75 / 914400.0).to_emu(), 1);
115 assert_eq!(Length::inches(-1.75 / 914400.0).to_emu(), -1);
116 assert_eq!(Length::cm(1.75 / 360000.0).to_emu(), 1);
117 assert_eq!(Length::cm(-1.75 / 360000.0).to_emu(), -1);
118 assert_eq!(Length::pt(1.75 / 12700.0).to_emu(), 1);
119 assert_eq!(Length::pt(-1.75 / 12700.0).to_emu(), -1);
120
121 assert_eq!(Length::emu(7).to_emu(), 7);
122 assert_eq!(Length::emu(-7).to_emu(), -7);
123 assert_eq!(Length::twips(7).to_emu(), 4445);
124 assert_eq!(Length::twips(-7).to_emu(), -4445);
125 }
126
127 #[test]
128 fn length_millimetres_round_trip() {
129 assert_eq!(Length::mm(25.4).to_emu(), 914_400);
130 assert_eq!(Length::mm(1.75 / 36_000.0).to_emu(), 1);
131 assert_eq!(Length::mm(-1.75 / 36_000.0).to_emu(), -1);
132 }
133}