diff --git a/PdfForQtLib/PdfForQtLib.pro b/PdfForQtLib/PdfForQtLib.pro
index 76dc6b9..8f4b532 100644
--- a/PdfForQtLib/PdfForQtLib.pro
+++ b/PdfForQtLib/PdfForQtLib.pro
@@ -42,6 +42,7 @@ SOURCES += \
sources/pdfccittfaxdecoder.cpp \
sources/pdfcms.cpp \
sources/pdfcompiler.cpp \
+ sources/pdfdocumentbuilder.cpp \
sources/pdfexecutionpolicy.cpp \
sources/pdffile.cpp \
sources/pdfitemmodels.cpp \
@@ -87,6 +88,7 @@ HEADERS += \
sources/pdfccittfaxdecoder.h \
sources/pdfcms.h \
sources/pdfcompiler.h \
+ sources/pdfdocumentbuilder.h \
sources/pdfdocumentdrawinterface.h \
sources/pdfexecutionpolicy.h \
sources/pdffile.h \
diff --git a/PdfForQtLib/sources/pdfdocumentbuilder.cpp b/PdfForQtLib/sources/pdfdocumentbuilder.cpp
new file mode 100644
index 0000000..cfc19ca
--- /dev/null
+++ b/PdfForQtLib/sources/pdfdocumentbuilder.cpp
@@ -0,0 +1,130 @@
+// Copyright (C) 2020 Jakub Melka
+//
+// This file is part of PdfForQt.
+//
+// PdfForQt is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// PdfForQt is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with PDFForQt. If not, see .
+
+#include "pdfdocumentbuilder.h"
+
+namespace pdf
+{
+
+void PDFObjectFactory::beginArray()
+{
+ m_items.emplace_back(ItemType::Array, PDFArray());
+}
+
+void PDFObjectFactory::endArray()
+{
+ Item topItem = qMove(m_items.back());
+ Q_ASSERT(topItem.type == ItemType::Array);
+ m_items.pop_back();
+ addObject(PDFObject::createArray(std::make_shared(qMove(std::get(topItem.object)))));
+}
+
+void PDFObjectFactory::beginDictionary()
+{
+ m_items.emplace_back(ItemType::Dictionary, PDFDictionary());
+}
+
+void PDFObjectFactory::endDictionary()
+{
+ Item topItem = qMove(m_items.back());
+ Q_ASSERT(topItem.type == ItemType::Dictionary);
+ m_items.pop_back();
+ addObject(PDFObject::createDictionary(std::make_shared(qMove(std::get(topItem.object)))));
+}
+
+void PDFObjectFactory::beginDictionaryItem(const QByteArray& name)
+{
+ m_items.emplace_back(ItemType::DictionaryItem, name, PDFObject());
+}
+
+void PDFObjectFactory::endDictionaryItem()
+{
+ Item topItem = qMove(m_items.back());
+ Q_ASSERT(topItem.type == ItemType::DictionaryItem);
+ m_items.pop_back();
+
+ Item& dictionaryItem = m_items.back();
+ Q_ASSERT(dictionaryItem.type == ItemType::Dictionary);
+ std::get(dictionaryItem.object).addEntry(qMove(topItem.itemName), qMove(std::get(topItem.object)));
+}
+
+void PDFObjectFactory::addObject(PDFObject object)
+{
+ if (m_items.empty())
+ {
+ m_items.emplace_back(ItemType::Object, qMove(object));
+ return;
+ }
+
+ Item& topItem = m_items.back();
+ switch (topItem.type)
+ {
+ case ItemType::Object:
+ // Just override the object
+ topItem.object = qMove(object);
+ break;
+
+ case ItemType::Dictionary:
+ // Do not do anything - we are inside dictionary
+ break;
+
+ case ItemType::DictionaryItem:
+ // Add item to dictionary item
+ topItem.object = qMove(object);
+ break;
+
+ case ItemType::Array:
+ std::get(topItem.object).appendItem(qMove(object));
+ break;
+
+ default:
+ Q_ASSERT(false);
+ break;
+ }
+}
+
+PDFObjectFactory& PDFObjectFactory::operator<<(std::nullptr_t)
+{
+ addObject(PDFObject::createNull());
+ return *this;
+}
+
+PDFObjectFactory& PDFObjectFactory::operator<<(bool value)
+{
+ addObject(PDFObject::createBool(value));
+ return *this;
+}
+
+PDFObjectFactory& PDFObjectFactory::operator<<(PDFReal value)
+{
+ addObject(PDFObject::createReal(value));
+ return *this;
+}
+
+PDFObjectFactory& PDFObjectFactory::operator<<(PDFInteger value)
+{
+ addObject(PDFObject::createInteger(value));
+ return *this;
+}
+
+PDFObjectFactory& PDFObjectFactory::operator<<(PDFObjectReference value)
+{
+ addObject(PDFObject::createReference(value));
+ return *this;
+}
+
+} // namespace pdf
diff --git a/PdfForQtLib/sources/pdfdocumentbuilder.h b/PdfForQtLib/sources/pdfdocumentbuilder.h
new file mode 100644
index 0000000..997f629
--- /dev/null
+++ b/PdfForQtLib/sources/pdfdocumentbuilder.h
@@ -0,0 +1,119 @@
+// Copyright (C) 2020 Jakub Melka
+//
+// This file is part of PdfForQt.
+//
+// PdfForQt is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// PdfForQt is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with PDFForQt. If not, see .
+
+#ifndef PDFDOCUMENTBUILDER_H
+#define PDFDOCUMENTBUILDER_H
+
+#include "pdfobject.h"
+
+namespace pdf
+{
+
+/// Factory for creating various PDF objects, such as simple objects,
+/// dictionaries, arrays etc.
+class PDFObjectFactory
+{
+public:
+ inline explicit PDFObjectFactory() = default;
+
+ void beginArray();
+ void endArray();
+
+ void beginDictionary();
+ void endDictionary();
+
+ void beginDictionaryItem(const QByteArray& name);
+ void endDictionaryItem();
+
+ PDFObjectFactory& operator<<(std::nullptr_t);
+ PDFObjectFactory& operator<<(bool value);
+ PDFObjectFactory& operator<<(PDFReal value);
+ PDFObjectFactory& operator<<(PDFInteger value);
+ PDFObjectFactory& operator<<(PDFObjectReference value);
+
+ /// Treat containers - write them as array
+ template()))>
+ PDFObjectFactory& operator<<(Container container)
+ {
+ beginArray();
+
+ auto it = std::begin(container);
+ auto itEnd = std::end(container);
+ for (; it != itEnd; ++it)
+ {
+ *this << *it;
+ }
+
+ endArray();
+
+ return *this;
+ }
+
+private:
+ void addObject(PDFObject object);
+
+ enum class ItemType
+ {
+ Object,
+ Dictionary,
+ DictionaryItem,
+ Array
+ };
+
+ /// What is stored in this structure, depends on the type.
+ /// If type is 'Object', then single simple object is in object,
+ /// if type is dictionary, then PDFDictionary is stored in object,
+ /// if type is dictionary item, then object and item name is stored
+ /// in the data, if item is array, then array is stored in the data.
+ struct Item
+ {
+ inline Item() = default;
+
+ template
+ inline Item(ItemType type, T&& data) :
+ type(type),
+ object(qMove(data))
+ {
+
+ }
+
+ template
+ inline Item(ItemType type, const QByteArray& itemName, T&& data) :
+ type(type),
+ itemName(qMove(itemName)),
+ object(qMove(data))
+ {
+
+ }
+
+ ItemType type = ItemType::Object;
+ QByteArray itemName;
+ std::variant object;
+ };
+
+ std::vector- m_items;
+};
+
+class PDFDocumentBuilder
+{
+public:
+ PDFDocumentBuilder();
+};
+
+} // namespace pdf
+
+#endif // PDFDOCUMENTBUILDER_H
diff --git a/PdfForQtLib/sources/pdfobject.h b/PdfForQtLib/sources/pdfobject.h
index 9b7f44d..da4e916 100644
--- a/PdfForQtLib/sources/pdfobject.h
+++ b/PdfForQtLib/sources/pdfobject.h
@@ -55,7 +55,7 @@ public:
class PDFFORQTLIBSHARED_EXPORT PDFObject
{
public:
- enum class Type
+ enum class Type : uint8_t
{
// Simple PDF objects
Null,