Document creation

This commit is contained in:
Jakub Melka 2020-03-21 18:18:08 +01:00
parent bc6ca3fc46
commit 1af6cf0c31
8 changed files with 508 additions and 129 deletions

View File

@ -400,6 +400,11 @@ void GeneratedFunction::generateCode(QTextStream& stream, CodeGeneratorParameter
}; };
applyFunctor(gatherParameters); applyFunctor(gatherParameters);
if (parameterTexts.isEmpty())
{
parameterTexts << "";
}
if (parameters.header) if (parameters.header)
{ {
// Generate header source code // Generate header source code

View File

@ -349,6 +349,7 @@ public:
enum FunctionType enum FunctionType
{ {
Structure,
Annotations, Annotations,
ColorSpace ColorSpace
}; };

View File

@ -22,6 +22,9 @@
namespace pdf namespace pdf
{ {
// Name of the library, together with version
static constexpr const char* PDF_LIBRARY_NAME = "PdfForQt 1.0.0";
// Structure file constants // Structure file constants
static constexpr const char* PDF_END_OF_FILE_MARK = "%%EOF"; static constexpr const char* PDF_END_OF_FILE_MARK = "%%EOF";
static constexpr const char* PDF_START_OF_XREF_MARK = "startxref"; static constexpr const char* PDF_START_OF_XREF_MARK = "startxref";

View File

@ -237,6 +237,11 @@ void PDFObjectStorage::setObject(PDFObjectReference reference, PDFObject object)
m_objects[reference.objectNumber] = Entry(reference.generation, qMove(object)); m_objects[reference.objectNumber] = Entry(reference.generation, qMove(object));
} }
void PDFObjectStorage::updateTrailerDictionary(PDFObject trailerDictionary)
{
m_trailerDictionary = PDFObjectManipulator::merge(m_trailerDictionary, trailerDictionary, PDFObjectManipulator::RemoveNullObjects);
}
QByteArray PDFDocumentDataLoaderDecorator::readName(const PDFObject& object) QByteArray PDFDocumentDataLoaderDecorator::readName(const PDFObject& object)
{ {
const PDFObject& dereferencedObject = m_document->getObject(object); const PDFObject& dereferencedObject = m_document->getObject(object);

View File

@ -89,6 +89,12 @@ public:
/// \param object New value of object /// \param object New value of object
void setObject(PDFObjectReference reference, PDFObject object); void setObject(PDFObjectReference reference, PDFObject object);
/// Updates trailer dictionary. Preserves items which are not in a new
/// dictionary \p trailerDictionary. It merges new dictionary to the
/// old one.
/// \param trailerDictionary New trailer dictionary
void updateTrailerDictionary(PDFObject trailerDictionary);
private: private:
PDFObjects m_objects; PDFObjects m_objects;
PDFObject m_trailerDictionary; PDFObject m_trailerDictionary;

View File

@ -17,6 +17,7 @@
#include "pdfdocumentbuilder.h" #include "pdfdocumentbuilder.h"
#include "pdfencoding.h" #include "pdfencoding.h"
#include "pdfconstants.h"
namespace pdf namespace pdf
{ {
@ -216,7 +217,7 @@ PDFObjectFactory& PDFObjectFactory::operator<<(PDFObjectReference value)
PDFDocumentBuilder::PDFDocumentBuilder() : PDFDocumentBuilder::PDFDocumentBuilder() :
m_version(1, 7) m_version(1, 7)
{ {
createDocument();
} }
PDFDocumentBuilder::PDFDocumentBuilder(const PDFDocument* document) : PDFDocumentBuilder::PDFDocumentBuilder(const PDFDocument* document) :
@ -226,8 +227,23 @@ PDFDocumentBuilder::PDFDocumentBuilder(const PDFDocument* document) :
} }
PDFDocument PDFDocumentBuilder::build() const void PDFDocumentBuilder::reset()
{ {
*this = PDFDocumentBuilder();
}
void PDFDocumentBuilder::createDocument()
{
reset();
PDFObjectReference catalog = createCatalog();
PDFObject trailerDictionary = createTrailerDictionary(catalog);
m_storage.updateTrailerDictionary(trailerDictionary);
}
PDFDocument PDFDocumentBuilder::build()
{
updateTrailerDictionary(m_storage.getObjects().size());
return PDFDocument(PDFObjectStorage(m_storage), m_version); return PDFDocument(PDFObjectStorage(m_storage), m_version);
} }
@ -246,6 +262,11 @@ QRectF PDFDocumentBuilder::getPopupWindowRect(const QRectF& rectangle) const
return rectangle.translated(rectangle.width() * 1.25, 0); return rectangle.translated(rectangle.width() * 1.25, 0);
} }
QString PDFDocumentBuilder::getProducerString() const
{
return PDF_LIBRARY_NAME;
}
/* START GENERATED CODE */ /* START GENERATED CODE */
PDFObjectReference PDFDocumentBuilder::createAnnotationSquare(PDFObjectReference page, PDFObjectReference PDFDocumentBuilder::createAnnotationSquare(PDFObjectReference page,
@ -300,14 +321,17 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationSquare(PDFObjectReference
PDFObjectReference annotationObject = addObject(objectBuilder.takeObject()); PDFObjectReference annotationObject = addObject(objectBuilder.takeObject());
PDFObjectReference popupAnnotation = createAnnotationPopup(page, annotationObject, getPopupWindowRect(rectangle), false); PDFObjectReference popupAnnotation = createAnnotationPopup(page, annotationObject, getPopupWindowRect(rectangle), false);
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Popup"); objectBuilder.beginDictionaryItem("Popup");
objectBuilder << popupAnnotation; objectBuilder << popupAnnotation;
objectBuilder.endDictionaryItem(); objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
PDFObject updateAnnotationPopup = objectBuilder.takeObject(); PDFObject updateAnnotationPopup = objectBuilder.takeObject();
mergeTo(annotationObject, updateAnnotationPopup); mergeTo(annotationObject, updateAnnotationPopup);
return PDFObjectReference(); return annotationObject;
} }
PDFObjectReference PDFDocumentBuilder::createAnnotationPopup(PDFObjectReference page, PDFObjectReference PDFDocumentBuilder::createAnnotationPopup(PDFObjectReference page,
PDFObjectReference parentAnnotation, PDFObjectReference parentAnnotation,
QRectF rectangle, QRectF rectangle,
@ -336,6 +360,75 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationPopup(PDFObjectReference
return popupAnnotation; return popupAnnotation;
} }
PDFObjectReference PDFDocumentBuilder::createCatalog()
{
PDFObjectFactory objectBuilder;
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Type");
objectBuilder << WrapName("Catalog");
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
PDFObjectReference catalogReference = addObject(objectBuilder.takeObject());
return catalogReference;
}
PDFObject PDFDocumentBuilder::createTrailerDictionary(PDFObjectReference catalog)
{
PDFObjectFactory objectBuilder;
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Size");
objectBuilder << 1;
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Root");
objectBuilder << catalog;
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Info");
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Producer");
objectBuilder << getProducerString();
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("CreationDate");
objectBuilder << WrapCurrentDateTime();
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("ModDate");
objectBuilder << WrapCurrentDateTime();
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
PDFObject trailerDictionary = objectBuilder.takeObject();
return trailerDictionary;
}
void PDFDocumentBuilder::updateTrailerDictionary(PDFInteger objectCount)
{
PDFObjectFactory objectBuilder;
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Size");
objectBuilder << objectCount;
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Info");
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Producer");
objectBuilder << getProducerString();
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("ModDate");
objectBuilder << WrapCurrentDateTime();
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
PDFObject trailerDictionary = objectBuilder.takeObject();
m_storage.updateTrailerDictionary(qMove(trailerDictionary));
}
/* END GENERATED CODE */ /* END GENERATED CODE */
} // namespace pdf } // namespace pdf

View File

@ -144,10 +144,21 @@ private:
class PDFDocumentBuilder class PDFDocumentBuilder
{ {
public: public:
/// Creates a new blank document (with no pages)
explicit PDFDocumentBuilder(); explicit PDFDocumentBuilder();
///
explicit PDFDocumentBuilder(const PDFDocument* document); explicit PDFDocumentBuilder(const PDFDocument* document);
PDFDocument build() const; /// Resets the object to the initial state.
/// \warning All data are lost
void reset();
/// Create a new blank document with no pages. If some document
/// is edited at call of this function, then it is lost.
void createDocument();
PDFDocument build();
/* START GENERATED CODE */ /* START GENERATED CODE */
@ -188,12 +199,30 @@ public:
bool opened); bool opened);
/// Creates empty catalog. This function is used, when a new document is being created. Do not call
/// this function manually.
PDFObjectReference createCatalog();
/// This function is used to create a new trailer dictionary, when blank document is created. Do not
/// call this function manually.
/// \param catalog Reference to document catalog
PDFObject createTrailerDictionary(PDFObjectReference catalog);
/// This function is used to update trailer dictionary. Must be called each time the final document is
/// being built.
/// \param objectCount Number of objects (including empty ones)
void updateTrailerDictionary(PDFInteger objectCount);
/* END GENERATED CODE */ /* END GENERATED CODE */
private: private:
PDFObjectReference addObject(PDFObject object); PDFObjectReference addObject(PDFObject object);
void mergeTo(PDFObjectReference reference, PDFObject object); void mergeTo(PDFObjectReference reference, PDFObject object);
QRectF getPopupWindowRect(const QRectF& rectangle) const; QRectF getPopupWindowRect(const QRectF& rectangle) const;
QString getProducerString() const;
PDFObjectStorage m_storage; PDFObjectStorage m_storage;
PDFVersion m_version; PDFVersion m_version;

View File

@ -184,9 +184,17 @@
<property name="items"> <property name="items">
<QObject class="codegen::GeneratedPDFObject"> <QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property> <property name="objectName"></property>
<property name="items"/> <property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Popup</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">popupAnnotation</property>
</QObject>
</property>
<property name="dictionaryItemName">Popup</property> <property name="dictionaryItemName">Popup</property>
<property name="objectType">DictionaryItemSimple</property> <property name="objectType">Dictionary</property>
<property name="value">popupAnnotation</property> <property name="value">popupAnnotation</property>
</QObject> </QObject>
</property> </property>
@ -316,5 +324,234 @@ return annotationObject;</property>
<property name="functionDescription">Creates a new popup annotation on the page. Popup annotation is represented usually by floating window, which can be opened, or closed. Popup annotation is associated with parent annotation, which can be usually markup annotation. Popup annotation displays parent annotation's texts, for example, title, comment, date etc.</property> <property name="functionDescription">Creates a new popup annotation on the page. Popup annotation is represented usually by floating window, which can be opened, or closed. Popup annotation is associated with parent annotation, which can be usually markup annotation. Popup annotation displays parent annotation's texts, for example, title, comment, date etc.</property>
<property name="returnType">_PDFObjectReference</property> <property name="returnType">_PDFObjectReference</property>
</QObject> </QObject>
<QObject class="codegen::GeneratedFunction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Type</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">WrapName("Catalog")</property>
</QObject>
</property>
<property name="dictionaryItemName"></property>
<property name="objectType">Dictionary</property>
<property name="value"></property>
</QObject>
</property>
<property name="actionType">CreateObject</property>
<property name="variableName">catalogReference</property>
<property name="variableType">_PDFObjectReference</property>
<property name="code"></property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items"/>
<property name="actionType">Code</property>
<property name="variableName"></property>
<property name="variableType">_void</property>
<property name="code">return catalogReference;</property>
</QObject>
</property>
<property name="functionType">Structure</property>
<property name="functionName">createCatalog</property>
<property name="functionDescription">Creates empty catalog. This function is used, when a new document is being created. Do not call this function manually.</property>
<property name="returnType">_PDFObjectReference</property>
</QObject>
<QObject class="codegen::GeneratedFunction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">catalog</property>
<property name="parameterType">_PDFObjectReference</property>
<property name="parameterDescription">Reference to document catalog</property>
</QObject>
</property>
<property name="actionType">Parameters</property>
<property name="variableName"></property>
<property name="variableType">_void</property>
<property name="code"></property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Size</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">1</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Root</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">catalog</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Producer</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">getProducerString()</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">CreationDate</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">WrapCurrentDateTime()</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">ModDate</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">WrapCurrentDateTime()</property>
</QObject>
</property>
<property name="dictionaryItemName"></property>
<property name="objectType">Dictionary</property>
<property name="value"></property>
</QObject>
</property>
<property name="dictionaryItemName">Info</property>
<property name="objectType">DictionaryItemComplex</property>
<property name="value"></property>
</QObject>
</property>
<property name="dictionaryItemName"></property>
<property name="objectType">Dictionary</property>
<property name="value"></property>
</QObject>
</property>
<property name="actionType">CreateObject</property>
<property name="variableName">trailerDictionary</property>
<property name="variableType">_PDFObject</property>
<property name="code"></property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items"/>
<property name="actionType">Code</property>
<property name="variableName"></property>
<property name="variableType">_void</property>
<property name="code">return trailerDictionary;</property>
</QObject>
</property>
<property name="functionType">Structure</property>
<property name="functionName">createTrailerDictionary</property>
<property name="functionDescription">This function is used to create a new trailer dictionary, when blank document is created. Do not call this function manually.</property>
<property name="returnType">_PDFObject</property>
</QObject>
<QObject class="codegen::GeneratedFunction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">objectCount</property>
<property name="parameterType">_PDFInteger</property>
<property name="parameterDescription">Number of objects (including empty ones)</property>
</QObject>
</property>
<property name="actionType">Parameters</property>
<property name="variableName"></property>
<property name="variableType">_void</property>
<property name="code"></property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Size</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">objectCount</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Producer</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">getProducerString()</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">ModDate</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">WrapCurrentDateTime()</property>
</QObject>
</property>
<property name="dictionaryItemName"></property>
<property name="objectType">Dictionary</property>
<property name="value"></property>
</QObject>
</property>
<property name="dictionaryItemName">Info</property>
<property name="objectType">DictionaryItemComplex</property>
<property name="value"></property>
</QObject>
</property>
<property name="dictionaryItemName"></property>
<property name="objectType">Dictionary</property>
<property name="value"></property>
</QObject>
</property>
<property name="actionType">CreateObject</property>
<property name="variableName">trailerDictionary</property>
<property name="variableType">_PDFObject</property>
<property name="code"></property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items"/>
<property name="actionType">Code</property>
<property name="variableName"></property>
<property name="variableType">_void</property>
<property name="code">m_storage.updateTrailerDictionary(qMove(trailerDictionary));</property>
</QObject>
</property>
<property name="functionType">Structure</property>
<property name="functionName">updateTrailerDictionary</property>
<property name="functionDescription">This function is used to update trailer dictionary. Must be called each time the final document is being built.</property>
<property name="returnType">_void</property>
</QObject>
</property> </property>
</root> </root>