Skip to main content

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