PoDoFo 1.2.0
Loading...
Searching...
No Matches
PdfDocument.h
1// SPDX-FileCopyrightText: 2006 Dominik Seichter <domseichter@web.de>
2// SPDX-FileCopyrightText: 2020 Francesco Pretto <ceztko@gmail.com>
3// SPDX-License-Identifier: LGPL-2.0-or-later OR MPL-2.0
4
5#ifndef PDF_DOCUMENT_H
6#define PDF_DOCUMENT_H
7
8#include "PdfTrailer.h"
9#include "PdfCatalog.h"
10#include "PdfIndirectObjectList.h"
11#include "PdfAcroForm.h"
12#include "PdfFontManager.h"
13#include "PdfMetadata.h"
14#include "PdfPageCollection.h"
15#include "PdfNameTrees.h"
16#include "PdfXObjectForm.h"
17#include "PdfImage.h"
18#include "PdfColorSpace.h"
19#include "PdfPattern.h"
20#include "PdfFunction.h"
21#include "PdfInfo.h"
22#include "PdfOutlines.h"
23#include "PdfExtension.h"
24
25namespace PoDoFo {
26
27class PdfAction;
28class PdfExtGState;
29class PdfEncrypt;
30class PdfDocument;
31
32template <typename TField>
33class PdfDocumentFieldIterableBase final
34{
35 friend class PdfDocument;
36
37public:
38 PdfDocumentFieldIterableBase()
39 : m_doc(nullptr) { }
40
41private:
42 PdfDocumentFieldIterableBase(PdfDocument& doc)
43 : m_doc(&doc) { }
44
45public:
46 class Iterator final
47 {
48 friend class PdfDocumentFieldIterableBase;
49 public:
50 using difference_type = void;
51 using value_type = TField*;
52 using pointer = void;
53 using reference = void;
54 using iterator_category = std::forward_iterator_tag;
55 public:
56 Iterator();
57 private:
58 Iterator(PdfDocument& doc);
59 public:
60 Iterator(const Iterator&) = default;
61 Iterator& operator=(const Iterator&) = default;
62 bool operator==(const Iterator& rhs) const;
63 bool operator!=(const Iterator& rhs) const;
64 Iterator& operator++();
65 Iterator operator++(int);
66 value_type operator*() { return m_Field; }
67 value_type operator->() { return m_Field; }
68 private:
69 void increment();
70 void stepIntoPageOrForm(PdfPageCollection& pages);
71 bool stepIntoPageAnnot(PdfAnnotationCollection& annots);
72 void stepIntoFormField(PdfAcroForm& form);
73 private:
74 PdfDocument* m_doc;
75 unsigned m_pageIndex;
76 PdfAnnotationCollection::iterator m_pageAnnotIterator;
77 PdfAcroForm::iterator m_acroFormIterator;
78 value_type m_Field;
79 std::unordered_set<PdfReference> m_visitedObjs;
80 };
81
82public:
83 Iterator begin() const;
84 Iterator end() const;
85
86private:
87 PdfDocument* m_doc;
88};
89
90using PdfDocumentFieldIterable = PdfDocumentFieldIterableBase<PdfField>;
91using PdfDocumentConstFieldIterable = PdfDocumentFieldIterableBase<const PdfField>;
92
107class PODOFO_API PdfDocument
108{
109 friend class PdfMetadata;
110 friend class PdfXObjectForm;
111 friend class PdfPageCollection;
112 friend class PdfMemDocument;
113 friend class PdfStreamedDocument;
114
115public:
117 virtual ~PdfDocument();
118
123 PdfOutlines& GetOrCreateOutlines();
124
131 PdfNameTrees& GetOrCreateNames();
132
140 PdfAcroForm& GetOrCreateAcroForm(PdfAcroFormDefaulAppearance eDefaultAppearance = PdfAcroFormDefaulAppearance::ArialBlack);
141
142 void CollectGarbage(PdfGarbageCollectionFlags flags = PdfGarbageCollectionFlags::None);
143
145 std::unique_ptr<PdfImage> CreateImage();
146
147 std::unique_ptr<PdfXObjectForm> CreateXObjectForm(const Rect& rect);
148
149 std::unique_ptr<PdfDestination> CreateDestination();
150
151 std::unique_ptr<PdfColorSpace> CreateColorSpace(PdfColorSpaceFilterPtr filter);
152
153 std::unique_ptr<PdfFunction> CreateFunction(PdfFunctionDefinitionPtr definition);
154
155 std::unique_ptr<PdfUncolouredTilingPattern> CreateTilingPattern(std::shared_ptr<PdfUncolouredTilingPatternDefinition> definition);
156
157 std::unique_ptr<PdfColouredTilingPattern> CreateTilingPattern(std::shared_ptr<PdfColouredTilingPatternDefinition> definition);
158
159 std::unique_ptr<PdfShadingPattern> CreateShadingPattern(PdfShadingPatternDefinitionPtr definition);
160
161 std::unique_ptr<PdfShadingDictionary> CreateShadingDictionary(PdfShadingDefinitionPtr definition);
162
163 std::unique_ptr<PdfExtGState> CreateExtGState(PdfExtGStateDefinitionPtr definition);
164
165 template <typename Taction>
166 std::unique_ptr<Taction> CreateAction();
167
168 std::unique_ptr<PdfAction> CreateAction(PdfActionType type);
169
170 std::unique_ptr<PdfFileSpec> CreateFileSpec();
171
178 bool IsPrintAllowed() const;
179
186 bool IsEditAllowed() const;
187
194 bool IsCopyAllowed() const;
195
202 bool IsEditNotesAllowed() const;
203
210 bool IsFillAndSignAllowed() const;
211
218 bool IsAccessibilityAllowed() const;
219
226 bool IsDocAssemblyAllowed() const;
227
234 bool IsHighPrintAllowed() const;
235
238 void PushPdfExtension(const PdfExtension& extension);
239
245 bool HasPdfExtension(const std::string_view& ns, int64_t level) const;
246
250 void RemovePdfExtension(const std::string_view& ns, int64_t level);
251
254 std::vector<PdfExtension> GetPdfExtensions() const;
255
262 void GetSortedSignatures(std::vector<const PdfSignature*>& signatures) const;
263
264 void GetSortedSignatures(std::vector<PdfSignature*>& signatures);
265
266 PdfAcroForm& MustGetAcroForm();
267
268 const PdfAcroForm& MustGetAcroForm() const;
269
270 PdfNameTrees& MustGetNames();
271
272 const PdfNameTrees& MustGetNames() const;
273
274 PdfOutlines& MustGetOutlines();
275
276 const PdfOutlines& MustGetOutlines() const;
277
281 PdfDocumentFieldIterable GetFieldsIterator();
282 PdfDocumentConstFieldIterable GetFieldsIterator() const;
283
285 void Reset();
286
287public:
295 virtual bool HasOwnerPermissions() const = 0;
296
297 virtual const PdfEncrypt* GetEncrypt() const = 0;
298
300 bool IsEncrypted() const;
301
302public:
303 bool IsStrictParsing() const { return m_IsStrictParsing; }
304
309 PdfCatalog& GetCatalog() { return *m_Catalog; }
310
315 const PdfCatalog& GetCatalog() const { return *m_Catalog; }
316
319 PdfPageCollection& GetPages() { return *m_Pages; }
320
323 const PdfPageCollection& GetPages() const { return *m_Pages; }
324
329 PdfTrailer &GetTrailer() { return *m_Trailer; }
330
335 const PdfTrailer& GetTrailer() const { return *m_Trailer; }
336
342 const PdfInfo* GetInfo() const;
343
344 PdfMetadata& GetMetadata() { return m_Metadata; }
345
346 const PdfMetadata& GetMetadata() const { return m_Metadata; }
347
352 PdfIndirectObjectList& GetObjects() { return m_Objects; }
353
358 const PdfIndirectObjectList& GetObjects() const { return m_Objects; }
359
360 PdfAcroForm* GetAcroForm() { return m_AcroForm.get(); }
361
362 const PdfAcroForm* GetAcroForm() const { return m_AcroForm.get(); }
363
364 PdfNameTrees* GetNames() { return m_NameTrees.get(); }
365
366 const PdfNameTrees* GetNames() const { return m_NameTrees.get(); }
367
368 PdfOutlines* GetOutlines();
369
370 const PdfOutlines* GetOutlines() const;
371
372 PdfFontManager& GetFonts() { return m_FontManager; }
373
374protected:
376 void SetEntryPoints(std::unique_ptr<PdfObject>&& trailer, PdfObject& catalog);
377
378 void SetStrictParsing(bool value);
379
381 void Init();
382
383 virtual void reset();
384
386 void Clear();
387
388 virtual void clear();
389
392 virtual PdfVersion GetPdfVersion() const = 0;
393
397
398private:
401 PdfDocument(bool empty = false);
402
404
405 // Called by PdfPageCollection
406 void AppendDocumentPages(const PdfDocument& doc);
407 void InsertDocumentPageAt(unsigned atIndex, const PdfDocument& doc, unsigned pageIndex, std::unordered_map<PdfReference, PdfObject*>& map);
408 void AppendDocumentPages(const PdfDocument& doc, unsigned pageIndex, unsigned pageCount, std::unordered_map<PdfReference, PdfObject*>& map);
409
410 // Called by PdfXObjectForm
411 Rect FillXObjectFromPage(PdfXObjectForm& xobj, const PdfPage& page, PdfFillFormFlags flags, std::unordered_map<PdfReference, PdfObject*>* map);
412
413 PdfInfo& GetOrCreateInfo();
414
415 void createAction(PdfActionType type, std::unique_ptr<PdfAction>& action);
416
417private:
418 void deletePages(unsigned atIndex, unsigned pageCount);
419
420 void appendOutlineItems(PdfOutlineItem& destParent, const PdfOutlineItem* srcItem,
421 const PdfIndirectObjectList& srcObjects, std::unordered_map<PdfReference, PdfObject*>& mappedObjects);
422
423 void resetPrivate();
424
425 void lazyLoadOutlines();
426 void lazyLoadInfo();
427
428private:
429 PdfDocument& operator=(const PdfDocument&) = delete;
430
431private:
432 PdfIndirectObjectList m_Objects;
433 PdfMetadata m_Metadata;
434 PdfFontManager m_FontManager;
435 bool m_IsStrictParsing;
436 bool m_InfoLazyLoaded;
437 bool m_OutlinesLazyLoaded;
438 std::unique_ptr<PdfObject> m_TrailerObj;
439 std::unique_ptr<PdfTrailer> m_Trailer;
440 std::unique_ptr<PdfCatalog> m_Catalog;
441 std::unique_ptr<PdfInfo> m_Info;
442 std::unique_ptr<PdfPageCollection> m_Pages;
443 std::unique_ptr<PdfAcroForm> m_AcroForm;
444 std::unique_ptr<PdfOutlines> m_Outlines;
445 std::unique_ptr<PdfNameTrees> m_NameTrees;
446};
447
448template<typename TAction>
449std::unique_ptr<TAction> PdfDocument::CreateAction()
450{
451 std::unique_ptr<TAction> ret;
452 createAction(PdfAction::GetActionType<TAction>(), reinterpret_cast<std::unique_ptr<PdfAction>&>(ret));
453 return ret;
454}
455
456template<typename TField>
457typename PdfDocumentFieldIterableBase<TField>::Iterator PdfDocumentFieldIterableBase<TField>::begin() const
458{
459 if (m_doc == nullptr)
460 return Iterator();
461 else
462 return Iterator(*m_doc);
463}
464
465template<typename TField>
466typename PdfDocumentFieldIterableBase<TField>::Iterator PdfDocumentFieldIterableBase<TField>::end() const
467{
468 return Iterator();
469}
470
471template<typename TField>
472PdfDocumentFieldIterableBase<TField>::Iterator::Iterator()
473 : m_doc(nullptr), m_pageIndex(0), m_Field(nullptr)
474{
475}
476
477template<typename TField>
478PdfDocumentFieldIterableBase<TField>::Iterator::Iterator(PdfDocument& doc)
479 : m_doc(&doc), m_pageIndex(0), m_Field(nullptr)
480{
481 stepIntoPageOrForm(doc.GetPages());
482}
483
484template<typename TField>
485bool PdfDocumentFieldIterableBase<TField>::Iterator::operator==(const Iterator& rhs) const
486{
487 if (m_doc == nullptr && rhs.m_doc == nullptr)
488 return true;
489
490 return m_doc == rhs.m_doc && m_pageIndex == rhs.m_pageIndex && m_pageAnnotIterator == rhs.m_pageAnnotIterator && m_acroFormIterator == rhs.m_acroFormIterator;
491}
492
493template<typename TField>
494bool PdfDocumentFieldIterableBase<TField>::Iterator::operator!=(const Iterator& rhs) const
495{
496 if (m_doc == nullptr && rhs.m_doc == nullptr)
497 return false;
498
499 return m_doc != rhs.m_doc || m_pageIndex != rhs.m_pageIndex || m_pageAnnotIterator != rhs.m_pageAnnotIterator || m_acroFormIterator != rhs.m_acroFormIterator;
500}
501
502template<typename TField>
503typename PdfDocumentFieldIterableBase<TField>::Iterator& PdfDocumentFieldIterableBase<TField>::Iterator::operator++()
504{
505 increment();
506 return *this;
507}
508
509template<typename TField>
510typename PdfDocumentFieldIterableBase<TField>::Iterator PdfDocumentFieldIterableBase<TField>::Iterator::operator++(int)
511{
512 auto copy = *this;
513 increment();
514 return copy;
515}
516
517template<typename TField>
518void PdfDocumentFieldIterableBase<TField>::Iterator::increment()
519{
520 if (m_doc == nullptr)
521 return;
522
523 auto& pages = m_doc->GetPages();
524 if (m_pageIndex < pages.GetCount())
525 {
526 m_pageAnnotIterator++;
527 if (stepIntoPageAnnot(pages.GetPageAt(m_pageIndex).GetAnnotations()))
528 return;
529
530 m_pageIndex++;
531 stepIntoPageOrForm(pages);
532 }
533 else
534 {
535 m_acroFormIterator++;
536 stepIntoFormField(m_doc->MustGetAcroForm());
537 }
538}
539
540// Update the iterator for the current page index, or switch to form iteration
541template<typename TField>
542void PdfDocumentFieldIterableBase<TField>::Iterator::stepIntoPageOrForm(PdfPageCollection& pages)
543{
544 while (true)
545 {
546 if (m_pageIndex >= pages.GetCount())
547 break;
548
549 auto& annots = pages.GetPageAt(m_pageIndex).GetAnnotations();
550 m_pageAnnotIterator = annots.begin();
551 if (stepIntoPageAnnot(annots))
552 return;
553
554 m_pageIndex++;
555 }
556
557 auto form = m_doc->GetAcroForm();
558 if (form != nullptr)
559 {
560 m_acroFormIterator = form->begin();
561 stepIntoFormField(*form);
562 return;
563 }
564
565 // End of iteration
566 m_doc = nullptr;
567 m_Field = nullptr;
568 m_visitedObjs.clear();
569}
570
571// Verify the current page annotation iterator. It updates the current field
572// and returns true if a valid unvisited field is found, false otherwise
573template<typename TField>
574bool PdfDocumentFieldIterableBase<TField>::Iterator::stepIntoPageAnnot(PdfAnnotationCollection& annots)
575{
576 while (true)
577 {
578 if (m_pageAnnotIterator == annots.end())
579 break;
580
581 auto& annot = **m_pageAnnotIterator;
582 PdfField* field = nullptr;
583 if (annot.GetType() == PdfAnnotationType::Widget &&
584 (field = &static_cast<PdfAnnotationWidget&>(annot).GetField(),
585 m_visitedObjs.find(field->GetObject().GetIndirectReference()) == m_visitedObjs.end()))
586 {
587 m_Field = field;
588 m_visitedObjs.insert(field->GetObject().GetIndirectReference());
589 return true;
590 }
591
592 m_pageAnnotIterator++;
593 }
594
595 return false;
596}
597
598// Verify the current AcroForm field iterator. It updates the current field
599// if a valid unvisited leaf field is found, or it ends the iteration otherwise
600template<typename TField>
601void PdfDocumentFieldIterableBase<TField>::Iterator::stepIntoFormField(PdfAcroForm& form)
602{
603 while (true)
604 {
605 if (m_acroFormIterator == form.end())
606 break;
607
608 auto& field = **m_acroFormIterator;
609 if (field.GetChildren().GetCount() == 0
610 && m_visitedObjs.find(field.GetObject().GetIndirectReference()) == m_visitedObjs.end())
611 {
612 m_Field = &field;
613 m_visitedObjs.insert(field.GetObject().GetIndirectReference());
614 return;
615 }
616
617 m_acroFormIterator++;
618 }
619
620 // End of iteration
621 m_doc = nullptr;
622 m_Field = nullptr;
623 m_visitedObjs.clear();
624}
625
626};
627
628
629#endif // PDF_DOCUMENT_H
PdfDocument is the core interface for working with PDF documents.
Definition PdfDocument.h:108
PdfPageCollection & GetPages()
Get access to the page tree.
Definition PdfDocument.h:319
void GetSortedSignatures(std::vector< const PdfSignature * > &signatures) const
Retrieve the signed signatures of the document, sorted by the upper boundary of their /ByteRange,...
const PdfPageCollection & GetPages() const
Get access to the page tree.
Definition PdfDocument.h:323
virtual PdfVersion GetPdfVersion() const =0
Get the PDF version of the document.
const PdfTrailer & GetTrailer() const
Get access to the internal trailer dictionary or root object.
Definition PdfDocument.h:335
virtual bool HasOwnerPermissions() const =0
Checks if document has been opened with full owner privileges.
PdfTrailer & GetTrailer()
Get access to the internal trailer dictionary or root object.
Definition PdfDocument.h:329
virtual void SetPdfVersion(PdfVersion version)=0
Get the PDF version of the document.
PdfCatalog & GetCatalog()
Get access to the internal Catalog dictionary or root object.
Definition PdfDocument.h:309
PdfIndirectObjectList & GetObjects()
Get access to the internal vector of objects or root object.
Definition PdfDocument.h:352
const PdfIndirectObjectList & GetObjects() const
Get access to the internal vector of objects or root object.
Definition PdfDocument.h:358
const PdfCatalog & GetCatalog() const
Get access to the internal Catalog dictionary or root object.
Definition PdfDocument.h:315
A class that is used to encrypt a PDF file and set document permissions on the PDF file.
Definition PdfEncrypt.h:113
PdfExtension is a simple class that describes a vendor-specific extension to the official specificati...
Definition PdfExtension.h:15
This class assists PdfDocument with caching font information.
Definition PdfFontManager.h:50
A list of PdfObjects that constitutes the indirect object list of the document The PdfParser will rea...
Definition PdfIndirectObjectList.h:34
This class provides access to the documents info dictionary, which provides information about the PDF...
Definition PdfInfo.h:18
PdfMemDocument is the core class for reading and manipulating PDF files and writing them back to disk...
Definition PdfMemDocument.h:35
Interface to access names trees in the document.
Definition PdfNameTrees.h:18
A PDF outline item has a title and a destination.
Definition PdfOutlines.h:33
The main PDF outlines dictionary.
Definition PdfOutlines.h:175
Class for managing the tree of Pages in a PDF document Don't use this class directly.
Definition PdfPageCollection.h:37
PdfPage is one page in the pdf document.
Definition PdfPage.h:133
PdfStreamedDocument is the preferred class for creating new PDF documents.
Definition PdfStreamedDocument.h:47
An normalized rectangle defined by position (left-bottom) and size.
Definition Rect.h:17
Convenient type for char array storage and/or buffer with std::string compatibility.
Definition basetypes.h:30
All classes, functions, types and enums of PoDoFo are members of these namespace.
Definition basetypes.h:13
std::shared_ptr< const PdfColorSpaceFilter > PdfColorSpaceFilterPtr
Convenience alias for a constant PdfColorSpaceFilter shared ptr.
Definition PdfColorSpaceFilter.h:71
PdfGarbageCollectionFlags
Definition PdfIndirectObjectList.h:17
std::shared_ptr< const PdfShadingDefinition > PdfShadingDefinitionPtr
Convenience alias for a constant PdfShadingDefinition shared ptr.
Definition PdfPatternDefinition.h:180
PdfAcroFormDefaulAppearance
Definition PdfAcroForm.h:15
std::shared_ptr< const PdfShadingPatternDefinition > PdfShadingPatternDefinitionPtr
Convenience alias for a constant PdfShadingPatternDefinition shared ptr.
Definition PdfPatternDefinition.h:409
PdfFillFormFlags
Definition PdfXObjectForm.h:18
std::shared_ptr< const PdfExtGStateDefinition > PdfExtGStateDefinitionPtr
Convenience alias for a constant PdfExtGStateDefinition shared ptr.
Definition PdfExtGStateDefinition.h:30
PdfActionType
The type of the action.
Definition PdfAction.h:25
PdfVersion
Enum to identify different versions of the PDF file format.
Definition PdfDeclarations.h:61
std::shared_ptr< const PdfFunctionDefinition > PdfFunctionDefinitionPtr
Convenience alias for a constant PdfFunction shared ptr.
Definition PdfFunctionDefinition.h:54