pdfium_render/pdf/font/
glyph.rs1use 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
15pub 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 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 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> {}
80pub 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> {}