1use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign};
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize)]
7pub struct PdfRect {
8 pub x: f64,
10 pub y: f64,
12 pub width: f64,
14 pub height: f64,
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Deserialize)]
20pub struct PdfPoint {
21 pub x: f64,
23 pub y: f64,
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Deserialize)]
29pub struct PdfSize {
30 pub width: f64,
32 pub height: f64,
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Deserialize)]
38pub struct PdfEdgeInsets {
39 pub top: f64,
41 pub left: f64,
43 pub bottom: f64,
45 pub right: f64,
47}
48
49#[derive(Debug, Clone, Copy, PartialEq, Deserialize)]
51pub struct PdfColor {
52 pub red: f64,
54 pub green: f64,
56 pub blue: f64,
58 pub alpha: f64,
60}
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
64pub struct PdfTextRange {
65 pub location: usize,
67 pub length: usize,
69}
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq)]
73#[repr(i32)]
74pub enum DisplayBox {
75 MediaBox = 0,
77 CropBox = 1,
79 BleedBox = 2,
81 TrimBox = 3,
83 ArtBox = 4,
85}
86
87impl DisplayBox {
88 #[must_use]
90 pub const fn as_raw(self) -> i32 {
91 self as i32
92 }
93}
94
95#[derive(Debug, Clone, Copy, PartialEq, Eq)]
97#[repr(i32)]
98pub enum PdfBorderStyle {
99 Solid = 0,
101 Dashed = 1,
103 Beveled = 2,
105 Inset = 3,
107 Underline = 4,
109}
110
111impl PdfBorderStyle {
112 #[must_use]
114 pub const fn from_raw(raw: i32) -> Option<Self> {
115 match raw {
116 0 => Some(Self::Solid),
117 1 => Some(Self::Dashed),
118 2 => Some(Self::Beveled),
119 3 => Some(Self::Inset),
120 4 => Some(Self::Underline),
121 _ => None,
122 }
123 }
124}
125
126#[derive(Debug, Clone, Copy, PartialEq, Eq)]
128#[repr(i32)]
129pub enum PdfActionNamedName {
130 None = 0,
132 NextPage = 1,
134 PreviousPage = 2,
136 FirstPage = 3,
138 LastPage = 4,
140 GoBack = 5,
142 GoForward = 6,
144 GoToPage = 7,
146 Find = 8,
148 Print = 9,
150 ZoomIn = 10,
152 ZoomOut = 11,
154}
155
156impl PdfActionNamedName {
157 #[must_use]
159 pub const fn as_raw(self) -> i32 {
160 self as i32
161 }
162
163 #[must_use]
165 pub const fn from_raw(raw: i32) -> Option<Self> {
166 match raw {
167 0 => Some(Self::None),
168 1 => Some(Self::NextPage),
169 2 => Some(Self::PreviousPage),
170 3 => Some(Self::FirstPage),
171 4 => Some(Self::LastPage),
172 5 => Some(Self::GoBack),
173 6 => Some(Self::GoForward),
174 7 => Some(Self::GoToPage),
175 8 => Some(Self::Find),
176 9 => Some(Self::Print),
177 10 => Some(Self::ZoomIn),
178 11 => Some(Self::ZoomOut),
179 _ => None,
180 }
181 }
182}
183
184#[derive(Debug, Clone, Copy, PartialEq, Eq)]
186#[repr(i32)]
187pub enum PdfLineStyle {
188 None = 0,
190 Square = 1,
192 Circle = 2,
194 Diamond = 3,
196 OpenArrow = 4,
198 ClosedArrow = 5,
200}
201
202impl PdfLineStyle {
203 #[must_use]
205 pub const fn from_raw(raw: i32) -> Option<Self> {
206 match raw {
207 0 => Some(Self::None),
208 1 => Some(Self::Square),
209 2 => Some(Self::Circle),
210 3 => Some(Self::Diamond),
211 4 => Some(Self::OpenArrow),
212 5 => Some(Self::ClosedArrow),
213 _ => None,
214 }
215 }
216}
217
218#[derive(Debug, Clone, Copy, PartialEq, Eq)]
220#[repr(i32)]
221pub enum PdfTextAnnotationIconType {
222 Comment = 0,
224 Key = 1,
226 Note = 2,
228 Help = 3,
230 NewParagraph = 4,
232 Paragraph = 5,
234 Insert = 6,
236}
237
238impl PdfTextAnnotationIconType {
239 #[must_use]
241 pub const fn as_raw(self) -> i32 {
242 self as i32
243 }
244
245 #[must_use]
247 pub const fn from_raw(raw: i32) -> Option<Self> {
248 match raw {
249 0 => Some(Self::Comment),
250 1 => Some(Self::Key),
251 2 => Some(Self::Note),
252 3 => Some(Self::Help),
253 4 => Some(Self::NewParagraph),
254 5 => Some(Self::Paragraph),
255 6 => Some(Self::Insert),
256 _ => None,
257 }
258 }
259}
260
261#[derive(Debug, Clone, Copy, PartialEq, Eq)]
263#[repr(i32)]
264pub enum PdfMarkupType {
265 Highlight = 0,
267 StrikeOut = 1,
269 Underline = 2,
271 Redact = 3,
273}
274
275impl PdfMarkupType {
276 #[must_use]
278 pub const fn from_raw(raw: i32) -> Option<Self> {
279 match raw {
280 0 => Some(Self::Highlight),
281 1 => Some(Self::StrikeOut),
282 2 => Some(Self::Underline),
283 3 => Some(Self::Redact),
284 _ => None,
285 }
286 }
287}
288
289#[derive(Debug, Clone, Copy, PartialEq, Eq)]
291#[repr(i32)]
292pub enum PdfDisplayMode {
293 SinglePage = 0,
295 SinglePageContinuous = 1,
297 TwoUp = 2,
299 TwoUpContinuous = 3,
301}
302
303impl PdfDisplayMode {
304 #[must_use]
306 pub const fn from_raw(raw: i32) -> Option<Self> {
307 match raw {
308 0 => Some(Self::SinglePage),
309 1 => Some(Self::SinglePageContinuous),
310 2 => Some(Self::TwoUp),
311 3 => Some(Self::TwoUpContinuous),
312 _ => None,
313 }
314 }
315}
316
317#[derive(Debug, Clone, Copy, PartialEq, Eq)]
319#[repr(i32)]
320pub enum PdfDisplayDirection {
321 Vertical = 0,
323 Horizontal = 1,
325}
326
327impl PdfDisplayDirection {
328 #[must_use]
330 pub const fn from_raw(raw: i32) -> Option<Self> {
331 match raw {
332 0 => Some(Self::Vertical),
333 1 => Some(Self::Horizontal),
334 _ => None,
335 }
336 }
337}
338
339#[derive(Debug, Clone, Copy, PartialEq, Eq)]
341#[repr(i32)]
342pub enum PdfInterpolationQuality {
343 None = 0,
345 Low = 1,
347 High = 2,
349}
350
351impl PdfInterpolationQuality {
352 #[must_use]
354 pub const fn from_raw(raw: i32) -> Option<Self> {
355 match raw {
356 0 => Some(Self::None),
357 1 => Some(Self::Low),
358 2 => Some(Self::High),
359 _ => None,
360 }
361 }
362}
363
364#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
366pub struct PdfAreaOfInterest(u64);
367
368impl PdfAreaOfInterest {
369 pub const NONE: Self = Self(0);
371 pub const PAGE: Self = Self(1 << 0);
373 pub const TEXT: Self = Self(1 << 1);
375 pub const ANNOTATION: Self = Self(1 << 2);
377 pub const LINK: Self = Self(1 << 3);
379 pub const CONTROL: Self = Self(1 << 4);
381 pub const TEXT_FIELD: Self = Self(1 << 5);
383 pub const ICON: Self = Self(1 << 6);
385 pub const POPUP: Self = Self(1 << 7);
387 pub const IMAGE: Self = Self(1 << 8);
389 pub const ANY: Self = Self(i64::MAX as u64);
391
392 #[must_use]
394 pub const fn from_bits(bits: u64) -> Self {
395 Self(bits)
396 }
397
398 #[must_use]
400 pub const fn bits(self) -> u64 {
401 self.0
402 }
403
404 #[must_use]
406 pub const fn is_empty(self) -> bool {
407 self.0 == 0
408 }
409
410 #[must_use]
412 pub const fn contains(self, other: Self) -> bool {
413 (self.0 & other.0) == other.0
414 }
415
416 #[must_use]
418 pub const fn intersects(self, other: Self) -> bool {
419 (self.0 & other.0) != 0
420 }
421}
422
423impl BitOr for PdfAreaOfInterest {
424 type Output = Self;
425
426 fn bitor(self, rhs: Self) -> Self::Output {
427 Self(self.0 | rhs.0)
428 }
429}
430
431impl BitOrAssign for PdfAreaOfInterest {
432 fn bitor_assign(&mut self, rhs: Self) {
433 self.0 |= rhs.0;
434 }
435}
436
437impl BitAnd for PdfAreaOfInterest {
438 type Output = Self;
439
440 fn bitand(self, rhs: Self) -> Self::Output {
441 Self(self.0 & rhs.0)
442 }
443}
444
445impl BitAndAssign for PdfAreaOfInterest {
446 fn bitand_assign(&mut self, rhs: Self) {
447 self.0 &= rhs.0;
448 }
449}
450
451#[derive(Debug, Clone, Copy, PartialEq, Eq)]
453#[repr(i32)]
454pub enum PdfWidgetControlType {
455 Unknown = -1,
457 PushButton = 0,
459 RadioButton = 1,
461 CheckBox = 2,
463}
464
465impl PdfWidgetControlType {
466 #[must_use]
468 pub const fn from_raw(raw: i32) -> Option<Self> {
469 match raw {
470 -1 => Some(Self::Unknown),
471 0 => Some(Self::PushButton),
472 1 => Some(Self::RadioButton),
473 2 => Some(Self::CheckBox),
474 _ => None,
475 }
476 }
477}
478
479#[derive(Debug, Clone, Copy, PartialEq, Eq)]
481#[repr(i32)]
482pub enum PdfWidgetCellState {
483 Mixed = -1,
485 Off = 0,
487 On = 1,
489}
490
491impl PdfWidgetCellState {
492 #[must_use]
494 pub const fn as_raw(self) -> i32 {
495 self as i32
496 }
497
498 #[must_use]
500 pub const fn from_raw(raw: i32) -> Option<Self> {
501 match raw {
502 -1 => Some(Self::Mixed),
503 0 => Some(Self::Off),
504 1 => Some(Self::On),
505 _ => None,
506 }
507 }
508}
509
510#[derive(Debug, Clone, Copy, PartialEq, Eq)]
512#[repr(i32)]
513pub enum PdfPrintScalingMode {
514 None = 0,
516 ToFit = 1,
518 DownToFit = 2,
520}
521
522impl PdfPrintScalingMode {
523 #[must_use]
525 pub const fn as_raw(self) -> i32 {
526 self as i32
527 }
528
529 #[must_use]
531 pub const fn from_raw(raw: i32) -> Option<Self> {
532 match raw {
533 0 => Some(Self::None),
534 1 => Some(Self::ToFit),
535 2 => Some(Self::DownToFit),
536 _ => None,
537 }
538 }
539}
540
541#[derive(Debug, Clone, Copy, PartialEq, Eq)]
543#[repr(i32)]
544pub enum PdfDocumentPermissions {
545 None = 0,
547 User = 1,
549 Owner = 2,
551}
552
553impl PdfDocumentPermissions {
554 #[must_use]
556 pub const fn from_raw(raw: i32) -> Option<Self> {
557 match raw {
558 0 => Some(Self::None),
559 1 => Some(Self::User),
560 2 => Some(Self::Owner),
561 _ => None,
562 }
563 }
564}
565
566#[derive(Debug, Clone, Copy, PartialEq, Eq)]
568#[repr(u64)]
569pub enum PdfSelectionGranularity {
570 Character = 0,
572 Word = 1,
574 Line = 2,
576}
577
578impl PdfSelectionGranularity {
579 #[must_use]
581 pub const fn as_raw(self) -> u64 {
582 self as u64
583 }
584
585 #[must_use]
587 pub const fn from_raw(raw: u64) -> Option<Self> {
588 match raw {
589 0 => Some(Self::Character),
590 1 => Some(Self::Word),
591 2 => Some(Self::Line),
592 _ => None,
593 }
594 }
595}
596
597#[derive(Debug, Clone, Deserialize)]
599pub struct PdfDocumentInfo {
600 pub document_url: Option<String>,
602 pub major_version: i32,
604 pub minor_version: i32,
606 pub is_encrypted: bool,
608 pub is_locked: bool,
610 pub permissions_status: i32,
612 pub access_permissions: u64,
614 pub allows_printing: bool,
616 pub allows_copying: bool,
618 pub allows_document_changes: bool,
620 pub allows_document_assembly: bool,
622 pub allows_content_accessibility: bool,
624 pub allows_commenting: bool,
626 pub allows_form_field_entry: bool,
628 pub page_class: String,
630}
631
632impl PdfDocumentInfo {
633 #[must_use]
635 pub fn permissions_status_enum(&self) -> Option<PdfDocumentPermissions> {
636 PdfDocumentPermissions::from_raw(self.permissions_status)
637 }
638}
639
640#[derive(Debug, Clone, Deserialize)]
642pub struct PdfDocumentAttributes {
643 pub title: Option<String>,
645 pub author: Option<String>,
647 pub subject: Option<String>,
649 pub creator: Option<String>,
651 pub producer: Option<String>,
653 pub creation_date: Option<String>,
655 pub modification_date: Option<String>,
657 pub keywords: Option<Vec<String>>,
659}
660
661#[derive(Debug, Clone, Default, PartialEq, Serialize)]
663pub struct PdfPageImageInitializationOptions {
664 pub media_box: Option<PdfRect>,
666 pub rotation: Option<i32>,
668 pub upscale_if_smaller: bool,
670 pub compression_quality: Option<f64>,
672}
673
674impl PdfPageImageInitializationOptions {
675 pub fn with_media_box(mut self, value: PdfRect) -> Self {
677 self.media_box = Some(value);
678 self
679 }
680
681 pub fn with_rotation(mut self, value: i32) -> Self {
683 self.rotation = Some(value);
684 self
685 }
686
687 pub fn with_upscale_if_smaller(mut self, value: bool) -> Self {
689 self.upscale_if_smaller = value;
690 self
691 }
692
693 pub fn with_compression_quality(mut self, value: f64) -> Self {
695 self.compression_quality = Some(value);
696 self
697 }
698}
699
700#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)]
702pub struct PdfDocumentWriteOptions {
703 pub owner_password: Option<String>,
705 pub user_password: Option<String>,
707 pub access_permissions: Option<u64>,
709 pub burn_in_annotations: bool,
711 pub save_text_from_ocr: bool,
713 pub save_images_as_jpeg: bool,
715 pub optimize_images_for_screen: bool,
717}
718
719impl PdfDocumentWriteOptions {
720 pub fn with_owner_password(mut self, value: impl Into<String>) -> Self {
722 self.owner_password = Some(value.into());
723 self
724 }
725
726 pub fn with_user_password(mut self, value: impl Into<String>) -> Self {
728 self.user_password = Some(value.into());
729 self
730 }
731
732 pub fn with_access_permissions(mut self, value: u64) -> Self {
734 self.access_permissions = Some(value);
735 self
736 }
737
738 pub fn with_burn_in_annotations(mut self, value: bool) -> Self {
740 self.burn_in_annotations = value;
741 self
742 }
743
744 pub fn with_save_text_from_ocr(mut self, value: bool) -> Self {
746 self.save_text_from_ocr = value;
747 self
748 }
749
750 pub fn with_save_images_as_jpeg(mut self, value: bool) -> Self {
752 self.save_images_as_jpeg = value;
753 self
754 }
755
756 pub fn with_optimize_images_for_screen(mut self, value: bool) -> Self {
758 self.optimize_images_for_screen = value;
759 self
760 }
761}
762
763#[derive(Debug, Clone, Deserialize)]
765pub struct PdfBorderInfo {
766 pub style: i32,
768 pub line_width: f64,
770 pub dash_pattern: Option<Vec<f64>>,
772}
773
774impl PdfBorderInfo {
775 #[must_use]
777 pub fn style_enum(&self) -> Option<PdfBorderStyle> {
778 PdfBorderStyle::from_raw(self.style)
779 }
780}
781
782#[derive(Debug, Clone, Deserialize)]
784pub struct PdfAnnotationInfo {
785 pub annotation_type: Option<String>,
787 pub bounds: PdfRect,
789 pub contents: Option<String>,
791 pub should_display: bool,
793 pub should_print: bool,
795 pub has_appearance_stream: bool,
797 pub user_name: Option<String>,
799 pub modification_date: Option<String>,
801 pub color: Option<PdfColor>,
803 pub highlighted: bool,
805 pub action_type: Option<String>,
807 pub border: Option<PdfBorderInfo>,
809}
810
811#[derive(Debug, Clone, Deserialize)]
813pub struct PdfDestinationInfo {
814 pub page_label: Option<String>,
816 pub page_index: Option<usize>,
818 pub point: PdfPoint,
820 pub zoom: f64,
822}
823
824#[derive(Debug, Clone, Deserialize)]
826pub struct PdfAppearanceCharacteristicsInfo {
827 pub control_type: i32,
829 pub background_color: Option<PdfColor>,
831 pub border_color: Option<PdfColor>,
833 pub rotation: i32,
835 pub caption: Option<String>,
837 pub rollover_caption: Option<String>,
839 pub down_caption: Option<String>,
841}
842
843impl PdfAppearanceCharacteristicsInfo {
844 #[must_use]
846 pub fn control_type_enum(&self) -> Option<PdfWidgetControlType> {
847 PdfWidgetControlType::from_raw(self.control_type)
848 }
849}
850
851#[derive(Debug, Clone, Deserialize)]
853pub struct PdfViewInfo {
854 pub display_mode: i32,
856 pub display_direction: i32,
858 pub displays_page_breaks: bool,
860 pub page_break_margins: PdfEdgeInsets,
862 pub display_box: i32,
864 pub displays_as_book: bool,
866 pub displays_rtl: bool,
868 pub background_color: Option<PdfColor>,
870 pub interpolation_quality: i32,
872 pub page_shadows_enabled: bool,
874 pub scale_factor: f64,
876 pub min_scale_factor: f64,
878 pub max_scale_factor: f64,
880 pub auto_scales: bool,
882 pub scale_factor_for_size_to_fit: f64,
884 pub in_markup_mode: bool,
886 pub has_document_view: bool,
888 pub visible_page_count: usize,
890 pub current_page_label: Option<String>,
892}
893
894impl PdfViewInfo {
895 #[must_use]
897 pub fn display_mode_enum(&self) -> Option<PdfDisplayMode> {
898 PdfDisplayMode::from_raw(self.display_mode)
899 }
900
901 #[must_use]
903 pub fn display_direction_enum(&self) -> Option<PdfDisplayDirection> {
904 PdfDisplayDirection::from_raw(self.display_direction)
905 }
906
907 #[must_use]
909 pub fn interpolation_quality_enum(&self) -> Option<PdfInterpolationQuality> {
910 PdfInterpolationQuality::from_raw(self.interpolation_quality)
911 }
912
913 #[must_use]
915 pub fn display_box_enum(&self) -> Option<DisplayBox> {
916 match self.display_box {
917 0 => Some(DisplayBox::MediaBox),
918 1 => Some(DisplayBox::CropBox),
919 2 => Some(DisplayBox::BleedBox),
920 3 => Some(DisplayBox::TrimBox),
921 4 => Some(DisplayBox::ArtBox),
922 _ => None,
923 }
924 }
925}
926
927#[derive(Debug, Clone, Copy, PartialEq, Eq)]
929#[repr(i32)]
930pub enum PdfThumbnailLayoutMode {
931 Vertical = 0,
933 Horizontal = 1,
935}
936
937impl PdfThumbnailLayoutMode {
938 #[must_use]
940 pub const fn as_raw(self) -> i32 {
941 self as i32
942 }
943
944 #[must_use]
946 pub const fn from_raw(raw: i32) -> Option<Self> {
947 match raw {
948 0 => Some(Self::Vertical),
949 1 => Some(Self::Horizontal),
950 _ => None,
951 }
952 }
953}
954
955#[derive(Debug, Clone, Deserialize)]
957pub struct PdfThumbnailViewInfo {
958 pub has_pdf_view: bool,
960 pub background_color: Option<PdfColor>,
962 pub selected_pages_count: usize,
964 pub thumbnail_size: PdfSize,
966 pub maximum_number_of_columns: usize,
968 pub allows_dragging: bool,
970 pub allows_multiple_selection: bool,
972}
973
974#[cfg(test)]
975mod tests {
976 use super::{
977 DisplayBox, PdfActionNamedName, PdfAreaOfInterest, PdfBorderStyle, PdfColor,
978 PdfDisplayDirection, PdfDisplayMode, PdfDocumentWriteOptions,
979 PdfPageImageInitializationOptions, PdfInterpolationQuality, PdfLineStyle, PdfMarkupType,
980 PdfPoint, PdfRect, PdfSelectionGranularity, PdfSize, PdfTextAnnotationIconType,
981 PdfThumbnailLayoutMode, PdfWidgetCellState,
982 };
983
984 fn assert_close(left: f64, right: f64) {
985 assert!((left - right).abs() < f64::EPSILON, "expected {left} to match {right}");
986 }
987
988 #[test]
989 fn geometry_wrappers_preserve_field_values() {
990 let rect = PdfRect {
991 x: 1.0,
992 y: 2.0,
993 width: 3.0,
994 height: 4.0,
995 };
996 let point = PdfPoint { x: -1.0, y: 5.0 };
997 let size = PdfSize {
998 width: 8.0,
999 height: 9.0,
1000 };
1001 let color = PdfColor {
1002 red: 0.1,
1003 green: 0.2,
1004 blue: 0.3,
1005 alpha: 0.4,
1006 };
1007
1008 assert_close(rect.x, 1.0);
1009 assert_close(rect.y, 2.0);
1010 assert_close(rect.width, 3.0);
1011 assert_close(rect.height, 4.0);
1012 assert_close(point.x, -1.0);
1013 assert_close(point.y, 5.0);
1014 assert_close(size.width, 8.0);
1015 assert_close(size.height, 9.0);
1016 assert_close(color.red, 0.1);
1017 assert_close(color.green, 0.2);
1018 assert_close(color.blue, 0.3);
1019 assert_close(color.alpha, 0.4);
1020 }
1021
1022 #[test]
1023 fn action_and_annotation_enums_round_trip_raw_values() {
1024 assert_eq!(DisplayBox::CropBox.as_raw(), 1);
1025 assert_eq!(PdfBorderStyle::from_raw(4), Some(PdfBorderStyle::Underline));
1026 assert_eq!(PdfBorderStyle::from_raw(99), None);
1027 assert_eq!(PdfActionNamedName::GoToPage.as_raw(), 7);
1028 assert_eq!(PdfActionNamedName::from_raw(7), Some(PdfActionNamedName::GoToPage));
1029 assert_eq!(PdfLineStyle::from_raw(5), Some(PdfLineStyle::ClosedArrow));
1030 assert_eq!(PdfTextAnnotationIconType::Insert.as_raw(), 6);
1031 assert_eq!(PdfTextAnnotationIconType::from_raw(6), Some(PdfTextAnnotationIconType::Insert));
1032 assert_eq!(PdfMarkupType::from_raw(3), Some(PdfMarkupType::Redact));
1033 }
1034
1035 #[test]
1036 fn view_related_enums_round_trip_raw_values() {
1037 assert_eq!(PdfDisplayMode::from_raw(3), Some(PdfDisplayMode::TwoUpContinuous));
1038 assert_eq!(PdfDisplayDirection::from_raw(1), Some(PdfDisplayDirection::Horizontal));
1039 assert_eq!(PdfInterpolationQuality::from_raw(2), Some(PdfInterpolationQuality::High));
1040 assert_eq!(PdfWidgetCellState::Mixed.as_raw(), -1);
1041 assert_eq!(PdfWidgetCellState::from_raw(-1), Some(PdfWidgetCellState::Mixed));
1042 assert_eq!(PdfSelectionGranularity::Line.as_raw(), 2);
1043 assert_eq!(PdfSelectionGranularity::from_raw(2), Some(PdfSelectionGranularity::Line));
1044 assert_eq!(PdfThumbnailLayoutMode::Horizontal.as_raw(), 1);
1045 assert_eq!(PdfThumbnailLayoutMode::from_raw(1), Some(PdfThumbnailLayoutMode::Horizontal));
1046 }
1047
1048 #[test]
1049 fn area_of_interest_bitflags_combine_and_mask() {
1050 let mut area = PdfAreaOfInterest::PAGE | PdfAreaOfInterest::TEXT;
1051 area |= PdfAreaOfInterest::LINK;
1052
1053 assert!(!PdfAreaOfInterest::NONE.intersects(PdfAreaOfInterest::PAGE));
1054 assert!(area.contains(PdfAreaOfInterest::PAGE));
1055 assert!(area.contains(PdfAreaOfInterest::TEXT));
1056 assert!(area.intersects(PdfAreaOfInterest::LINK));
1057 assert!(!area.contains(PdfAreaOfInterest::IMAGE));
1058 assert_eq!((area & PdfAreaOfInterest::TEXT).bits(), PdfAreaOfInterest::TEXT.bits());
1059 assert!(!PdfAreaOfInterest::NONE.bits().eq(&PdfAreaOfInterest::ANY.bits()));
1060 }
1061
1062 #[test]
1063 fn builder_options_capture_selected_values() {
1064 let image_options = PdfPageImageInitializationOptions::default()
1065 .with_media_box(PdfRect {
1066 x: 0.0,
1067 y: 1.0,
1068 width: 200.0,
1069 height: 100.0,
1070 })
1071 .with_rotation(90)
1072 .with_upscale_if_smaller(true)
1073 .with_compression_quality(0.8);
1074 let write_options = PdfDocumentWriteOptions::default()
1075 .with_owner_password("owner")
1076 .with_user_password("user")
1077 .with_access_permissions(0x15)
1078 .with_burn_in_annotations(true)
1079 .with_save_text_from_ocr(true)
1080 .with_save_images_as_jpeg(true)
1081 .with_optimize_images_for_screen(true);
1082
1083 assert_eq!(image_options.rotation, Some(90));
1084 assert!(image_options.upscale_if_smaller);
1085 assert_close(
1086 image_options
1087 .compression_quality
1088 .expect("compression quality should be set"),
1089 0.8,
1090 );
1091 assert_eq!(write_options.owner_password.as_deref(), Some("owner"));
1092 assert_eq!(write_options.user_password.as_deref(), Some("user"));
1093 assert_eq!(write_options.access_permissions, Some(0x15));
1094 assert!(write_options.burn_in_annotations);
1095 assert!(write_options.save_text_from_ocr);
1096 assert!(write_options.save_images_as_jpeg);
1097 assert!(write_options.optimize_images_for_screen);
1098 }
1099}