Skip to main content

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