rust_pdf_box/pd/
catalog.rs1use crate::cos::document::COSDocument;
2use crate::cos::object::{COSArray, COSDictionary, COSName, ObjectId};
3use crate::error::{PdfError, PdfResult};
4
5#[derive(Debug, Clone)]
7pub struct PDDocumentCatalog {
8 pub catalog_id: ObjectId,
9 pub pages_id: ObjectId,
10}
11
12impl PDDocumentCatalog {
13 pub fn new(cos_doc: &mut COSDocument) -> Self {
15 let pages_id = cos_doc.allocate_id();
16 let mut pages_dict = COSDictionary::new();
17 pages_dict.set("Type", COSName::new("Pages"));
18 pages_dict.set("Kids", COSArray::new());
19 pages_dict.set("Count", 0);
20 cos_doc.set_object(pages_id, pages_dict);
21
22 let catalog_id = cos_doc.allocate_id();
23 let mut cat_dict = COSDictionary::new();
24 cat_dict.set("Type", COSName::new("Catalog"));
25 cat_dict.set("Pages", pages_id);
26 cos_doc.set_object(catalog_id, cat_dict);
27
28 cos_doc.trailer.set("Root", catalog_id);
29
30 Self {
31 catalog_id,
32 pages_id,
33 }
34 }
35
36 pub fn from_doc(cos_doc: &COSDocument) -> PdfResult<Self> {
38 let catalog_id = cos_doc
39 .trailer
40 .get_reference("Root")
41 .ok_or_else(|| PdfError::MissingEntry("Trailer missing /Root".to_string()))?;
42
43 let cat_dict = cos_doc
44 .get_catalog()
45 .ok_or_else(|| PdfError::MissingEntry("Root is not a dictionary".to_string()))?;
46
47 let pages_id = cat_dict.get_reference("Pages").ok_or_else(|| {
48 PdfError::MissingEntry("Catalog missing /Pages reference".to_string())
49 })?;
50
51 Ok(Self {
52 catalog_id,
53 pages_id,
54 })
55 }
56
57 pub fn collect_page_ids(&self, cos_doc: &COSDocument) -> Vec<ObjectId> {
59 let mut page_ids = Vec::new();
60 self.collect_pages_recursive(cos_doc, self.pages_id, &mut page_ids);
61 page_ids
62 }
63
64 fn collect_pages_recursive(
65 &self,
66 cos_doc: &COSDocument,
67 node_id: ObjectId,
68 page_ids: &mut Vec<ObjectId>,
69 ) {
70 if let Some(obj) = cos_doc.get_object(node_id) {
71 if let Some(dict) = obj.as_dict() {
72 match dict.get_name("Type") {
73 Some("Page") => {
74 page_ids.push(node_id);
75 }
76 Some("Pages") => {
77 if let Some(kids) = dict.get_array("Kids") {
78 for kid in kids.iter() {
79 if let Some(kid_id) = kid.as_reference() {
80 self.collect_pages_recursive(cos_doc, kid_id, page_ids);
81 }
82 }
83 }
84 }
85 _ => {}
86 }
87 }
88 }
89 }
90}