1use crate::cos::object::{COSArray, COSDictionary, COSName, COSObject, ObjectId};
2use crate::pd::rectangle::PDRectangle;
3use crate::pd::resources::PDResources;
4
5#[derive(Debug, Clone)]
7pub struct PDPage {
8 pub dict: COSDictionary,
9 pub page_id: Option<ObjectId>,
10 pub resources: PDResources,
11}
12
13impl PDPage {
14 pub fn new(media_box: PDRectangle) -> Self {
16 let mut dict = COSDictionary::new();
17 dict.set("Type", COSName::new("Page"));
18 dict.set("MediaBox", media_box);
19
20 let resources = PDResources::new();
21 dict.set("Resources", resources.dict.clone());
22
23 Self {
24 dict,
25 page_id: None,
26 resources,
27 }
28 }
29
30 pub fn from_dict(dict: COSDictionary, page_id: ObjectId) -> Self {
32 let resources_dict = dict.get_dict("Resources").cloned().unwrap_or_default();
33 let resources = PDResources::from_dict(resources_dict);
34
35 Self {
36 dict,
37 page_id: Some(page_id),
38 resources,
39 }
40 }
41
42 pub fn media_box(&self) -> PDRectangle {
43 self.dict
44 .get_array("MediaBox")
45 .and_then(PDRectangle::from_cos_array)
46 .unwrap_or(PDRectangle::A4)
47 }
48
49 pub fn set_media_box(&mut self, rect: PDRectangle) {
50 self.dict.set("MediaBox", rect);
51 }
52
53 pub fn crop_box(&self) -> PDRectangle {
54 self.dict
55 .get_array("CropBox")
56 .and_then(PDRectangle::from_cos_array)
57 .unwrap_or_else(|| self.media_box())
58 }
59
60 pub fn set_crop_box(&mut self, rect: PDRectangle) {
61 self.dict.set("CropBox", rect);
62 }
63
64 pub fn rotation(&self) -> i32 {
65 self.dict.get_integer("Rotate").unwrap_or(0) as i32
66 }
67
68 pub fn set_rotation(&mut self, rotation: i32) {
69 let normalized = ((rotation % 360) + 360) % 360;
71 self.dict.set("Rotate", normalized as i64);
72 }
73
74 pub fn sync_resources(&mut self) {
76 self.dict.set("Resources", self.resources.dict.clone());
77 }
78
79 pub fn content_stream_ids(&self) -> Vec<ObjectId> {
81 match self.dict.get("Contents") {
82 Some(COSObject::Reference(id)) => vec![*id],
83 Some(COSObject::Array(arr)) => {
84 arr.iter().filter_map(|item| item.as_reference()).collect()
85 }
86 _ => Vec::new(),
87 }
88 }
89
90 pub fn set_contents(&mut self, content_ref: ObjectId) {
92 self.dict.set("Contents", content_ref);
93 }
94
95 pub fn set_contents_array(&mut self, content_refs: Vec<ObjectId>) {
97 let mut arr = COSArray::new();
98 for id in content_refs {
99 arr.push(id);
100 }
101 self.dict.set("Contents", arr);
102 }
103}