Skip to main content

rustyfi_pdf/
base14.rs

1//! Base-14 Helvetica metrics (advance widths transcribed from the freely
2//! redistributable Adobe Core-14 AFM files), covering ASCII 32–126. No font
3//! files are parsed — advances come from this fixed table.
4
5use rustyfi_backend::{FontKey, FontMetrics, Length};
6
7pub(crate) const FONT_BOLD: FontKey = FontKey(1);
8
9/// PostScript base font names, indexed by `FontKey`.
10pub(crate) const BASE_FONT_NAMES: [&str; 3] = ["Helvetica", "Helvetica-Bold", "Helvetica-Oblique"];
11
12/// Helvetica advance widths for chars 32..=126, in 1/1000 em.
13/// (Helvetica-Oblique shares these.)
14#[rustfmt::skip]
15const HELVETICA: [u16; 95] = [
16    278, 278, 355, 556, 556, 889, 667, 191, 333, 333, // ' ' ! " # $ % & ' ( )
17    389, 584, 278, 333, 278, 278,                     // * + , - . /
18    556, 556, 556, 556, 556, 556, 556, 556, 556, 556, // 0-9
19    278, 278, 584, 584, 584, 556, 1015,               // : ; < = > ? @
20    667, 667, 722, 722, 667, 611, 778, 722, 278, 500, // A-J
21    667, 556, 833, 722, 778, 667, 778, 722, 667, 611, // K-T
22    722, 667, 944, 667, 667, 611,                     // U-Z
23    278, 278, 278, 469, 556, 333,                     // [ \ ] ^ _ `
24    556, 556, 500, 556, 556, 278, 556, 556, 222, 222, // a-j
25    500, 222, 833, 556, 556, 556, 556, 333, 500, 278, // k-t
26    556, 500, 722, 500, 500, 500,                     // u-z
27    334, 260, 334, 584,                               // { | } ~
28];
29
30/// Helvetica-Bold advance widths for chars 32..=126, in 1/1000 em.
31#[rustfmt::skip]
32const HELVETICA_BOLD: [u16; 95] = [
33    278, 333, 474, 556, 556, 889, 722, 238, 333, 333, // ' ' ! " # $ % & ' ( )
34    389, 584, 278, 333, 278, 278,                     // * + , - . /
35    556, 556, 556, 556, 556, 556, 556, 556, 556, 556, // 0-9
36    333, 333, 584, 584, 584, 611, 975,                // : ; < = > ? @
37    722, 722, 722, 722, 667, 611, 778, 722, 278, 556, // A-J
38    722, 611, 833, 722, 778, 667, 778, 722, 667, 611, // K-T
39    722, 667, 944, 667, 667, 611,                     // U-Z
40    333, 278, 333, 584, 556, 333,                     // [ \ ] ^ _ `
41    556, 611, 556, 611, 556, 333, 611, 611, 278, 278, // a-j
42    556, 278, 889, 611, 611, 611, 611, 389, 556, 333, // k-t
43    611, 556, 778, 556, 556, 500,                     // u-z
44    389, 280, 389, 584,                               // { | } ~
45];
46
47/// Font-wide vertical metrics from the AFMs, in 1/1000 em.
48const ASCENDER: f64 = 718.0;
49const DESCENDER: f64 = 207.0;
50
51pub struct Base14Metrics;
52
53impl Base14Metrics {
54    fn widths(font: FontKey) -> &'static [u16; 95] {
55        match font {
56            FONT_BOLD => &HELVETICA_BOLD,
57            _ => &HELVETICA,
58        }
59    }
60}
61
62impl FontMetrics for Base14Metrics {
63    fn advance(&self, font: FontKey, c: char, size: Length) -> Option<Length> {
64        let code = c as u32;
65        if !(32..=126).contains(&code) {
66            return None;
67        }
68        let per_mille = Self::widths(font)[(code - 32) as usize] as f64;
69        Some(size * (per_mille / 1000.0))
70    }
71
72    fn ascender(&self, _font: FontKey, size: Length) -> Length {
73        size * (ASCENDER / 1000.0)
74    }
75
76    fn descender(&self, _font: FontKey, size: Length) -> Length {
77        size * (DESCENDER / 1000.0)
78    }
79}