1use crate::bindgen::{
5 FPDF_BOOL, FPDF_DOCUMENT, FPDF_FILLMODE_ALTERNATE, FPDF_FILLMODE_NONE, FPDF_FILLMODE_WINDING, FPDF_PAGEOBJECT,
6};
7use crate::bindings::PdfiumLibraryBindings;
8use crate::error::{PdfiumError, PdfiumInternalError};
9use crate::pdf::color::PdfColor;
10use crate::pdf::document::PdfDocument;
11use crate::pdf::document::page::object::private::internal::PdfPageObjectPrivate;
12use crate::pdf::document::page::object::{PdfPageObject, PdfPageObjectCommon, PdfPageObjectOwnership};
13use crate::pdf::matrix::{PdfMatrix, PdfMatrixValue};
14use crate::pdf::path::segment::{PdfPathSegment, PdfPathSegmentType};
15use crate::pdf::path::segments::{PdfPathSegmentIndex, PdfPathSegments, PdfPathSegmentsIterator};
16use crate::pdf::points::PdfPoints;
17use crate::pdf::rect::PdfRect;
18use crate::{create_transform_getters, create_transform_setters};
19use std::convert::TryInto;
20use std::os::raw::{c_int, c_uint};
21
22#[cfg(doc)]
23use {
24 crate::pdf::document::page::PdfPage, crate::pdf::document::page::object::PdfPageObjectType,
25 crate::pdf::document::page::objects::common::PdfPageObjectsCommon,
26};
27
28#[derive(Copy, Clone, Debug, PartialEq)]
34pub enum PdfPathFillMode {
35 None = FPDF_FILLMODE_NONE as isize,
37
38 EvenOdd = FPDF_FILLMODE_ALTERNATE as isize,
49
50 Winding = FPDF_FILLMODE_WINDING as isize,
67}
68
69impl PdfPathFillMode {
70 #[inline]
71 pub(crate) fn from_pdfium(value: c_int) -> Result<PdfPathFillMode, PdfiumError> {
72 match value as u32 {
73 FPDF_FILLMODE_NONE => Ok(PdfPathFillMode::None),
74 FPDF_FILLMODE_ALTERNATE => Ok(PdfPathFillMode::EvenOdd),
75 FPDF_FILLMODE_WINDING => Ok(PdfPathFillMode::Winding),
76 _ => Err(PdfiumError::UnknownPdfPagePathFillMode),
77 }
78 }
79
80 #[inline]
81 #[allow(dead_code)]
82 pub(crate) fn as_pdfium(&self) -> c_uint {
83 match self {
84 PdfPathFillMode::None => FPDF_FILLMODE_NONE,
85 PdfPathFillMode::EvenOdd => FPDF_FILLMODE_ALTERNATE,
86 PdfPathFillMode::Winding => FPDF_FILLMODE_WINDING,
87 }
88 }
89}
90
91impl Default for PdfPathFillMode {
92 #[inline]
96 fn default() -> Self {
97 PdfPathFillMode::Winding
98 }
99}
100
101pub struct PdfPagePathObject<'a> {
149 object_handle: FPDF_PAGEOBJECT,
150 ownership: PdfPageObjectOwnership,
151 bindings: &'a dyn PdfiumLibraryBindings,
152 current_point_x: PdfPoints,
153 current_point_y: PdfPoints,
154}
155
156impl<'a> PdfPagePathObject<'a> {
157 #[inline]
158 pub(crate) fn from_pdfium(
159 object_handle: FPDF_PAGEOBJECT,
160 ownership: PdfPageObjectOwnership,
161 bindings: &'a dyn PdfiumLibraryBindings,
162 ) -> Self {
163 PdfPagePathObject {
164 object_handle,
165 ownership,
166 bindings,
167 current_point_x: PdfPoints::ZERO,
168 current_point_y: PdfPoints::ZERO,
169 }
170 }
171
172 #[inline]
189 pub fn new(
190 document: &PdfDocument<'a>,
191 x: PdfPoints,
192 y: PdfPoints,
193 stroke_color: Option<PdfColor>,
194 stroke_width: Option<PdfPoints>,
195 fill_color: Option<PdfColor>,
196 ) -> Result<Self, PdfiumError> {
197 Self::new_from_bindings(document.bindings(), x, y, stroke_color, stroke_width, fill_color)
198 }
199
200 pub(crate) fn new_from_bindings(
201 bindings: &'a dyn PdfiumLibraryBindings,
202 x: PdfPoints,
203 y: PdfPoints,
204 stroke_color: Option<PdfColor>,
205 stroke_width: Option<PdfPoints>,
206 fill_color: Option<PdfColor>,
207 ) -> Result<Self, PdfiumError> {
208 let handle = bindings.FPDFPageObj_CreateNewPath(x.value, y.value);
209
210 if handle.is_null() {
211 Err(PdfiumError::PdfiumLibraryInternalError(PdfiumInternalError::Unknown))
212 } else {
213 let mut result = PdfPagePathObject {
214 object_handle: handle,
215 ownership: PdfPageObjectOwnership::unowned(),
216 bindings,
217 current_point_x: x,
218 current_point_y: y,
219 };
220
221 result.move_to(x, y)?;
222
223 let do_stroke = if let Some(stroke_color) = stroke_color {
224 if let Some(stroke_width) = stroke_width {
225 result.set_stroke_color(stroke_color)?;
226 result.set_stroke_width(stroke_width)?;
227
228 true
229 } else {
230 false
231 }
232 } else {
233 false
234 };
235
236 let fill_mode = if let Some(fill_color) = fill_color {
237 result.set_fill_color(fill_color)?;
238
239 PdfPathFillMode::default()
240 } else {
241 PdfPathFillMode::None
242 };
243
244 result.set_fill_and_stroke_mode(fill_mode, do_stroke)?;
245
246 Ok(result)
247 }
248 }
249
250 #[inline]
251 pub(crate) fn new_line_from_bindings(
252 bindings: &'a dyn PdfiumLibraryBindings,
253 x1: PdfPoints,
254 y1: PdfPoints,
255 x2: PdfPoints,
256 y2: PdfPoints,
257 stroke_color: PdfColor,
258 stroke_width: PdfPoints,
259 ) -> Result<Self, PdfiumError> {
260 let mut result = Self::new_from_bindings(bindings, x1, y1, Some(stroke_color), Some(stroke_width), None)?;
261
262 result.line_to(x2, y2)?;
263
264 Ok(result)
265 }
266
267 #[inline]
274 pub fn new_line(
275 document: &PdfDocument<'a>,
276 x1: PdfPoints,
277 y1: PdfPoints,
278 x2: PdfPoints,
279 y2: PdfPoints,
280 stroke_color: PdfColor,
281 stroke_width: PdfPoints,
282 ) -> Result<Self, PdfiumError> {
283 Self::new_line_from_bindings(document.bindings(), x1, y1, x2, y2, stroke_color, stroke_width)
284 }
285
286 #[allow(clippy::too_many_arguments)]
287 #[inline]
288 pub(crate) fn new_bezier_from_bindings(
289 bindings: &'a dyn PdfiumLibraryBindings,
290 x1: PdfPoints,
291 y1: PdfPoints,
292 x2: PdfPoints,
293 y2: PdfPoints,
294 control1_x: PdfPoints,
295 control1_y: PdfPoints,
296 control2_x: PdfPoints,
297 control2_y: PdfPoints,
298 stroke_color: PdfColor,
299 stroke_width: PdfPoints,
300 ) -> Result<Self, PdfiumError> {
301 let mut result = Self::new_from_bindings(bindings, x1, y1, Some(stroke_color), Some(stroke_width), None)?;
302
303 result.bezier_to(x2, y2, control1_x, control1_y, control2_x, control2_y)?;
304
305 Ok(result)
306 }
307
308 #[allow(clippy::too_many_arguments)]
315 #[inline]
316 pub fn new_bezier(
317 document: &PdfDocument<'a>,
318 x1: PdfPoints,
319 y1: PdfPoints,
320 x2: PdfPoints,
321 y2: PdfPoints,
322 control1_x: PdfPoints,
323 control1_y: PdfPoints,
324 control2_x: PdfPoints,
325 control2_y: PdfPoints,
326 stroke_color: PdfColor,
327 stroke_width: PdfPoints,
328 ) -> Result<Self, PdfiumError> {
329 Self::new_bezier_from_bindings(
330 document.bindings(),
331 x1,
332 y1,
333 x2,
334 y2,
335 control1_x,
336 control1_y,
337 control2_x,
338 control2_y,
339 stroke_color,
340 stroke_width,
341 )
342 }
343
344 #[inline]
345 pub(crate) fn new_rect_from_bindings(
346 bindings: &'a dyn PdfiumLibraryBindings,
347 rect: PdfRect,
348 stroke_color: Option<PdfColor>,
349 stroke_width: Option<PdfPoints>,
350 fill_color: Option<PdfColor>,
351 ) -> Result<Self, PdfiumError> {
352 let mut result = Self::new_from_bindings(
353 bindings,
354 rect.left(),
355 rect.bottom(),
356 stroke_color,
357 stroke_width,
358 fill_color,
359 )?;
360
361 result.rect_to(rect.right(), rect.top())?;
362
363 Ok(result)
364 }
365
366 #[inline]
374 pub fn new_rect(
375 document: &PdfDocument<'a>,
376 rect: PdfRect,
377 stroke_color: Option<PdfColor>,
378 stroke_width: Option<PdfPoints>,
379 fill_color: Option<PdfColor>,
380 ) -> Result<Self, PdfiumError> {
381 Self::new_rect_from_bindings(document.bindings(), rect, stroke_color, stroke_width, fill_color)
382 }
383
384 #[inline]
385 pub(crate) fn new_circle_from_bindings(
386 bindings: &'a dyn PdfiumLibraryBindings,
387 rect: PdfRect,
388 stroke_color: Option<PdfColor>,
389 stroke_width: Option<PdfPoints>,
390 fill_color: Option<PdfColor>,
391 ) -> Result<Self, PdfiumError> {
392 let mut result = Self::new_from_bindings(
393 bindings,
394 rect.left(),
395 rect.bottom(),
396 stroke_color,
397 stroke_width,
398 fill_color,
399 )?;
400
401 result.circle_to(rect.right(), rect.top())?;
402
403 Ok(result)
404 }
405
406 #[inline]
414 pub fn new_circle(
415 document: &PdfDocument<'a>,
416 rect: PdfRect,
417 stroke_color: Option<PdfColor>,
418 stroke_width: Option<PdfPoints>,
419 fill_color: Option<PdfColor>,
420 ) -> Result<Self, PdfiumError> {
421 Self::new_circle_from_bindings(document.bindings(), rect, stroke_color, stroke_width, fill_color)
422 }
423
424 #[inline]
425 pub(crate) fn new_circle_at_from_bindings(
426 bindings: &'a dyn PdfiumLibraryBindings,
427 center_x: PdfPoints,
428 center_y: PdfPoints,
429 radius: PdfPoints,
430 stroke_color: Option<PdfColor>,
431 stroke_width: Option<PdfPoints>,
432 fill_color: Option<PdfColor>,
433 ) -> Result<Self, PdfiumError> {
434 Self::new_circle_from_bindings(
435 bindings,
436 PdfRect::new(
437 center_y - radius,
438 center_x - radius,
439 center_y + radius,
440 center_x + radius,
441 ),
442 stroke_color,
443 stroke_width,
444 fill_color,
445 )
446 }
447
448 #[inline]
456 pub fn new_circle_at(
457 document: &PdfDocument<'a>,
458 center_x: PdfPoints,
459 center_y: PdfPoints,
460 radius: PdfPoints,
461 stroke_color: Option<PdfColor>,
462 stroke_width: Option<PdfPoints>,
463 fill_color: Option<PdfColor>,
464 ) -> Result<Self, PdfiumError> {
465 Self::new_circle_at_from_bindings(
466 document.bindings(),
467 center_x,
468 center_y,
469 radius,
470 stroke_color,
471 stroke_width,
472 fill_color,
473 )
474 }
475
476 #[inline]
477 pub(crate) fn new_ellipse_from_bindings(
478 bindings: &'a dyn PdfiumLibraryBindings,
479 rect: PdfRect,
480 stroke_color: Option<PdfColor>,
481 stroke_width: Option<PdfPoints>,
482 fill_color: Option<PdfColor>,
483 ) -> Result<Self, PdfiumError> {
484 let mut result = Self::new_from_bindings(
485 bindings,
486 rect.left(),
487 rect.bottom(),
488 stroke_color,
489 stroke_width,
490 fill_color,
491 )?;
492
493 result.ellipse_to(rect.right(), rect.top())?;
494
495 Ok(result)
496 }
497
498 #[inline]
506 pub fn new_ellipse(
507 document: &PdfDocument<'a>,
508 rect: PdfRect,
509 stroke_color: Option<PdfColor>,
510 stroke_width: Option<PdfPoints>,
511 fill_color: Option<PdfColor>,
512 ) -> Result<Self, PdfiumError> {
513 Self::new_ellipse_from_bindings(document.bindings(), rect, stroke_color, stroke_width, fill_color)
514 }
515
516 #[allow(clippy::too_many_arguments)]
517 #[inline]
518 pub(crate) fn new_ellipse_at_from_bindings(
519 bindings: &'a dyn PdfiumLibraryBindings,
520 center_x: PdfPoints,
521 center_y: PdfPoints,
522 x_radius: PdfPoints,
523 y_radius: PdfPoints,
524 stroke_color: Option<PdfColor>,
525 stroke_width: Option<PdfPoints>,
526 fill_color: Option<PdfColor>,
527 ) -> Result<Self, PdfiumError> {
528 Self::new_ellipse_from_bindings(
529 bindings,
530 PdfRect::new(
531 center_y - y_radius,
532 center_x - x_radius,
533 center_y + y_radius,
534 center_x + x_radius,
535 ),
536 stroke_color,
537 stroke_width,
538 fill_color,
539 )
540 }
541
542 #[allow(clippy::too_many_arguments)]
550 #[inline]
551 pub fn new_ellipse_at(
552 document: &PdfDocument<'a>,
553 center_x: PdfPoints,
554 center_y: PdfPoints,
555 x_radius: PdfPoints,
556 y_radius: PdfPoints,
557 stroke_color: Option<PdfColor>,
558 stroke_width: Option<PdfPoints>,
559 fill_color: Option<PdfColor>,
560 ) -> Result<Self, PdfiumError> {
561 Self::new_ellipse_at_from_bindings(
562 document.bindings(),
563 center_x,
564 center_y,
565 x_radius,
566 y_radius,
567 stroke_color,
568 stroke_width,
569 fill_color,
570 )
571 }
572
573 pub fn move_to(&mut self, x: PdfPoints, y: PdfPoints) -> Result<(), PdfiumError> {
576 if self
577 .bindings()
578 .is_true(self.bindings().FPDFPath_MoveTo(self.object_handle(), x.value, y.value))
579 {
580 self.current_point_x = x;
581 self.current_point_y = y;
582
583 Ok(())
584 } else {
585 Err(PdfiumError::PdfiumLibraryInternalError(PdfiumInternalError::Unknown))
586 }
587 }
588
589 pub fn line_to(&mut self, x: PdfPoints, y: PdfPoints) -> Result<(), PdfiumError> {
592 if self
593 .bindings()
594 .is_true(self.bindings().FPDFPath_LineTo(self.object_handle(), x.value, y.value))
595 {
596 self.current_point_x = x;
597 self.current_point_y = y;
598
599 Ok(())
600 } else {
601 Err(PdfiumError::PdfiumLibraryInternalError(PdfiumInternalError::Unknown))
602 }
603 }
604
605 pub fn bezier_to(
609 &mut self,
610 x: PdfPoints,
611 y: PdfPoints,
612 control1_x: PdfPoints,
613 control1_y: PdfPoints,
614 control2_x: PdfPoints,
615 control2_y: PdfPoints,
616 ) -> Result<(), PdfiumError> {
617 if self.bindings().is_true(self.bindings().FPDFPath_BezierTo(
618 self.object_handle(),
619 control1_x.value,
620 control1_y.value,
621 control2_x.value,
622 control2_y.value,
623 x.value,
624 y.value,
625 )) {
626 self.current_point_x = x;
627 self.current_point_y = y;
628
629 Ok(())
630 } else {
631 Err(PdfiumError::PdfiumLibraryInternalError(PdfiumInternalError::Unknown))
632 }
633 }
634
635 pub fn rect_to(&mut self, x: PdfPoints, y: PdfPoints) -> Result<(), PdfiumError> {
639 let orig_x = self.current_point_x;
640
641 let orig_y = self.current_point_y;
642
643 self.close_path()?;
644 self.line_to(orig_x, y)?;
645 self.line_to(x, y)?;
646 self.line_to(x, orig_y)?;
647 self.close_path()?;
648 self.move_to(x, y)
649 }
650
651 pub fn ellipse_to(&mut self, x: PdfPoints, y: PdfPoints) -> Result<(), PdfiumError> {
655 let x_radius = (x - self.current_point_x) / 2.0;
656
657 let y_radius = (y - self.current_point_y) / 2.0;
658
659 self.close_path()?;
660 self.move_to(self.current_point_x + x_radius, self.current_point_y + y_radius)?;
661 self.ellipse(x_radius, y_radius)?;
662 self.move_to(x, y)
663 }
664
665 pub fn circle_to(&mut self, x: PdfPoints, y: PdfPoints) -> Result<(), PdfiumError> {
673 let radius = (x - self.current_point_x) / 2.0;
674
675 self.move_to(self.current_point_x + radius, self.current_point_y + radius)?;
676 self.ellipse(radius, radius)?;
677 self.move_to(x, y)
678 }
679
680 fn ellipse(&mut self, x_radius: PdfPoints, y_radius: PdfPoints) -> Result<(), PdfiumError> {
683 const C: f32 = 0.551915;
684
685 let x_c = x_radius * C;
686
687 let y_c = y_radius * C;
688
689 let orig_x = self.current_point_x;
690
691 let orig_y = self.current_point_y;
692
693 self.move_to(orig_x - x_radius, orig_y)?;
694 self.bezier_to(
695 orig_x,
696 orig_y + y_radius,
697 orig_x - x_radius,
698 orig_y + y_c,
699 orig_x - x_c,
700 orig_y + y_radius,
701 )?;
702 self.bezier_to(
703 orig_x + x_radius,
704 orig_y,
705 orig_x + x_c,
706 orig_y + y_radius,
707 orig_x + x_radius,
708 orig_y + y_c,
709 )?;
710 self.bezier_to(
711 orig_x,
712 orig_y - y_radius,
713 orig_x + x_radius,
714 orig_y - y_c,
715 orig_x + x_c,
716 orig_y - y_radius,
717 )?;
718 self.bezier_to(
719 orig_x - x_radius,
720 orig_y,
721 orig_x - x_c,
722 orig_y - y_radius,
723 orig_x - x_radius,
724 orig_y - y_c,
725 )?;
726 self.close_path()
727 }
728
729 pub fn close_path(&mut self) -> Result<(), PdfiumError> {
732 if self
733 .bindings
734 .is_true(self.bindings().FPDFPath_Close(self.object_handle))
735 {
736 Ok(())
737 } else {
738 Err(PdfiumError::PdfiumLibraryInternalError(PdfiumInternalError::Unknown))
739 }
740 }
741
742 pub fn fill_mode(&self) -> Result<PdfPathFillMode, PdfiumError> {
745 let mut raw_fill_mode: c_int = 0;
746
747 let mut _raw_stroke: FPDF_BOOL = self.bindings().FALSE();
748
749 if self.bindings().is_true(self.bindings.FPDFPath_GetDrawMode(
750 self.object_handle(),
751 &mut raw_fill_mode,
752 &mut _raw_stroke,
753 )) {
754 PdfPathFillMode::from_pdfium(raw_fill_mode)
755 } else {
756 Err(PdfiumError::PdfiumLibraryInternalError(PdfiumInternalError::Unknown))
757 }
758 }
759
760 pub fn is_stroked(&self) -> Result<bool, PdfiumError> {
766 let mut _raw_fill_mode: c_int = 0;
767
768 let mut raw_stroke: FPDF_BOOL = self.bindings().FALSE();
769
770 if self.bindings().is_true(self.bindings().FPDFPath_GetDrawMode(
771 self.object_handle(),
772 &mut _raw_fill_mode,
773 &mut raw_stroke,
774 )) {
775 Ok(self.bindings().is_true(raw_stroke))
776 } else {
777 Err(PdfiumError::PdfiumLibraryInternalError(PdfiumInternalError::Unknown))
778 }
779 }
780
781 pub fn set_fill_and_stroke_mode(&mut self, fill_mode: PdfPathFillMode, do_stroke: bool) -> Result<(), PdfiumError> {
787 if self.bindings().is_true(self.bindings().FPDFPath_SetDrawMode(
788 self.object_handle(),
789 fill_mode.as_pdfium() as c_int,
790 self.bindings.bool_to_pdfium(do_stroke),
791 )) {
792 Ok(())
793 } else {
794 Err(PdfiumError::PdfiumLibraryInternalError(PdfiumInternalError::Unknown))
795 }
796 }
797
798 #[inline]
800 pub fn segments(&self) -> PdfPagePathObjectSegments<'_> {
801 PdfPagePathObjectSegments::from_pdfium(self.object_handle(), self.bindings())
802 }
803
804 create_transform_setters!(
805 &mut Self,
806 Result<(), PdfiumError>,
807 "this [PdfPagePathObject]",
808 "this [PdfPagePathObject].",
809 "this [PdfPagePathObject],"
810 );
811
812 create_transform_getters!(
813 "this [PdfPagePathObject]",
814 "this [PdfPagePathObject].",
815 "this [PdfPagePathObject],"
816 );
817}
818
819impl<'a> PdfPageObjectPrivate<'a> for PdfPagePathObject<'a> {
820 #[inline]
821 fn object_handle(&self) -> FPDF_PAGEOBJECT {
822 self.object_handle
823 }
824
825 #[inline]
826 fn ownership(&self) -> &PdfPageObjectOwnership {
827 &self.ownership
828 }
829
830 #[inline]
831 fn set_ownership(&mut self, ownership: PdfPageObjectOwnership) {
832 self.ownership = ownership;
833 }
834
835 #[inline]
836 fn bindings(&self) -> &dyn PdfiumLibraryBindings {
837 self.bindings
838 }
839
840 #[inline]
841 fn is_copyable_impl(&self) -> bool {
842 !self
843 .segments()
844 .iter()
845 .any(|segment| segment.segment_type() == PdfPathSegmentType::BezierTo)
846 }
847
848 fn try_copy_impl<'b>(
849 &self,
850 _: FPDF_DOCUMENT,
851 bindings: &'b dyn PdfiumLibraryBindings,
852 ) -> Result<PdfPageObject<'b>, PdfiumError> {
853 let mut copy =
854 PdfPagePathObject::new_from_bindings(bindings, PdfPoints::ZERO, PdfPoints::ZERO, None, None, None)?;
855
856 copy.set_fill_and_stroke_mode(self.fill_mode()?, self.is_stroked()?)?;
857 copy.set_fill_color(self.fill_color()?)?;
858 copy.set_stroke_color(self.stroke_color()?)?;
859 copy.set_stroke_width(self.stroke_width()?)?;
860 copy.set_line_join(self.line_join()?)?;
861 copy.set_line_cap(self.line_cap()?)?;
862
863 for segment in self.segments().iter() {
864 if segment.segment_type() == PdfPathSegmentType::Unknown {
865 return Err(PdfiumError::PathObjectUnknownSegmentTypeNotCopyable);
866 } else if segment.segment_type() == PdfPathSegmentType::BezierTo {
867 return Err(PdfiumError::PathObjectBezierControlPointsNotCopyable);
868 } else {
869 match segment.segment_type() {
870 PdfPathSegmentType::Unknown | PdfPathSegmentType::BezierTo => {}
871 PdfPathSegmentType::LineTo => copy.line_to(segment.x(), segment.y())?,
872 PdfPathSegmentType::MoveTo => copy.move_to(segment.x(), segment.y())?,
873 }
874
875 if segment.is_close() {
876 copy.close_path()?;
877 }
878 }
879 }
880
881 copy.reset_matrix(self.matrix()?)?;
882
883 Ok(PdfPageObject::Path(copy))
884 }
885}
886
887pub struct PdfPagePathObjectSegments<'a> {
894 handle: FPDF_PAGEOBJECT,
895 matrix: Option<PdfMatrix>,
896 bindings: &'a dyn PdfiumLibraryBindings,
897}
898
899impl<'a> PdfPagePathObjectSegments<'a> {
900 #[inline]
901 pub(crate) fn from_pdfium(handle: FPDF_PAGEOBJECT, bindings: &'a dyn PdfiumLibraryBindings) -> Self {
902 Self {
903 handle,
904 matrix: None,
905 bindings,
906 }
907 }
908
909 #[inline]
912 pub fn transform(&self, matrix: PdfMatrix) -> PdfPagePathObjectSegments<'a> {
913 Self {
914 handle: self.handle,
915 matrix: Some(matrix),
916 bindings: self.bindings,
917 }
918 }
919
920 #[inline]
923 pub fn raw(&self) -> PdfPagePathObjectSegments<'a> {
924 Self {
925 handle: self.handle,
926 matrix: None,
927 bindings: self.bindings,
928 }
929 }
930}
931
932impl<'a> PdfPathSegments<'a> for PdfPagePathObjectSegments<'a> {
933 #[inline]
934 fn bindings(&self) -> &'a dyn PdfiumLibraryBindings {
935 self.bindings
936 }
937
938 #[inline]
939 fn len(&self) -> PdfPathSegmentIndex {
940 self.bindings()
941 .FPDFPath_CountSegments(self.handle)
942 .try_into()
943 .unwrap_or(0)
944 }
945
946 fn get(&self, index: PdfPathSegmentIndex) -> Result<PdfPathSegment<'a>, PdfiumError> {
947 let handle = self.bindings().FPDFPath_GetPathSegment(self.handle, index as c_int);
948
949 if handle.is_null() {
950 Err(PdfiumError::PdfiumLibraryInternalError(PdfiumInternalError::Unknown))
951 } else {
952 Ok(PdfPathSegment::from_pdfium(handle, self.matrix, self.bindings()))
953 }
954 }
955
956 #[inline]
957 fn iter(&'a self) -> PdfPathSegmentsIterator<'a> {
958 PdfPathSegmentsIterator::new(self)
959 }
960}
961
962impl<'a> Drop for PdfPagePathObject<'a> {
963 fn drop(&mut self) {
965 self.drop_impl();
966 }
967}