mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Generating code
This commit is contained in:
@@ -232,6 +232,11 @@ PDFObjectReference PDFObjectStorage::addObject(PDFObject object)
|
||||
return reference;
|
||||
}
|
||||
|
||||
void PDFObjectStorage::setObject(PDFObjectReference reference, PDFObject object)
|
||||
{
|
||||
m_objects[reference.objectNumber] = Entry(reference.generation, qMove(object));
|
||||
}
|
||||
|
||||
QByteArray PDFDocumentDataLoaderDecorator::readName(const PDFObject& object)
|
||||
{
|
||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
||||
|
@@ -84,6 +84,11 @@ public:
|
||||
/// \returns Reference to new object
|
||||
PDFObjectReference addObject(PDFObject object);
|
||||
|
||||
/// Sets object to object storage. Reference must exist.
|
||||
/// \param reference Reference to object
|
||||
/// \param object New value of object
|
||||
void setObject(PDFObjectReference reference, PDFObject object);
|
||||
|
||||
private:
|
||||
PDFObjects m_objects;
|
||||
PDFObject m_trailerDictionary;
|
||||
|
@@ -16,6 +16,7 @@
|
||||
// along with PDFForQt. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "pdfdocumentbuilder.h"
|
||||
#include "pdfencoding.h"
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
@@ -62,6 +63,82 @@ void PDFObjectFactory::endDictionaryItem()
|
||||
std::get<PDFDictionary>(dictionaryItem.object).addEntry(qMove(topItem.itemName), qMove(std::get<PDFObject>(topItem.object)));
|
||||
}
|
||||
|
||||
PDFObjectFactory& PDFObjectFactory::operator<<(QString textString)
|
||||
{
|
||||
if (!PDFEncoding::canConvertToEncoding(textString, PDFEncoding::Encoding::PDFDoc))
|
||||
{
|
||||
// Use unicode encoding
|
||||
QByteArray ba;
|
||||
|
||||
{
|
||||
QTextStream textStream(&ba, QIODevice::WriteOnly);
|
||||
textStream.setCodec("UTF-16BE");
|
||||
textStream.setGenerateByteOrderMark(true);
|
||||
textStream << textString;
|
||||
}
|
||||
|
||||
addObject(PDFObject::createString(std::make_shared<PDFString>(qMove(ba))));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use PDF document encoding
|
||||
addObject(PDFObject::createString(std::make_shared<PDFString>(PDFEncoding::convertToEncoding(textString, PDFEncoding::Encoding::PDFDoc))));
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
PDFObjectFactory& PDFObjectFactory::operator<<(WrapAnnotationColor color)
|
||||
{
|
||||
if (color.color.isValid())
|
||||
{
|
||||
// Jakub Melka: we will decide, if we have gray/rgb/cmyk color
|
||||
QColor value = color.color;
|
||||
if (value.spec() == QColor::Cmyk)
|
||||
{
|
||||
*this << std::initializer_list<PDFReal>{ value.cyanF(), value.magentaF(), value.yellowF(), value.blackF() };
|
||||
}
|
||||
else if (qIsGray(value.rgb()))
|
||||
{
|
||||
*this << std::initializer_list<PDFReal>{ value.redF() };
|
||||
}
|
||||
else
|
||||
{
|
||||
*this << std::initializer_list<PDFReal>{ value.redF(), value.greenF(), value.blueF() };
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
addObject(PDFObject::createNull());
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
PDFObjectFactory& PDFObjectFactory::operator<<(WrapCurrentDateTime)
|
||||
{
|
||||
addObject(PDFObject::createString(std::make_shared<PDFString>(PDFEncoding::converDateTimeToString(QDateTime::currentDateTime()))));
|
||||
return *this;
|
||||
}
|
||||
|
||||
PDFObjectFactory& PDFObjectFactory::operator<<(const QRectF& value)
|
||||
{
|
||||
*this << std::initializer_list<PDFReal>{ value.left(), value.top(), value.right(), value.bottom() };
|
||||
return *this;
|
||||
}
|
||||
|
||||
PDFObjectFactory& PDFObjectFactory::operator<<(int value)
|
||||
{
|
||||
*this << PDFInteger(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PDFObjectFactory& PDFObjectFactory::operator<<(WrapName wrapName)
|
||||
{
|
||||
addObject(PDFObject::createName(std::make_shared<PDFString>(qMove(wrapName.name))));
|
||||
return *this;
|
||||
}
|
||||
|
||||
PDFObject PDFObjectFactory::takeObject()
|
||||
{
|
||||
Q_ASSERT(m_items.size() == 1);
|
||||
@@ -154,8 +231,111 @@ PDFDocument PDFDocumentBuilder::build() const
|
||||
return PDFDocument(PDFObjectStorage(m_storage), m_version);
|
||||
}
|
||||
|
||||
PDFObjectReference PDFDocumentBuilder::addObject(PDFObject object)
|
||||
{
|
||||
return m_storage.addObject(PDFObjectManipulator::removeNullObjects(object));
|
||||
}
|
||||
|
||||
void PDFDocumentBuilder::mergeTo(PDFObjectReference reference, PDFObject object)
|
||||
{
|
||||
m_storage.setObject(reference, PDFObjectManipulator::merge(m_storage.getObject(reference), qMove(object), PDFObjectManipulator::RemoveNullObjects));
|
||||
}
|
||||
|
||||
QRectF PDFDocumentBuilder::getPopupWindowRect(const QRectF& rectangle) const
|
||||
{
|
||||
return rectangle.translated(rectangle.width() * 1.25, 0);
|
||||
}
|
||||
|
||||
/* START GENERATED CODE */
|
||||
|
||||
PDFObjectReference PDFDocumentBuilder::createAnnotationSquare(PDFObjectReference page,
|
||||
QRectF rectangle,
|
||||
PDFReal borderWidth,
|
||||
QColor fillColor,
|
||||
QColor strokeColor,
|
||||
QString title,
|
||||
QString subject,
|
||||
QString contents)
|
||||
{
|
||||
PDFObjectFactory objectBuilder;
|
||||
|
||||
objectBuilder.beginDictionary();
|
||||
objectBuilder.beginDictionaryItem("Subtype");
|
||||
objectBuilder << WrapName("Square");
|
||||
objectBuilder.endDictionaryItem();
|
||||
objectBuilder.beginDictionaryItem("Rect");
|
||||
objectBuilder << rectangle;
|
||||
objectBuilder.endDictionaryItem();
|
||||
objectBuilder.beginDictionaryItem("F");
|
||||
objectBuilder << 4;
|
||||
objectBuilder.endDictionaryItem();
|
||||
objectBuilder.beginDictionaryItem("P");
|
||||
objectBuilder << page;
|
||||
objectBuilder.endDictionaryItem();
|
||||
objectBuilder.beginDictionaryItem("M");
|
||||
objectBuilder << WrapCurrentDateTime();
|
||||
objectBuilder.endDictionaryItem();
|
||||
objectBuilder.beginDictionaryItem("CreationDate");
|
||||
objectBuilder << WrapCurrentDateTime();
|
||||
objectBuilder.endDictionaryItem();
|
||||
objectBuilder.beginDictionaryItem("Border");
|
||||
objectBuilder << std::initializer_list<PDFReal>{ 0.0, 0.0, borderWidth };
|
||||
objectBuilder.endDictionaryItem();
|
||||
objectBuilder.beginDictionaryItem("C");
|
||||
objectBuilder << WrapAnnotationColor(strokeColor);
|
||||
objectBuilder.endDictionaryItem();
|
||||
objectBuilder.beginDictionaryItem("IC");
|
||||
objectBuilder << WrapAnnotationColor(fillColor);
|
||||
objectBuilder.endDictionaryItem();
|
||||
objectBuilder.beginDictionaryItem("T");
|
||||
objectBuilder << title;
|
||||
objectBuilder.endDictionaryItem();
|
||||
objectBuilder.beginDictionaryItem("Contents");
|
||||
objectBuilder << contents;
|
||||
objectBuilder.endDictionaryItem();
|
||||
objectBuilder.beginDictionaryItem("Subj");
|
||||
objectBuilder << subject;
|
||||
objectBuilder.endDictionaryItem();
|
||||
objectBuilder.endDictionary();
|
||||
PDFObjectReference annotationObject = addObject(objectBuilder.takeObject());
|
||||
PDFObjectReference popupAnnotation = createAnnotationPopup(page, annotationObject, getPopupWindowRect(rectangle), false);
|
||||
|
||||
objectBuilder.beginDictionaryItem("Popup");
|
||||
objectBuilder << popupAnnotation;
|
||||
objectBuilder.endDictionaryItem();
|
||||
PDFObject updateAnnotationPopup = objectBuilder.takeObject();
|
||||
mergeTo(annotationObject, updateAnnotationPopup);
|
||||
return PDFObjectReference();
|
||||
}
|
||||
|
||||
PDFObjectReference PDFDocumentBuilder::createAnnotationPopup(PDFObjectReference page,
|
||||
PDFObjectReference parentAnnotation,
|
||||
QRectF rectangle,
|
||||
bool opened)
|
||||
{
|
||||
PDFObjectFactory objectBuilder;
|
||||
|
||||
objectBuilder.beginDictionary();
|
||||
objectBuilder.beginDictionaryItem("Subtype");
|
||||
objectBuilder << WrapName("Popup");
|
||||
objectBuilder.endDictionaryItem();
|
||||
objectBuilder.beginDictionaryItem("Rect");
|
||||
objectBuilder << rectangle;
|
||||
objectBuilder.endDictionaryItem();
|
||||
objectBuilder.beginDictionaryItem("P");
|
||||
objectBuilder << page;
|
||||
objectBuilder.endDictionaryItem();
|
||||
objectBuilder.beginDictionaryItem("Parent");
|
||||
objectBuilder << parentAnnotation;
|
||||
objectBuilder.endDictionaryItem();
|
||||
objectBuilder.beginDictionaryItem("Open");
|
||||
objectBuilder << opened;
|
||||
objectBuilder.endDictionaryItem();
|
||||
objectBuilder.endDictionary();
|
||||
PDFObjectReference popupAnnotation = addObject(objectBuilder.takeObject());
|
||||
return popupAnnotation;
|
||||
}
|
||||
|
||||
/* END GENERATED CODE */
|
||||
|
||||
} // namespace pdf
|
||||
|
@@ -24,6 +24,30 @@
|
||||
namespace pdf
|
||||
{
|
||||
|
||||
struct WrapName
|
||||
{
|
||||
WrapName(const char* name) :
|
||||
name(name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QByteArray name;
|
||||
};
|
||||
|
||||
struct WrapAnnotationColor
|
||||
{
|
||||
WrapAnnotationColor(QColor color) :
|
||||
color(color)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QColor color;
|
||||
};
|
||||
|
||||
struct WrapCurrentDateTime { };
|
||||
|
||||
/// Factory for creating various PDF objects, such as simple objects,
|
||||
/// dictionaries, arrays etc.
|
||||
class PDFObjectFactory
|
||||
@@ -45,6 +69,12 @@ public:
|
||||
PDFObjectFactory& operator<<(PDFReal value);
|
||||
PDFObjectFactory& operator<<(PDFInteger value);
|
||||
PDFObjectFactory& operator<<(PDFObjectReference value);
|
||||
PDFObjectFactory& operator<<(WrapName wrapName);
|
||||
PDFObjectFactory& operator<<(int value);
|
||||
PDFObjectFactory& operator<<(const QRectF& value);
|
||||
PDFObjectFactory& operator<<(WrapCurrentDateTime);
|
||||
PDFObjectFactory& operator<<(WrapAnnotationColor color);
|
||||
PDFObjectFactory& operator<<(QString textString);
|
||||
|
||||
/// Treat containers - write them as array
|
||||
template<typename Container, typename ValueType = decltype(*std::begin(std::declval<Container>()))>
|
||||
@@ -119,11 +149,52 @@ public:
|
||||
|
||||
PDFDocument build() const;
|
||||
|
||||
/* START GENERATED CODE */
|
||||
/* START GENERATED CODE */
|
||||
|
||||
/* END GENERATED CODE */
|
||||
/// Square annotation displays rectangle (or square). When opened, they display pop-up window
|
||||
/// containing the text of associated note (and window title). Square border/fill color can be defined,
|
||||
/// along with border width.
|
||||
/// \param page Page to which is annotation added
|
||||
/// \param rectangle Area in which is rectangle displayed
|
||||
/// \param borderWidth Width of the border line of rectangle
|
||||
/// \param fillColor Fill color of rectangle (interior color). If you do not want to have area color filled,
|
||||
/// then use invalid QColor.
|
||||
/// \param strokeColor Stroke color (color of the rectangle border). If you do not want to have a
|
||||
/// border, then use invalid QColor.
|
||||
/// \param title Title (it is displayed as title of popup window)
|
||||
/// \param subject Subject (short description of the subject being adressed by the annotation)
|
||||
/// \param contents Contents (text displayed, for example, in the marked annotation dialog)
|
||||
PDFObjectReference createAnnotationSquare(PDFObjectReference page,
|
||||
QRectF rectangle,
|
||||
PDFReal borderWidth,
|
||||
QColor fillColor,
|
||||
QColor strokeColor,
|
||||
QString title,
|
||||
QString subject,
|
||||
QString contents);
|
||||
|
||||
|
||||
/// 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.
|
||||
/// \param page Page to which is annotation added
|
||||
/// \param parentAnnotation Parent annotation (for which is popup window displayed)
|
||||
/// \param rectangle Area on the page, where popup window appears
|
||||
/// \param opened Is the window opened?
|
||||
PDFObjectReference createAnnotationPopup(PDFObjectReference page,
|
||||
PDFObjectReference parentAnnotation,
|
||||
QRectF rectangle,
|
||||
bool opened);
|
||||
|
||||
|
||||
/* END GENERATED CODE */
|
||||
|
||||
private:
|
||||
PDFObjectReference addObject(PDFObject object);
|
||||
void mergeTo(PDFObjectReference reference, PDFObject object);
|
||||
QRectF getPopupWindowRect(const QRectF& rectangle) const;
|
||||
|
||||
PDFObjectStorage m_storage;
|
||||
PDFVersion m_version;
|
||||
};
|
||||
|
@@ -2149,6 +2149,7 @@ QByteArray PDFEncoding::convertToEncoding(const QString& string, PDFEncoding::En
|
||||
if (unicode == (*table)[static_cast<unsigned char>(i)])
|
||||
{
|
||||
converted = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2158,6 +2159,34 @@ QByteArray PDFEncoding::convertToEncoding(const QString& string, PDFEncoding::En
|
||||
return result;
|
||||
}
|
||||
|
||||
bool PDFEncoding::canConvertToEncoding(const QString& string, PDFEncoding::Encoding encoding)
|
||||
{
|
||||
const encoding::EncodingTable* table = getTableForEncoding(encoding);
|
||||
Q_ASSERT(table);
|
||||
|
||||
for (QChar character : string)
|
||||
{
|
||||
ushort unicode = character.unicode();
|
||||
bool converted = false;
|
||||
|
||||
for (int i = 0; i < table->size(); ++i)
|
||||
{
|
||||
if (unicode == (*table)[static_cast<unsigned char>(i)])
|
||||
{
|
||||
converted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!converted)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString PDFEncoding::convertTextString(const QByteArray& stream)
|
||||
{
|
||||
if (hasUnicodeLeadMarkings(stream))
|
||||
@@ -2259,6 +2288,13 @@ QDateTime PDFEncoding::convertToDateTime(const QByteArray& stream)
|
||||
return QDateTime();
|
||||
}
|
||||
|
||||
QByteArray PDFEncoding::converDateTimeToString(QDateTime dateTime)
|
||||
{
|
||||
QDateTime utcDateTime = dateTime.toUTC();
|
||||
QString convertedDateTime = QString("D:%1").arg(utcDateTime.toString("yyyyMMddhhmmss"));
|
||||
return convertedDateTime.toLatin1();
|
||||
}
|
||||
|
||||
const encoding::EncodingTable* PDFEncoding::getTableForEncoding(Encoding encoding)
|
||||
{
|
||||
switch (encoding)
|
||||
|
@@ -70,6 +70,13 @@ public:
|
||||
/// \sa convert
|
||||
static QByteArray convertToEncoding(const QString& string, Encoding encoding);
|
||||
|
||||
/// Verifies, if string with given unicode characters can be converted using
|
||||
/// the specified encoding (so, all unicode characters present in the string
|
||||
/// are also present in given encoding).
|
||||
/// \param string String to be tested
|
||||
/// \param encoding Encoding used in verification of conversion
|
||||
static bool canConvertToEncoding(const QString& string, Encoding encoding);
|
||||
|
||||
/// Convert text string to the unicode string, using either PDFDocEncoding,
|
||||
/// or UTF-16BE encoding. Please see PDF Reference 1.7, Chapter 3.8.1. If
|
||||
/// UTF-16BE encoding is used, then leading bytes should be 0xFE and 0xFF
|
||||
@@ -88,6 +95,11 @@ public:
|
||||
/// \param stream Stream, from which date/time is read
|
||||
static QDateTime convertToDateTime(const QByteArray& stream);
|
||||
|
||||
/// Convert date/time to string according to PDF Reference 1.7, Chapter 3.8.1.
|
||||
/// If date is invalid, empty byte array is returned.
|
||||
/// \param dateTime Date and time to be converted
|
||||
static QByteArray converDateTimeToString(QDateTime dateTime);
|
||||
|
||||
/// Returns conversion table for particular encoding
|
||||
/// \param encoding Encoding
|
||||
static const encoding::EncodingTable* getTableForEncoding(Encoding encoding);
|
||||
|
@@ -204,6 +204,25 @@ const PDFObject& PDFDictionary::get(const char* key) const
|
||||
}
|
||||
}
|
||||
|
||||
void PDFDictionary::setEntry(const QByteArray& key, PDFObject&& value)
|
||||
{
|
||||
auto it = find(key);
|
||||
if (it != m_dictionary.end())
|
||||
{
|
||||
it->second = qMove(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
addEntry(QByteArray(key), qMove(value));
|
||||
}
|
||||
}
|
||||
|
||||
void PDFDictionary::removeNullObjects()
|
||||
{
|
||||
m_dictionary.erase(std::remove_if(m_dictionary.begin(), m_dictionary.end(), [](const DictionaryEntry& entry) { return entry.second.isNull(); }), m_dictionary.end());
|
||||
m_dictionary.shrink_to_fit();
|
||||
}
|
||||
|
||||
void PDFDictionary::optimize()
|
||||
{
|
||||
m_dictionary.shrink_to_fit();
|
||||
@@ -219,6 +238,11 @@ std::vector<PDFDictionary::DictionaryEntry>::const_iterator PDFDictionary::find(
|
||||
return std::find_if(m_dictionary.cbegin(), m_dictionary.cend(), [&key](const DictionaryEntry& entry) { return entry.first == key; });
|
||||
}
|
||||
|
||||
std::vector<PDFDictionary::DictionaryEntry>::iterator PDFDictionary::find(const QByteArray& key)
|
||||
{
|
||||
return std::find_if(m_dictionary.begin(), m_dictionary.end(), [&key](const DictionaryEntry& entry) { return entry.first == key; });
|
||||
}
|
||||
|
||||
std::vector<PDFDictionary::DictionaryEntry>::const_iterator PDFDictionary::find(const char* key) const
|
||||
{
|
||||
return std::find_if(m_dictionary.cbegin(), m_dictionary.cend(), [&key](const DictionaryEntry& entry) { return entry.first == key; });
|
||||
@@ -231,4 +255,59 @@ bool PDFStream::equals(const PDFObjectContent* other) const
|
||||
return m_dictionary.equals(&otherStream->m_dictionary) && m_content == otherStream->m_content;
|
||||
}
|
||||
|
||||
PDFObject PDFObjectManipulator::merge(PDFObject left, PDFObject right, MergeFlags flags)
|
||||
{
|
||||
if (left.getType() != right.getType())
|
||||
{
|
||||
return right;
|
||||
}
|
||||
|
||||
if (left.isDictionary())
|
||||
{
|
||||
Q_ASSERT(right.isDictionary());
|
||||
|
||||
PDFDictionary targetDictionary = *left.getDictionary();
|
||||
const PDFDictionary& sourceDictionary = *right.getDictionary();
|
||||
|
||||
for (size_t i = 0, count = sourceDictionary.getCount(); i < count; ++i)
|
||||
{
|
||||
const QByteArray& key = sourceDictionary.getKey(i);
|
||||
PDFObject value = merge(targetDictionary.get(key), sourceDictionary.getValue(i), flags);
|
||||
targetDictionary.setEntry(key, qMove(value));
|
||||
}
|
||||
|
||||
if (flags.testFlag(RemoveNullObjects))
|
||||
{
|
||||
targetDictionary.removeNullObjects();
|
||||
}
|
||||
|
||||
return PDFObject::createDictionary(std::make_shared<PDFDictionary>(qMove(targetDictionary)));
|
||||
}
|
||||
else if (left.isArray() && flags.testFlag(ConcatenateArrays))
|
||||
{
|
||||
// Concatenate arrays
|
||||
const PDFArray* leftArray = left.getArray();
|
||||
const PDFArray* rightArray = right.getArray();
|
||||
|
||||
std::vector<PDFObject> objects;
|
||||
objects.reserve(leftArray->getCount() + rightArray->getCount());
|
||||
for (size_t i = 0, count = leftArray->getCount(); i < count; ++i)
|
||||
{
|
||||
objects.emplace_back(leftArray->getItem(i));
|
||||
}
|
||||
for (size_t i = 0, count = rightArray->getCount(); i < count; ++i)
|
||||
{
|
||||
objects.emplace_back(rightArray->getItem(i));
|
||||
}
|
||||
return PDFObject::createArray(std::make_shared<PDFArray>(qMove(objects)));
|
||||
}
|
||||
|
||||
return right;
|
||||
}
|
||||
|
||||
PDFObject PDFObjectManipulator::removeNullObjects(PDFObject object)
|
||||
{
|
||||
return merge(object, object, RemoveNullObjects);
|
||||
}
|
||||
|
||||
} // namespace pdf
|
||||
|
@@ -95,6 +95,8 @@ public:
|
||||
constexpr inline PDFObject& operator=(const PDFObject&) = default;
|
||||
constexpr inline PDFObject& operator=(PDFObject&&) = default;
|
||||
|
||||
inline Type getType() const { return m_type; }
|
||||
|
||||
// Test operators
|
||||
inline bool isNull() const { return m_type == Type::Null; }
|
||||
inline bool isBool() const { return m_type == Type::Bool; }
|
||||
@@ -260,6 +262,12 @@ public:
|
||||
/// \param value Value
|
||||
void addEntry(QByteArray&& key, PDFObject&& value) { m_dictionary.emplace_back(std::move(key), std::move(value)); }
|
||||
|
||||
/// Sets entry value. If entry with given key doesn't exist,
|
||||
/// then it is created.
|
||||
/// \param key Key
|
||||
/// \param value Value
|
||||
void setEntry(const QByteArray& key, PDFObject&& value);
|
||||
|
||||
/// Returns count of items in the dictionary
|
||||
size_t getCount() const { return m_dictionary.size(); }
|
||||
|
||||
@@ -274,6 +282,9 @@ public:
|
||||
/// \param index Zero-based index of value in the dictionary
|
||||
const PDFObject& getValue(size_t index) const { return m_dictionary[index].second; }
|
||||
|
||||
/// Removes null objects from dictionary
|
||||
void removeNullObjects();
|
||||
|
||||
/// Optimizes the dictionary for memory consumption
|
||||
virtual void optimize() override;
|
||||
|
||||
@@ -283,6 +294,11 @@ private:
|
||||
/// \param key Key to be found
|
||||
std::vector<DictionaryEntry>::const_iterator find(const QByteArray& key) const;
|
||||
|
||||
/// Finds an item in the dictionary array, if the item is not in the dictionary,
|
||||
/// then end iterator is returned.
|
||||
/// \param key Key to be found
|
||||
std::vector<DictionaryEntry>::iterator find(const QByteArray& key);
|
||||
|
||||
/// Finds an item in the dictionary array, if the item is not in the dictionary,
|
||||
/// then end iterator is returned.
|
||||
/// \param key Key to be found
|
||||
@@ -322,6 +338,34 @@ private:
|
||||
QByteArray m_content;
|
||||
};
|
||||
|
||||
class PDFObjectManipulator
|
||||
{
|
||||
public:
|
||||
explicit PDFObjectManipulator() = delete;
|
||||
|
||||
enum MergeFlag
|
||||
{
|
||||
RemoveNullObjects = 0x0001, ///< Remove null object from dictionaries
|
||||
ConcatenateArrays = 0x0002, ///< Concatenate arrays instead of replace
|
||||
};
|
||||
Q_DECLARE_FLAGS(MergeFlags, MergeFlag)
|
||||
|
||||
/// Merges two objects. If object type is different, then object from right is used.
|
||||
/// If both objects are dictionaries, then their content is merged, object \p right
|
||||
/// has precedence over object \p left. If both objects are arrays, and concatenating
|
||||
/// flag is turned on, then they are concatenated instead of replacing left array
|
||||
/// by right array. If remove null objects flag is turend on, then null objects
|
||||
/// are removed from dictionaries.
|
||||
/// \param left Left, 'slave' object
|
||||
/// \param right Right 'master' object, has priority over left
|
||||
/// \param flags Merge flags
|
||||
static PDFObject merge(PDFObject left, PDFObject right, MergeFlags flags);
|
||||
|
||||
/// Remove null objects from all dictionaries
|
||||
/// \param object Object
|
||||
static PDFObject removeNullObjects(PDFObject object);
|
||||
};
|
||||
|
||||
} // namespace pdf
|
||||
|
||||
#endif // PDFOBJECT_H
|
||||
|
@@ -68,7 +68,6 @@ private:
|
||||
PDFObjectReference m_reference;
|
||||
};
|
||||
|
||||
|
||||
void PDFDecryptObjectVisitor::visitNull()
|
||||
{
|
||||
m_objectStack.push_back(PDFObject::createNull());
|
||||
|
Reference in New Issue
Block a user