pdfium_render/pdf/font.rs
1//! Defines the [PdfFont] struct, exposing functionality related to a single font used to
2//! render text in a `PdfDocument`.
3
4pub mod glyph;
5pub mod glyphs;
6
7use crate::bindgen::{FPDF_FONT, FPDF_FONT_TRUETYPE, FPDF_FONT_TYPE1};
8use crate::bindings::PdfiumLibraryBindings;
9use crate::error::{PdfiumError, PdfiumInternalError};
10use crate::pdf::document::fonts::PdfFontBuiltin;
11use crate::pdf::document::PdfDocument;
12use crate::pdf::font::glyphs::PdfFontGlyphs;
13use crate::pdf::points::PdfPoints;
14use crate::utils::mem::create_byte_buffer;
15use bitflags::bitflags;
16use std::io::Read;
17use std::os::raw::{c_char, c_int, c_uint};
18
19#[cfg(not(target_arch = "wasm32"))]
20use std::fs::File;
21
22#[cfg(not(target_arch = "wasm32"))]
23use std::path::Path;
24
25#[cfg(target_arch = "wasm32")]
26use wasm_bindgen::JsCast;
27
28#[cfg(target_arch = "wasm32")]
29use wasm_bindgen_futures::JsFuture;
30
31#[cfg(target_arch = "wasm32")]
32use js_sys::{ArrayBuffer, Uint8Array};
33
34#[cfg(target_arch = "wasm32")]
35use web_sys::{window, Blob, Response};
36
37// The following dummy declaration is used only when running cargo doc.
38// It allows documentation of WASM-specific functionality to be included
39// in documentation generated on non-WASM targets.
40
41#[cfg(doc)]
42struct Blob;
43
44bitflags! {
45 pub(crate) struct FpdfFontDescriptorFlags: u32 {
46 const FIXED_PITCH_BIT_1 = 0b00000000000000000000000000000001;
47 const SERIF_BIT_2 = 0b00000000000000000000000000000010;
48 const SYMBOLIC_BIT_3 = 0b00000000000000000000000000000100;
49 const SCRIPT_BIT_4 = 0b00000000000000000000000000001000;
50 const NON_SYMBOLIC_BIT_6 = 0b00000000000000000000000000100000;
51 const ITALIC_BIT_7 = 0b00000000000000000000000001000000;
52 const ALL_CAP_BIT_17 = 0b00000000000000010000000000000000;
53 const SMALL_CAP_BIT_18 = 0b00000000000000100000000000000000;
54 const FORCE_BOLD_BIT_19 = 0b00000000000001000000000000000000;
55 }
56}
57
58/// The weight of a [PdfFont]. Typical values are 400 (normal) and 700 (bold).
59#[derive(Copy, Clone, Debug, PartialEq)]
60pub enum PdfFontWeight {
61 Weight100,
62 Weight200,
63 Weight300,
64 Weight400Normal,
65 Weight500,
66 Weight600,
67 Weight700Bold,
68 Weight800,
69 Weight900,
70
71 /// Any font weight value that falls outside the typical 100 - 900 value range.
72 Custom(u32),
73}
74
75impl PdfFontWeight {
76 pub(crate) fn from_pdfium(value: c_int) -> Option<PdfFontWeight> {
77 match value {
78 -1 => None,
79 100 => Some(PdfFontWeight::Weight100),
80 200 => Some(PdfFontWeight::Weight200),
81 300 => Some(PdfFontWeight::Weight300),
82 400 => Some(PdfFontWeight::Weight400Normal),
83 500 => Some(PdfFontWeight::Weight500),
84 600 => Some(PdfFontWeight::Weight600),
85 700 => Some(PdfFontWeight::Weight700Bold),
86 800 => Some(PdfFontWeight::Weight800),
87 900 => Some(PdfFontWeight::Weight900),
88 other => Some(PdfFontWeight::Custom(other as u32)),
89 }
90 }
91}
92
93/// A single font used to render text in a [PdfDocument].
94///
95/// The PDF specification defines 14 built-in fonts that can be used in any PDF file without
96/// font embedding. Additionally, custom fonts can be directly embedded into any PDF file as
97/// a data stream.
98pub struct PdfFont<'a> {
99 built_in: Option<PdfFontBuiltin>,
100 handle: FPDF_FONT,
101 bindings: &'a dyn PdfiumLibraryBindings,
102 glyphs: PdfFontGlyphs<'a>,
103 is_font_memory_loaded: bool,
104}
105
106impl<'a> PdfFont<'a> {
107 #[inline]
108 pub(crate) fn from_pdfium(
109 handle: FPDF_FONT,
110 bindings: &'a dyn PdfiumLibraryBindings,
111 built_in: Option<PdfFontBuiltin>,
112 is_font_memory_loaded: bool,
113 ) -> Self {
114 PdfFont {
115 built_in,
116 handle,
117 bindings,
118 glyphs: PdfFontGlyphs::from_pdfium(handle, bindings),
119 is_font_memory_loaded,
120 }
121 }
122
123 /// Creates a new [PdfFont] from the given given built-in font argument.
124 ///
125 /// This function is now deprecated and will be removed in release 0.9.0.
126 /// Use the `PdfFonts::new_built_in()` function instead.
127 #[deprecated(
128 since = "0.8.1",
129 note = "This function has been moved. Use the PdfFonts::new_built_in() function instead."
130 )]
131 #[doc(hidden)]
132 #[inline]
133 pub fn new_built_in(document: &'a PdfDocument<'a>, font: PdfFontBuiltin) -> PdfFont<'a> {
134 Self::from_pdfium(
135 document
136 .bindings()
137 .FPDFText_LoadStandardFont(document.handle(), font.to_pdf_font_name()),
138 document.bindings(),
139 Some(font),
140 true,
141 )
142 }
143
144 /// Creates a new [PdfFont] for the built-in "Times-Roman" font.
145 ///
146 /// This function is now deprecated and will be removed in release 0.9.0.
147 /// Use the `PdfFonts::times_roman()` function instead.
148 #[deprecated(
149 since = "0.8.1",
150 note = "This function has been moved. Use the PdfFonts::times_roman() function instead."
151 )]
152 #[doc(hidden)]
153 #[inline]
154 pub fn times_roman(document: &'a PdfDocument<'a>) -> PdfFont<'a> {
155 #[allow(deprecated)]
156 Self::new_built_in(document, PdfFontBuiltin::TimesRoman)
157 }
158
159 /// Creates a new [PdfFont] for the built-in "Times-Bold" font.
160 ///
161 /// This function is now deprecated and will be removed in release 0.9.0.
162 /// Use the `PdfFonts::times_bold()` function instead.
163 #[deprecated(
164 since = "0.8.1",
165 note = "This function has been moved. Use the PdfFonts::times_bold() function instead."
166 )]
167 #[doc(hidden)]
168 #[inline]
169 pub fn times_bold(document: &'a PdfDocument<'a>) -> PdfFont<'a> {
170 #[allow(deprecated)]
171 Self::new_built_in(document, PdfFontBuiltin::TimesBold)
172 }
173
174 /// Creates a new [PdfFont] for the built-in "Times-Italic" font.
175 ///
176 /// This function is now deprecated and will be removed in release 0.9.0.
177 /// Use the `PdfFonts::times_italic()` function instead.
178 #[deprecated(
179 since = "0.8.1",
180 note = "This function has been moved. Use the PdfFonts::times_italic() function instead."
181 )]
182 #[doc(hidden)]
183 #[inline]
184 pub fn times_italic(document: &'a PdfDocument<'a>) -> PdfFont<'a> {
185 #[allow(deprecated)]
186 Self::new_built_in(document, PdfFontBuiltin::TimesItalic)
187 }
188
189 /// Creates a new [PdfFont] for the built-in "Times-BoldItalic" font.
190 ///
191 /// This function is now deprecated and will be removed in release 0.9.0.
192 /// Use the `PdfFonts::times_bold_italic()` function instead.
193 #[deprecated(
194 since = "0.8.1",
195 note = "This function has been moved. Use the PdfFonts::times_bold_italic() function instead."
196 )]
197 #[doc(hidden)]
198 #[inline]
199 pub fn times_bold_italic(document: &'a PdfDocument<'a>) -> PdfFont<'a> {
200 #[allow(deprecated)]
201 Self::new_built_in(document, PdfFontBuiltin::TimesBoldItalic)
202 }
203
204 /// Creates a new [PdfFont] for the built-in "Helvetica" font.
205 ///
206 /// This function is now deprecated and will be removed in release 0.9.0.
207 /// Use the `PdfFonts::helvetica()` function instead.
208 #[deprecated(
209 since = "0.8.1",
210 note = "This function has been moved. Use the PdfFonts::helvetica() function instead."
211 )]
212 #[doc(hidden)]
213 #[inline]
214 pub fn helvetica(document: &'a PdfDocument<'a>) -> PdfFont<'a> {
215 #[allow(deprecated)]
216 Self::new_built_in(document, PdfFontBuiltin::Helvetica)
217 }
218
219 /// Creates a new [PdfFont] for the built-in "Helvetica-Bold" font.
220 ///
221 /// This function is now deprecated and will be removed in release 0.9.0.
222 /// Use the `PdfFonts::helvetica_bold()` function instead.
223 #[deprecated(
224 since = "0.8.1",
225 note = "This function has been moved. Use the PdfFonts::helvetica_bold() function instead."
226 )]
227 #[doc(hidden)]
228 #[inline]
229 pub fn helvetica_bold(document: &'a PdfDocument<'a>) -> PdfFont<'a> {
230 #[allow(deprecated)]
231 Self::new_built_in(document, PdfFontBuiltin::HelveticaBold)
232 }
233
234 /// Creates a new [PdfFont] for the built-in "Helvetica-Oblique" font.
235 ///
236 /// This function is now deprecated and will be removed in release 0.9.0.
237 /// Use the `PdfFonts::helvetica_oblique()` function instead.
238 #[deprecated(
239 since = "0.8.1",
240 note = "This function has been moved. Use the PdfFonts::helvetica_oblique() function instead."
241 )]
242 #[doc(hidden)]
243 #[inline]
244 pub fn helvetica_oblique(document: &'a PdfDocument<'a>) -> PdfFont<'a> {
245 #[allow(deprecated)]
246 Self::new_built_in(document, PdfFontBuiltin::HelveticaOblique)
247 }
248
249 /// Creates a new [PdfFont] for the built-in "Helvetica-BoldOblique" font.
250 ///
251 /// This function is now deprecated and will be removed in release 0.9.0.
252 /// Use the `PdfFonts::helvetica_bold_oblique()` function instead.
253 #[deprecated(
254 since = "0.8.1",
255 note = "This function has been moved. Use the PdfFonts::helvetica_bold_oblique() function instead."
256 )]
257 #[doc(hidden)]
258 #[inline]
259 pub fn helvetica_bold_oblique(document: &'a PdfDocument<'a>) -> PdfFont<'a> {
260 #[allow(deprecated)]
261 Self::new_built_in(document, PdfFontBuiltin::HelveticaBoldOblique)
262 }
263
264 /// Creates a new [PdfFont] for the built-in "Courier" font.
265 ///
266 /// This function is now deprecated and will be removed in release 0.9.0.
267 /// Use the `PdfFonts::courier()` function instead.
268 #[deprecated(
269 since = "0.8.1",
270 note = "This function has been moved. Use the PdfFonts::courier() function instead."
271 )]
272 #[doc(hidden)]
273 #[inline]
274 pub fn courier(document: &'a PdfDocument<'a>) -> PdfFont<'a> {
275 #[allow(deprecated)]
276 Self::new_built_in(document, PdfFontBuiltin::Courier)
277 }
278
279 /// Creates a new [PdfFont] for the built-in "Courier-Bold" font.
280 ///
281 /// This function is now deprecated and will be removed in release 0.9.0.
282 /// Use the `PdfFonts::courier_bold()` function instead.
283 #[deprecated(
284 since = "0.8.1",
285 note = "This function has been moved. Use the PdfFonts::courier_bold() function instead."
286 )]
287 #[doc(hidden)]
288 #[inline]
289 pub fn courier_bold(document: &'a PdfDocument<'a>) -> PdfFont<'a> {
290 #[allow(deprecated)]
291 Self::new_built_in(document, PdfFontBuiltin::CourierBold)
292 }
293
294 /// Creates a new [PdfFont] for the built-in "Courier-Oblique" font.
295 ///
296 /// This function is now deprecated and will be removed in release 0.9.0.
297 /// Use the `PdfFonts::courier_oblique()` function instead.
298 #[deprecated(
299 since = "0.8.1",
300 note = "This function has been moved. Use the PdfFonts::courier_oblique() function instead."
301 )]
302 #[doc(hidden)]
303 #[inline]
304 pub fn courier_oblique(document: &'a PdfDocument<'a>) -> PdfFont<'a> {
305 #[allow(deprecated)]
306 Self::new_built_in(document, PdfFontBuiltin::CourierOblique)
307 }
308
309 /// Creates a new [PdfFont] for the built-in "Courier-BoldOblique" font.
310 ///
311 /// This function is now deprecated and will be removed in release 0.9.0.
312 /// Use the `PdfFonts::courier_bold_oblique()` function instead.
313 #[deprecated(
314 since = "0.8.1",
315 note = "This function has been moved. Use the PdfFonts::courier_bold_oblique() function instead."
316 )]
317 #[doc(hidden)]
318 #[inline]
319 pub fn courier_bold_oblique(document: &'a PdfDocument<'a>) -> PdfFont<'a> {
320 #[allow(deprecated)]
321 Self::new_built_in(document, PdfFontBuiltin::CourierBoldOblique)
322 }
323
324 /// Creates a new [PdfFont] for the built-in "Symbol" font.
325 ///
326 /// This function is now deprecated and will be removed in release 0.9.0.
327 /// Use the `PdfFonts::symbol()` function instead.
328 #[deprecated(
329 since = "0.8.1",
330 note = "This function has been moved. Use the PdfFonts::symbol() function instead."
331 )]
332 #[doc(hidden)]
333 #[inline]
334 pub fn symbol(document: &'a PdfDocument<'a>) -> PdfFont<'a> {
335 #[allow(deprecated)]
336 Self::new_built_in(document, PdfFontBuiltin::Symbol)
337 }
338
339 /// Creates a new [PdfFont] for the built-in "ZapfDingbats" font.
340 ///
341 /// This function is now deprecated and will be removed in release 0.9.0.
342 /// Use the `PdfFonts::zapf_dingbats()` function instead.
343 #[deprecated(
344 since = "0.8.1",
345 note = "This function has been moved. Use the PdfFonts::zapf_dingbats() function instead."
346 )]
347 #[doc(hidden)]
348 #[inline]
349 pub fn zapf_dingbats(document: &'a PdfDocument<'a>) -> PdfFont<'a> {
350 #[allow(deprecated)]
351 Self::new_built_in(document, PdfFontBuiltin::ZapfDingbats)
352 }
353
354 /// Attempts to load a Type 1 font file from the given file path.
355 ///
356 /// Set the `is_cid_font` parameter to `true` if the given font is keyed by
357 /// 16-bit character ID (CID), indicating that it supports an extended glyphset of
358 /// 65,535 glyphs. This is typically the case with fonts that support Asian character sets
359 /// or right-to-left languages.
360 ///
361 /// This function is not available when compiling to WASM. You have several options for
362 /// loading font data in WASM:
363 /// * Use the [PdfFonts::load_type1_from_fetch()] function to download font data from a
364 /// URL using the browser's built-in `fetch()` API. This function is only available when
365 /// compiling to WASM.
366 /// * Use the [PdfFonts::load_type1_from_blob()] function to load font data from a
367 /// Javascript File or Blob object (such as a File object returned from an HTML
368 /// `<input type="file">` element). This function is only available when compiling to WASM.
369 /// * Use the [PdfFonts::load_type1_from_reader()] function to load font data from any
370 /// valid Rust reader.
371 /// * Use another method to retrieve the bytes of the target font over the network,
372 /// then load those bytes into Pdfium using the [PdfFonts::new_type1_from_bytes()] function.
373 /// * Embed the bytes of the desired font directly into the compiled WASM module
374 /// using the `include_bytes!()` macro.
375 ///
376 /// This function is now deprecated and will be removed in release 0.9.0.
377 /// Use the `PdfFonts::load_type1_from_file()` function instead.
378 #[deprecated(
379 since = "0.8.1",
380 note = "This function has been moved. Use the PdfFonts::load_type1_from_file() function instead."
381 )]
382 #[doc(hidden)]
383 #[cfg(not(target_arch = "wasm32"))]
384 pub fn load_type1_from_file(
385 document: &'a PdfDocument<'a>,
386 path: &(impl AsRef<Path> + ?Sized),
387 is_cid_font: bool,
388 ) -> Result<PdfFont<'a>, PdfiumError> {
389 #[allow(deprecated)]
390 Self::load_type1_from_reader(
391 document,
392 File::open(path).map_err(PdfiumError::IoError)?,
393 is_cid_font,
394 )
395 }
396
397 /// Attempts to load a Type 1 font file from the given reader.
398 ///
399 /// Set the `is_cid_font` parameter to `true` if the given font is keyed by
400 /// 16-bit character ID (CID), indicating that it supports an extended glyphset of
401 /// 65,535 glyphs. This is typically the case with fonts that support Asian character sets
402 /// or right-to-left languages.
403 ///
404 /// This function is now deprecated and will be removed in release 0.9.0.
405 /// Use the `PdfFonts::load_type1_from_reader()` function instead.
406 #[deprecated(
407 since = "0.8.1",
408 note = "This function has been moved. Use the PdfFonts::load_type1_from_reader() function instead."
409 )]
410 #[doc(hidden)]
411 pub fn load_type1_from_reader(
412 document: &'a PdfDocument<'a>,
413 mut reader: impl Read,
414 is_cid_font: bool,
415 ) -> Result<PdfFont<'a>, PdfiumError> {
416 let mut bytes = Vec::new();
417
418 reader
419 .read_to_end(&mut bytes)
420 .map_err(PdfiumError::IoError)?;
421
422 #[allow(deprecated)]
423 Self::new_type1_from_bytes(document, bytes.as_slice(), is_cid_font)
424 }
425
426 /// Attempts to load a Type 1 font file from the given URL.
427 /// The Javascript `fetch()` API is used to download data over the network.
428 ///
429 /// Set the `is_cid_font` parameter to `true` if the given font is keyed by
430 /// 16-bit character ID (CID), indicating that it supports an extended glyphset of
431 /// 65,535 glyphs. This is typically the case with fonts that support Asian character sets
432 /// or right-to-left languages.
433 ///
434 /// This function is only available when compiling to WASM.
435 ///
436 /// This function is now deprecated and will be removed in release 0.9.0.
437 /// Use the `PdfFonts::load_type1_from_fetch()` function instead.
438 #[deprecated(
439 since = "0.8.1",
440 note = "This function has been moved. Use the PdfFonts::load_type1_from_fetch() function instead."
441 )]
442 #[doc(hidden)]
443 #[cfg(any(doc, target_arch = "wasm32"))]
444 pub async fn load_type1_from_fetch(
445 document: &'a PdfDocument<'a>,
446 url: impl ToString,
447 is_cid_font: bool,
448 ) -> Result<PdfFont<'a>, PdfiumError> {
449 if let Some(window) = window() {
450 let fetch_result = JsFuture::from(window.fetch_with_str(url.to_string().as_str()))
451 .await
452 .map_err(PdfiumError::WebSysFetchError)?;
453
454 debug_assert!(fetch_result.is_instance_of::<Response>());
455
456 let response: Response = fetch_result
457 .dyn_into()
458 .map_err(|_| PdfiumError::WebSysInvalidResponseError)?;
459
460 let blob: Blob =
461 JsFuture::from(response.blob().map_err(PdfiumError::WebSysFetchError)?)
462 .await
463 .map_err(PdfiumError::WebSysFetchError)?
464 .into();
465
466 #[allow(deprecated)]
467 Self::load_type1_from_blob(document, blob, is_cid_font).await
468 } else {
469 Err(PdfiumError::WebSysWindowObjectNotAvailable)
470 }
471 }
472
473 /// Attempts to load a Type 1 font from the given Blob.
474 /// A File object returned from a FileList is a suitable Blob:
475 ///
476 /// ```text
477 /// <input id="filePicker" type="file">
478 ///
479 /// const file = document.getElementById('filePicker').files[0];
480 /// ```
481 ///
482 /// Set the `is_cid_font` parameter to `true` if the given font is keyed by
483 /// 16-bit character ID (CID), indicating that it supports an extended glyphset of
484 /// 65,535 glyphs. This is typically the case with fonts that support Asian character sets
485 /// or right-to-left languages.
486 ///
487 /// This function is only available when compiling to WASM.
488 ///
489 /// This function is now deprecated and will be removed in release 0.9.0.
490 /// Use the `PdfFonts::load_type1_from_blob()` function instead.
491 #[deprecated(
492 since = "0.8.1",
493 note = "This function has been moved. Use the PdfFonts::load_type1_from_blob() function instead."
494 )]
495 #[doc(hidden)]
496 #[cfg(any(doc, target_arch = "wasm32"))]
497 pub async fn load_type1_from_blob(
498 document: &'a PdfDocument<'a>,
499 blob: Blob,
500 is_cid_font: bool,
501 ) -> Result<PdfFont<'a>, PdfiumError> {
502 let array_buffer: ArrayBuffer = JsFuture::from(blob.array_buffer())
503 .await
504 .map_err(PdfiumError::WebSysFetchError)?
505 .into();
506
507 let u8_array: Uint8Array = Uint8Array::new(&array_buffer);
508
509 let bytes: Vec<u8> = u8_array.to_vec();
510
511 #[allow(deprecated)]
512 Self::new_type1_from_bytes(document, bytes.as_slice(), is_cid_font)
513 }
514
515 /// Attempts to load the given byte data as a Type 1 font file.
516 ///
517 /// Set the `is_cid_font` parameter to `true` if the given font is keyed by
518 /// 16-bit character ID (CID), indicating that it supports an extended glyphset of
519 /// 65,535 glyphs. This is typically the case with fonts that support Asian character sets
520 /// or right-to-left languages.
521 ///
522 /// This function is now deprecated and will be removed in release 0.9.0.
523 /// Use the `PdfFonts::load_type1_from_bytes()` function instead.
524 #[deprecated(
525 since = "0.8.1",
526 note = "This function has been moved. Use the PdfFonts::load_type1_from_bytes() function instead."
527 )]
528 #[doc(hidden)]
529 pub fn new_type1_from_bytes(
530 document: &'a PdfDocument<'a>,
531 font_data: &[u8],
532 is_cid_font: bool,
533 ) -> Result<PdfFont<'a>, PdfiumError> {
534 Self::new_font_from_bytes(document, font_data, FPDF_FONT_TYPE1, is_cid_font)
535 }
536
537 /// Attempts to load a TrueType font file from the given file path.
538 ///
539 /// Set the `is_cid_font` parameter to `true` if the given font is keyed by
540 /// 16-bit character ID (CID), indicating that it supports an extended glyphset of
541 /// 65,535 glyphs. This is typically the case with fonts that support Asian character sets
542 /// or right-to-left languages.
543 ///
544 /// This function is not available when compiling to WASM. You have several options for
545 /// loading font data in WASM:
546 /// * Use the [PdfFonts::load_true_type_from_fetch()] function to download font data from a
547 /// URL using the browser's built-in `fetch()` API. This function is only available when
548 /// compiling to WASM.
549 /// * Use the [PdfFonts::load_true_type_from_blob()] function to load font data from a
550 /// Javascript `File` or `Blob` object (such as a `File` object returned from an HTML
551 /// `<input type="file">` element). This function is only available when compiling to WASM.
552 /// * Use the [PdfFonts::load_true_type_from_reader()] function to load font data from any
553 /// valid Rust reader.
554 /// * Use another method to retrieve the bytes of the target font over the network,
555 /// then load those bytes into Pdfium using the [PdfFonts::new_true_type_from_bytes()] function.
556 /// * Embed the bytes of the desired font directly into the compiled WASM module
557 /// using the `include_bytes!()` macro.
558 ///
559 /// This function is now deprecated and will be removed in release 0.9.0.
560 /// Use the `PdfFonts::load_true_type_from_file()` function instead.
561 #[deprecated(
562 since = "0.8.1",
563 note = "This function has been moved. Use the PdfFonts::load_true_type_from_file() function instead."
564 )]
565 #[doc(hidden)]
566 #[cfg(not(target_arch = "wasm32"))]
567 pub fn load_true_type_from_file(
568 document: &'a PdfDocument<'a>,
569 path: &(impl AsRef<Path> + ?Sized),
570 is_cid_font: bool,
571 ) -> Result<PdfFont<'a>, PdfiumError> {
572 #[allow(deprecated)]
573 Self::load_true_type_from_reader(
574 document,
575 File::open(path).map_err(PdfiumError::IoError)?,
576 is_cid_font,
577 )
578 }
579
580 /// Attempts to load a TrueType font file from the given reader.
581 ///
582 /// Set the `is_cid_font` parameter to `true` if the given font is keyed by
583 /// 16-bit character ID (CID), indicating that it supports an extended glyphset of
584 /// 65,535 glyphs. This is typically the case with fonts that support Asian character sets
585 /// or right-to-left languages.
586 ///
587 /// This function is now deprecated and will be removed in release 0.9.0.
588 /// Use the `PdfFonts::load_true_type_from_reader()` function instead.
589 #[deprecated(
590 since = "0.8.1",
591 note = "This function has been moved. Use the PdfFonts::load_true_type_from_reader() function instead."
592 )]
593 #[doc(hidden)]
594 pub fn load_true_type_from_reader(
595 document: &'a PdfDocument<'a>,
596 mut reader: impl Read,
597 is_cid_font: bool,
598 ) -> Result<PdfFont<'a>, PdfiumError> {
599 let mut bytes = Vec::new();
600
601 reader
602 .read_to_end(&mut bytes)
603 .map_err(PdfiumError::IoError)?;
604
605 #[allow(deprecated)]
606 Self::new_true_type_from_bytes(document, bytes.as_slice(), is_cid_font)
607 }
608
609 /// Attempts to load a TrueType font file from the given URL.
610 /// The Javascript `fetch()` API is used to download data over the network.
611 ///
612 /// Set the `is_cid_font` parameter to `true` if the given font is keyed by
613 /// 16-bit character ID (CID), indicating that it supports an extended glyphset of
614 /// 65,535 glyphs. This is typically the case with fonts that support Asian character sets
615 /// or right-to-left languages.
616 ///
617 /// This function is only available when compiling to WASM.
618 ///
619 /// This function is now deprecated and will be removed in release 0.9.0.
620 /// Use the `PdfFonts::load_true_type_from_fetch()` function instead.
621 #[deprecated(
622 since = "0.8.1",
623 note = "This function has been moved. Use the PdfFonts::load_true_type_from_fetch() function instead."
624 )]
625 #[doc(hidden)]
626 #[cfg(any(doc, target_arch = "wasm32"))]
627 pub async fn load_true_type_from_fetch(
628 document: &'a PdfDocument<'a>,
629 url: impl ToString,
630 is_cid_font: bool,
631 ) -> Result<PdfFont<'a>, PdfiumError> {
632 if let Some(window) = window() {
633 let fetch_result = JsFuture::from(window.fetch_with_str(url.to_string().as_str()))
634 .await
635 .map_err(PdfiumError::WebSysFetchError)?;
636
637 debug_assert!(fetch_result.is_instance_of::<Response>());
638
639 let response: Response = fetch_result
640 .dyn_into()
641 .map_err(|_| PdfiumError::WebSysInvalidResponseError)?;
642
643 let blob: Blob =
644 JsFuture::from(response.blob().map_err(PdfiumError::WebSysFetchError)?)
645 .await
646 .map_err(PdfiumError::WebSysFetchError)?
647 .into();
648
649 #[allow(deprecated)]
650 Self::load_true_type_from_blob(document, blob, is_cid_font).await
651 } else {
652 Err(PdfiumError::WebSysWindowObjectNotAvailable)
653 }
654 }
655
656 /// Attempts to load a TrueType font from the given `Blob`.
657 /// A `File` object returned from a `FileList` is a suitable `Blob`:
658 ///
659 /// ```text
660 /// <input id="filePicker" type="file">
661 ///
662 /// const file = document.getElementById('filePicker').files[0];
663 /// ```
664 ///
665 /// Set the `is_cid_font` parameter to `true` if the given font is keyed by
666 /// 16-bit character ID (CID), indicating that it supports an extended glyphset of
667 /// 65,535 glyphs. This is typically the case with fonts that support Asian character sets
668 /// or right-to-left languages.
669 ///
670 /// This function is only available when compiling to WASM.
671 ///
672 /// This function is now deprecated and will be removed in release 0.9.0.
673 /// Use the `PdfFonts::load_true_type_from_blob()` function instead.
674 #[deprecated(
675 since = "0.8.1",
676 note = "This function has been moved. Use the PdfFonts::load_true_type_from_blob() function instead."
677 )]
678 #[doc(hidden)]
679 #[cfg(any(doc, target_arch = "wasm32"))]
680 pub async fn load_true_type_from_blob(
681 document: &'a PdfDocument<'a>,
682 blob: Blob,
683 is_cid_font: bool,
684 ) -> Result<PdfFont<'a>, PdfiumError> {
685 let array_buffer: ArrayBuffer = JsFuture::from(blob.array_buffer())
686 .await
687 .map_err(PdfiumError::WebSysFetchError)?
688 .into();
689
690 let u8_array: Uint8Array = Uint8Array::new(&array_buffer);
691
692 let bytes: Vec<u8> = u8_array.to_vec();
693
694 #[allow(deprecated)]
695 Self::new_true_type_from_bytes(document, bytes.as_slice(), is_cid_font)
696 }
697
698 /// Attempts to load the given byte data as a TrueType font file.
699 ///
700 /// Set the `is_cid_font` parameter to `true` if the given font is keyed by
701 /// 16-bit character ID (CID), indicating that it supports an extended glyphset of
702 /// 65,535 glyphs. This is typically the case with fonts that support Asian character sets
703 /// or right-to-left languages.
704 ///
705 /// This function is now deprecated and will be removed in release 0.9.0.
706 /// Use the `PdfFonts::load_true_type_from_bytes()` function instead.
707 #[deprecated(
708 since = "0.8.1",
709 note = "This function has been moved. Use the PdfFonts::load_true_type_from_bytes() function instead."
710 )]
711 #[doc(hidden)]
712 pub fn new_true_type_from_bytes(
713 document: &'a PdfDocument<'a>,
714 font_data: &[u8],
715 is_cid_font: bool,
716 ) -> Result<PdfFont<'a>, PdfiumError> {
717 Self::new_font_from_bytes(document, font_data, FPDF_FONT_TRUETYPE, is_cid_font)
718 }
719
720 #[inline]
721 pub(crate) fn new_font_from_bytes(
722 document: &'a PdfDocument<'a>,
723 font_data: &[u8],
724 font_type: c_uint,
725 is_cid_font: bool,
726 ) -> Result<PdfFont<'a>, PdfiumError> {
727 let handle = document.bindings().FPDFText_LoadFont(
728 document.handle(),
729 font_data.as_ptr(),
730 font_data.len() as c_uint,
731 font_type as c_int,
732 document.bindings().bool_to_pdfium(is_cid_font),
733 );
734
735 if handle.is_null() {
736 Err(PdfiumError::PdfiumLibraryInternalError(
737 PdfiumInternalError::Unknown,
738 ))
739 } else {
740 Ok(PdfFont::from_pdfium(
741 handle,
742 document.bindings(),
743 None,
744 true,
745 ))
746 }
747 }
748
749 /// Returns the internal `FPDF_FONT` handle for this [PdfFont].
750 #[inline]
751 pub(crate) fn handle(&self) -> FPDF_FONT {
752 self.handle
753 }
754
755 /// Returns the [PdfiumLibraryBindings] used by this [PdfFont].
756 #[inline]
757 pub fn bindings(&self) -> &'a dyn PdfiumLibraryBindings {
758 self.bindings
759 }
760
761 #[cfg(any(
762 feature = "pdfium_6611",
763 feature = "pdfium_6569",
764 feature = "pdfium_6555",
765 feature = "pdfium_6490",
766 feature = "pdfium_6406",
767 feature = "pdfium_6337",
768 feature = "pdfium_6295",
769 feature = "pdfium_6259",
770 feature = "pdfium_6164",
771 feature = "pdfium_6124",
772 feature = "pdfium_6110",
773 feature = "pdfium_6084",
774 feature = "pdfium_6043",
775 feature = "pdfium_6015",
776 feature = "pdfium_5961"
777 ))]
778 #[inline]
779 #[deprecated(
780 since = "0.8.22",
781 note = "This function has been renamed in line with upstream Pdfium. Use the PdfFont::family() function instead."
782 )]
783 /// Returns the name of this [PdfFont].
784 pub fn name(&self) -> String {
785 self.family()
786 }
787
788 #[cfg(any(
789 feature = "pdfium_future",
790 feature = "pdfium_7350",
791 feature = "pdfium_7215",
792 feature = "pdfium_7123",
793 feature = "pdfium_6996",
794 feature = "pdfium_6721",
795 feature = "pdfium_6666"
796 ))]
797 /// Returns the name of this [PdfFont].
798 pub fn name(&self) -> String {
799 // Retrieving the font name from Pdfium is a two-step operation. First, we call
800 // FPDFFont_GetBaseFontName() with a null buffer; this will retrieve the length of
801 // the font name in bytes. If the length is zero, then there is no font name.
802
803 // If the length is non-zero, then we reserve a byte buffer of the given
804 // length and call FPDFFont_GetBaseFontName() again with a pointer to the buffer;
805 // this will write the font name into the buffer. Unlike most text handling in
806 // Pdfium, font names are returned in UTF-8 format.
807
808 let buffer_length =
809 self.bindings
810 .FPDFFont_GetBaseFontName(self.handle, std::ptr::null_mut(), 0);
811
812 if buffer_length == 0 {
813 // The font name is not present.
814
815 return String::new();
816 }
817
818 let mut buffer = create_byte_buffer(buffer_length as usize);
819
820 let result = self.bindings.FPDFFont_GetBaseFontName(
821 self.handle,
822 buffer.as_mut_ptr() as *mut c_char,
823 buffer_length,
824 );
825
826 assert_eq!(result, buffer_length);
827
828 String::from_utf8(buffer)
829 // Trim any trailing nulls. All strings returned from Pdfium are generally terminated
830 // by one null byte.
831 .map(|str| str.trim_end_matches(char::from(0)).to_owned())
832 .unwrap_or_else(|_| String::new())
833 }
834
835 /// Returns the family of this [PdfFont].
836 pub fn family(&self) -> String {
837 // Retrieving the family name from Pdfium is a two-step operation. First, we call
838 // FPDFFont_GetFamilyName() with a null buffer; this will retrieve the length of
839 // the font name in bytes. If the length is zero, then there is no font name.
840
841 // If the length is non-zero, then we reserve a byte buffer of the given
842 // length and call FPDFFont_GetFamilyName() again with a pointer to the buffer;
843 // this will write the font name into the buffer. Unlike most text handling in
844 // Pdfium, font names are returned in UTF-8 format.
845
846 #[cfg(any(
847 feature = "pdfium_future",
848 feature = "pdfium_7350",
849 feature = "pdfium_7215",
850 feature = "pdfium_7123",
851 feature = "pdfium_6996",
852 feature = "pdfium_6721",
853 feature = "pdfium_6666",
854 feature = "pdfium_6611"
855 ))]
856 let buffer_length =
857 self.bindings
858 .FPDFFont_GetFamilyName(self.handle, std::ptr::null_mut(), 0);
859
860 #[cfg(any(
861 feature = "pdfium_6569",
862 feature = "pdfium_6555",
863 feature = "pdfium_6490",
864 feature = "pdfium_6406",
865 feature = "pdfium_6337",
866 feature = "pdfium_6295",
867 feature = "pdfium_6259",
868 feature = "pdfium_6164",
869 feature = "pdfium_6124",
870 feature = "pdfium_6110",
871 feature = "pdfium_6084",
872 feature = "pdfium_6043",
873 feature = "pdfium_6015",
874 feature = "pdfium_5961"
875 ))]
876 let buffer_length =
877 self.bindings
878 .FPDFFont_GetFontName(self.handle, std::ptr::null_mut(), 0);
879
880 if buffer_length == 0 {
881 // The font name is not present.
882
883 return String::new();
884 }
885
886 let mut buffer = create_byte_buffer(buffer_length as usize);
887
888 #[cfg(any(
889 feature = "pdfium_future",
890 feature = "pdfium_7350",
891 feature = "pdfium_7215",
892 feature = "pdfium_7123",
893 feature = "pdfium_6996",
894 feature = "pdfium_6721",
895 feature = "pdfium_6666",
896 feature = "pdfium_6611"
897 ))]
898 let result = self.bindings.FPDFFont_GetFamilyName(
899 self.handle,
900 buffer.as_mut_ptr() as *mut c_char,
901 buffer_length,
902 );
903
904 #[cfg(any(
905 feature = "pdfium_6569",
906 feature = "pdfium_6555",
907 feature = "pdfium_6490",
908 feature = "pdfium_6406",
909 feature = "pdfium_6337",
910 feature = "pdfium_6295",
911 feature = "pdfium_6259",
912 feature = "pdfium_6164",
913 feature = "pdfium_6124",
914 feature = "pdfium_6110",
915 feature = "pdfium_6084",
916 feature = "pdfium_6043",
917 feature = "pdfium_6015",
918 feature = "pdfium_5961"
919 ))]
920 let result = self.bindings.FPDFFont_GetFontName(
921 self.handle,
922 buffer.as_mut_ptr() as *mut c_char,
923 buffer_length,
924 );
925
926 assert_eq!(result, buffer_length);
927
928 String::from_utf8(buffer)
929 // Trim any trailing nulls. All strings returned from Pdfium are generally terminated
930 // by one null byte.
931 .map(|str| str.trim_end_matches(char::from(0)).to_owned())
932 .unwrap_or_else(|_| String::new())
933 }
934
935 /// Returns the weight of this [PdfFont].
936 ///
937 /// Pdfium may not reliably return the correct value of this property for built-in fonts.
938 pub fn weight(&self) -> Result<PdfFontWeight, PdfiumError> {
939 PdfFontWeight::from_pdfium(self.bindings.FPDFFont_GetWeight(self.handle)).ok_or(
940 PdfiumError::PdfiumLibraryInternalError(PdfiumInternalError::Unknown),
941 )
942 }
943
944 /// Returns the italic angle of this [PdfFont]. The italic angle is the angle,
945 /// expressed in degrees counter-clockwise from the vertical, of the dominant vertical
946 /// strokes of the font. The value is zero for non-italic fonts, and negative for fonts
947 /// that slope to the right (as almost all italic fonts do).
948 ///
949 /// Pdfium may not reliably return the correct value of this property for built-in fonts.
950 pub fn italic_angle(&self) -> Result<i32, PdfiumError> {
951 let mut angle = 0;
952
953 if self.bindings.is_true(
954 self.bindings
955 .FPDFFont_GetItalicAngle(self.handle, &mut angle),
956 ) {
957 Ok(angle)
958 } else {
959 Err(PdfiumError::PdfiumLibraryInternalError(
960 PdfiumInternalError::Unknown,
961 ))
962 }
963 }
964
965 /// Returns the ascent of this [PdfFont] for the given font size. The ascent is the maximum
966 /// height above the baseline reached by glyphs in this font, excluding the height of glyphs
967 /// for accented characters.
968 pub fn ascent(&self, font_size: PdfPoints) -> Result<PdfPoints, PdfiumError> {
969 let mut ascent = 0.0;
970
971 if self.bindings.is_true(self.bindings.FPDFFont_GetAscent(
972 self.handle,
973 font_size.value,
974 &mut ascent,
975 )) {
976 Ok(PdfPoints::new(ascent))
977 } else {
978 Err(PdfiumError::PdfiumLibraryInternalError(
979 PdfiumInternalError::Unknown,
980 ))
981 }
982 }
983
984 /// Returns the descent of this [PdfFont] for the given font size. The descent is the
985 /// maximum distance below the baseline reached by glyphs in this font, expressed as a
986 /// negative points value.
987 pub fn descent(&self, font_size: PdfPoints) -> Result<PdfPoints, PdfiumError> {
988 let mut descent = 0.0;
989
990 if self.bindings.is_true(self.bindings.FPDFFont_GetDescent(
991 self.handle,
992 font_size.value,
993 &mut descent,
994 )) {
995 Ok(PdfPoints::new(descent))
996 } else {
997 Err(PdfiumError::PdfiumLibraryInternalError(
998 PdfiumInternalError::Unknown,
999 ))
1000 }
1001 }
1002
1003 /// Returns the raw font descriptor bitflags for the containing [PdfFont].
1004 #[inline]
1005 fn get_flags_bits(&self) -> FpdfFontDescriptorFlags {
1006 FpdfFontDescriptorFlags::from_bits_truncate(
1007 self.bindings.FPDFFont_GetFlags(self.handle) as u32
1008 )
1009 }
1010
1011 /// Returns `true` if all the glyphs in this [PdfFont] have the same width.
1012 ///
1013 /// Pdfium may not reliably return the correct value of this flag for built-in fonts.
1014 pub fn is_fixed_pitch(&self) -> bool {
1015 self.get_flags_bits()
1016 .contains(FpdfFontDescriptorFlags::FIXED_PITCH_BIT_1)
1017 }
1018
1019 /// Returns `true` if the glyphs in this [PdfFont] have variable widths.
1020 ///
1021 /// Pdfium may not reliably return the correct value of this flag for built-in fonts.
1022 #[inline]
1023 pub fn is_proportional_pitch(&self) -> bool {
1024 !self.is_fixed_pitch()
1025 }
1026
1027 /// Returns `true` if one or more glyphs in this [PdfFont] have serifs - short strokes
1028 /// drawn at an angle on the top or bottom of glyph stems to decorate the glyphs.
1029 /// For example, Times New Roman is a serif font.
1030 ///
1031 /// Pdfium may not reliably return the correct value of this flag for built-in fonts.
1032 pub fn is_serif(&self) -> bool {
1033 self.get_flags_bits()
1034 .contains(FpdfFontDescriptorFlags::SERIF_BIT_2)
1035 }
1036
1037 /// Returns `true` if no glyphs in this [PdfFont] have serifs - short strokes
1038 /// drawn at an angle on the top or bottom of glyph stems to decorate the glyphs.
1039 /// For example, Helvetica is a sans-serif font.
1040 ///
1041 /// Pdfium may not reliably return the correct value of this flag for built-in fonts.
1042 #[inline]
1043 pub fn is_sans_serif(&self) -> bool {
1044 !self.is_serif()
1045 }
1046
1047 /// Returns `true` if this [PdfFont] contains glyphs outside the Adobe standard Latin
1048 /// character set.
1049 ///
1050 /// This classification of non-symbolic and symbolic fonts is peculiar to PDF. A font may
1051 /// contain additional characters that are used in Latin writing systems but are outside the
1052 /// Adobe standard Latin character set; PDF considers such a font to be symbolic.
1053 ///
1054 /// Pdfium may not reliably return the correct value of this flag for built-in fonts.
1055 pub fn is_symbolic(&self) -> bool {
1056 // This flag bit and the non-symbolic flag bit cannot both be set or both be clear.
1057
1058 self.get_flags_bits()
1059 .contains(FpdfFontDescriptorFlags::SYMBOLIC_BIT_3)
1060 }
1061
1062 /// Returns `true` if this [PdfFont] does not contain glyphs outside the Adobe standard
1063 /// Latin character set.
1064 ///
1065 /// This classification of non-symbolic and symbolic fonts is peculiar to PDF. A font may
1066 /// contain additional characters that are used in Latin writing systems but are outside the
1067 /// Adobe standard Latin character set; PDF considers such a font to be symbolic.
1068 ///
1069 /// Pdfium may not reliably return the correct value of this flag for built-in fonts.
1070 pub fn is_non_symbolic(&self) -> bool {
1071 // This flag bit and the symbolic flag bit cannot both be set or both be clear.
1072
1073 self.get_flags_bits()
1074 .contains(FpdfFontDescriptorFlags::NON_SYMBOLIC_BIT_6)
1075 }
1076
1077 /// Returns `true` if the glyphs in this [PdfFont] are designed to resemble cursive handwriting.
1078 ///
1079 /// Pdfium may not reliably return the correct value of this flag for built-in fonts.
1080 pub fn is_cursive(&self) -> bool {
1081 self.get_flags_bits()
1082 .contains(FpdfFontDescriptorFlags::SCRIPT_BIT_4)
1083 }
1084
1085 /// Returns `true` if the glyphs in this [PdfFont] include dominant vertical strokes
1086 /// that are slanted.
1087 ///
1088 /// The designed vertical stroke angle can be retrieved using the [PdfFont::italic_angle()] function.
1089 ///
1090 /// Pdfium may not reliably return the correct value of this flag for built-in fonts.
1091 pub fn is_italic(&self) -> bool {
1092 self.get_flags_bits()
1093 .contains(FpdfFontDescriptorFlags::ITALIC_BIT_7)
1094 }
1095
1096 /// Returns `true` if this [PdfFont] contains no lowercase letters by design.
1097 ///
1098 /// Pdfium may not reliably return the correct value of this flag for built-in fonts.
1099 pub fn is_all_caps(&self) -> bool {
1100 self.get_flags_bits()
1101 .contains(FpdfFontDescriptorFlags::ALL_CAP_BIT_17)
1102 }
1103
1104 /// Returns `true` if the lowercase letters in this [PdfFont] have the same shapes as the
1105 /// corresponding uppercase letters but are sized proportionally so they have the same size
1106 /// and stroke weight as lowercase glyphs in the same typeface family.
1107 ///
1108 /// Pdfium may not reliably return the correct value of this flag for built-in fonts.
1109 pub fn is_small_caps(&self) -> bool {
1110 self.get_flags_bits()
1111 .contains(FpdfFontDescriptorFlags::SMALL_CAP_BIT_18)
1112 }
1113
1114 /// Returns `true` if bold glyphs in this [PdfFont] are painted with extra pixels
1115 /// at very small font sizes.
1116 ///
1117 /// Typically when glyphs are painted at small sizes on low-resolution devices, individual strokes
1118 /// of bold glyphs may appear only one pixel wide. Because this is the minimum width of a pixel
1119 /// based device, individual strokes of non-bold glyphs may also appear as one pixel wide
1120 /// and therefore cannot be distinguished from bold glyphs. If this flag is set, individual
1121 /// strokes of bold glyphs may be thickened at small font sizes.
1122 ///
1123 /// Pdfium may not reliably return the correct value of this flag for built-in fonts.
1124 pub fn is_bold_reenforced(&self) -> bool {
1125 self.get_flags_bits()
1126 .contains(FpdfFontDescriptorFlags::FORCE_BOLD_BIT_19)
1127 }
1128
1129 /// Returns `true` if this [PdfFont] is an instance of one of the 14 built-in fonts
1130 /// provided as part of the PDF specification.
1131 #[inline]
1132 pub fn is_built_in(&self) -> bool {
1133 self.built_in.is_some()
1134 }
1135
1136 /// Returns the [PdfFontBuiltin] type of this built-in font, or `None` if this font is
1137 /// not one of the 14 built-in fonts provided as part of the PDF specification.
1138 #[inline]
1139 pub fn built_in(&self) -> Option<PdfFontBuiltin> {
1140 self.built_in
1141 }
1142
1143 /// Returns `true` if the data for this [PdfFont] is embedded in the containing [PdfDocument].
1144 pub fn is_embedded(&self) -> Result<bool, PdfiumError> {
1145 let result = self.bindings.FPDFFont_GetIsEmbedded(self.handle);
1146
1147 match result {
1148 1 => Ok(true),
1149 0 => Ok(false),
1150 _ => Err(PdfiumError::PdfiumLibraryInternalError(
1151 PdfiumInternalError::Unknown,
1152 )),
1153 }
1154 }
1155
1156 /// Writes this [PdfFont] to a new byte buffer, returning the byte buffer.
1157 ///
1158 /// If this [PdfFont] is not embedded in the containing [PdfDocument], then the data
1159 /// returned will be for the substitution font instead.
1160 pub fn data(&self) -> Result<Vec<u8>, PdfiumError> {
1161 // Retrieving the font data from Pdfium is a two-step operation. First, we call
1162 // FPDFFont_GetFontData() with a null buffer; this will retrieve the length of
1163 // the data in bytes. If the length is zero, then there is no data associated
1164 // with this font.
1165
1166 // If the length is non-zero, then we reserve a byte buffer of the given
1167 // length and call FPDFFont_GetFontData() again with a pointer to the buffer;
1168 // this will write the font data to the buffer.
1169
1170 let mut out_buflen: usize = 0;
1171
1172 if self
1173 .bindings()
1174 .is_true(self.bindings().FPDFFont_GetFontData(
1175 self.handle,
1176 std::ptr::null_mut(),
1177 0,
1178 &mut out_buflen,
1179 ))
1180 {
1181 // out_buflen now contains the length of the font data.
1182
1183 let buffer_length = out_buflen;
1184
1185 let mut buffer = create_byte_buffer(buffer_length);
1186
1187 let result = self.bindings().FPDFFont_GetFontData(
1188 self.handle,
1189 buffer.as_mut_ptr(),
1190 buffer_length,
1191 &mut out_buflen,
1192 );
1193
1194 assert!(self.bindings.is_true(result));
1195 assert_eq!(buffer_length, out_buflen);
1196
1197 Ok(buffer)
1198 } else {
1199 Err(PdfiumError::PdfiumLibraryInternalError(
1200 PdfiumInternalError::Unknown,
1201 ))
1202 }
1203 }
1204
1205 /// Returns a collection of all the [PdfFontGlyphs] defined for this [PdfFont] in the containing
1206 /// `PdfDocument`.
1207 ///
1208 /// Note that documents typically include only the specific glyphs they need from any given font,
1209 /// not the entire font glyphset. This is a PDF feature known as font subsetting. The collection
1210 /// of glyphs returned by this function may therefore not cover the entire font glyphset.
1211 #[inline]
1212 pub fn glyphs(&self) -> &PdfFontGlyphs {
1213 self.glyphs.initialize_len();
1214 &self.glyphs
1215 }
1216}
1217
1218impl<'a> Drop for PdfFont<'a> {
1219 /// Closes this [PdfFont], releasing held memory.
1220 #[inline]
1221 fn drop(&mut self) {
1222 // The documentation for FPDFText_LoadFont() and FPDFText_LoadStandardFont() both state
1223 // that the font loaded by the function can be closed by calling FPDFFont_Close().
1224 // I had taken this to mean that _any_ FPDF_Font handle returned from a Pdfium function
1225 // should be closed via FPDFFont_Close(), but testing suggests this is not the case;
1226 // rather, it is only fonts specifically loaded by calling FPDFText_LoadFont() or
1227 // FPDFText_LoadStandardFont() that need to be actively closed.
1228
1229 // In other words, retrieving a handle to a font that already exists in a document evidently
1230 // does not allocate any additional resources, so we don't need to free anything.
1231 // (Indeed, if we try to, Pdfium segfaults.)
1232
1233 if self.is_font_memory_loaded {
1234 self.bindings.FPDFFont_Close(self.handle);
1235 }
1236 }
1237}