mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-01-29 16:49:32 +01:00
Final bugfixing of unite tool
This commit is contained in:
parent
d17715b17e
commit
e131ca769c
@ -20,6 +20,7 @@
|
||||
#include "pdfconstants.h"
|
||||
#include "pdfdocumentreader.h"
|
||||
#include "pdfobjectutils.h"
|
||||
#include "pdfnametreeloader.h"
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QPainter>
|
||||
@ -798,6 +799,80 @@ void PDFDocumentBuilder::createDocumentParts(const std::vector<size_t>& parts)
|
||||
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)
|
||||
{
|
||||
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 */
|
||||
|
||||
} // namespace pdf
|
||||
|
@ -354,6 +354,12 @@ public:
|
||||
/// \param parts Parts (page count of each document part)
|
||||
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 */
|
||||
|
||||
/// Appends a new page after last page.
|
||||
@ -1082,6 +1088,11 @@ public:
|
||||
void updateTrailerDictionary(PDFInteger objectCount);
|
||||
|
||||
|
||||
/// Set reference to 'Names' dictionary to catalog.
|
||||
/// \param names Reference to Names dictionary.
|
||||
void setCatalogNames(PDFObjectReference names);
|
||||
|
||||
|
||||
/* END GENERATED CODE */
|
||||
|
||||
private:
|
||||
|
@ -74,6 +74,7 @@ int PDFToolUnite::execute(const PDFToolOptions& options)
|
||||
|
||||
pdf::PDFObjectReference ocPropertiesMerged = documentBuilder.addObject(pdf::PDFObject());
|
||||
pdf::PDFObjectReference formMerged = documentBuilder.addObject(pdf::PDFObject());
|
||||
pdf::PDFObjectReference namesMerged = documentBuilder.addObject(pdf::PDFObject());
|
||||
|
||||
std::vector<pdf::PDFObjectReference> pages;
|
||||
for (const QString& fileName : files)
|
||||
@ -161,6 +162,7 @@ int PDFToolUnite::execute(const PDFToolOptions& options)
|
||||
|
||||
documentBuilder.appendTo(ocPropertiesMerged, documentBuilder.getObjectByReference(ocPropertiesReference));
|
||||
documentBuilder.appendTo(formMerged, documentBuilder.getObjectByReference(acroFormReference));
|
||||
documentBuilder.mergeNames(namesMerged, namesReference);
|
||||
pages.insert(pages.end(), references.cbegin(), references.cend());
|
||||
}
|
||||
|
||||
@ -170,6 +172,11 @@ int PDFToolUnite::execute(const PDFToolOptions& options)
|
||||
documentBuilder.setCatalogOptionalContentProperties(ocPropertiesMerged);
|
||||
}
|
||||
|
||||
if (!documentBuilder.getObjectByReference(namesMerged).isNull())
|
||||
{
|
||||
documentBuilder.setCatalogNames(namesMerged);
|
||||
}
|
||||
|
||||
if (!documentBuilder.getObjectByReference(formMerged).isNull())
|
||||
{
|
||||
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="returnType">_void</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">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>
|
||||
</root>
|
||||
|
Loading…
x
Reference in New Issue
Block a user