Skip to main content

lopdf/
font.rs

1/// This struct represents the data of a font.
2/// It contains information about the font's bounding box, ascent, descent, cap height, italic angle, and stemV.
3/// Reference: https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/pdfreference1.5_v6.pdf
4#[derive(Debug, Clone)]
5pub struct FontData {
6    /// (Required) The PostScript name of the font. This should be the same as the value of BaseFont in the font or
7    /// CIDFont dictionary that refers to this font descriptor.
8    pub font_name: String,
9    /// (Required) A collection of flags defining various characteristics of the font.
10    pub flags: i64,
11    /// (Required, except for Type 3 fonts) A rectangle (see Section 3.8.4, “Rectangles”), expressed in the glyph
12    /// coordinate system, specifying the font bounding box. This is the smallest rectangle enclosing the shape that
13    /// would result if all of the glyphs of the font were placed with their origins coincident and then filled.
14    /// Format as: (x_min, y_min, x_max, y_max).
15    pub font_bbox: (i64, i64, i64, i64),
16    /// (Required) The angle, expressed in degrees counterclockwise from the vertical, of the dominant vertical strokes
17    /// of the font. (For example, the 9-o’clock position is 90 degrees, and the 3-o’clock position is –90 degrees.)
18    /// The value is negative for fonts that slope to the right, as almost all italic fonts do.
19    pub italic_angle: i64,
20    /// (Required, except for Type 3 fonts) The maximum height above the baseline reached by glyphs in this font,
21    /// excluding the height of glyphs for accentedc haracters.
22    pub ascent: i64,
23    /// (Required, except for Type 3 fonts) The maximum depth below the baseline reached by glyphs in this font. The
24    /// value is a negative number.
25    pub descent: i64,
26    /// (Required for fonts that have Latin characters, except for Type 3 fonts) The vertical coordinate of the top of
27    /// flat capital letters, measured from the baseline.
28    pub cap_height: i64,
29    /// (Required, except for Type 3 fonts) The thickness, measured horizontally, of the dominant vertical stems of
30    /// glyphs in the font.
31    pub stem_v: i64,
32    /// (Required) The name of a predefined CMap, or a stream containing a CMap program, that maps character codes to
33    /// font numbers and CIDs. If the descendant is a Type 2 CIDFont whose associated TrueType font program is not
34    /// embedded in the PDF file, the Encoding entry must be a predefined CMap name Read more (page 422): https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/pdfreference1.5_v6.pdf
35    pub encoding: String,
36    /// Size of the font data in bytes.
37    /// This is used to set the `Length1` key in the font stream dictionary.
38    font: Vec<u8>,
39}
40
41/// This struct is used to store font metadata extracted from a TrueType Fonts (TTF) file.
42/// # Examples
43///
44/// ```no_run
45/// // Read a TrueType Fonts (TTF) file.
46/// let font_file = std::fs::read("./SomeFont.ttf").unwrap();
47///
48/// // Create a new FontData instance.
49/// let font_name = "SomeFont".to_string();
50/// let font_data = lopdf::FontData::new(&font_file, font_name);
51/// ```
52///
53/// Also provides methods to set various font properties such as bounding box, italic angle, ascent, descent, and stemV.
54/// # Examples
55///
56/// ```no_run
57/// let font_file = std::fs::read("./SomeFont.ttf").unwrap();
58///
59/// // Create a new FontData instance along custome value.
60/// let font_data = lopdf::FontData::new(&font_file, "SomeFont".to_string())
61///                     .set_stem_v(100)
62///                     .set_italic_angle(10);
63/// ```
64impl FontData {
65    /// Create a new `FontData` instance by parsing the provided TTF file.
66    /// The TTF file is expected to be in bytes.
67    pub fn new(font_file: &[u8], font_name: String) -> Self {
68        // Parse the TTF file using ttf_parser crate
69        let font = ttf_parser::Face::parse(font_file, 0).expect("Failed to parse font file");
70
71        // Extract font metadata
72        // Note: The ttf_parser crate provides methods to get font bounding box, ascent, descent, cap height, italic
73        // angle, and stemV.
74        let font_bbox = font.global_bounding_box();
75        let ascent = font.ascender();
76        let descent = font.descender();
77        let cap_height = font.capital_height().unwrap_or(ascent);
78        let italic_angle = font.italic_angle();
79        let flags = 1; // Default flags, can be modified later if needed
80
81        // Calculate stemV based on the font bounding box
82        // Reference: https://stackoverflow.com/questions/35485179/stemv-value-of-the-truetype-font
83        // The stemV is typically calculated as 13% of the font's bbox width value.
84        let stem_v = (font_bbox.width() as f64 * 0.13).round() as i64;
85
86        Self {
87            font_name,
88            flags,
89            font_bbox: (
90                font_bbox.x_min as i64,
91                font_bbox.y_min as i64,
92                font_bbox.x_max as i64,
93                font_bbox.y_max as i64,
94            ),
95            italic_angle: italic_angle.round() as i64,
96            ascent: ascent as i64,
97            descent: descent as i64,
98            cap_height: cap_height as i64,
99            stem_v,
100            encoding: "WinAnsiEncoding".to_string(), // Default encoding, can be modified later if needed
101            font: font_file.to_vec(),
102        }
103    }
104
105    pub fn set_flags(&mut self, flags: i64) -> &mut Self {
106        self.flags = flags;
107        self
108    }
109
110    pub fn set_font_bbox(&mut self, font_bbox: (i64, i64, i64, i64)) -> &mut Self {
111        self.font_bbox = font_bbox;
112        self
113    }
114
115    pub fn set_italic_angle(&mut self, italic_angle: i64) -> &mut Self {
116        self.italic_angle = italic_angle;
117        self
118    }
119
120    pub fn set_ascent(&mut self, ascent: i64) -> &mut Self {
121        self.ascent = ascent;
122        self
123    }
124
125    pub fn set_descent(&mut self, descent: i64) -> &mut Self {
126        self.descent = descent;
127        self
128    }
129
130    pub fn set_cap_height(&mut self, cap_height: i64) -> &mut Self {
131        self.cap_height = cap_height;
132        self
133    }
134
135    pub fn set_stem_v(&mut self, stem_v: i64) -> &mut Self {
136        self.stem_v = stem_v;
137        self
138    }
139
140    pub fn set_encoding(&mut self, encoding: String) -> &mut Self {
141        self.encoding = encoding;
142        self
143    }
144
145    pub fn bytes(&self) -> Vec<u8> {
146        self.font.clone()
147    }
148}