mirror of https://github.com/JakubMelka/PDF4QT.git
Final bugfixing of unite tool
This commit is contained in:
parent
d17715b17e
commit
e131ca769c
|
@ -20,6 +20,7 @@
|
||||||
#include "pdfconstants.h"
|
#include "pdfconstants.h"
|
||||||
#include "pdfdocumentreader.h"
|
#include "pdfdocumentreader.h"
|
||||||
#include "pdfobjectutils.h"
|
#include "pdfobjectutils.h"
|
||||||
|
#include "pdfnametreeloader.h"
|
||||||
|
|
||||||
#include <QBuffer>
|
#include <QBuffer>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
@ -798,6 +799,80 @@ void PDFDocumentBuilder::createDocumentParts(const std::vector<size_t>& parts)
|
||||||
mergeTo(root, objectFactory.takeObject());
|
mergeTo(root, objectFactory.takeObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFDocumentBuilder::mergeNames(PDFObjectReference a, PDFObjectReference b)
|
||||||
|
{
|
||||||
|
PDFObject aObject = getObjectByReference(a);
|
||||||
|
|
||||||
|
// First object is null, do nothing
|
||||||
|
if (aObject.isNull())
|
||||||
|
{
|
||||||
|
setObject(a, getObjectByReference(b));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jakub Melka: otherwise we must merge names tree
|
||||||
|
PDFObject bObject = getObjectByReference(b);
|
||||||
|
const PDFDictionary* aDict = getDictionaryFromObject(aObject);
|
||||||
|
const PDFDictionary* bDict = getDictionaryFromObject(bObject);
|
||||||
|
|
||||||
|
// Store keys
|
||||||
|
std::set<QByteArray> keys;
|
||||||
|
for (size_t i = 0; i < aDict->getCount(); ++i)
|
||||||
|
{
|
||||||
|
keys.insert(aDict->getKey(i).getString());
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < bDict->getCount(); ++i)
|
||||||
|
{
|
||||||
|
keys.insert(bDict->getKey(i).getString());
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFObjectFactory factory;
|
||||||
|
factory.beginDictionary();
|
||||||
|
|
||||||
|
for (const QByteArray& key : keys)
|
||||||
|
{
|
||||||
|
auto getObject = [](const PDFObjectStorage*, const PDFObject& object) { return object; };
|
||||||
|
auto aMap = PDFNameTreeLoader<PDFObject>::parse(&m_storage, aDict->get(key), getObject);
|
||||||
|
auto bMap = PDFNameTreeLoader<PDFObject>::parse(&m_storage, bDict->get(key), getObject);
|
||||||
|
aMap.merge(qMove(bMap));
|
||||||
|
|
||||||
|
if (aMap.empty())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
factory.beginDictionaryItem(key);
|
||||||
|
factory.beginDictionary();
|
||||||
|
|
||||||
|
factory.beginDictionaryItem("Names");
|
||||||
|
factory.beginArray();
|
||||||
|
|
||||||
|
for (const auto& item : aMap)
|
||||||
|
{
|
||||||
|
factory << WrapName(item.first);
|
||||||
|
factory << item.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
factory.endArray();
|
||||||
|
factory.endDictionaryItem();
|
||||||
|
|
||||||
|
factory.beginDictionaryItem("Limits");
|
||||||
|
factory.beginArray();
|
||||||
|
|
||||||
|
factory << WrapName((*aMap.begin()).first);
|
||||||
|
factory << WrapName((*aMap.rbegin()).first);
|
||||||
|
|
||||||
|
factory.endArray();
|
||||||
|
factory.endDictionaryItem();
|
||||||
|
|
||||||
|
factory.endDictionary();
|
||||||
|
factory.endDictionaryItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
factory.endDictionary();
|
||||||
|
setObject(a, factory.takeObject());
|
||||||
|
}
|
||||||
|
|
||||||
void PDFDocumentBuilder::appendTo(PDFObjectReference reference, PDFObject object)
|
void PDFDocumentBuilder::appendTo(PDFObjectReference reference, PDFObject object)
|
||||||
{
|
{
|
||||||
m_storage.setObject(reference, PDFObjectManipulator::merge(m_storage.getObject(reference), qMove(object), PDFObjectManipulator::ConcatenateArrays));
|
m_storage.setObject(reference, PDFObjectManipulator::merge(m_storage.getObject(reference), qMove(object), PDFObjectManipulator::ConcatenateArrays));
|
||||||
|
@ -3458,6 +3533,20 @@ void PDFDocumentBuilder::updateTrailerDictionary(PDFInteger objectCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PDFDocumentBuilder::setCatalogNames(PDFObjectReference names)
|
||||||
|
{
|
||||||
|
PDFObjectFactory objectBuilder;
|
||||||
|
|
||||||
|
objectBuilder.beginDictionary();
|
||||||
|
objectBuilder.beginDictionaryItem("Names");
|
||||||
|
objectBuilder << ((names.isValid()) ? PDFObject::createReference(names) : PDFObject());
|
||||||
|
objectBuilder.endDictionaryItem();
|
||||||
|
objectBuilder.endDictionary();
|
||||||
|
PDFObject updatedCatalog = objectBuilder.takeObject();
|
||||||
|
mergeTo(getCatalogReference(), updatedCatalog);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* END GENERATED CODE */
|
/* END GENERATED CODE */
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
|
|
@ -354,6 +354,12 @@ public:
|
||||||
/// \param parts Parts (page count of each document part)
|
/// \param parts Parts (page count of each document part)
|
||||||
void createDocumentParts(const std::vector<size_t>& parts);
|
void createDocumentParts(const std::vector<size_t>& parts);
|
||||||
|
|
||||||
|
/// Merges two independent 'Names' entry in catalog dictionary. It is used,
|
||||||
|
/// for example, when documents are being merged.
|
||||||
|
/// \param a First 'Names' entry
|
||||||
|
/// \param b Second 'Names' entry
|
||||||
|
void mergeNames(PDFObjectReference a, PDFObjectReference b);
|
||||||
|
|
||||||
/* START GENERATED CODE */
|
/* START GENERATED CODE */
|
||||||
|
|
||||||
/// Appends a new page after last page.
|
/// Appends a new page after last page.
|
||||||
|
@ -1082,6 +1088,11 @@ public:
|
||||||
void updateTrailerDictionary(PDFInteger objectCount);
|
void updateTrailerDictionary(PDFInteger objectCount);
|
||||||
|
|
||||||
|
|
||||||
|
/// Set reference to 'Names' dictionary to catalog.
|
||||||
|
/// \param names Reference to Names dictionary.
|
||||||
|
void setCatalogNames(PDFObjectReference names);
|
||||||
|
|
||||||
|
|
||||||
/* END GENERATED CODE */
|
/* END GENERATED CODE */
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -74,6 +74,7 @@ int PDFToolUnite::execute(const PDFToolOptions& options)
|
||||||
|
|
||||||
pdf::PDFObjectReference ocPropertiesMerged = documentBuilder.addObject(pdf::PDFObject());
|
pdf::PDFObjectReference ocPropertiesMerged = documentBuilder.addObject(pdf::PDFObject());
|
||||||
pdf::PDFObjectReference formMerged = documentBuilder.addObject(pdf::PDFObject());
|
pdf::PDFObjectReference formMerged = documentBuilder.addObject(pdf::PDFObject());
|
||||||
|
pdf::PDFObjectReference namesMerged = documentBuilder.addObject(pdf::PDFObject());
|
||||||
|
|
||||||
std::vector<pdf::PDFObjectReference> pages;
|
std::vector<pdf::PDFObjectReference> pages;
|
||||||
for (const QString& fileName : files)
|
for (const QString& fileName : files)
|
||||||
|
@ -161,6 +162,7 @@ int PDFToolUnite::execute(const PDFToolOptions& options)
|
||||||
|
|
||||||
documentBuilder.appendTo(ocPropertiesMerged, documentBuilder.getObjectByReference(ocPropertiesReference));
|
documentBuilder.appendTo(ocPropertiesMerged, documentBuilder.getObjectByReference(ocPropertiesReference));
|
||||||
documentBuilder.appendTo(formMerged, documentBuilder.getObjectByReference(acroFormReference));
|
documentBuilder.appendTo(formMerged, documentBuilder.getObjectByReference(acroFormReference));
|
||||||
|
documentBuilder.mergeNames(namesMerged, namesReference);
|
||||||
pages.insert(pages.end(), references.cbegin(), references.cend());
|
pages.insert(pages.end(), references.cbegin(), references.cend());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,6 +172,11 @@ int PDFToolUnite::execute(const PDFToolOptions& options)
|
||||||
documentBuilder.setCatalogOptionalContentProperties(ocPropertiesMerged);
|
documentBuilder.setCatalogOptionalContentProperties(ocPropertiesMerged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!documentBuilder.getObjectByReference(namesMerged).isNull())
|
||||||
|
{
|
||||||
|
documentBuilder.setCatalogNames(namesMerged);
|
||||||
|
}
|
||||||
|
|
||||||
if (!documentBuilder.getObjectByReference(formMerged).isNull())
|
if (!documentBuilder.getObjectByReference(formMerged).isNull())
|
||||||
{
|
{
|
||||||
documentBuilder.setCatalogAcroForm(formMerged);
|
documentBuilder.setCatalogAcroForm(formMerged);
|
||||||
|
|
|
@ -7859,5 +7859,62 @@ updateDocumentInfo(qMove(updatedInfoDictionary));</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="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>
|
<property name="returnType">_void</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::GeneratedParameter">
|
||||||
|
<property name="objectName"></property>
|
||||||
|
<property name="items"/>
|
||||||
|
<property name="parameterName">names</property>
|
||||||
|
<property name="parameterType">_PDFObjectReference</property>
|
||||||
|
<property name="parameterDescription">Reference to Names dictionary.</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">Names</property>
|
||||||
|
<property name="objectType">DictionaryItemSimple</property>
|
||||||
|
<property name="value">((names.isValid()) ? PDFObject::createReference(names) : PDFObject())</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">updatedCatalog</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">mergeTo(getCatalogReference(), updatedCatalog);</property>
|
||||||
|
</QObject>
|
||||||
|
</property>
|
||||||
|
<property name="functionType">Structure</property>
|
||||||
|
<property name="functionName">setCatalogNames</property>
|
||||||
|
<property name="functionDescription">Set reference to 'Names' dictionary to catalog.</property>
|
||||||
|
<property name="returnType">_void</property>
|
||||||
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
</root>
|
</root>
|
||||||
|
|
Loading…
Reference in New Issue