pdfium_render/pdf/font/
glyph.rs

1//! Defines the [PdfFontGlyph] struct, exposing functionality related to a single
2//! font glyph in a `PdfFontGlyphs` collection.
3
4use crate::bindgen::{FPDF_FONT, FPDF_GLYPHPATH};
5use crate::bindings::PdfiumLibraryBindings;
6use crate::error::{PdfiumError, PdfiumInternalError};
7use crate::pdf::font::glyphs::PdfFontGlyphIndex;
8use crate::pdf::path::segment::PdfPathSegment;
9use crate::pdf::path::segments::{PdfPathSegmentIndex, PdfPathSegments, PdfPathSegmentsIterator};
10use crate::pdf::points::PdfPoints;
11use std::convert::TryInto;
12use std::os::raw::{c_float, c_int, c_uint};
13
14/// A single font glyph in a `PdfFontGlyphs` collection.
15pub struct PdfFontGlyph<'a> {
16    handle: FPDF_FONT,
17    index: PdfFontGlyphIndex,
18    bindings: &'a dyn PdfiumLibraryBindings,
19}
20
21impl<'a> PdfFontGlyph<'a> {
22    #[inline]
23    pub(crate) fn from_pdfium(
24        handle: FPDF_FONT,
25        index: PdfFontGlyphIndex,
26        bindings: &'a dyn PdfiumLibraryBindings,
27    ) -> Self {
28        Self {
29            handle,
30            index,
31            bindings,
32        }
33    }
34
35    /// Returns the [PdfiumLibraryBindings] used by this [PdfFontGlyph].
36    #[inline]
37    pub fn bindings(&self) -> &'a dyn PdfiumLibraryBindings {
38        self.bindings
39    }
40
41    /// Returns the width of this [PdfFontGlyph] when rendered at the given font size.
42    pub fn width_at_font_size(&self, size: PdfPoints) -> PdfPoints {
43        let mut width = 0.0;
44
45        if self.bindings.is_true(self.bindings.FPDFFont_GetGlyphWidth(
46            self.handle,
47            self.index as c_uint,
48            size.value as c_float,
49            &mut width,
50        )) {
51            PdfPoints::new(width)
52        } else {
53            PdfPoints::ZERO
54        }
55    }
56
57    /// Returns the path segments of this [PdfFontGlyph] when rendered at the given font size.
58    pub fn segments_at_font_size(&self, size: PdfPoints) -> Result<PdfFontGlyphPath, PdfiumError> {
59        let handle = self.bindings().FPDFFont_GetGlyphPath(
60            self.handle,
61            self.index as c_uint,
62            size.value as c_float,
63        );
64
65        if handle.is_null() {
66            Err(PdfiumError::PdfiumLibraryInternalError(
67                PdfiumInternalError::Unknown,
68            ))
69        } else {
70            Ok(PdfFontGlyphPath::from_pdfium(handle, self.bindings()))
71        }
72    }
73}
74
75/// The collection of [PdfPathSegment] objects inside a font glyph path.
76pub struct PdfFontGlyphPath<'a> {
77    handle: FPDF_GLYPHPATH,
78    bindings: &'a dyn PdfiumLibraryBindings,
79}
80
81impl<'a> PdfFontGlyphPath<'a> {
82    #[inline]
83    pub(crate) fn from_pdfium(
84        handle: FPDF_GLYPHPATH,
85        bindings: &'a dyn PdfiumLibraryBindings,
86    ) -> Self {
87        Self { handle, bindings }
88    }
89}
90
91impl<'a> PdfPathSegments<'a> for PdfFontGlyphPath<'a> {
92    #[inline]
93    fn bindings(&self) -> &'a dyn PdfiumLibraryBindings {
94        self.bindings
95    }
96
97    #[inline]
98    fn len(&self) -> PdfPathSegmentIndex {
99        self.bindings()
100            .FPDFGlyphPath_CountGlyphSegments(self.handle)
101            .try_into()
102            .unwrap_or(0)
103    }
104
105    fn get(&self, index: PdfPathSegmentIndex) -> Result<PdfPathSegment<'a>, PdfiumError> {
106        let handle = self
107            .bindings()
108            .FPDFGlyphPath_GetGlyphPathSegment(self.handle, index as c_int);
109
110        if handle.is_null() {
111            Err(PdfiumError::PdfiumLibraryInternalError(
112                PdfiumInternalError::Unknown,
113            ))
114        } else {
115            Ok(PdfPathSegment::from_pdfium(handle, None, self.bindings()))
116        }
117    }
118
119    #[inline]
120    fn iter(&'a self) -> PdfPathSegmentsIterator<'a> {
121        PdfPathSegmentsIterator::new(self)
122    }
123}