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}