pdfium_render/pdf/path/
clip_path.rs1use crate::bindgen::FPDF_CLIPPATH;
4use crate::bindings::PdfiumLibraryBindings;
5use crate::error::{PdfiumError, PdfiumInternalError};
6use crate::pdf::document::page::object::ownership::PdfPageObjectOwnership;
7use crate::pdf::path::segment::PdfPathSegment;
8use crate::pdf::path::segments::{PdfPathSegmentIndex, PdfPathSegments, PdfPathSegmentsIterator};
9use std::convert::TryInto;
10use std::ops::{Range, RangeInclusive};
11use std::os::raw::c_int;
12
13pub type PdfClipPathSegmentIndex = u16;
16
17pub struct PdfClipPath<'a> {
19 handle: FPDF_CLIPPATH,
20 ownership: PdfPageObjectOwnership,
21 bindings: &'a dyn PdfiumLibraryBindings,
22}
23
24impl<'a> PdfClipPath<'a> {
25 #[inline]
26 pub(crate) fn from_pdfium(
27 handle: FPDF_CLIPPATH,
28 ownership: PdfPageObjectOwnership,
29 bindings: &'a dyn PdfiumLibraryBindings,
30 ) -> Self {
31 Self {
32 handle,
33 ownership,
34 bindings,
35 }
36 }
37
38 #[inline]
40 pub(crate) fn handle(&self) -> FPDF_CLIPPATH {
41 self.handle
42 }
43
44 #[inline]
46 pub fn bindings(&self) -> &'a dyn PdfiumLibraryBindings {
47 self.bindings
48 }
49
50 #[inline]
52 pub fn len(&self) -> PdfClipPathSegmentIndex {
53 self.bindings().FPDFClipPath_CountPaths(self.handle()) as PdfClipPathSegmentIndex
54 }
55
56 #[inline]
58 pub fn is_empty(&self) -> bool {
59 self.len() == 0
60 }
61
62 #[inline]
64 pub fn as_range(&self) -> Range<PdfClipPathSegmentIndex> {
65 0..self.len()
66 }
67
68 #[inline]
70 pub fn as_range_inclusive(&self) -> RangeInclusive<PdfClipPathSegmentIndex> {
71 if self.is_empty() {
72 0..=0
73 } else {
74 0..=(self.len() - 1)
75 }
76 }
77
78 pub fn get(
80 &self,
81 index: PdfClipPathSegmentIndex,
82 ) -> Result<PdfClipPathSegments<'a>, PdfiumError> {
83 if index >= self.len() {
84 return Err(PdfiumError::PdfClipPathSegmentIndexOutOfBounds);
85 }
86
87 Ok(PdfClipPathSegments::from_pdfium(
88 self.handle(),
89 index,
90 self.bindings(),
91 ))
92 }
93
94 #[inline]
96 pub fn iter(&self) -> PdfClipPathIterator<'_> {
97 PdfClipPathIterator::new(self)
98 }
99}
100
101impl<'a> Drop for PdfClipPath<'a> {
102 #[inline]
104 fn drop(&mut self) {
105 if !self.ownership.is_owned() {
106 self.bindings.FPDF_DestroyClipPath(self.handle)
110 }
111 }
112}
113
114pub struct PdfClipPathIterator<'a> {
116 clip_path: &'a PdfClipPath<'a>,
117 next_index: PdfClipPathSegmentIndex,
118}
119
120impl<'a> PdfClipPathIterator<'a> {
121 #[inline]
122 pub(crate) fn new(clip_path: &'a PdfClipPath<'a>) -> Self {
123 PdfClipPathIterator {
124 clip_path,
125 next_index: 0,
126 }
127 }
128}
129
130impl<'a> Iterator for PdfClipPathIterator<'a> {
131 type Item = PdfClipPathSegments<'a>;
132
133 fn next(&mut self) -> Option<Self::Item> {
134 let next = self.clip_path.get(self.next_index);
135
136 self.next_index += 1;
137
138 next.ok()
139 }
140}
141
142pub struct PdfClipPathSegments<'a> {
144 handle: FPDF_CLIPPATH,
145 index: PdfClipPathSegmentIndex,
146 bindings: &'a dyn PdfiumLibraryBindings,
147}
148
149impl<'a> PdfClipPathSegments<'a> {
150 #[inline]
151 pub(crate) fn from_pdfium(
152 handle: FPDF_CLIPPATH,
153 path_index: PdfClipPathSegmentIndex,
154 bindings: &'a dyn PdfiumLibraryBindings,
155 ) -> Self {
156 Self {
157 handle,
158 index: path_index,
159 bindings,
160 }
161 }
162}
163
164impl<'a> PdfPathSegments<'a> for PdfClipPathSegments<'a> {
165 #[inline]
166 fn bindings(&self) -> &'a dyn PdfiumLibraryBindings {
167 self.bindings
168 }
169
170 #[inline]
171 fn len(&self) -> PdfPathSegmentIndex {
172 self.bindings()
173 .FPDFClipPath_CountPathSegments(self.handle, self.index as i32)
174 .try_into()
175 .unwrap_or(0)
176 }
177
178 fn get(&self, index: PdfPathSegmentIndex) -> Result<PdfPathSegment<'a>, PdfiumError> {
179 let handle = self.bindings().FPDFClipPath_GetPathSegment(
180 self.handle,
181 self.index as i32,
182 index as c_int,
183 );
184
185 if handle.is_null() {
186 Err(PdfiumError::PdfiumLibraryInternalError(
187 PdfiumInternalError::Unknown,
188 ))
189 } else {
190 Ok(PdfPathSegment::from_pdfium(handle, None, self.bindings()))
191 }
192 }
193
194 #[inline]
195 fn iter(&'a self) -> PdfPathSegmentsIterator<'a> {
196 PdfPathSegmentsIterator::new(self)
197 }
198}