1use std::fmt::Write;
6
7pub trait FontFormat: Sized {
9 const DEFAULT_FILE_EXTENSION: &'static str;
10 type Error: std::error::Error + 'static;
11
12 fn parse(b: &[u8]) -> Result<Self, Self::Error>;
14}
15
16#[derive(Default, PartialEq, Eq, Debug, Copy, Clone, PartialOrd, Ord, Hash)]
26#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
27pub struct Scaled(pub i32);
28
29impl Scaled {
30 pub const ZERO: Scaled = Scaled(0);
32
33 pub const ONE: Scaled = Scaled(1 << 16);
35
36 pub const TWO: Scaled = Scaled(1 << 17);
38
39 pub const MAX_DIMEN: Scaled = Scaled((1 << 30) - 1);
45
46 pub fn from_integer(i: i32) -> Result<Scaled, OverflowError> {
51 if i >= (1 << 14) || i <= -(1 << 14) {
52 Err(OverflowError {})
53 } else {
54 Ok(Scaled(Scaled::ONE.0 * i))
55 }
56 }
57
58 pub fn from_decimal_digits(digits: &[u8]) -> Scaled {
62 let mut a = 0;
63 for d in digits.iter().rev() {
64 a = (a + (*d as i32) * Scaled::TWO.0) / 10
65 }
66 Scaled((a + 1) / 2)
67 }
68
69 pub fn new(
73 integer_part: i32,
74 fractional_part: Scaled,
75 scaled_unit: ScaledUnit,
76 ) -> Result<Scaled, OverflowError> {
77 if scaled_unit == ScaledUnit::ScaledPoint {
78 return if integer_part > Scaled::MAX_DIMEN.0 {
79 Err(OverflowError)
80 } else {
81 Ok(Scaled(integer_part))
83 };
84 }
85 let (n, d) = scaled_unit.conversion_fraction();
86 let (Scaled(i), Scaled(remainder)) = Scaled(integer_part).xn_over_d(n, d)?;
88 let f =
89 fractional_part.nx_plus_y(n, Scaled::from_integer(remainder).expect("remainder<d<=7200<2^13, so a valid scaled number"))
90 .expect("fractional_part<2^16, remainder<2^16*d, so nx_plus_y<2^16(n+d). Each (n,d) makes this <2^30")
91 / d;
92 let integer_part = Scaled::from_integer(i + f.integer_part())?;
93 Ok(integer_part + f.fractional_part())
94 }
95
96 pub fn xn_over_d(&self, n: i32, d: i32) -> Result<(Scaled, Scaled), OverflowError> {
107 debug_assert!(n <= 0o200000);
108 debug_assert!(d <= 0o200000);
109 let mut b: i64 = self.0.into();
110 b *= n as i64; let remainder: i32 = (b % (d as i64)).try_into().expect("d<=2^16 so b%d<2^16");
112 b /= d as i64;
113 if b < -(Scaled::MAX_DIMEN.0 as i64) || b > Scaled::MAX_DIMEN.0 as i64 {
114 return Err(OverflowError {});
115 }
116 let b: i32 = b.try_into().expect("b in (-2^30, +2^30)");
117 Ok((Scaled(b), Scaled(remainder)))
118 }
119
120 pub fn nx_plus_y(self, mut n: i32, y: Scaled) -> Result<Scaled, OverflowError> {
122 let max_answer = Scaled::MAX_DIMEN;
123 if n == 0 {
124 return Ok(y);
125 }
126 let mut x = self;
127 if n < 0 {
128 n = -n;
129 x = -x;
130 }
131 if x <= (max_answer - y) / n && -x <= (max_answer + y) / n {
132 Ok(x * n + y)
133 } else {
134 Err(OverflowError {})
135 }
136 }
137
138 pub fn integer_part(self) -> i32 {
139 self.0 / Scaled::ONE.0
140 }
141
142 pub fn fractional_part(self) -> Scaled {
143 self % Scaled::ONE.0
144 }
145
146 pub fn abs(self) -> Scaled {
147 Scaled(self.0.abs())
148 }
149
150 pub fn wrapping_add(self, rhs: Scaled) -> Self {
151 Scaled(self.0.wrapping_add(rhs.0))
152 }
153 pub fn checked_add(self, rhs: Scaled) -> Option<Self> {
154 Some(Scaled(self.0.checked_add(rhs.0)?))
155 }
156 pub fn wrapping_mul(self, rhs: i32) -> Self {
157 Scaled(self.0.wrapping_mul(rhs))
158 }
159 pub fn checked_mul(self, rhs: i32) -> Option<Self> {
160 self.nx_plus_y(rhs, Scaled::ZERO).ok()
163 }
164 pub fn checked_div(self, rhs: i32) -> Option<Self> {
165 Some(Scaled(self.0.checked_div(rhs)?))
166 }
167 pub fn display_no_units(self) -> impl std::fmt::Display {
169 struct D {
170 s: Scaled,
171 }
172 impl std::fmt::Display for D {
173 fn fmt(&self, fm: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
174 if self.s.0 < 0 {
175 write!(fm, "-")?;
176 }
177 write!(fm, "{}.", self.s.integer_part().abs())?;
178 let mut f = self.s.abs().fractional_part() * 10 + Scaled(5);
180 let mut delta = Scaled(10);
181 loop {
182 if delta > Scaled::ONE {
183 f += Scaled(0o100000 - 50000);
185 }
186 fm.write_char(
187 char::from_digit(f.integer_part().try_into().unwrap(), 10).unwrap(),
188 )?;
189 f = f.fractional_part() * 10;
190 delta = delta * 10;
191 if f <= delta {
192 break;
193 }
194 }
195 Ok(())
196 }
197 }
198 D { s: self }
199 }
200}
201
202#[derive(Debug)]
203pub struct OverflowError;
204
205impl std::fmt::Display for Scaled {
206 fn fmt(&self, fm: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
207 write!(fm, "{}", self.display_no_units())?;
209 write!(fm, "pt")?;
211 Ok(())
212 }
213}
214
215impl std::iter::Sum for Scaled {
216 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
217 Self(iter.map(|s| s.0).sum())
218 }
219}
220
221impl std::ops::Add<Scaled> for Scaled {
222 type Output = Scaled;
223 fn add(self, rhs: Scaled) -> Self::Output {
224 Scaled(self.0 + rhs.0)
225 }
226}
227
228impl std::ops::AddAssign<Scaled> for Scaled {
229 fn add_assign(&mut self, rhs: Scaled) {
230 self.0 += rhs.0;
231 }
232}
233impl std::ops::Sub<Scaled> for Scaled {
234 type Output = Scaled;
235 fn sub(self, rhs: Scaled) -> Self::Output {
236 Scaled(self.0 - rhs.0)
237 }
238}
239
240impl std::ops::Mul<i32> for Scaled {
241 type Output = Scaled;
242 fn mul(self, rhs: i32) -> Self::Output {
243 Scaled(self.0 * rhs)
244 }
245}
246
247impl std::ops::Div<i32> for Scaled {
248 type Output = Scaled;
249 fn div(self, rhs: i32) -> Self::Output {
250 Scaled(self.0 / rhs)
251 }
252}
253
254impl std::ops::DivAssign<i32> for Scaled {
255 fn div_assign(&mut self, rhs: i32) {
256 self.0 = self.0 / rhs
257 }
258}
259
260impl std::ops::Rem<i32> for Scaled {
261 type Output = Scaled;
262 fn rem(self, rhs: i32) -> Self::Output {
263 Scaled(self.0 % rhs)
264 }
265}
266
267impl std::ops::Neg for Scaled {
268 type Output = Scaled;
269 fn neg(self) -> Self::Output {
270 Scaled(-self.0)
271 }
272}
273
274#[derive(Debug, Clone, Copy, PartialEq, Eq)]
278pub enum ScaledUnit {
279 Point,
280 Pica,
281 Inch,
282 BigPoint,
283 Centimeter,
284 Millimeter,
285 DidotPoint,
286 Cicero,
287 ScaledPoint,
288}
289
290impl ScaledUnit {
291 pub fn parse(s: &str) -> Option<Self> {
296 use ScaledUnit::*;
297 Some(match s {
298 "pt" => Point,
299 "pc" => Pica,
300 "in" => Inch,
301 "bp" => BigPoint,
302 "cm" => Centimeter,
303 "mm" => Millimeter,
304 "dd" => DidotPoint,
305 "cc" => Cicero,
306 "sp" => ScaledPoint,
307 _ => return None,
308 })
309 }
310
311 pub fn conversion_fraction(&self) -> (i32, i32) {
319 use ScaledUnit::*;
320 match self {
321 Point => (1, 1),
322 Pica => (12, 1),
323 Inch => (7227, 100),
324 BigPoint => (7227, 7200),
325 Centimeter => (7227, 254),
326 Millimeter => (7227, 2540),
327 DidotPoint => (1238, 1157),
328 Cicero => (14856, 1157),
329 ScaledPoint => (1, 1 << 16),
330 }
331 }
332}
333
334#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
345#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
346pub struct Glue {
347 pub width: Scaled,
348 pub stretch: Scaled,
349 pub stretch_order: GlueOrder,
350 pub shrink: Scaled,
351 pub shrink_order: GlueOrder,
352}
353
354impl std::ops::Mul<i32> for Glue {
355 type Output = Glue;
356 fn mul(self, rhs: i32) -> Self::Output {
357 Glue {
358 width: self.width * rhs,
359 stretch: self.stretch * rhs,
360 stretch_order: self.stretch_order,
361 shrink: self.shrink * rhs,
362 shrink_order: self.shrink_order,
363 }
364 }
365}
366
367impl Glue {
368 pub fn wrapping_add(self, rhs: Glue) -> Self {
370 use std::cmp::Ordering::*;
371 Glue {
372 width: self.width.wrapping_add(rhs.width),
373 stretch: match self.stretch_order.cmp(&rhs.stretch_order) {
374 Less => rhs.stretch,
375 Equal => self.stretch.wrapping_add(rhs.stretch),
376 Greater => self.stretch,
377 },
378 stretch_order: self.stretch_order.max(rhs.stretch_order),
379 shrink: match self.shrink_order.cmp(&rhs.shrink_order) {
380 Less => rhs.shrink,
381 Equal => self.shrink.wrapping_add(rhs.shrink),
382 Greater => self.shrink,
383 },
384 shrink_order: self.shrink_order.max(rhs.shrink_order),
385 }
386 }
387 pub fn checked_add(self, rhs: Glue) -> Option<Self> {
388 use std::cmp::Ordering::*;
389 Some(Glue {
390 width: self.width.checked_add(rhs.width)?,
391 stretch: match self.stretch_order.cmp(&rhs.stretch_order) {
392 Less => rhs.stretch,
393 Equal => self.stretch.checked_add(rhs.stretch)?,
394 Greater => self.stretch,
395 },
396 stretch_order: self.stretch_order.max(rhs.stretch_order),
397 shrink: match self.shrink_order.cmp(&rhs.shrink_order) {
398 Less => rhs.shrink,
399 Equal => self.shrink.checked_add(rhs.shrink)?,
400 Greater => self.shrink,
401 },
402 shrink_order: self.shrink_order.max(rhs.shrink_order),
403 })
404 }
405 pub fn checked_mul(self, rhs: i32) -> Option<Self> {
406 Some(Glue {
407 width: self.width.checked_mul(rhs)?,
408 stretch: self.stretch.checked_mul(rhs)?,
409 stretch_order: self.stretch_order,
410 shrink: self.shrink.checked_mul(rhs)?,
411 shrink_order: self.shrink_order,
412 })
413 }
414 pub fn wrapping_mul(self, rhs: i32) -> Self {
415 Glue {
416 width: self.width.wrapping_mul(rhs),
417 stretch: self.stretch.wrapping_mul(rhs),
418 stretch_order: self.stretch_order,
419 shrink: self.shrink.wrapping_mul(rhs),
420 shrink_order: self.shrink_order,
421 }
422 }
423 pub fn checked_div(self, rhs: i32) -> Option<Self> {
424 Some(Glue {
425 width: self.width.checked_div(rhs)?,
426 stretch: self.stretch.checked_div(rhs)?,
427 stretch_order: self.stretch_order,
428 shrink: self.shrink.checked_div(rhs)?,
429 shrink_order: self.shrink_order,
430 })
431 }
432}
433
434impl std::fmt::Display for Glue {
435 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
437 write!(f, "{}", self.width)?;
438 if self.stretch != Scaled::ZERO {
439 write!(f, " plus ")?;
440 write!(f, "{}", self.stretch.display_no_units())?;
441 write!(f, "{}", self.stretch_order)?;
442 }
443 if self.shrink != Scaled::ZERO {
444 write!(f, " minus ")?;
445 write!(f, "{}", self.shrink.display_no_units())?;
446 write!(f, "{}", self.shrink_order)?;
447 }
448 Ok(())
449 }
450}
451
452#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, PartialOrd, Ord)]
465#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
466pub enum GlueOrder {
467 #[default]
468 Normal,
469 Fil,
470 Fill,
471 Filll,
472}
473
474impl GlueOrder {
475 pub fn parse(s: &str) -> Option<Self> {
477 use GlueOrder::*;
478 Some(match s {
479 "fil" => Fil,
480 "fill" => Fill,
481 "filll" => Filll,
482 _ => return None,
483 })
484 }
485 pub fn inf_str(&self) -> Option<&'static str> {
486 use GlueOrder::*;
487 match self {
488 Normal => None,
489 Fil => Some("fil"),
490 Fill => Some("fill"),
491 Filll => Some("filll"),
492 }
493 }
494 pub fn next(&self) -> Option<Self> {
496 use GlueOrder::*;
497 match self {
498 Normal => Some(Fil),
499 Fil => Some(Fill),
500 Fill => Some(Filll),
501 Filll => None,
502 }
503 }
504}
505
506impl std::fmt::Display for GlueOrder {
507 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
508 write!(f, "{}", self.inf_str().unwrap_or("pt"))
509 }
510}
511
512#[cfg(test)]
513mod tests {
514 use super::*;
515
516 #[test]
517 fn type_sizes() {
518 assert_eq!(16, std::mem::size_of::<Glue>());
519 }
520}