mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Annotation painting, first part
This commit is contained in:
@ -188,7 +188,7 @@ void PDFExamplesGenerator::generateAnnotationsExample()
|
|||||||
|
|
||||||
{
|
{
|
||||||
pdf::PDFObjectReference annotation = builder.createAnnotationSquare(page5, QRectF(150, 250, 50, 50), 3.0, Qt::green, Qt::red, "Title1", "Subject1", "Contents - green filling, red boundary");
|
pdf::PDFObjectReference annotation = builder.createAnnotationSquare(page5, QRectF(150, 250, 50, 50), 3.0, Qt::green, Qt::red, "Title1", "Subject1", "Contents - green filling, red boundary");
|
||||||
builder.setAnnotationBorderStyle(annotation, pdf::PDFAnnotationBorder::Style::Inset, 2.718);
|
builder.setAnnotationBorder(annotation, 5.0, 3.0, 2.0);
|
||||||
builder.setAnnotationColor(annotation, Qt::black);
|
builder.setAnnotationColor(annotation, Qt::black);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,10 +23,10 @@
|
|||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
|
|
||||||
PDFActionPtr PDFAction::parse(const PDFDocument* document, PDFObject object)
|
PDFActionPtr PDFAction::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
std::set<PDFObjectReference> usedReferences;
|
std::set<PDFObjectReference> usedReferences;
|
||||||
return parseImpl(document, qMove(object), usedReferences);
|
return parseImpl(storage, qMove(object), usedReferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFAction::apply(const std::function<void (const PDFAction*)>& callback)
|
void PDFAction::apply(const std::function<void (const PDFAction*)>& callback)
|
||||||
@ -46,7 +46,7 @@ std::vector<const PDFAction*> PDFAction::getActionList() const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFActionPtr PDFAction::parseImpl(const PDFDocument* document, PDFObject object, std::set<PDFObjectReference>& usedReferences)
|
PDFActionPtr PDFAction::parseImpl(const PDFObjectStorage* storage, PDFObject object, std::set<PDFObjectReference>& usedReferences)
|
||||||
{
|
{
|
||||||
if (object.isReference())
|
if (object.isReference())
|
||||||
{
|
{
|
||||||
@ -56,7 +56,7 @@ PDFActionPtr PDFAction::parseImpl(const PDFDocument* document, PDFObject object,
|
|||||||
throw PDFException(PDFTranslationContext::tr("Circular dependence in actions found."));
|
throw PDFException(PDFTranslationContext::tr("Circular dependence in actions found."));
|
||||||
}
|
}
|
||||||
usedReferences.insert(reference);
|
usedReferences.insert(reference);
|
||||||
object = document->getObjectByReference(reference);
|
object = storage->getObjectByReference(reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (object.isNull())
|
if (object.isNull())
|
||||||
@ -69,34 +69,34 @@ PDFActionPtr PDFAction::parseImpl(const PDFDocument* document, PDFObject object,
|
|||||||
throw PDFException(PDFTranslationContext::tr("Invalid action."));
|
throw PDFException(PDFTranslationContext::tr("Invalid action."));
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
const PDFDictionary* dictionary = object.getDictionary();
|
const PDFDictionary* dictionary = object.getDictionary();
|
||||||
QByteArray name = loader.readNameFromDictionary(dictionary, "S");
|
QByteArray name = loader.readNameFromDictionary(dictionary, "S");
|
||||||
|
|
||||||
if (name == "GoTo") // Goto action
|
if (name == "GoTo") // Goto action
|
||||||
{
|
{
|
||||||
PDFDestination destination = PDFDestination::parse(document, dictionary->get("D"));
|
PDFDestination destination = PDFDestination::parse(storage, dictionary->get("D"));
|
||||||
return PDFActionPtr(new PDFActionGoTo(qMove(destination)));
|
return PDFActionPtr(new PDFActionGoTo(qMove(destination)));
|
||||||
}
|
}
|
||||||
else if (name == "GoToR")
|
else if (name == "GoToR")
|
||||||
{
|
{
|
||||||
PDFDestination destination = PDFDestination::parse(document, dictionary->get("D"));
|
PDFDestination destination = PDFDestination::parse(storage, dictionary->get("D"));
|
||||||
PDFFileSpecification fileSpecification = PDFFileSpecification::parse(document, dictionary->get("F"));
|
PDFFileSpecification fileSpecification = PDFFileSpecification::parse(storage, dictionary->get("F"));
|
||||||
return PDFActionPtr(new PDFActionGoToR(qMove(destination), qMove(fileSpecification), loader.readBooleanFromDictionary(dictionary, "NewWindow", false)));
|
return PDFActionPtr(new PDFActionGoToR(qMove(destination), qMove(fileSpecification), loader.readBooleanFromDictionary(dictionary, "NewWindow", false)));
|
||||||
}
|
}
|
||||||
else if (name == "GoToE")
|
else if (name == "GoToE")
|
||||||
{
|
{
|
||||||
PDFDestination destination = PDFDestination::parse(document, dictionary->get("D"));
|
PDFDestination destination = PDFDestination::parse(storage, dictionary->get("D"));
|
||||||
PDFFileSpecification fileSpecification = PDFFileSpecification::parse(document, dictionary->get("F"));
|
PDFFileSpecification fileSpecification = PDFFileSpecification::parse(storage, dictionary->get("F"));
|
||||||
return PDFActionPtr(new PDFActionGoToE(qMove(destination), qMove(fileSpecification), loader.readBooleanFromDictionary(dictionary, "NewWindow", false), document->getObject(dictionary->get("T"))));
|
return PDFActionPtr(new PDFActionGoToE(qMove(destination), qMove(fileSpecification), loader.readBooleanFromDictionary(dictionary, "NewWindow", false), storage->getObject(dictionary->get("T"))));
|
||||||
}
|
}
|
||||||
else if (name == "Launch")
|
else if (name == "Launch")
|
||||||
{
|
{
|
||||||
PDFFileSpecification fileSpecification = PDFFileSpecification::parse(document, dictionary->get("F"));
|
PDFFileSpecification fileSpecification = PDFFileSpecification::parse(storage, dictionary->get("F"));
|
||||||
const bool newWindow = loader.readBooleanFromDictionary(dictionary, "NewWindow", false);
|
const bool newWindow = loader.readBooleanFromDictionary(dictionary, "NewWindow", false);
|
||||||
PDFActionLaunch::Win win;
|
PDFActionLaunch::Win win;
|
||||||
|
|
||||||
const PDFObject& winDictionaryObject = document->getObject(dictionary->get("Win"));
|
const PDFObject& winDictionaryObject = storage->getObject(dictionary->get("Win"));
|
||||||
if (winDictionaryObject.isDictionary())
|
if (winDictionaryObject.isDictionary())
|
||||||
{
|
{
|
||||||
const PDFDictionary* winDictionary = winDictionaryObject.getDictionary();
|
const PDFDictionary* winDictionary = winDictionaryObject.getDictionary();
|
||||||
@ -110,7 +110,7 @@ PDFActionPtr PDFAction::parseImpl(const PDFDocument* document, PDFObject object,
|
|||||||
}
|
}
|
||||||
else if (name == "Thread")
|
else if (name == "Thread")
|
||||||
{
|
{
|
||||||
PDFFileSpecification fileSpecification = PDFFileSpecification::parse(document, dictionary->get("F"));
|
PDFFileSpecification fileSpecification = PDFFileSpecification::parse(storage, dictionary->get("F"));
|
||||||
PDFActionThread::Thread thread;
|
PDFActionThread::Thread thread;
|
||||||
PDFActionThread::Bead bead;
|
PDFActionThread::Bead bead;
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ PDFActionPtr PDFAction::parseImpl(const PDFDocument* document, PDFObject object,
|
|||||||
const bool isSynchronous = loader.readBooleanFromDictionary(dictionary, "Synchronous", false);
|
const bool isSynchronous = loader.readBooleanFromDictionary(dictionary, "Synchronous", false);
|
||||||
const bool isRepeat = loader.readBooleanFromDictionary(dictionary, "Repeat", false);
|
const bool isRepeat = loader.readBooleanFromDictionary(dictionary, "Repeat", false);
|
||||||
const bool isMix = loader.readBooleanFromDictionary(dictionary, "Mix", false);
|
const bool isMix = loader.readBooleanFromDictionary(dictionary, "Mix", false);
|
||||||
return PDFActionPtr(new PDFActionSound(PDFSound::parse(document, dictionary->get("Sound")), volume, isSynchronous, isRepeat, isMix));
|
return PDFActionPtr(new PDFActionSound(PDFSound::parse(storage, dictionary->get("Sound")), volume, isSynchronous, isRepeat, isMix));
|
||||||
}
|
}
|
||||||
else if (name == "Movie")
|
else if (name == "Movie")
|
||||||
{
|
{
|
||||||
@ -220,7 +220,7 @@ PDFActionPtr PDFAction::parseImpl(const PDFDocument* document, PDFObject object,
|
|||||||
const bool isRadioButtonsPreserved = loader.readBooleanFromDictionary(dictionary, "PreserveRB", true);
|
const bool isRadioButtonsPreserved = loader.readBooleanFromDictionary(dictionary, "PreserveRB", true);
|
||||||
PDFActionSetOCGState::StateChangeItems items;
|
PDFActionSetOCGState::StateChangeItems items;
|
||||||
|
|
||||||
PDFObject stateArrayObject = document->getObject(dictionary->get("State"));
|
PDFObject stateArrayObject = storage->getObject(dictionary->get("State"));
|
||||||
if (stateArrayObject.isArray())
|
if (stateArrayObject.isArray())
|
||||||
{
|
{
|
||||||
constexpr const std::array<std::pair<const char*, PDFActionSetOCGState::SwitchType>, 3> types = {
|
constexpr const std::array<std::pair<const char*, PDFActionSetOCGState::SwitchType>, 3> types = {
|
||||||
@ -258,23 +258,23 @@ PDFActionPtr PDFAction::parseImpl(const PDFDocument* document, PDFObject object,
|
|||||||
|
|
||||||
if (dictionary->hasKey("R"))
|
if (dictionary->hasKey("R"))
|
||||||
{
|
{
|
||||||
rendition = PDFRendition::parse(document, dictionary->get("R"));
|
rendition = PDFRendition::parse(storage, dictionary->get("R"));
|
||||||
}
|
}
|
||||||
PDFObject javascriptObject = document->getObject(dictionary->get("JS"));
|
PDFObject javascriptObject = storage->getObject(dictionary->get("JS"));
|
||||||
if (javascriptObject.isString())
|
if (javascriptObject.isString())
|
||||||
{
|
{
|
||||||
javascript = PDFEncoding::convertTextString(javascriptObject.getString());
|
javascript = PDFEncoding::convertTextString(javascriptObject.getString());
|
||||||
}
|
}
|
||||||
else if (javascriptObject.isStream())
|
else if (javascriptObject.isStream())
|
||||||
{
|
{
|
||||||
javascript = PDFEncoding::convertTextString(document->getDecodedStream(javascriptObject.getStream()));
|
javascript = PDFEncoding::convertTextString(storage->getDecodedStream(javascriptObject.getStream()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return PDFActionPtr(new PDFActionRendition(qMove(rendition), annotation, operation, qMove(javascript)));
|
return PDFActionPtr(new PDFActionRendition(qMove(rendition), annotation, operation, qMove(javascript)));
|
||||||
}
|
}
|
||||||
else if (name == "Trans")
|
else if (name == "Trans")
|
||||||
{
|
{
|
||||||
return PDFActionPtr(new PDFActionTransition(PDFPageTransition::parse(document, dictionary->get("Trans"))));
|
return PDFActionPtr(new PDFActionTransition(PDFPageTransition::parse(storage, dictionary->get("Trans"))));
|
||||||
}
|
}
|
||||||
else if (name == "GoTo3DView")
|
else if (name == "GoTo3DView")
|
||||||
{
|
{
|
||||||
@ -283,14 +283,14 @@ PDFActionPtr PDFAction::parseImpl(const PDFDocument* document, PDFObject object,
|
|||||||
else if (name == "JavaScript")
|
else if (name == "JavaScript")
|
||||||
{
|
{
|
||||||
QByteArray textJavaScript;
|
QByteArray textJavaScript;
|
||||||
const PDFObject& javaScriptObject = document->getObject(dictionary->get("JS"));
|
const PDFObject& javaScriptObject = storage->getObject(dictionary->get("JS"));
|
||||||
if (javaScriptObject.isString())
|
if (javaScriptObject.isString())
|
||||||
{
|
{
|
||||||
textJavaScript = javaScriptObject.getString();
|
textJavaScript = javaScriptObject.getString();
|
||||||
}
|
}
|
||||||
else if (javaScriptObject.isStream())
|
else if (javaScriptObject.isStream())
|
||||||
{
|
{
|
||||||
textJavaScript = document->getDecodedStream(javaScriptObject.getStream());
|
textJavaScript = storage->getDecodedStream(javaScriptObject.getStream());
|
||||||
}
|
}
|
||||||
return PDFActionPtr(new PDFActionJavaScript(PDFEncoding::convertTextString(textJavaScript)));
|
return PDFActionPtr(new PDFActionJavaScript(PDFEncoding::convertTextString(textJavaScript)));
|
||||||
}
|
}
|
||||||
@ -311,10 +311,10 @@ void PDFAction::fillActionList(std::vector<const PDFAction*>& actionList) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFDestination PDFDestination::parse(const PDFDocument* document, PDFObject object)
|
PDFDestination PDFDestination::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
PDFDestination result;
|
PDFDestination result;
|
||||||
object = document->getObject(object);
|
object = storage->getObject(object);
|
||||||
|
|
||||||
if (object.isName() || object.isString())
|
if (object.isName() || object.isString())
|
||||||
{
|
{
|
||||||
@ -330,7 +330,7 @@ PDFDestination PDFDestination::parse(const PDFDocument* document, PDFObject obje
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
|
|
||||||
// First parse page number/page index
|
// First parse page number/page index
|
||||||
PDFObject pageNumberObject = array->getItem(0);
|
PDFObject pageNumberObject = array->getItem(0);
|
||||||
|
@ -34,6 +34,7 @@ namespace pdf
|
|||||||
{
|
{
|
||||||
class PDFAction;
|
class PDFAction;
|
||||||
class PDFDocument;
|
class PDFDocument;
|
||||||
|
class PDFObjectStorage;
|
||||||
|
|
||||||
enum class ActionType
|
enum class ActionType
|
||||||
{
|
{
|
||||||
@ -87,9 +88,9 @@ public:
|
|||||||
|
|
||||||
/// Parses the destination from the object. If object contains invalid destination,
|
/// Parses the destination from the object. If object contains invalid destination,
|
||||||
/// then empty destination is returned. If object is empty, empty destination is returned.
|
/// then empty destination is returned. If object is empty, empty destination is returned.
|
||||||
/// \param document Document
|
/// \param storage Object storage
|
||||||
/// \param object Destination object
|
/// \param object Destination object
|
||||||
static PDFDestination parse(const PDFDocument* document, PDFObject object);
|
static PDFDestination parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DestinationType m_destinationType = DestinationType::Invalid;
|
DestinationType m_destinationType = DestinationType::Invalid;
|
||||||
@ -120,9 +121,9 @@ public:
|
|||||||
|
|
||||||
/// Tries to parse the action. If serious error occurs, then exception is thrown.
|
/// Tries to parse the action. If serious error occurs, then exception is thrown.
|
||||||
/// If \p object is null object, then nullptr is returned.
|
/// If \p object is null object, then nullptr is returned.
|
||||||
/// \param document Document
|
/// \param storage Object storage
|
||||||
/// \param object Object containing the action
|
/// \param object Object containing the action
|
||||||
static PDFActionPtr parse(const PDFDocument* document, PDFObject object);
|
static PDFActionPtr parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
/// Calls the lambda function with action as parameter, then following
|
/// Calls the lambda function with action as parameter, then following
|
||||||
/// the 'Next' entry, as described by PDF 1.7 specification.
|
/// the 'Next' entry, as described by PDF 1.7 specification.
|
||||||
@ -132,7 +133,7 @@ public:
|
|||||||
std::vector<const PDFAction*> getActionList() const;
|
std::vector<const PDFAction*> getActionList() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static PDFActionPtr parseImpl(const PDFDocument* document, PDFObject object, std::set<PDFObjectReference>& usedReferences);
|
static PDFActionPtr parseImpl(const PDFObjectStorage* storage, PDFObject object, std::set<PDFObjectReference>& usedReferences);
|
||||||
|
|
||||||
void fillActionList(std::vector<const PDFAction*>& actionList) const;
|
void fillActionList(std::vector<const PDFAction*>& actionList) const;
|
||||||
|
|
||||||
|
@ -22,21 +22,22 @@
|
|||||||
#include "pdfdrawspacecontroller.h"
|
#include "pdfdrawspacecontroller.h"
|
||||||
#include "pdfcms.h"
|
#include "pdfcms.h"
|
||||||
#include "pdfwidgetutils.h"
|
#include "pdfwidgetutils.h"
|
||||||
|
#include "pdfpagecontentprocessor.h"
|
||||||
|
|
||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
|
|
||||||
PDFAnnotationBorder PDFAnnotationBorder::parseBorder(const PDFDocument* document, PDFObject object)
|
PDFAnnotationBorder PDFAnnotationBorder::parseBorder(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
PDFAnnotationBorder result;
|
PDFAnnotationBorder result;
|
||||||
object = document->getObject(object);
|
object = storage->getObject(object);
|
||||||
|
|
||||||
if (object.isArray())
|
if (object.isArray())
|
||||||
{
|
{
|
||||||
const PDFArray* array = object.getArray();
|
const PDFArray* array = object.getArray();
|
||||||
if (array->getCount() >= 3)
|
if (array->getCount() >= 3)
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
result.m_definition = Definition::Simple;
|
result.m_definition = Definition::Simple;
|
||||||
result.m_hCornerRadius = loader.readNumber(array->getItem(0), 0.0);
|
result.m_hCornerRadius = loader.readNumber(array->getItem(0), 0.0);
|
||||||
result.m_vCornerRadius = loader.readNumber(array->getItem(1), 0.0);
|
result.m_vCornerRadius = loader.readNumber(array->getItem(1), 0.0);
|
||||||
@ -52,13 +53,13 @@ PDFAnnotationBorder PDFAnnotationBorder::parseBorder(const PDFDocument* document
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFAnnotationBorder PDFAnnotationBorder::parseBS(const PDFDocument* document, PDFObject object)
|
PDFAnnotationBorder PDFAnnotationBorder::parseBS(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
PDFAnnotationBorder result;
|
PDFAnnotationBorder result;
|
||||||
|
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
result.m_definition = Definition::BorderStyle;
|
result.m_definition = Definition::BorderStyle;
|
||||||
result.m_width = loader.readNumberFromDictionary(dictionary, "W", 1.0);
|
result.m_width = loader.readNumberFromDictionary(dictionary, "W", 1.0);
|
||||||
|
|
||||||
@ -76,13 +77,13 @@ PDFAnnotationBorder PDFAnnotationBorder::parseBS(const PDFDocument* document, PD
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFAnnotationBorderEffect PDFAnnotationBorderEffect::parse(const PDFDocument* document, PDFObject object)
|
PDFAnnotationBorderEffect PDFAnnotationBorderEffect::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
PDFAnnotationBorderEffect result;
|
PDFAnnotationBorderEffect result;
|
||||||
|
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
result.m_intensity = loader.readNumberFromDictionary(dictionary, "I", 0.0);
|
result.m_intensity = loader.readNumberFromDictionary(dictionary, "I", 0.0);
|
||||||
|
|
||||||
constexpr const std::array<std::pair<const char*, Effect>, 2> effects = {
|
constexpr const std::array<std::pair<const char*, Effect>, 2> effects = {
|
||||||
@ -96,16 +97,16 @@ PDFAnnotationBorderEffect PDFAnnotationBorderEffect::parse(const PDFDocument* do
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFAppeareanceStreams PDFAppeareanceStreams::parse(const PDFDocument* document, PDFObject object)
|
PDFAppeareanceStreams PDFAppeareanceStreams::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
PDFAppeareanceStreams result;
|
PDFAppeareanceStreams result;
|
||||||
|
|
||||||
auto processSubdicitonary = [&result, document](Appearance appearance, PDFObject subdictionaryObject)
|
auto processSubdicitonary = [&result, storage](Appearance appearance, PDFObject subdictionaryObject)
|
||||||
{
|
{
|
||||||
subdictionaryObject = document->getObject(subdictionaryObject);
|
subdictionaryObject = storage->getObject(subdictionaryObject);
|
||||||
if (subdictionaryObject.isDictionary())
|
if (subdictionaryObject.isDictionary())
|
||||||
{
|
{
|
||||||
const PDFDictionary* subdictionary = document->getDictionaryFromObject(subdictionaryObject);
|
const PDFDictionary* subdictionary = storage->getDictionaryFromObject(subdictionaryObject);
|
||||||
for (size_t i = 0; i < subdictionary->getCount(); ++i)
|
for (size_t i = 0; i < subdictionary->getCount(); ++i)
|
||||||
{
|
{
|
||||||
result.m_appearanceStreams[std::make_pair(appearance, subdictionary->getKey(i))] = subdictionary->getValue(i);
|
result.m_appearanceStreams[std::make_pair(appearance, subdictionary->getKey(i))] = subdictionary->getValue(i);
|
||||||
@ -117,7 +118,7 @@ PDFAppeareanceStreams PDFAppeareanceStreams::parse(const PDFDocument* document,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
processSubdicitonary(Appearance::Normal, dictionary->get("N"));
|
processSubdicitonary(Appearance::Normal, dictionary->get("N"));
|
||||||
processSubdicitonary(Appearance::Rollover, dictionary->get("R"));
|
processSubdicitonary(Appearance::Rollover, dictionary->get("R"));
|
||||||
@ -158,17 +159,27 @@ PDFAnnotation::PDFAnnotation() :
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object)
|
void PDFAnnotation::draw(AnnotationDrawParameters& parameters) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<PDFAppeareanceStreams::Key> PDFAnnotation::getDrawKeys() const
|
||||||
|
{
|
||||||
|
return { PDFAppeareanceStreams::Key{ PDFAppeareanceStreams::Appearance::Normal, QByteArray() } };
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
PDFAnnotationPtr result;
|
PDFAnnotationPtr result;
|
||||||
|
|
||||||
const PDFDictionary* dictionary = document->getDictionaryFromObject(object);
|
const PDFDictionary* dictionary = storage->getDictionaryFromObject(object);
|
||||||
if (!dictionary)
|
if (!dictionary)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
|
|
||||||
QRectF annotationsRectangle = loader.readRectangle(dictionary->get("Rect"), QRectF());
|
QRectF annotationsRectangle = loader.readRectangle(dictionary->get("Rect"), QRectF());
|
||||||
|
|
||||||
@ -189,13 +200,13 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
|||||||
PDFLinkAnnotation* linkAnnotation = new PDFLinkAnnotation;
|
PDFLinkAnnotation* linkAnnotation = new PDFLinkAnnotation;
|
||||||
result.reset(linkAnnotation);
|
result.reset(linkAnnotation);
|
||||||
|
|
||||||
linkAnnotation->m_action = PDFAction::parse(document, dictionary->get("A"));
|
linkAnnotation->m_action = PDFAction::parse(storage, dictionary->get("A"));
|
||||||
if (!linkAnnotation->m_action)
|
if (!linkAnnotation->m_action)
|
||||||
{
|
{
|
||||||
PDFDestination destination = PDFDestination::parse(document, dictionary->get("Dest"));
|
PDFDestination destination = PDFDestination::parse(storage, dictionary->get("Dest"));
|
||||||
linkAnnotation->m_action.reset(new PDFActionGoTo(destination));
|
linkAnnotation->m_action.reset(new PDFActionGoTo(destination));
|
||||||
}
|
}
|
||||||
linkAnnotation->m_previousAction = PDFAction::parse(document, dictionary->get("PA"));
|
linkAnnotation->m_previousAction = PDFAction::parse(storage, dictionary->get("PA"));
|
||||||
|
|
||||||
constexpr const std::array<std::pair<const char*, LinkHighlightMode>, 4> highlightMode = {
|
constexpr const std::array<std::pair<const char*, LinkHighlightMode>, 4> highlightMode = {
|
||||||
std::pair<const char*, LinkHighlightMode>{ "N", LinkHighlightMode::None },
|
std::pair<const char*, LinkHighlightMode>{ "N", LinkHighlightMode::None },
|
||||||
@ -205,7 +216,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
|||||||
};
|
};
|
||||||
|
|
||||||
linkAnnotation->m_highlightMode = loader.readEnumByName(dictionary->get("H"), highlightMode.begin(), highlightMode.end(), LinkHighlightMode::Invert);
|
linkAnnotation->m_highlightMode = loader.readEnumByName(dictionary->get("H"), highlightMode.begin(), highlightMode.end(), LinkHighlightMode::Invert);
|
||||||
linkAnnotation->m_activationRegion = parseQuadrilaterals(document, dictionary->get("QuadPoints"), annotationsRectangle);
|
linkAnnotation->m_activationRegion = parseQuadrilaterals(storage, dictionary->get("QuadPoints"), annotationsRectangle);
|
||||||
}
|
}
|
||||||
else if (subtype == "FreeText")
|
else if (subtype == "FreeText")
|
||||||
{
|
{
|
||||||
@ -220,9 +231,9 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
|||||||
freeTextAnnotation->m_defaultAppearance = loader.readStringFromDictionary(dictionary, "DA");
|
freeTextAnnotation->m_defaultAppearance = loader.readStringFromDictionary(dictionary, "DA");
|
||||||
freeTextAnnotation->m_justification = static_cast<PDFFreeTextAnnotation::Justification>(loader.readIntegerFromDictionary(dictionary, "Q", 0));
|
freeTextAnnotation->m_justification = static_cast<PDFFreeTextAnnotation::Justification>(loader.readIntegerFromDictionary(dictionary, "Q", 0));
|
||||||
freeTextAnnotation->m_defaultStyleString = loader.readTextStringFromDictionary(dictionary, "DS", QString());
|
freeTextAnnotation->m_defaultStyleString = loader.readTextStringFromDictionary(dictionary, "DS", QString());
|
||||||
freeTextAnnotation->m_calloutLine = PDFAnnotationCalloutLine::parse(document, dictionary->get("CL"));
|
freeTextAnnotation->m_calloutLine = PDFAnnotationCalloutLine::parse(storage, dictionary->get("CL"));
|
||||||
freeTextAnnotation->m_intent = loader.readEnumByName(dictionary->get("IT"), intents.begin(), intents.end(), PDFFreeTextAnnotation::Intent::None);
|
freeTextAnnotation->m_intent = loader.readEnumByName(dictionary->get("IT"), intents.begin(), intents.end(), PDFFreeTextAnnotation::Intent::None);
|
||||||
freeTextAnnotation->m_effect = PDFAnnotationBorderEffect::parse(document, dictionary->get("BE"));
|
freeTextAnnotation->m_effect = PDFAnnotationBorderEffect::parse(storage, dictionary->get("BE"));
|
||||||
|
|
||||||
std::vector<PDFReal> differenceRectangle = loader.readNumberArrayFromDictionary(dictionary, "RD");
|
std::vector<PDFReal> differenceRectangle = loader.readNumberArrayFromDictionary(dictionary, "RD");
|
||||||
if (differenceRectangle.size() == 4)
|
if (differenceRectangle.size() == 4)
|
||||||
@ -266,7 +277,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
|||||||
lineAnnotation->m_captionRendered = loader.readBooleanFromDictionary(dictionary, "Cap", false);
|
lineAnnotation->m_captionRendered = loader.readBooleanFromDictionary(dictionary, "Cap", false);
|
||||||
lineAnnotation->m_intent = (loader.readNameFromDictionary(dictionary, "IT") == "LineDimension") ? PDFLineAnnotation::Intent::Dimension : PDFLineAnnotation::Intent::Arrow;
|
lineAnnotation->m_intent = (loader.readNameFromDictionary(dictionary, "IT") == "LineDimension") ? PDFLineAnnotation::Intent::Dimension : PDFLineAnnotation::Intent::Arrow;
|
||||||
lineAnnotation->m_captionPosition = (loader.readNameFromDictionary(dictionary, "CP") == "Top") ? PDFLineAnnotation::CaptionPosition::Top : PDFLineAnnotation::CaptionPosition::Inline;
|
lineAnnotation->m_captionPosition = (loader.readNameFromDictionary(dictionary, "CP") == "Top") ? PDFLineAnnotation::CaptionPosition::Top : PDFLineAnnotation::CaptionPosition::Inline;
|
||||||
lineAnnotation->m_measureDictionary = document->getObject(dictionary->get("Measure"));
|
lineAnnotation->m_measureDictionary = storage->getObject(dictionary->get("Measure"));
|
||||||
|
|
||||||
std::vector<PDFReal> captionOffset = loader.readNumberArrayFromDictionary(dictionary, "CO");
|
std::vector<PDFReal> captionOffset = loader.readNumberArrayFromDictionary(dictionary, "CO");
|
||||||
if (captionOffset.size() == 2)
|
if (captionOffset.size() == 2)
|
||||||
@ -280,7 +291,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
|||||||
result.reset(annotation);
|
result.reset(annotation);
|
||||||
|
|
||||||
annotation->m_interiorColor = loader.readNumberArrayFromDictionary(dictionary, "IC");
|
annotation->m_interiorColor = loader.readNumberArrayFromDictionary(dictionary, "IC");
|
||||||
annotation->m_effect = PDFAnnotationBorderEffect::parse(document, dictionary->get("BE"));
|
annotation->m_effect = PDFAnnotationBorderEffect::parse(storage, dictionary->get("BE"));
|
||||||
|
|
||||||
std::vector<PDFReal> differenceRectangle = loader.readNumberArrayFromDictionary(dictionary, "RD");
|
std::vector<PDFReal> differenceRectangle = loader.readNumberArrayFromDictionary(dictionary, "RD");
|
||||||
if (differenceRectangle.size() == 4)
|
if (differenceRectangle.size() == 4)
|
||||||
@ -313,7 +324,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
|||||||
}
|
}
|
||||||
|
|
||||||
annotation->m_interiorColor = loader.readNumberArrayFromDictionary(dictionary, "IC");
|
annotation->m_interiorColor = loader.readNumberArrayFromDictionary(dictionary, "IC");
|
||||||
annotation->m_effect = PDFAnnotationBorderEffect::parse(document, dictionary->get("BE"));
|
annotation->m_effect = PDFAnnotationBorderEffect::parse(storage, dictionary->get("BE"));
|
||||||
|
|
||||||
constexpr const std::array<std::pair<const char*, PDFPolygonalGeometryAnnotation::Intent>, 3> intents = {
|
constexpr const std::array<std::pair<const char*, PDFPolygonalGeometryAnnotation::Intent>, 3> intents = {
|
||||||
std::pair<const char*, PDFPolygonalGeometryAnnotation::Intent>{ "PolygonCloud", PDFPolygonalGeometryAnnotation::Intent::Cloud },
|
std::pair<const char*, PDFPolygonalGeometryAnnotation::Intent>{ "PolygonCloud", PDFPolygonalGeometryAnnotation::Intent::Cloud },
|
||||||
@ -322,7 +333,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
|||||||
};
|
};
|
||||||
|
|
||||||
annotation->m_intent = loader.readEnumByName(dictionary->get("IT"), intents.begin(), intents.end(), PDFPolygonalGeometryAnnotation::Intent::None);
|
annotation->m_intent = loader.readEnumByName(dictionary->get("IT"), intents.begin(), intents.end(), PDFPolygonalGeometryAnnotation::Intent::None);
|
||||||
annotation->m_measure = document->getObject(dictionary->get("Measure"));
|
annotation->m_measure = storage->getObject(dictionary->get("Measure"));
|
||||||
}
|
}
|
||||||
else if (subtype == "Highlight" ||
|
else if (subtype == "Highlight" ||
|
||||||
subtype == "Underline" ||
|
subtype == "Underline" ||
|
||||||
@ -346,7 +357,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
|||||||
PDFHighlightAnnotation* annotation = new PDFHighlightAnnotation(type);
|
PDFHighlightAnnotation* annotation = new PDFHighlightAnnotation(type);
|
||||||
result.reset(annotation);
|
result.reset(annotation);
|
||||||
|
|
||||||
annotation->m_highlightArea = parseQuadrilaterals(document, dictionary->get("QuadPoints"), annotationsRectangle);
|
annotation->m_highlightArea = parseQuadrilaterals(storage, dictionary->get("QuadPoints"), annotationsRectangle);
|
||||||
}
|
}
|
||||||
else if (subtype == "Caret")
|
else if (subtype == "Caret")
|
||||||
{
|
{
|
||||||
@ -394,7 +405,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
|||||||
PDFInkAnnotation* annotation = new PDFInkAnnotation();
|
PDFInkAnnotation* annotation = new PDFInkAnnotation();
|
||||||
result.reset(annotation);
|
result.reset(annotation);
|
||||||
|
|
||||||
PDFObject inkList = document->getObject(dictionary->get("InkList"));
|
PDFObject inkList = storage->getObject(dictionary->get("InkList"));
|
||||||
if (inkList.isArray())
|
if (inkList.isArray())
|
||||||
{
|
{
|
||||||
const PDFArray* inkListArray = inkList.getArray();
|
const PDFArray* inkListArray = inkList.getArray();
|
||||||
@ -432,7 +443,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
|||||||
PDFFileAttachmentAnnotation* annotation = new PDFFileAttachmentAnnotation();
|
PDFFileAttachmentAnnotation* annotation = new PDFFileAttachmentAnnotation();
|
||||||
result.reset(annotation);
|
result.reset(annotation);
|
||||||
|
|
||||||
annotation->m_fileSpecification = PDFFileSpecification::parse(document, dictionary->get("FS"));
|
annotation->m_fileSpecification = PDFFileSpecification::parse(storage, dictionary->get("FS"));
|
||||||
|
|
||||||
constexpr const std::array<std::pair<const char*, PDFFileAttachmentAnnotation::Icon>, 4> icons = {
|
constexpr const std::array<std::pair<const char*, PDFFileAttachmentAnnotation::Icon>, 4> icons = {
|
||||||
std::pair<const char*, PDFFileAttachmentAnnotation::Icon>{ "Graph", PDFFileAttachmentAnnotation::Icon::Graph },
|
std::pair<const char*, PDFFileAttachmentAnnotation::Icon>{ "Graph", PDFFileAttachmentAnnotation::Icon::Graph },
|
||||||
@ -448,7 +459,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
|||||||
PDFSoundAnnotation* annotation = new PDFSoundAnnotation();
|
PDFSoundAnnotation* annotation = new PDFSoundAnnotation();
|
||||||
result.reset(annotation);
|
result.reset(annotation);
|
||||||
|
|
||||||
annotation->m_sound = PDFSound::parse(document, dictionary->get("Sound"));
|
annotation->m_sound = PDFSound::parse(storage, dictionary->get("Sound"));
|
||||||
|
|
||||||
constexpr const std::array<std::pair<const char*, PDFSoundAnnotation::Icon>, 2> icons = {
|
constexpr const std::array<std::pair<const char*, PDFSoundAnnotation::Icon>, 2> icons = {
|
||||||
std::pair<const char*, PDFSoundAnnotation::Icon>{ "Speaker", PDFSoundAnnotation::Icon::Speaker },
|
std::pair<const char*, PDFSoundAnnotation::Icon>{ "Speaker", PDFSoundAnnotation::Icon::Speaker },
|
||||||
@ -463,9 +474,9 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
|||||||
result.reset(annotation);
|
result.reset(annotation);
|
||||||
|
|
||||||
annotation->m_movieTitle = loader.readStringFromDictionary(dictionary, "T");
|
annotation->m_movieTitle = loader.readStringFromDictionary(dictionary, "T");
|
||||||
annotation->m_movie = PDFMovie::parse(document, dictionary->get("Movie"));
|
annotation->m_movie = PDFMovie::parse(storage, dictionary->get("Movie"));
|
||||||
|
|
||||||
PDFObject activation = document->getObject(dictionary->get("A"));
|
PDFObject activation = storage->getObject(dictionary->get("A"));
|
||||||
if (activation.isBool())
|
if (activation.isBool())
|
||||||
{
|
{
|
||||||
annotation->m_playMovie = activation.getBool();
|
annotation->m_playMovie = activation.getBool();
|
||||||
@ -473,7 +484,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
|||||||
else if (activation.isDictionary())
|
else if (activation.isDictionary())
|
||||||
{
|
{
|
||||||
annotation->m_playMovie = true;
|
annotation->m_playMovie = true;
|
||||||
annotation->m_movieActivation = PDFMovieActivation::parse(document, activation);
|
annotation->m_movieActivation = PDFMovieActivation::parse(storage, activation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (subtype == "Screen")
|
else if (subtype == "Screen")
|
||||||
@ -482,9 +493,9 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
|||||||
result.reset(annotation);
|
result.reset(annotation);
|
||||||
|
|
||||||
annotation->m_screenTitle = loader.readTextStringFromDictionary(dictionary, "T", QString());
|
annotation->m_screenTitle = loader.readTextStringFromDictionary(dictionary, "T", QString());
|
||||||
annotation->m_appearanceCharacteristics = PDFAnnotationAppearanceCharacteristics::parse(document, dictionary->get("MK"));
|
annotation->m_appearanceCharacteristics = PDFAnnotationAppearanceCharacteristics::parse(storage, dictionary->get("MK"));
|
||||||
annotation->m_action = PDFAction::parse(document, dictionary->get("A"));
|
annotation->m_action = PDFAction::parse(storage, dictionary->get("A"));
|
||||||
annotation->m_additionalActions = PDFAnnotationAdditionalActions::parse(document, dictionary->get("AA"));
|
annotation->m_additionalActions = PDFAnnotationAdditionalActions::parse(storage, dictionary->get("AA"));
|
||||||
}
|
}
|
||||||
else if (subtype == "Widget")
|
else if (subtype == "Widget")
|
||||||
{
|
{
|
||||||
@ -500,9 +511,9 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
|||||||
};
|
};
|
||||||
|
|
||||||
annotation->m_highlightMode = loader.readEnumByName(dictionary->get("H"), highlightModes.begin(), highlightModes.end(), PDFWidgetAnnotation::HighlightMode::Invert);
|
annotation->m_highlightMode = loader.readEnumByName(dictionary->get("H"), highlightModes.begin(), highlightModes.end(), PDFWidgetAnnotation::HighlightMode::Invert);
|
||||||
annotation->m_appearanceCharacteristics = PDFAnnotationAppearanceCharacteristics::parse(document, dictionary->get("MK"));
|
annotation->m_appearanceCharacteristics = PDFAnnotationAppearanceCharacteristics::parse(storage, dictionary->get("MK"));
|
||||||
annotation->m_action = PDFAction::parse(document, dictionary->get("A"));
|
annotation->m_action = PDFAction::parse(storage, dictionary->get("A"));
|
||||||
annotation->m_additionalActions = PDFAnnotationAdditionalActions::parse(document, dictionary->get("AA"));
|
annotation->m_additionalActions = PDFAnnotationAdditionalActions::parse(storage, dictionary->get("AA"));
|
||||||
}
|
}
|
||||||
else if (subtype == "PrinterMark")
|
else if (subtype == "PrinterMark")
|
||||||
{
|
{
|
||||||
@ -519,7 +530,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
|||||||
PDFWatermarkAnnotation* annotation = new PDFWatermarkAnnotation();
|
PDFWatermarkAnnotation* annotation = new PDFWatermarkAnnotation();
|
||||||
result.reset(annotation);
|
result.reset(annotation);
|
||||||
|
|
||||||
if (const PDFDictionary* fixedPrintDictionary = document->getDictionaryFromObject(dictionary->get("FixedPrint")))
|
if (const PDFDictionary* fixedPrintDictionary = storage->getDictionaryFromObject(dictionary->get("FixedPrint")))
|
||||||
{
|
{
|
||||||
annotation->m_matrix = loader.readMatrixFromDictionary(fixedPrintDictionary, "Matrix", QMatrix());
|
annotation->m_matrix = loader.readMatrixFromDictionary(fixedPrintDictionary, "Matrix", QMatrix());
|
||||||
annotation->m_relativeHorizontalOffset = loader.readNumberFromDictionary(fixedPrintDictionary, "H", 0.0);
|
annotation->m_relativeHorizontalOffset = loader.readNumberFromDictionary(fixedPrintDictionary, "H", 0.0);
|
||||||
@ -547,13 +558,13 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
|||||||
}
|
}
|
||||||
|
|
||||||
result->m_flags = Flags(loader.readIntegerFromDictionary(dictionary, "F", 0));
|
result->m_flags = Flags(loader.readIntegerFromDictionary(dictionary, "F", 0));
|
||||||
result->m_appearanceStreams = PDFAppeareanceStreams::parse(document, dictionary->get("AP"));
|
result->m_appearanceStreams = PDFAppeareanceStreams::parse(storage, dictionary->get("AP"));
|
||||||
result->m_appearanceState = loader.readNameFromDictionary(dictionary, "AS");
|
result->m_appearanceState = loader.readNameFromDictionary(dictionary, "AS");
|
||||||
|
|
||||||
result->m_annotationBorder = PDFAnnotationBorder::parseBS(document, dictionary->get("BS"));
|
result->m_annotationBorder = PDFAnnotationBorder::parseBS(storage, dictionary->get("BS"));
|
||||||
if (!result->m_annotationBorder.isValid())
|
if (!result->m_annotationBorder.isValid())
|
||||||
{
|
{
|
||||||
result->m_annotationBorder = PDFAnnotationBorder::parseBorder(document, dictionary->get("Border"));
|
result->m_annotationBorder = PDFAnnotationBorder::parseBorder(storage, dictionary->get("Border"));
|
||||||
}
|
}
|
||||||
result->m_color = loader.readNumberArrayFromDictionary(dictionary, "C");
|
result->m_color = loader.readNumberArrayFromDictionary(dictionary, "C");
|
||||||
result->m_structParent = loader.readIntegerFromDictionary(dictionary, "StructParent", 0);
|
result->m_structParent = loader.readIntegerFromDictionary(dictionary, "StructParent", 0);
|
||||||
@ -570,18 +581,18 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
|||||||
markupAnnotation->m_subject = loader.readTextStringFromDictionary(dictionary, "Subj", QString());
|
markupAnnotation->m_subject = loader.readTextStringFromDictionary(dictionary, "Subj", QString());
|
||||||
markupAnnotation->m_replyType = (loader.readNameFromDictionary(dictionary, "RT") == "Group") ? PDFMarkupAnnotation::ReplyType::Group : PDFMarkupAnnotation::ReplyType::Reply;
|
markupAnnotation->m_replyType = (loader.readNameFromDictionary(dictionary, "RT") == "Group") ? PDFMarkupAnnotation::ReplyType::Group : PDFMarkupAnnotation::ReplyType::Reply;
|
||||||
markupAnnotation->m_intent = loader.readNameFromDictionary(dictionary, "IT");
|
markupAnnotation->m_intent = loader.readNameFromDictionary(dictionary, "IT");
|
||||||
markupAnnotation->m_externalData = document->getObject(dictionary->get("ExData"));
|
markupAnnotation->m_externalData = storage->getObject(dictionary->get("ExData"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFAnnotationQuadrilaterals PDFAnnotation::parseQuadrilaterals(const PDFDocument* document, PDFObject quadrilateralsObject, const QRectF annotationRect)
|
PDFAnnotationQuadrilaterals PDFAnnotation::parseQuadrilaterals(const PDFObjectStorage* storage, PDFObject quadrilateralsObject, const QRectF annotationRect)
|
||||||
{
|
{
|
||||||
QPainterPath path;
|
QPainterPath path;
|
||||||
std::vector<QLineF> underlines;
|
std::vector<QLineF> underlines;
|
||||||
|
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
std::vector<PDFReal> points = loader.readNumberArray(quadrilateralsObject);
|
std::vector<PDFReal> points = loader.readNumberArray(quadrilateralsObject);
|
||||||
const size_t quadrilateralCount = points.size() % 8;
|
const size_t quadrilateralCount = points.size() % 8;
|
||||||
path.reserve(int(quadrilateralCount) + 5);
|
path.reserve(int(quadrilateralCount) + 5);
|
||||||
@ -639,9 +650,89 @@ AnnotationLineEnding PDFAnnotation::convertNameToLineEnding(const QByteArray& na
|
|||||||
return AnnotationLineEnding::None;
|
return AnnotationLineEnding::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFAnnotationCalloutLine PDFAnnotationCalloutLine::parse(const PDFDocument* document, PDFObject object)
|
QColor PDFAnnotation::getStrokeColor() const
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
return getDrawColorFromAnnotationColor(getColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor PDFAnnotation::getFillColor() const
|
||||||
|
{
|
||||||
|
return QColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor PDFAnnotation::getDrawColorFromAnnotationColor(const std::vector<PDFReal>& color) const
|
||||||
|
{
|
||||||
|
switch (color.size())
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
const PDFReal gray = color.back();
|
||||||
|
return QColor::fromRgbF(gray, gray, gray, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
const PDFReal r = color[0];
|
||||||
|
const PDFReal g = color[1];
|
||||||
|
const PDFReal b = color[2];
|
||||||
|
return QColor::fromRgbF(r, g, b, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
const PDFReal c = color[0];
|
||||||
|
const PDFReal m = color[1];
|
||||||
|
const PDFReal y = color[2];
|
||||||
|
const PDFReal k = color[3];
|
||||||
|
return QColor::fromCmykF(c, m, y, k, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QColor(Qt::black);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPen PDFAnnotation::getPen() const
|
||||||
|
{
|
||||||
|
QColor strokeColor = getStrokeColor();
|
||||||
|
const PDFAnnotationBorder& border = getBorder();
|
||||||
|
|
||||||
|
if (qFuzzyIsNull(border.getWidth()))
|
||||||
|
{
|
||||||
|
// No border is drawn
|
||||||
|
return Qt::NoPen;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPen pen(strokeColor);
|
||||||
|
pen.setWidthF(border.getWidth());
|
||||||
|
|
||||||
|
if (!border.getDashPattern().empty())
|
||||||
|
{
|
||||||
|
PDFLineDashPattern lineDashPattern(border.getDashPattern(), 0.0);
|
||||||
|
pen.setStyle(Qt::CustomDashLine);
|
||||||
|
pen.setDashPattern(QVector<PDFReal>::fromStdVector(lineDashPattern.getDashArray()));
|
||||||
|
pen.setDashOffset(lineDashPattern.getDashOffset());
|
||||||
|
}
|
||||||
|
|
||||||
|
return pen;
|
||||||
|
}
|
||||||
|
|
||||||
|
QBrush PDFAnnotation::getBrush() const
|
||||||
|
{
|
||||||
|
QColor color = getFillColor();
|
||||||
|
if (color.isValid())
|
||||||
|
{
|
||||||
|
return QBrush(color, Qt::SolidPattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
return QBrush(Qt::NoBrush);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFAnnotationCalloutLine PDFAnnotationCalloutLine::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
|
{
|
||||||
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
std::vector<PDFReal> points = loader.readNumberArray(object);
|
std::vector<PDFReal> points = loader.readNumberArray(object);
|
||||||
|
|
||||||
switch (points.size())
|
switch (points.size())
|
||||||
@ -659,13 +750,13 @@ PDFAnnotationCalloutLine PDFAnnotationCalloutLine::parse(const PDFDocument* docu
|
|||||||
return PDFAnnotationCalloutLine();
|
return PDFAnnotationCalloutLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFAnnotationAppearanceCharacteristics PDFAnnotationAppearanceCharacteristics::parse(const PDFDocument* document, PDFObject object)
|
PDFAnnotationAppearanceCharacteristics PDFAnnotationAppearanceCharacteristics::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
PDFAnnotationAppearanceCharacteristics result;
|
PDFAnnotationAppearanceCharacteristics result;
|
||||||
|
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
|
|
||||||
result.m_rotation = loader.readIntegerFromDictionary(dictionary, "R", 0);
|
result.m_rotation = loader.readIntegerFromDictionary(dictionary, "R", 0);
|
||||||
result.m_borderColor = loader.readNumberArrayFromDictionary(dictionary, "BC");
|
result.m_borderColor = loader.readNumberArrayFromDictionary(dictionary, "BC");
|
||||||
@ -673,22 +764,22 @@ PDFAnnotationAppearanceCharacteristics PDFAnnotationAppearanceCharacteristics::p
|
|||||||
result.m_normalCaption = loader.readTextStringFromDictionary(dictionary, "CA", QString());
|
result.m_normalCaption = loader.readTextStringFromDictionary(dictionary, "CA", QString());
|
||||||
result.m_rolloverCaption = loader.readTextStringFromDictionary(dictionary, "RC", QString());
|
result.m_rolloverCaption = loader.readTextStringFromDictionary(dictionary, "RC", QString());
|
||||||
result.m_downCaption = loader.readTextStringFromDictionary(dictionary, "AC", QString());
|
result.m_downCaption = loader.readTextStringFromDictionary(dictionary, "AC", QString());
|
||||||
result.m_normalIcon = document->getObject(dictionary->get("I"));
|
result.m_normalIcon = storage->getObject(dictionary->get("I"));
|
||||||
result.m_rolloverIcon = document->getObject(dictionary->get("RI"));
|
result.m_rolloverIcon = storage->getObject(dictionary->get("RI"));
|
||||||
result.m_downIcon = document->getObject(dictionary->get("IX"));
|
result.m_downIcon = storage->getObject(dictionary->get("IX"));
|
||||||
result.m_iconFit = PDFAnnotationIconFitInfo::parse(document, dictionary->get("IF"));
|
result.m_iconFit = PDFAnnotationIconFitInfo::parse(storage, dictionary->get("IF"));
|
||||||
result.m_pushButtonMode = static_cast<PushButtonMode>(loader.readIntegerFromDictionary(dictionary, "TP", PDFInteger(PDFAnnotationAppearanceCharacteristics::PushButtonMode::NoIcon)));
|
result.m_pushButtonMode = static_cast<PushButtonMode>(loader.readIntegerFromDictionary(dictionary, "TP", PDFInteger(PDFAnnotationAppearanceCharacteristics::PushButtonMode::NoIcon)));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFAnnotationIconFitInfo PDFAnnotationIconFitInfo::parse(const PDFDocument* document, PDFObject object)
|
PDFAnnotationIconFitInfo PDFAnnotationIconFitInfo::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
PDFAnnotationIconFitInfo info;
|
PDFAnnotationIconFitInfo info;
|
||||||
|
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
|
|
||||||
constexpr const std::array<std::pair<const char*, PDFAnnotationIconFitInfo::ScaleCondition>, 4> scaleConditions = {
|
constexpr const std::array<std::pair<const char*, PDFAnnotationIconFitInfo::ScaleCondition>, 4> scaleConditions = {
|
||||||
std::pair<const char*, PDFAnnotationIconFitInfo::ScaleCondition>{ "A", PDFAnnotationIconFitInfo::ScaleCondition::Always },
|
std::pair<const char*, PDFAnnotationIconFitInfo::ScaleCondition>{ "A", PDFAnnotationIconFitInfo::ScaleCondition::Always },
|
||||||
@ -717,22 +808,22 @@ PDFAnnotationIconFitInfo PDFAnnotationIconFitInfo::parse(const PDFDocument* docu
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFAnnotationAdditionalActions PDFAnnotationAdditionalActions::parse(const PDFDocument* document, PDFObject object)
|
PDFAnnotationAdditionalActions PDFAnnotationAdditionalActions::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
PDFAnnotationAdditionalActions result;
|
PDFAnnotationAdditionalActions result;
|
||||||
|
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
result.m_actions[CursorEnter] = PDFAction::parse(document, dictionary->get("E"));
|
result.m_actions[CursorEnter] = PDFAction::parse(storage, dictionary->get("E"));
|
||||||
result.m_actions[CursorLeave] = PDFAction::parse(document, dictionary->get("X"));
|
result.m_actions[CursorLeave] = PDFAction::parse(storage, dictionary->get("X"));
|
||||||
result.m_actions[MousePressed] = PDFAction::parse(document, dictionary->get("D"));
|
result.m_actions[MousePressed] = PDFAction::parse(storage, dictionary->get("D"));
|
||||||
result.m_actions[MouseReleased] = PDFAction::parse(document, dictionary->get("U"));
|
result.m_actions[MouseReleased] = PDFAction::parse(storage, dictionary->get("U"));
|
||||||
result.m_actions[FocusIn] = PDFAction::parse(document, dictionary->get("Fo"));
|
result.m_actions[FocusIn] = PDFAction::parse(storage, dictionary->get("Fo"));
|
||||||
result.m_actions[FocusOut] = PDFAction::parse(document, dictionary->get("Bl"));
|
result.m_actions[FocusOut] = PDFAction::parse(storage, dictionary->get("Bl"));
|
||||||
result.m_actions[PageOpened] = PDFAction::parse(document, dictionary->get("PO"));
|
result.m_actions[PageOpened] = PDFAction::parse(storage, dictionary->get("PO"));
|
||||||
result.m_actions[PageClosed] = PDFAction::parse(document, dictionary->get("PC"));
|
result.m_actions[PageClosed] = PDFAction::parse(storage, dictionary->get("PC"));
|
||||||
result.m_actions[PageShow] = PDFAction::parse(document, dictionary->get("PV"));
|
result.m_actions[PageShow] = PDFAction::parse(storage, dictionary->get("PV"));
|
||||||
result.m_actions[PageHide] = PDFAction::parse(document, dictionary->get("PI"));
|
result.m_actions[PageHide] = PDFAction::parse(storage, dictionary->get("PI"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -931,7 +1022,7 @@ PDFAnnotationManager::PageAnnotations& PDFAnnotationManager::getPageAnnotations(
|
|||||||
annotations.annotations.reserve(pageAnnotations.size());
|
annotations.annotations.reserve(pageAnnotations.size());
|
||||||
for (PDFObjectReference annotationReference : pageAnnotations)
|
for (PDFObjectReference annotationReference : pageAnnotations)
|
||||||
{
|
{
|
||||||
PDFAnnotationPtr annotationPtr = PDFAnnotation::parse(m_document, m_document->getObjectByReference(annotationReference));
|
PDFAnnotationPtr annotationPtr = PDFAnnotation::parse(&m_document->getStorage(), m_document->getObjectByReference(annotationReference));
|
||||||
if (annotationPtr)
|
if (annotationPtr)
|
||||||
{
|
{
|
||||||
PageAnnotation annotation;
|
PageAnnotation annotation;
|
||||||
@ -956,4 +1047,78 @@ void PDFAnnotationManager::setTarget(Target target)
|
|||||||
m_target = target;
|
m_target = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFSimpleGeometryAnnotation::draw(AnnotationDrawParameters& parameters) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(parameters.painter);
|
||||||
|
parameters.boundingRectangle = getRectangle();
|
||||||
|
|
||||||
|
QPainter& painter = *parameters.painter;
|
||||||
|
painter.setPen(getPen());
|
||||||
|
painter.setBrush(getBrush());
|
||||||
|
|
||||||
|
switch (getType())
|
||||||
|
{
|
||||||
|
case AnnotationType::Square:
|
||||||
|
{
|
||||||
|
const PDFAnnotationBorder& border = getBorder();
|
||||||
|
|
||||||
|
const PDFReal hCornerRadius = border.getHorizontalCornerRadius();
|
||||||
|
const PDFReal vCornerRadius = border.getVerticalCornerRadius();
|
||||||
|
const bool isRounded = !qFuzzyIsNull(hCornerRadius) || !qFuzzyIsNull(vCornerRadius);
|
||||||
|
|
||||||
|
if (isRounded)
|
||||||
|
{
|
||||||
|
painter.drawRoundedRect(getRectangle(), hCornerRadius, vCornerRadius, Qt::AbsoluteSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
painter.drawRect(getRectangle());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case AnnotationType::Circle:
|
||||||
|
{
|
||||||
|
painter.drawEllipse(getRectangle());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
Q_ASSERT(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor PDFSimpleGeometryAnnotation::getFillColor() const
|
||||||
|
{
|
||||||
|
QColor color = getDrawColorFromAnnotationColor(getInteriorColor());
|
||||||
|
if (color.isValid())
|
||||||
|
{
|
||||||
|
color.setAlphaF(getOpacity());
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor PDFMarkupAnnotation::getStrokeColor() const
|
||||||
|
{
|
||||||
|
QColor color = PDFAnnotation::getStrokeColor();
|
||||||
|
if (color.isValid())
|
||||||
|
{
|
||||||
|
color.setAlphaF(m_opacity);
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor PDFMarkupAnnotation::getFillColor() const
|
||||||
|
{
|
||||||
|
QColor color = PDFAnnotation::getFillColor();
|
||||||
|
if (color.isValid())
|
||||||
|
{
|
||||||
|
color.setAlphaF(m_opacity);
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
class PDFDocument;
|
class PDFObjectStorage;
|
||||||
class PDFDrawWidgetProxy;
|
class PDFDrawWidgetProxy;
|
||||||
|
|
||||||
using TextAlignment = Qt::Alignment;
|
using TextAlignment = Qt::Alignment;
|
||||||
@ -105,15 +105,15 @@ public:
|
|||||||
|
|
||||||
/// Parses the annotation border from the array. If object contains invalid annotation border,
|
/// Parses the annotation border from the array. If object contains invalid annotation border,
|
||||||
/// then default annotation border is returned. If object is empty, empty annotation border is returned.
|
/// then default annotation border is returned. If object is empty, empty annotation border is returned.
|
||||||
/// \param document Document
|
/// \param storage Object storage
|
||||||
/// \param object Border object
|
/// \param object Border object
|
||||||
static PDFAnnotationBorder parseBorder(const PDFDocument* document, PDFObject object);
|
static PDFAnnotationBorder parseBorder(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
/// Parses the annotation border from the BS dictionary. If object contains invalid annotation border,
|
/// Parses the annotation border from the BS dictionary. If object contains invalid annotation border,
|
||||||
/// then default annotation border is returned. If object is empty, empty annotation border is returned.
|
/// then default annotation border is returned. If object is empty, empty annotation border is returned.
|
||||||
/// \param document Document
|
/// \param storage Object storage
|
||||||
/// \param object Border object
|
/// \param object Border object
|
||||||
static PDFAnnotationBorder parseBS(const PDFDocument* document, PDFObject object);
|
static PDFAnnotationBorder parseBS(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
/// Returns true, if object is correctly defined
|
/// Returns true, if object is correctly defined
|
||||||
bool isValid() const { return m_definition != Definition::Invalid; }
|
bool isValid() const { return m_definition != Definition::Invalid; }
|
||||||
@ -150,9 +150,9 @@ public:
|
|||||||
|
|
||||||
/// Parses the annotation border effect from the object. If object contains invalid annotation border effect,
|
/// Parses the annotation border effect from the object. If object contains invalid annotation border effect,
|
||||||
/// then default annotation border effect is returned. If object is empty, also default annotation border effect is returned.
|
/// then default annotation border effect is returned. If object is empty, also default annotation border effect is returned.
|
||||||
/// \param document Document
|
/// \param storage Object storage
|
||||||
/// \param object Border effect object
|
/// \param object Border effect object
|
||||||
static PDFAnnotationBorderEffect parse(const PDFDocument* document, PDFObject object);
|
static PDFAnnotationBorderEffect parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Effect m_effect = Effect::None;
|
Effect m_effect = Effect::None;
|
||||||
@ -179,9 +179,9 @@ public:
|
|||||||
|
|
||||||
/// Parses annotation appearance streams from the object. If object is invalid, then
|
/// Parses annotation appearance streams from the object. If object is invalid, then
|
||||||
/// empty appearance stream is constructed.
|
/// empty appearance stream is constructed.
|
||||||
/// \param document Document
|
/// \param storage Object storage
|
||||||
/// \param object Appearance streams object
|
/// \param object Appearance streams object
|
||||||
static PDFAppeareanceStreams parse(const PDFDocument* document, PDFObject object);
|
static PDFAppeareanceStreams parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
/// Tries to search for appearance stream for given appearance. If no appearance is found,
|
/// Tries to search for appearance stream for given appearance. If no appearance is found,
|
||||||
/// then null object is returned.
|
/// then null object is returned.
|
||||||
@ -248,9 +248,9 @@ public:
|
|||||||
|
|
||||||
/// Parses annotation callout line from the object. If object is invalid, then
|
/// Parses annotation callout line from the object. If object is invalid, then
|
||||||
/// invalid callout line is constructed.
|
/// invalid callout line is constructed.
|
||||||
/// \param document Document
|
/// \param storage Object storage
|
||||||
/// \param object Callout line object
|
/// \param object Callout line object
|
||||||
static PDFAnnotationCalloutLine parse(const PDFDocument* document, PDFObject object);
|
static PDFAnnotationCalloutLine parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
bool isValid() const { return m_type != Type::Invalid; }
|
bool isValid() const { return m_type != Type::Invalid; }
|
||||||
Type getType() const { return m_type; }
|
Type getType() const { return m_type; }
|
||||||
@ -284,9 +284,9 @@ public:
|
|||||||
|
|
||||||
/// Parses annotation appearance icon fit info from the object. If object is invalid, then
|
/// Parses annotation appearance icon fit info from the object. If object is invalid, then
|
||||||
/// default appearance icon fit info is constructed.
|
/// default appearance icon fit info is constructed.
|
||||||
/// \param document Document
|
/// \param storage Object storage
|
||||||
/// \param object Appearance icon fit info object
|
/// \param object Appearance icon fit info object
|
||||||
static PDFAnnotationIconFitInfo parse(const PDFDocument* document, PDFObject object);
|
static PDFAnnotationIconFitInfo parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ScaleCondition m_scaleCondition = ScaleCondition::Always;
|
ScaleCondition m_scaleCondition = ScaleCondition::Always;
|
||||||
@ -329,9 +329,9 @@ public:
|
|||||||
|
|
||||||
/// Parses annotation appearance characteristics from the object. If object is invalid, then
|
/// Parses annotation appearance characteristics from the object. If object is invalid, then
|
||||||
/// default appearance characteristics is constructed.
|
/// default appearance characteristics is constructed.
|
||||||
/// \param document Document
|
/// \param storage Object storage
|
||||||
/// \param object Appearance characteristics object
|
/// \param object Appearance characteristics object
|
||||||
static PDFAnnotationAppearanceCharacteristics parse(const PDFDocument* document, PDFObject object);
|
static PDFAnnotationAppearanceCharacteristics parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFInteger m_rotation = 0;
|
PDFInteger m_rotation = 0;
|
||||||
@ -376,9 +376,9 @@ public:
|
|||||||
|
|
||||||
/// Parses annotation additional actions from the object. If object is invalid, then
|
/// Parses annotation additional actions from the object. If object is invalid, then
|
||||||
/// empty additional actions is constructed.
|
/// empty additional actions is constructed.
|
||||||
/// \param document Document
|
/// \param storage Object storage
|
||||||
/// \param object Additional actions object
|
/// \param object Additional actions object
|
||||||
static PDFAnnotationAdditionalActions parse(const PDFDocument* document, PDFObject object);
|
static PDFAnnotationAdditionalActions parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<PDFActionPtr, End> m_actions;
|
std::array<PDFActionPtr, End> m_actions;
|
||||||
@ -390,6 +390,22 @@ class PDFTextAnnotation;
|
|||||||
|
|
||||||
using PDFAnnotationPtr = QSharedPointer<PDFAnnotation>;
|
using PDFAnnotationPtr = QSharedPointer<PDFAnnotation>;
|
||||||
|
|
||||||
|
struct AnnotationDrawParameters
|
||||||
|
{
|
||||||
|
/// Painter, onto which is annotation graphics drawn
|
||||||
|
QPainter* painter = nullptr;
|
||||||
|
|
||||||
|
/// Output parameter. Marks annotation's graphics bounding
|
||||||
|
/// rectangle (it can be different/adjusted from original
|
||||||
|
/// annotation bounding rectangle, in that case, it must be adjusted).
|
||||||
|
/// If this rectangle is invalid, then appearance content stream
|
||||||
|
/// is assumed to be empty.
|
||||||
|
QRectF boundingRectangle;
|
||||||
|
|
||||||
|
/// Appeareance mode (normal/rollover/down, and appearance state)
|
||||||
|
PDFAppeareanceStreams::Key key;
|
||||||
|
};
|
||||||
|
|
||||||
/// Base class for all annotation types. Represents PDF annotation object.
|
/// Base class for all annotation types. Represents PDF annotation object.
|
||||||
/// Annotations are various enhancements to pages graphical representation,
|
/// Annotations are various enhancements to pages graphical representation,
|
||||||
/// such as graphics, text, highlight or multimedia content, such as sounds,
|
/// such as graphics, text, highlight or multimedia content, such as sounds,
|
||||||
@ -421,6 +437,17 @@ public:
|
|||||||
virtual PDFMarkupAnnotation* asMarkupAnnotation() { return nullptr; }
|
virtual PDFMarkupAnnotation* asMarkupAnnotation() { return nullptr; }
|
||||||
virtual const PDFMarkupAnnotation* asMarkupAnnotation() const { return nullptr; }
|
virtual const PDFMarkupAnnotation* asMarkupAnnotation() const { return nullptr; }
|
||||||
|
|
||||||
|
/// Draws the annotation using parameters. Annotation is drawn onto painter,
|
||||||
|
/// but actual graphics can be drawn outside of annotation's rectangle.
|
||||||
|
/// In that case, adjusted annotation's rectangle is passed to the parameters.
|
||||||
|
/// Painter must use annotation's coordinate system (for example, line points
|
||||||
|
/// must match in both in painter and this annotation).
|
||||||
|
/// \param parameters Graphics parameters
|
||||||
|
virtual void draw(AnnotationDrawParameters& parameters) const;
|
||||||
|
|
||||||
|
/// Returns a list of appearance states, which must be created for this annotation
|
||||||
|
virtual std::vector<PDFAppeareanceStreams::Key> getDrawKeys() const;
|
||||||
|
|
||||||
const QRectF& getRectangle() const { return m_rectangle; }
|
const QRectF& getRectangle() const { return m_rectangle; }
|
||||||
const QString& getContents() const { return m_contents; }
|
const QString& getContents() const { return m_contents; }
|
||||||
PDFObjectReference getPageReference() const { return m_pageReference; }
|
PDFObjectReference getPageReference() const { return m_pageReference; }
|
||||||
@ -436,24 +463,39 @@ public:
|
|||||||
PDFObjectReference getOptionalContent() const { return m_optionalContentReference; }
|
PDFObjectReference getOptionalContent() const { return m_optionalContentReference; }
|
||||||
|
|
||||||
/// Parses annotation from the object. If error occurs, then nullptr is returned.
|
/// Parses annotation from the object. If error occurs, then nullptr is returned.
|
||||||
/// \param document Document
|
/// \param storage Object storage
|
||||||
/// \param object Annotation object
|
/// \param object Annotation object
|
||||||
static PDFAnnotationPtr parse(const PDFDocument* document, PDFObject object);
|
static PDFAnnotationPtr parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
/// Parses quadrilaterals and fills them in the painter path. If no quadrilaterals are defined,
|
/// Parses quadrilaterals and fills them in the painter path. If no quadrilaterals are defined,
|
||||||
/// then annotation rectangle is used. If annotation rectangle is also invalid,
|
/// then annotation rectangle is used. If annotation rectangle is also invalid,
|
||||||
/// then empty painter path is used.
|
/// then empty painter path is used.
|
||||||
/// \param document Document
|
/// \param storage Object storage
|
||||||
/// \param quadrilateralsObject Object with quadrilaterals definition
|
/// \param quadrilateralsObject Object with quadrilaterals definition
|
||||||
/// \param annotationRect Annotation rectangle
|
/// \param annotationRect Annotation rectangle
|
||||||
static PDFAnnotationQuadrilaterals parseQuadrilaterals(const PDFDocument* document, PDFObject quadrilateralsObject, const QRectF annotationRect);
|
static PDFAnnotationQuadrilaterals parseQuadrilaterals(const PDFObjectStorage* storage, PDFObject quadrilateralsObject, const QRectF annotationRect);
|
||||||
|
|
||||||
/// Converts name to line ending. If appropriate line ending for name is not found,
|
/// Converts name to line ending. If appropriate line ending for name is not found,
|
||||||
/// then None line ending is returned.
|
/// then None line ending is returned.
|
||||||
/// \param name Name of the line ending
|
/// \param name Name of the line ending
|
||||||
static AnnotationLineEnding convertNameToLineEnding(const QByteArray& name);
|
static AnnotationLineEnding convertNameToLineEnding(const QByteArray& name);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual QColor getStrokeColor() const;
|
||||||
|
virtual QColor getFillColor() const;
|
||||||
|
|
||||||
|
/// Returns draw color from defined annotation color
|
||||||
|
QColor getDrawColorFromAnnotationColor(const std::vector<PDFReal>& color) const;
|
||||||
|
|
||||||
|
/// Returns pen from border settings and annotation color
|
||||||
|
QPen getPen() const;
|
||||||
|
|
||||||
|
/// Returns brush from interior color. If annotation doesn't have
|
||||||
|
/// a brush, then empty brush is returned.
|
||||||
|
QBrush getBrush() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QRectF m_rectangle; ///< Annotation rectangle, in page coordinates, "Rect" entry
|
QRectF m_rectangle; ///< Annotation rectangle, in page coordinates, "Rect" entry
|
||||||
QString m_contents; ///< Text to be displayed to the user (or alternate text), "Content" entry
|
QString m_contents; ///< Text to be displayed to the user (or alternate text), "Content" entry
|
||||||
PDFObjectReference m_pageReference; ///< Reference to annotation's page, "P" entry
|
PDFObjectReference m_pageReference; ///< Reference to annotation's page, "P" entry
|
||||||
@ -497,8 +539,12 @@ public:
|
|||||||
const QByteArray& getIntent() const { return m_intent; }
|
const QByteArray& getIntent() const { return m_intent; }
|
||||||
const PDFObject& getExternalData() const { return m_externalData; }
|
const PDFObject& getExternalData() const { return m_externalData; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual QColor getStrokeColor() const override;
|
||||||
|
virtual QColor getFillColor() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
QString m_windowTitle;
|
QString m_windowTitle;
|
||||||
PDFObjectReference m_popupAnnotation;
|
PDFObjectReference m_popupAnnotation;
|
||||||
@ -541,7 +587,7 @@ public:
|
|||||||
const QString& getStateModel() const { return m_stateModel; }
|
const QString& getStateModel() const { return m_stateModel; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
bool m_open = false;
|
bool m_open = false;
|
||||||
QByteArray m_iconName;
|
QByteArray m_iconName;
|
||||||
@ -572,7 +618,7 @@ public:
|
|||||||
const PDFAnnotationQuadrilaterals& getActivationRegion() const { return m_activationRegion; }
|
const PDFAnnotationQuadrilaterals& getActivationRegion() const { return m_activationRegion; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
PDFActionPtr m_action;
|
PDFActionPtr m_action;
|
||||||
LinkHighlightMode m_highlightMode = LinkHighlightMode::Invert;
|
LinkHighlightMode m_highlightMode = LinkHighlightMode::Invert;
|
||||||
@ -614,7 +660,7 @@ public:
|
|||||||
AnnotationLineEnding getEndLineEnding() const { return m_endLineEnding; }
|
AnnotationLineEnding getEndLineEnding() const { return m_endLineEnding; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
QByteArray m_defaultAppearance;
|
QByteArray m_defaultAppearance;
|
||||||
Justification m_justification = Justification::Left;
|
Justification m_justification = Justification::Left;
|
||||||
@ -663,7 +709,7 @@ public:
|
|||||||
const QPointF& getCaptionOffset() const { return m_captionOffset; }
|
const QPointF& getCaptionOffset() const { return m_captionOffset; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
QLineF m_line;
|
QLineF m_line;
|
||||||
AnnotationLineEnding m_startLineEnding = AnnotationLineEnding::None;
|
AnnotationLineEnding m_startLineEnding = AnnotationLineEnding::None;
|
||||||
@ -693,13 +739,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual AnnotationType getType() const override { return m_type; }
|
virtual AnnotationType getType() const override { return m_type; }
|
||||||
|
virtual void draw(AnnotationDrawParameters& parameters) const override;
|
||||||
|
|
||||||
const std::vector<PDFReal>& getInteriorColor() const { return m_interiorColor; }
|
const std::vector<PDFReal>& getInteriorColor() const { return m_interiorColor; }
|
||||||
const PDFAnnotationBorderEffect& getBorderEffect() const { return m_effect; }
|
const PDFAnnotationBorderEffect& getBorderEffect() const { return m_effect; }
|
||||||
const QRectF& getGeometryRectangle() const { return m_geometryRectangle; }
|
const QRectF& getGeometryRectangle() const { return m_geometryRectangle; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual QColor getFillColor() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
AnnotationType m_type;
|
AnnotationType m_type;
|
||||||
std::vector<PDFReal> m_interiorColor;
|
std::vector<PDFReal> m_interiorColor;
|
||||||
@ -738,7 +788,7 @@ public:
|
|||||||
const PDFObject& getMeasure() const { return m_measure; }
|
const PDFObject& getMeasure() const { return m_measure; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
AnnotationType m_type;
|
AnnotationType m_type;
|
||||||
std::vector<QPointF> m_vertices;
|
std::vector<QPointF> m_vertices;
|
||||||
@ -766,7 +816,7 @@ public:
|
|||||||
const PDFAnnotationQuadrilaterals& getHiglightArea() const { return m_highlightArea; }
|
const PDFAnnotationQuadrilaterals& getHiglightArea() const { return m_highlightArea; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
AnnotationType m_type;
|
AnnotationType m_type;
|
||||||
PDFAnnotationQuadrilaterals m_highlightArea;
|
PDFAnnotationQuadrilaterals m_highlightArea;
|
||||||
@ -790,7 +840,7 @@ public:
|
|||||||
Symbol getSymbol() const { return m_symbol; }
|
Symbol getSymbol() const { return m_symbol; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
QRectF m_caretRectangle;
|
QRectF m_caretRectangle;
|
||||||
Symbol m_symbol = Symbol::None;
|
Symbol m_symbol = Symbol::None;
|
||||||
@ -826,7 +876,7 @@ public:
|
|||||||
Stamp getStamp() const { return m_stamp; }
|
Stamp getStamp() const { return m_stamp; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
Stamp m_stamp = Stamp::Draft;
|
Stamp m_stamp = Stamp::Draft;
|
||||||
};
|
};
|
||||||
@ -842,7 +892,7 @@ public:
|
|||||||
const QPainterPath& getInkPath() const { return m_inkPath; }
|
const QPainterPath& getInkPath() const { return m_inkPath; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
QPainterPath m_inkPath;
|
QPainterPath m_inkPath;
|
||||||
};
|
};
|
||||||
@ -860,7 +910,7 @@ public:
|
|||||||
bool isOpened() const { return m_opened; }
|
bool isOpened() const { return m_opened; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
bool m_opened = false;
|
bool m_opened = false;
|
||||||
};
|
};
|
||||||
@ -887,7 +937,7 @@ public:
|
|||||||
Icon getIcon() const { return m_icon; }
|
Icon getIcon() const { return m_icon; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
PDFFileSpecification m_fileSpecification;
|
PDFFileSpecification m_fileSpecification;
|
||||||
Icon m_icon = Icon::PushPin;
|
Icon m_icon = Icon::PushPin;
|
||||||
@ -912,7 +962,7 @@ public:
|
|||||||
Icon getIcon() const { return m_icon; }
|
Icon getIcon() const { return m_icon; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
PDFSound m_sound;
|
PDFSound m_sound;
|
||||||
Icon m_icon = Icon::Speaker;
|
Icon m_icon = Icon::Speaker;
|
||||||
@ -933,7 +983,7 @@ public:
|
|||||||
const PDFMovieActivation& getMovieActivation() const { return m_movieActivation; }
|
const PDFMovieActivation& getMovieActivation() const { return m_movieActivation; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
QString m_movieTitle;
|
QString m_movieTitle;
|
||||||
bool m_playMovie = true;
|
bool m_playMovie = true;
|
||||||
@ -956,7 +1006,7 @@ public:
|
|||||||
const PDFAnnotationAdditionalActions& getAdditionalActions() const { return m_additionalActions; }
|
const PDFAnnotationAdditionalActions& getAdditionalActions() const { return m_additionalActions; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
QString m_screenTitle;
|
QString m_screenTitle;
|
||||||
PDFAnnotationAppearanceCharacteristics m_appearanceCharacteristics;
|
PDFAnnotationAppearanceCharacteristics m_appearanceCharacteristics;
|
||||||
@ -989,7 +1039,7 @@ public:
|
|||||||
const PDFAnnotationAdditionalActions& getAdditionalActions() const { return m_additionalActions; }
|
const PDFAnnotationAdditionalActions& getAdditionalActions() const { return m_additionalActions; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
HighlightMode m_highlightMode = HighlightMode::Invert;
|
HighlightMode m_highlightMode = HighlightMode::Invert;
|
||||||
PDFAnnotationAppearanceCharacteristics m_appearanceCharacteristics;
|
PDFAnnotationAppearanceCharacteristics m_appearanceCharacteristics;
|
||||||
@ -1031,7 +1081,7 @@ public:
|
|||||||
PDFReal getRelativeVerticalOffset() const { return m_relativeVerticalOffset; }
|
PDFReal getRelativeVerticalOffset() const { return m_relativeVerticalOffset; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
QMatrix m_matrix;
|
QMatrix m_matrix;
|
||||||
PDFReal m_relativeHorizontalOffset = 0.0;
|
PDFReal m_relativeHorizontalOffset = 0.0;
|
||||||
|
@ -95,11 +95,11 @@ PDFCatalog PDFCatalog::parse(const PDFObject& catalog, const PDFDocument* docume
|
|||||||
PDFObject openAction = document->getObject(catalogDictionary->get("OpenAction"));
|
PDFObject openAction = document->getObject(catalogDictionary->get("OpenAction"));
|
||||||
if (openAction.isArray())
|
if (openAction.isArray())
|
||||||
{
|
{
|
||||||
catalogObject.m_openAction.reset(new PDFActionGoTo(PDFDestination::parse(document, openAction)));
|
catalogObject.m_openAction.reset(new PDFActionGoTo(PDFDestination::parse(&document->getStorage(), openAction)));
|
||||||
}
|
}
|
||||||
if (openAction.isDictionary())
|
if (openAction.isDictionary())
|
||||||
{
|
{
|
||||||
catalogObject.m_openAction = PDFAction::parse(document, openAction);
|
catalogObject.m_openAction = PDFAction::parse(&document->getStorage(), openAction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,20 +136,20 @@ PDFCatalog PDFCatalog::parse(const PDFObject& catalog, const PDFDocument* docume
|
|||||||
|
|
||||||
if (const PDFDictionary* namesDictionary = document->getDictionaryFromObject(catalogDictionary->get("Names")))
|
if (const PDFDictionary* namesDictionary = document->getDictionaryFromObject(catalogDictionary->get("Names")))
|
||||||
{
|
{
|
||||||
auto parseDestination = [](const PDFDocument* document, PDFObject object)
|
auto parseDestination = [](const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
object = document->getObject(object);
|
object = storage->getObject(object);
|
||||||
if (object.isDictionary())
|
if (object.isDictionary())
|
||||||
{
|
{
|
||||||
object = object.getDictionary()->get("D");
|
object = object.getDictionary()->get("D");
|
||||||
}
|
}
|
||||||
|
|
||||||
return PDFDestination::parse(document, qMove(object));
|
return PDFDestination::parse(storage, qMove(object));
|
||||||
};
|
};
|
||||||
|
|
||||||
catalogObject.m_destinations = PDFNameTreeLoader<PDFDestination>::parse(document, namesDictionary->get("Dests"), parseDestination);
|
catalogObject.m_destinations = PDFNameTreeLoader<PDFDestination>::parse(&document->getStorage(), namesDictionary->get("Dests"), parseDestination);
|
||||||
catalogObject.m_javaScriptActions = PDFNameTreeLoader<PDFActionPtr>::parse(document, namesDictionary->get("JavaScript"), &PDFAction::parse);
|
catalogObject.m_javaScriptActions = PDFNameTreeLoader<PDFActionPtr>::parse(&document->getStorage(), namesDictionary->get("JavaScript"), &PDFAction::parse);
|
||||||
catalogObject.m_embeddedFiles = PDFNameTreeLoader<PDFFileSpecification>::parse(document, namesDictionary->get("EmbeddedFiles"), &PDFFileSpecification::parse);
|
catalogObject.m_embeddedFiles = PDFNameTreeLoader<PDFFileSpecification>::parse(&document->getStorage(), namesDictionary->get("EmbeddedFiles"), &PDFFileSpecification::parse);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Examine "Dests" dictionary
|
// Examine "Dests" dictionary
|
||||||
@ -158,7 +158,7 @@ PDFCatalog PDFCatalog::parse(const PDFObject& catalog, const PDFDocument* docume
|
|||||||
const size_t count = destsDictionary->getCount();
|
const size_t count = destsDictionary->getCount();
|
||||||
for (size_t i = 0; i < count; ++i)
|
for (size_t i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
catalogObject.m_destinations[destsDictionary->getKey(i)] = PDFDestination::parse(document, destsDictionary->getValue(i));
|
catalogObject.m_destinations[destsDictionary->getKey(i)] = PDFDestination::parse(&document->getStorage(), destsDictionary->getValue(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,9 +40,14 @@ static constexpr const char* PDF_DOCUMENT_INFO_ENTRY_TRAPPED_TRUE = "True";
|
|||||||
static constexpr const char* PDF_DOCUMENT_INFO_ENTRY_TRAPPED_FALSE = "False";
|
static constexpr const char* PDF_DOCUMENT_INFO_ENTRY_TRAPPED_FALSE = "False";
|
||||||
static constexpr const char* PDF_DOCUMENT_INFO_ENTRY_TRAPPED_UNKNOWN = "Unknown";
|
static constexpr const char* PDF_DOCUMENT_INFO_ENTRY_TRAPPED_UNKNOWN = "Unknown";
|
||||||
|
|
||||||
|
QByteArray PDFObjectStorage::getDecodedStream(const PDFStream* stream) const
|
||||||
|
{
|
||||||
|
return PDFStreamFilterStorage::getDecodedStream(stream, std::bind(QOverload<const PDFObject&>::of(&PDFObjectStorage::getObject), this, std::placeholders::_1), getSecurityHandler());
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray PDFDocument::getDecodedStream(const PDFStream* stream) const
|
QByteArray PDFDocument::getDecodedStream(const PDFStream* stream) const
|
||||||
{
|
{
|
||||||
return PDFStreamFilterStorage::getDecodedStream(stream, std::bind(&PDFDocument::getObject, this, std::placeholders::_1), m_pdfObjectStorage.getSecurityHandler());
|
return m_pdfObjectStorage.getDecodedStream(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
const PDFDictionary* PDFDocument::getTrailerDictionary() const
|
const PDFDictionary* PDFDocument::getTrailerDictionary() const
|
||||||
@ -242,9 +247,15 @@ void PDFObjectStorage::updateTrailerDictionary(PDFObject trailerDictionary)
|
|||||||
m_trailerDictionary = PDFObjectManipulator::merge(m_trailerDictionary, trailerDictionary, PDFObjectManipulator::RemoveNullObjects);
|
m_trailerDictionary = PDFObjectManipulator::merge(m_trailerDictionary, trailerDictionary, PDFObjectManipulator::RemoveNullObjects);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDFDocumentDataLoaderDecorator::PDFDocumentDataLoaderDecorator(const PDFDocument* document)
|
||||||
|
: m_storage(&document->getStorage())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray PDFDocumentDataLoaderDecorator::readName(const PDFObject& object)
|
QByteArray PDFDocumentDataLoaderDecorator::readName(const PDFObject& object)
|
||||||
{
|
{
|
||||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
const PDFObject& dereferencedObject = m_storage->getObject(object);
|
||||||
if (dereferencedObject.isName())
|
if (dereferencedObject.isName())
|
||||||
{
|
{
|
||||||
return dereferencedObject.getString();
|
return dereferencedObject.getString();
|
||||||
@ -255,7 +266,7 @@ QByteArray PDFDocumentDataLoaderDecorator::readName(const PDFObject& object)
|
|||||||
|
|
||||||
QByteArray PDFDocumentDataLoaderDecorator::readString(const PDFObject& object)
|
QByteArray PDFDocumentDataLoaderDecorator::readString(const PDFObject& object)
|
||||||
{
|
{
|
||||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
const PDFObject& dereferencedObject = m_storage->getObject(object);
|
||||||
if (dereferencedObject.isString())
|
if (dereferencedObject.isString())
|
||||||
{
|
{
|
||||||
return dereferencedObject.getString();
|
return dereferencedObject.getString();
|
||||||
@ -266,7 +277,7 @@ QByteArray PDFDocumentDataLoaderDecorator::readString(const PDFObject& object)
|
|||||||
|
|
||||||
PDFInteger PDFDocumentDataLoaderDecorator::readInteger(const PDFObject& object, PDFInteger defaultValue) const
|
PDFInteger PDFDocumentDataLoaderDecorator::readInteger(const PDFObject& object, PDFInteger defaultValue) const
|
||||||
{
|
{
|
||||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
const PDFObject& dereferencedObject = m_storage->getObject(object);
|
||||||
if (dereferencedObject.isInt())
|
if (dereferencedObject.isInt())
|
||||||
{
|
{
|
||||||
return dereferencedObject.getInteger();
|
return dereferencedObject.getInteger();
|
||||||
@ -277,7 +288,7 @@ PDFInteger PDFDocumentDataLoaderDecorator::readInteger(const PDFObject& object,
|
|||||||
|
|
||||||
PDFReal PDFDocumentDataLoaderDecorator::readNumber(const PDFObject& object, PDFReal defaultValue) const
|
PDFReal PDFDocumentDataLoaderDecorator::readNumber(const PDFObject& object, PDFReal defaultValue) const
|
||||||
{
|
{
|
||||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
const PDFObject& dereferencedObject = m_storage->getObject(object);
|
||||||
|
|
||||||
if (dereferencedObject.isReal())
|
if (dereferencedObject.isReal())
|
||||||
{
|
{
|
||||||
@ -292,7 +303,7 @@ PDFReal PDFDocumentDataLoaderDecorator::readNumber(const PDFObject& object, PDFR
|
|||||||
|
|
||||||
bool PDFDocumentDataLoaderDecorator::readBoolean(const PDFObject& object, bool defaultValue) const
|
bool PDFDocumentDataLoaderDecorator::readBoolean(const PDFObject& object, bool defaultValue) const
|
||||||
{
|
{
|
||||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
const PDFObject& dereferencedObject = m_storage->getObject(object);
|
||||||
|
|
||||||
if (dereferencedObject.isBool())
|
if (dereferencedObject.isBool())
|
||||||
{
|
{
|
||||||
@ -304,7 +315,7 @@ bool PDFDocumentDataLoaderDecorator::readBoolean(const PDFObject& object, bool d
|
|||||||
|
|
||||||
QString PDFDocumentDataLoaderDecorator::readTextString(const PDFObject& object, const QString& defaultValue) const
|
QString PDFDocumentDataLoaderDecorator::readTextString(const PDFObject& object, const QString& defaultValue) const
|
||||||
{
|
{
|
||||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
const PDFObject& dereferencedObject = m_storage->getObject(object);
|
||||||
if (dereferencedObject.isString())
|
if (dereferencedObject.isString())
|
||||||
{
|
{
|
||||||
return PDFEncoding::convertTextString(dereferencedObject.getString());
|
return PDFEncoding::convertTextString(dereferencedObject.getString());
|
||||||
@ -315,7 +326,7 @@ QString PDFDocumentDataLoaderDecorator::readTextString(const PDFObject& object,
|
|||||||
|
|
||||||
QRectF PDFDocumentDataLoaderDecorator::readRectangle(const PDFObject& object, const QRectF& defaultValue) const
|
QRectF PDFDocumentDataLoaderDecorator::readRectangle(const PDFObject& object, const QRectF& defaultValue) const
|
||||||
{
|
{
|
||||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
const PDFObject& dereferencedObject = m_storage->getObject(object);
|
||||||
if (dereferencedObject.isArray())
|
if (dereferencedObject.isArray())
|
||||||
{
|
{
|
||||||
const PDFArray* array = dereferencedObject.getArray();
|
const PDFArray* array = dereferencedObject.getArray();
|
||||||
@ -324,7 +335,7 @@ QRectF PDFDocumentDataLoaderDecorator::readRectangle(const PDFObject& object, co
|
|||||||
std::array<PDFReal, 4> items;
|
std::array<PDFReal, 4> items;
|
||||||
for (size_t i = 0; i < 4; ++i)
|
for (size_t i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
const PDFObject& object = m_document->getObject(array->getItem(i));
|
const PDFObject& object = m_storage->getObject(array->getItem(i));
|
||||||
if (object.isReal())
|
if (object.isReal())
|
||||||
{
|
{
|
||||||
items[i] = object.getReal();
|
items[i] = object.getReal();
|
||||||
@ -441,7 +452,7 @@ std::vector<PDFObjectReference> PDFDocumentDataLoaderDecorator::readReferenceArr
|
|||||||
|
|
||||||
std::vector<PDFReal> PDFDocumentDataLoaderDecorator::readNumberArray(const PDFObject& object, std::vector<PDFReal> defaultValue) const
|
std::vector<PDFReal> PDFDocumentDataLoaderDecorator::readNumberArray(const PDFObject& object, std::vector<PDFReal> defaultValue) const
|
||||||
{
|
{
|
||||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
const PDFObject& dereferencedObject = m_storage->getObject(object);
|
||||||
if (dereferencedObject.isArray())
|
if (dereferencedObject.isArray())
|
||||||
{
|
{
|
||||||
const PDFArray* array = dereferencedObject.getArray();
|
const PDFArray* array = dereferencedObject.getArray();
|
||||||
@ -469,7 +480,7 @@ std::vector<PDFReal> PDFDocumentDataLoaderDecorator::readNumberArray(const PDFOb
|
|||||||
|
|
||||||
std::vector<PDFInteger> PDFDocumentDataLoaderDecorator::readIntegerArray(const PDFObject& object) const
|
std::vector<PDFInteger> PDFDocumentDataLoaderDecorator::readIntegerArray(const PDFObject& object) const
|
||||||
{
|
{
|
||||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
const PDFObject& dereferencedObject = m_storage->getObject(object);
|
||||||
if (dereferencedObject.isArray())
|
if (dereferencedObject.isArray())
|
||||||
{
|
{
|
||||||
const PDFArray* array = dereferencedObject.getArray();
|
const PDFArray* array = dereferencedObject.getArray();
|
||||||
@ -512,7 +523,7 @@ PDFObjectReference PDFDocumentDataLoaderDecorator::readReferenceFromDictionary(c
|
|||||||
|
|
||||||
std::vector<PDFObjectReference> PDFDocumentDataLoaderDecorator::readReferenceArray(const PDFObject& object) const
|
std::vector<PDFObjectReference> PDFDocumentDataLoaderDecorator::readReferenceArray(const PDFObject& object) const
|
||||||
{
|
{
|
||||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
const PDFObject& dereferencedObject = m_storage->getObject(object);
|
||||||
if (dereferencedObject.isArray())
|
if (dereferencedObject.isArray())
|
||||||
{
|
{
|
||||||
const PDFArray* array = dereferencedObject.getArray();
|
const PDFArray* array = dereferencedObject.getArray();
|
||||||
@ -544,7 +555,7 @@ std::vector<PDFObjectReference> PDFDocumentDataLoaderDecorator::readReferenceArr
|
|||||||
|
|
||||||
std::vector<QByteArray> PDFDocumentDataLoaderDecorator::readNameArray(const PDFObject& object) const
|
std::vector<QByteArray> PDFDocumentDataLoaderDecorator::readNameArray(const PDFObject& object) const
|
||||||
{
|
{
|
||||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
const PDFObject& dereferencedObject = m_storage->getObject(object);
|
||||||
if (dereferencedObject.isArray())
|
if (dereferencedObject.isArray())
|
||||||
{
|
{
|
||||||
const PDFArray* array = dereferencedObject.getArray();
|
const PDFArray* array = dereferencedObject.getArray();
|
||||||
@ -626,7 +637,7 @@ std::vector<QByteArray> PDFDocumentDataLoaderDecorator::readStringArrayFromDicti
|
|||||||
|
|
||||||
std::vector<QByteArray> PDFDocumentDataLoaderDecorator::readStringArray(const PDFObject& object) const
|
std::vector<QByteArray> PDFDocumentDataLoaderDecorator::readStringArray(const PDFObject& object) const
|
||||||
{
|
{
|
||||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
const PDFObject& dereferencedObject = m_storage->getObject(object);
|
||||||
if (dereferencedObject.isArray())
|
if (dereferencedObject.isArray())
|
||||||
{
|
{
|
||||||
const PDFArray* array = dereferencedObject.getArray();
|
const PDFArray* array = dereferencedObject.getArray();
|
||||||
|
@ -69,6 +69,20 @@ public:
|
|||||||
/// then null object is returned (no exception is thrown).
|
/// then null object is returned (no exception is thrown).
|
||||||
const PDFObject& getObject(PDFObjectReference reference) const;
|
const PDFObject& getObject(PDFObjectReference reference) const;
|
||||||
|
|
||||||
|
/// If object is reference, the dereference attempt is performed
|
||||||
|
/// and object is returned. If it is not a reference, then self
|
||||||
|
/// is returned. If dereference attempt fails, then null object
|
||||||
|
/// is returned (no exception is thrown).
|
||||||
|
const PDFObject& getObject(const PDFObject& object) const;
|
||||||
|
|
||||||
|
/// Returns dictionary from an object. If object is not a dictionary,
|
||||||
|
/// then nullptr is returned (no exception is thrown).
|
||||||
|
const PDFDictionary* getDictionaryFromObject(const PDFObject& object) const;
|
||||||
|
|
||||||
|
/// Returns object by reference. If dereference attempt fails, then null object
|
||||||
|
/// is returned (no exception is thrown).
|
||||||
|
const PDFObject& getObjectByReference(PDFObjectReference reference) const;
|
||||||
|
|
||||||
/// Returns array of objects stored in this storage
|
/// Returns array of objects stored in this storage
|
||||||
const PDFObjects& getObjects() const { return m_objects; }
|
const PDFObjects& getObjects() const { return m_objects; }
|
||||||
|
|
||||||
@ -98,6 +112,11 @@ public:
|
|||||||
/// \param trailerDictionary New trailer dictionary
|
/// \param trailerDictionary New trailer dictionary
|
||||||
void updateTrailerDictionary(PDFObject trailerDictionary);
|
void updateTrailerDictionary(PDFObject trailerDictionary);
|
||||||
|
|
||||||
|
/// Returns the decoded stream. If stream data cannot be decoded,
|
||||||
|
/// then empty byte array is returned.
|
||||||
|
/// \param stream Stream to be decoded
|
||||||
|
QByteArray getDecodedStream(const PDFStream* stream) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFObjects m_objects;
|
PDFObjects m_objects;
|
||||||
PDFObject m_trailerDictionary;
|
PDFObject m_trailerDictionary;
|
||||||
@ -112,7 +131,8 @@ private:
|
|||||||
class PDFDocumentDataLoaderDecorator
|
class PDFDocumentDataLoaderDecorator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline explicit PDFDocumentDataLoaderDecorator(const PDFDocument* document) : m_document(document) { }
|
explicit PDFDocumentDataLoaderDecorator(const PDFDocument* document);
|
||||||
|
inline explicit PDFDocumentDataLoaderDecorator(const PDFObjectStorage* storage) : m_storage(storage) { }
|
||||||
inline ~PDFDocumentDataLoaderDecorator() = default;
|
inline ~PDFDocumentDataLoaderDecorator() = default;
|
||||||
|
|
||||||
/// Reads a name from the object, if it is possible. If object is not a name,
|
/// Reads a name from the object, if it is possible. If object is not a name,
|
||||||
@ -159,7 +179,7 @@ public:
|
|||||||
template<typename Enum, typename Iterator>
|
template<typename Enum, typename Iterator>
|
||||||
Enum readEnumByName(const PDFObject& object, Iterator begin, Iterator end, Enum defaultValue) const
|
Enum readEnumByName(const PDFObject& object, Iterator begin, Iterator end, Enum defaultValue) const
|
||||||
{
|
{
|
||||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
const PDFObject& dereferencedObject = m_storage->getObject(object);
|
||||||
if (dereferencedObject.isName() || dereferencedObject.isString())
|
if (dereferencedObject.isName() || dereferencedObject.isString())
|
||||||
{
|
{
|
||||||
QByteArray name = dereferencedObject.getString();
|
QByteArray name = dereferencedObject.getString();
|
||||||
@ -184,7 +204,7 @@ public:
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
void readNumberArray(const PDFObject& object, T first, T last)
|
void readNumberArray(const PDFObject& object, T first, T last)
|
||||||
{
|
{
|
||||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
const PDFObject& dereferencedObject = m_storage->getObject(object);
|
||||||
if (dereferencedObject.isArray())
|
if (dereferencedObject.isArray())
|
||||||
{
|
{
|
||||||
const PDFArray* array = dereferencedObject.getArray();
|
const PDFArray* array = dereferencedObject.getArray();
|
||||||
@ -318,7 +338,7 @@ public:
|
|||||||
std::vector<QByteArray> readStringArrayFromDictionary(const PDFDictionary* dictionary, const char* key) const;
|
std::vector<QByteArray> readStringArrayFromDictionary(const PDFDictionary* dictionary, const char* key) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const PDFDocument* m_document;
|
const PDFObjectStorage* m_storage;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// PDF document main class.
|
/// PDF document main class.
|
||||||
@ -458,6 +478,40 @@ const PDFObject& PDFDocument::getObjectByReference(PDFObjectReference reference)
|
|||||||
return m_pdfObjectStorage.getObject(reference);
|
return m_pdfObjectStorage.getObject(reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
const PDFObject& PDFObjectStorage::getObject(const PDFObject& object) const
|
||||||
|
{
|
||||||
|
if (object.isReference())
|
||||||
|
{
|
||||||
|
// Try to dereference the object
|
||||||
|
return getObject(object.getReference());
|
||||||
|
}
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
const PDFDictionary* PDFObjectStorage::getDictionaryFromObject(const PDFObject& object) const
|
||||||
|
{
|
||||||
|
const PDFObject& dereferencedObject = getObject(object);
|
||||||
|
if (dereferencedObject.isDictionary())
|
||||||
|
{
|
||||||
|
return dereferencedObject.getDictionary();
|
||||||
|
}
|
||||||
|
else if (dereferencedObject.isStream())
|
||||||
|
{
|
||||||
|
return dereferencedObject.getStream()->getDictionary();
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
const PDFObject& PDFObjectStorage::getObjectByReference(PDFObjectReference reference) const
|
||||||
|
{
|
||||||
|
return getObject(reference);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
|
||||||
#endif // PDFDOCUMENT_H
|
#endif // PDFDOCUMENT_H
|
||||||
|
@ -18,10 +18,165 @@
|
|||||||
#include "pdfdocumentbuilder.h"
|
#include "pdfdocumentbuilder.h"
|
||||||
#include "pdfencoding.h"
|
#include "pdfencoding.h"
|
||||||
#include "pdfconstants.h"
|
#include "pdfconstants.h"
|
||||||
|
#include "pdfdocumentreader.h"
|
||||||
|
#include "pdfvisitor.h"
|
||||||
|
|
||||||
|
#include <QBuffer>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QPdfWriter>
|
||||||
|
|
||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class PDFCollectReferencesVisitor : public PDFAbstractVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit PDFCollectReferencesVisitor(std::set<PDFObjectReference>& references) :
|
||||||
|
m_references(references)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void visitArray(const PDFArray* array) override;
|
||||||
|
virtual void visitDictionary(const PDFDictionary* dictionary) override;
|
||||||
|
virtual void visitStream(const PDFStream* stream) override;
|
||||||
|
virtual void visitReference(const PDFObjectReference reference) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::set<PDFObjectReference>& m_references;
|
||||||
|
};
|
||||||
|
|
||||||
|
void PDFCollectReferencesVisitor::visitArray(const PDFArray* array)
|
||||||
|
{
|
||||||
|
acceptArray(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFCollectReferencesVisitor::visitDictionary(const PDFDictionary* dictionary)
|
||||||
|
{
|
||||||
|
for (size_t i = 0, count = dictionary->getCount(); i < count; ++i)
|
||||||
|
{
|
||||||
|
dictionary->getValue(i).accept(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFCollectReferencesVisitor::visitStream(const PDFStream* stream)
|
||||||
|
{
|
||||||
|
visitDictionary(stream->getDictionary());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFCollectReferencesVisitor::visitReference(const PDFObjectReference reference)
|
||||||
|
{
|
||||||
|
m_references.insert(reference);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PDFReplaceReferencesVisitor : public PDFAbstractVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit PDFReplaceReferencesVisitor(const std::map<PDFObjectReference, PDFObjectReference>& replacements) :
|
||||||
|
m_replacements(replacements)
|
||||||
|
{
|
||||||
|
m_objectStack.reserve(32);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void visitNull() override;
|
||||||
|
virtual void visitBool(bool value) override;
|
||||||
|
virtual void visitInt(PDFInteger value) override;
|
||||||
|
virtual void visitReal(PDFReal value) override;
|
||||||
|
virtual void visitString(const PDFString* string) override;
|
||||||
|
virtual void visitName(const PDFString* name) override;
|
||||||
|
virtual void visitArray(const PDFArray* array) override;
|
||||||
|
virtual void visitDictionary(const PDFDictionary* dictionary) override;
|
||||||
|
virtual void visitStream(const PDFStream* stream) override;
|
||||||
|
virtual void visitReference(const PDFObjectReference reference) override;
|
||||||
|
|
||||||
|
PDFObject getObject();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::map<PDFObjectReference, PDFObjectReference>& m_replacements;
|
||||||
|
std::vector<PDFObject> m_objectStack;
|
||||||
|
};
|
||||||
|
|
||||||
|
void PDFReplaceReferencesVisitor::visitNull()
|
||||||
|
{
|
||||||
|
m_objectStack.push_back(PDFObject::createNull());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFReplaceReferencesVisitor::visitBool(bool value)
|
||||||
|
{
|
||||||
|
m_objectStack.push_back(PDFObject::createBool(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFReplaceReferencesVisitor::visitInt(PDFInteger value)
|
||||||
|
{
|
||||||
|
m_objectStack.push_back(PDFObject::createInteger(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFReplaceReferencesVisitor::visitReal(PDFReal value)
|
||||||
|
{
|
||||||
|
m_objectStack.push_back(PDFObject::createReal(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFReplaceReferencesVisitor::visitString(const PDFString* string)
|
||||||
|
{
|
||||||
|
m_objectStack.push_back(PDFObject::createString(std::make_shared<PDFString>(*string)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFReplaceReferencesVisitor::visitName(const PDFString* name)
|
||||||
|
{
|
||||||
|
m_objectStack.push_back(PDFObject::createName(std::make_shared<PDFString>(*name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFReplaceReferencesVisitor::visitArray(const PDFArray* array)
|
||||||
|
{
|
||||||
|
acceptArray(array);
|
||||||
|
|
||||||
|
// We have all objects on the stack
|
||||||
|
Q_ASSERT(array->getCount() <= m_objectStack.size());
|
||||||
|
|
||||||
|
auto it = std::next(m_objectStack.cbegin(), m_objectStack.size() - array->getCount());
|
||||||
|
std::vector<PDFObject> objects(it, m_objectStack.cend());
|
||||||
|
PDFObject object = PDFObject::createArray(std::make_shared<PDFArray>(qMove(objects)));
|
||||||
|
m_objectStack.erase(it, m_objectStack.cend());
|
||||||
|
m_objectStack.push_back(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFReplaceReferencesVisitor::visitDictionary(const PDFDictionary* dictionary)
|
||||||
|
{
|
||||||
|
Q_ASSERT(dictionary);
|
||||||
|
|
||||||
|
std::vector<PDFDictionary::DictionaryEntry> entries;
|
||||||
|
entries.reserve(dictionary->getCount());
|
||||||
|
|
||||||
|
for (size_t i = 0, count = dictionary->getCount(); i < count; ++i)
|
||||||
|
{
|
||||||
|
dictionary->getValue(i).accept(this);
|
||||||
|
entries.emplace_back(dictionary->getKey(i), m_objectStack.back());
|
||||||
|
m_objectStack.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_objectStack.push_back(PDFObject::createDictionary(std::make_shared<PDFDictionary>(qMove(entries))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFReplaceReferencesVisitor::visitStream(const PDFStream* stream)
|
||||||
|
{
|
||||||
|
// Replace references in the dictionary
|
||||||
|
visitDictionary(stream->getDictionary());
|
||||||
|
PDFObject dictionaryObject = m_objectStack.back();
|
||||||
|
m_objectStack.pop_back();
|
||||||
|
m_objectStack.push_back(PDFObject::createStream(std::make_shared<PDFStream>(PDFDictionary(*dictionaryObject.getDictionary()), QByteArray(*stream->getContent()))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFReplaceReferencesVisitor::visitReference(const PDFObjectReference reference)
|
||||||
|
{
|
||||||
|
m_objectStack.push_back(PDFObject::createReference(m_replacements.at(reference)));
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFObject PDFReplaceReferencesVisitor::getObject()
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_objectStack.size() == 1);
|
||||||
|
return qMove(m_objectStack.back());
|
||||||
|
}
|
||||||
|
|
||||||
void PDFObjectFactory::beginArray()
|
void PDFObjectFactory::beginArray()
|
||||||
{
|
{
|
||||||
m_items.emplace_back(ItemType::Array, PDFArray());
|
m_items.emplace_back(ItemType::Array, PDFArray());
|
||||||
@ -64,6 +219,12 @@ void PDFObjectFactory::endDictionaryItem()
|
|||||||
std::get<PDFDictionary>(dictionaryItem.object).addEntry(qMove(topItem.itemName), qMove(std::get<PDFObject>(topItem.object)));
|
std::get<PDFDictionary>(dictionaryItem.object).addEntry(qMove(topItem.itemName), qMove(std::get<PDFObject>(topItem.object)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDFObjectFactory& PDFObjectFactory::operator<<(const PDFObject& object)
|
||||||
|
{
|
||||||
|
addObject(object);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
PDFObjectFactory& PDFObjectFactory::operator<<(AnnotationBorderStyle style)
|
PDFObjectFactory& PDFObjectFactory::operator<<(AnnotationBorderStyle style)
|
||||||
{
|
{
|
||||||
switch (style)
|
switch (style)
|
||||||
@ -477,6 +638,157 @@ std::array<PDFReal, 4> PDFDocumentBuilder::getAnnotationReductionRectangle(const
|
|||||||
return { qAbs(innerRect.left() - boundingRect.left()), qAbs(boundingRect.bottom() - innerRect.bottom()), qAbs(boundingRect.right() - innerRect.right()), qAbs(boundingRect.top() - innerRect.top()) };
|
return { qAbs(innerRect.left() - boundingRect.left()), qAbs(boundingRect.bottom() - innerRect.bottom()), qAbs(boundingRect.right() - innerRect.right()), qAbs(boundingRect.top() - innerRect.top()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFDocumentBuilder::updateAnnotationAppearanceStreams(PDFObjectReference annotationReference)
|
||||||
|
{
|
||||||
|
PDFAnnotationPtr annotation = PDFAnnotation::parse(&m_storage, m_storage.getObject(annotationReference));
|
||||||
|
if (!annotation)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PDFDictionary* pageDictionary = m_storage.getDictionaryFromObject(m_storage.getObject(annotation->getPageReference()));
|
||||||
|
if (!pageDictionary)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFDocumentDataLoaderDecorator loader(&m_storage);
|
||||||
|
QRectF mediaBox = loader.readRectangle(pageDictionary->get("MediaBox"), QRectF());
|
||||||
|
if (!mediaBox.isValid())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<PDFAppeareanceStreams::Key> keys = annotation->getDrawKeys();
|
||||||
|
std::map<PDFAppeareanceStreams::Key, PDFObjectReference> appearanceStreams;
|
||||||
|
|
||||||
|
QRectF boundingRectangle;
|
||||||
|
for (const PDFAppeareanceStreams::Key& key : keys)
|
||||||
|
{
|
||||||
|
PDFContentStreamBuilder builder(mediaBox.size(), PDFContentStreamBuilder::CoordinateSystem::PDF);
|
||||||
|
|
||||||
|
AnnotationDrawParameters parameters;
|
||||||
|
parameters.key = key;
|
||||||
|
parameters.painter = builder.begin();
|
||||||
|
annotation->draw(parameters);
|
||||||
|
PDFContentStreamBuilder::ContentStream contentStream = builder.end(parameters.painter);
|
||||||
|
|
||||||
|
if (!parameters.boundingRectangle.isValid() || !contentStream.pageObject.isValid())
|
||||||
|
{
|
||||||
|
// Invalid stream, do nothing
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
boundingRectangle = boundingRectangle.united(parameters.boundingRectangle);
|
||||||
|
|
||||||
|
std::vector<PDFObject> copiedObjects = copyFrom({ contentStream.resources, contentStream.contents }, contentStream.document.getStorage(), true);
|
||||||
|
Q_ASSERT(copiedObjects.size() == 2);
|
||||||
|
|
||||||
|
PDFObjectReference resourcesReference = copiedObjects[0].getReference();
|
||||||
|
PDFObjectReference formReference = copiedObjects[1].getReference();
|
||||||
|
|
||||||
|
// Create form object
|
||||||
|
PDFObjectFactory formFactory;
|
||||||
|
|
||||||
|
formFactory.beginDictionary();
|
||||||
|
|
||||||
|
formFactory.beginDictionaryItem("Type");
|
||||||
|
formFactory << WrapName("XObject");
|
||||||
|
formFactory.endDictionaryItem();
|
||||||
|
|
||||||
|
formFactory.beginDictionaryItem("Subtype");
|
||||||
|
formFactory << WrapName("Form");
|
||||||
|
formFactory.endDictionaryItem();
|
||||||
|
|
||||||
|
formFactory.beginDictionaryItem("BBox");
|
||||||
|
formFactory << parameters.boundingRectangle;
|
||||||
|
formFactory.endDictionaryItem();
|
||||||
|
|
||||||
|
formFactory.beginDictionaryItem("Resources");
|
||||||
|
formFactory << resourcesReference;
|
||||||
|
formFactory.endDictionaryItem();
|
||||||
|
|
||||||
|
formFactory.endDictionary();
|
||||||
|
|
||||||
|
mergeTo(formReference, formFactory.takeObject());
|
||||||
|
appearanceStreams[key] = formReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!appearanceStreams.empty())
|
||||||
|
{
|
||||||
|
PDFObjectFactory asDictionaryFactory;
|
||||||
|
asDictionaryFactory.beginDictionary();
|
||||||
|
|
||||||
|
auto it = appearanceStreams.cbegin();
|
||||||
|
while (it != appearanceStreams.cend())
|
||||||
|
{
|
||||||
|
const PDFAppeareanceStreams::Key& key = it->first;
|
||||||
|
|
||||||
|
auto itEnd = std::next(it);
|
||||||
|
while (itEnd != appearanceStreams.cend() && itEnd->first.first == key.first)
|
||||||
|
{
|
||||||
|
++itEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray name;
|
||||||
|
switch (key.first)
|
||||||
|
{
|
||||||
|
case PDFAppeareanceStreams::Appearance::Normal:
|
||||||
|
name = "N";
|
||||||
|
break;
|
||||||
|
case PDFAppeareanceStreams::Appearance::Rollover:
|
||||||
|
name = "R";
|
||||||
|
break;
|
||||||
|
case PDFAppeareanceStreams::Appearance::Down:
|
||||||
|
name = "D";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Q_ASSERT(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
asDictionaryFactory.beginDictionaryItem(name);
|
||||||
|
const size_t streamCount = std::distance(it, itEnd);
|
||||||
|
if (streamCount == 1)
|
||||||
|
{
|
||||||
|
asDictionaryFactory << it->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
asDictionaryFactory.beginDictionary();
|
||||||
|
for (; it != itEnd; ++it)
|
||||||
|
{
|
||||||
|
asDictionaryFactory.beginDictionaryItem(it->first.second);
|
||||||
|
asDictionaryFactory << it->second;
|
||||||
|
asDictionaryFactory.endDictionaryItem();
|
||||||
|
}
|
||||||
|
asDictionaryFactory.endDictionary();
|
||||||
|
}
|
||||||
|
asDictionaryFactory.endDictionaryItem();
|
||||||
|
|
||||||
|
it = itEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
asDictionaryFactory.endDictionary();
|
||||||
|
|
||||||
|
PDFObjectFactory annotationFactory;
|
||||||
|
annotationFactory.beginDictionary();
|
||||||
|
|
||||||
|
annotationFactory.beginDictionaryItem("Rect");
|
||||||
|
annotationFactory << boundingRectangle;
|
||||||
|
annotationFactory.endDictionaryItem();
|
||||||
|
|
||||||
|
annotationFactory.beginDictionaryItem("AP");
|
||||||
|
annotationFactory << asDictionaryFactory.takeObject();
|
||||||
|
annotationFactory.endDictionaryItem();
|
||||||
|
|
||||||
|
annotationFactory.endDictionary();
|
||||||
|
|
||||||
|
mergeTo(annotationReference, annotationFactory.takeObject());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PDFObjectReference PDFDocumentBuilder::addObject(PDFObject object)
|
PDFObjectReference PDFDocumentBuilder::addObject(PDFObject object)
|
||||||
{
|
{
|
||||||
return m_storage.addObject(PDFObjectManipulator::removeNullObjects(object));
|
return m_storage.addObject(PDFObjectManipulator::removeNullObjects(object));
|
||||||
@ -585,6 +897,134 @@ void PDFDocumentBuilder::updateDocumentInfo(PDFObject info)
|
|||||||
mergeTo(infoReference, info);
|
mergeTo(infoReference, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<PDFObject> PDFDocumentBuilder::copyFrom(const std::vector<PDFObject>& objects, const PDFObjectStorage& storage, bool createReferences)
|
||||||
|
{
|
||||||
|
// 1) Collect all references, which we must copy
|
||||||
|
std::set<PDFObjectReference> references;
|
||||||
|
PDFCollectReferencesVisitor collectReferencesVisitor(references);
|
||||||
|
for (const PDFObject& object : objects)
|
||||||
|
{
|
||||||
|
object.accept(&collectReferencesVisitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Make room for new objects, together with mapping
|
||||||
|
std::map<PDFObjectReference, PDFObjectReference> referenceMapping;
|
||||||
|
for (const PDFObjectReference& reference : references)
|
||||||
|
{
|
||||||
|
referenceMapping[reference] = addObject(PDFObject::createNull());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3) Copy objects from other object to this one
|
||||||
|
for (const PDFObjectReference& sourceReference : references)
|
||||||
|
{
|
||||||
|
const PDFObjectReference targetReference = referenceMapping.at(sourceReference);
|
||||||
|
PDFReplaceReferencesVisitor replaceReferencesVisitor(referenceMapping);
|
||||||
|
storage.getObject(sourceReference).accept(&replaceReferencesVisitor);
|
||||||
|
m_storage.setObject(targetReference, replaceReferencesVisitor.getObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<PDFObject> result;
|
||||||
|
result.reserve(objects.size());
|
||||||
|
|
||||||
|
for (const PDFObject& object : objects)
|
||||||
|
{
|
||||||
|
if (object.isReference())
|
||||||
|
{
|
||||||
|
result.push_back(PDFObject::createReference(referenceMapping.at(object.getReference())));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PDFReplaceReferencesVisitor replaceReferencesVisitor(referenceMapping);
|
||||||
|
object.accept(&replaceReferencesVisitor);
|
||||||
|
|
||||||
|
if (createReferences)
|
||||||
|
{
|
||||||
|
result.push_back(PDFObject::createReference(addObject(replaceReferencesVisitor.getObject())));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.push_back(replaceReferencesVisitor.getObject());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFContentStreamBuilder::PDFContentStreamBuilder(QSizeF size, CoordinateSystem coordinateSystem) :
|
||||||
|
m_size(size),
|
||||||
|
m_coordinateSystem(coordinateSystem),
|
||||||
|
m_buffer(nullptr),
|
||||||
|
m_pdfWriter(nullptr),
|
||||||
|
m_painter(nullptr)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFContentStreamBuilder::~PDFContentStreamBuilder()
|
||||||
|
{
|
||||||
|
Q_ASSERT(!m_buffer);
|
||||||
|
Q_ASSERT(!m_pdfWriter);
|
||||||
|
Q_ASSERT(!m_painter);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPainter* PDFContentStreamBuilder::begin()
|
||||||
|
{
|
||||||
|
Q_ASSERT(!m_buffer);
|
||||||
|
Q_ASSERT(!m_pdfWriter);
|
||||||
|
Q_ASSERT(!m_painter);
|
||||||
|
|
||||||
|
m_buffer = new QBuffer();
|
||||||
|
m_buffer->open(QBuffer::ReadWrite);
|
||||||
|
|
||||||
|
m_pdfWriter = new QPdfWriter(m_buffer);
|
||||||
|
m_pdfWriter->setPdfVersion(QPdfWriter::PdfVersion_1_6);
|
||||||
|
m_pdfWriter->setPageSize(QPageSize(m_size, QPageSize::Point));
|
||||||
|
m_pdfWriter->setResolution(m_pdfWriter->logicalDpiX());
|
||||||
|
m_pdfWriter->setPageMargins(QMarginsF());
|
||||||
|
|
||||||
|
m_painter = new QPainter(m_pdfWriter);
|
||||||
|
|
||||||
|
if (m_coordinateSystem == CoordinateSystem::PDF)
|
||||||
|
{
|
||||||
|
m_painter->translate(0, m_size.height());
|
||||||
|
m_painter->scale(0.0, -1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_painter;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFContentStreamBuilder::ContentStream PDFContentStreamBuilder::end(QPainter* painter)
|
||||||
|
{
|
||||||
|
ContentStream result;
|
||||||
|
Q_ASSERT(m_painter == painter);
|
||||||
|
|
||||||
|
m_painter->end();
|
||||||
|
delete m_painter;
|
||||||
|
m_painter = nullptr;
|
||||||
|
|
||||||
|
delete m_pdfWriter;
|
||||||
|
m_pdfWriter = nullptr;
|
||||||
|
|
||||||
|
QByteArray bufferData = m_buffer->buffer();
|
||||||
|
m_buffer->close();
|
||||||
|
delete m_buffer;
|
||||||
|
m_buffer = nullptr;
|
||||||
|
|
||||||
|
PDFDocumentReader reader(nullptr, nullptr);
|
||||||
|
result.document = reader.readFromBuffer(bufferData);
|
||||||
|
|
||||||
|
if (result.document.getCatalog()->getPageCount() > 0)
|
||||||
|
{
|
||||||
|
const PDFPage* page = result.document.getCatalog()->getPage(0);
|
||||||
|
result.pageObject = page->getPageReference();
|
||||||
|
result.resources = page->getResources();
|
||||||
|
result.contents = page->getContents();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* START GENERATED CODE */
|
/* START GENERATED CODE */
|
||||||
|
|
||||||
PDFObjectReference PDFDocumentBuilder::appendPage(QRectF mediaBox)
|
PDFObjectReference PDFDocumentBuilder::appendPage(QRectF mediaBox)
|
||||||
@ -701,6 +1141,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationCircle(PDFObjectReference
|
|||||||
objectBuilder.endDictionary();
|
objectBuilder.endDictionary();
|
||||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||||
appendTo(page, pageAnnots);
|
appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;
|
return annotationObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -762,6 +1203,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationFreeText(PDFObjectReferen
|
|||||||
objectBuilder.endDictionary();
|
objectBuilder.endDictionary();
|
||||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||||
appendTo(page, pageAnnots);
|
appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;
|
return annotationObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -845,6 +1287,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationFreeText(PDFObjectReferen
|
|||||||
objectBuilder.endDictionary();
|
objectBuilder.endDictionary();
|
||||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||||
appendTo(page, pageAnnots);
|
appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;
|
return annotationObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -908,6 +1351,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationHighlight(PDFObjectRefere
|
|||||||
objectBuilder.endDictionary();
|
objectBuilder.endDictionary();
|
||||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||||
appendTo(page, pageAnnots);
|
appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;
|
return annotationObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -956,6 +1400,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationHighlight(PDFObjectRefere
|
|||||||
objectBuilder.endDictionary();
|
objectBuilder.endDictionary();
|
||||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||||
appendTo(page, pageAnnots);
|
appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;
|
return annotationObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1042,6 +1487,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationLine(PDFObjectReference p
|
|||||||
objectBuilder.endDictionary();
|
objectBuilder.endDictionary();
|
||||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||||
appendTo(page, pageAnnots);
|
appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;
|
return annotationObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1148,6 +1594,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationLine(PDFObjectReference p
|
|||||||
objectBuilder.endDictionary();
|
objectBuilder.endDictionary();
|
||||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||||
appendTo(page, pageAnnots);
|
appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;
|
return annotationObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1189,6 +1636,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationLink(PDFObjectReference p
|
|||||||
objectBuilder.endDictionary();
|
objectBuilder.endDictionary();
|
||||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||||
appendTo(page, pageAnnots);
|
appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationReference);
|
||||||
return annotationReference;
|
return annotationReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1271,6 +1719,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationPolygon(PDFObjectReferenc
|
|||||||
objectBuilder.endDictionary();
|
objectBuilder.endDictionary();
|
||||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||||
appendTo(page, pageAnnots);
|
appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;
|
return annotationObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1350,6 +1799,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationPolyline(PDFObjectReferen
|
|||||||
objectBuilder.endDictionary();
|
objectBuilder.endDictionary();
|
||||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||||
appendTo(page, pageAnnots);
|
appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;
|
return annotationObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1389,6 +1839,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationPopup(PDFObjectReference
|
|||||||
objectBuilder.endDictionary();
|
objectBuilder.endDictionary();
|
||||||
PDFObject upgradedParentAnnotation = objectBuilder.takeObject();
|
PDFObject upgradedParentAnnotation = objectBuilder.takeObject();
|
||||||
mergeTo(parentAnnotation, upgradedParentAnnotation);
|
mergeTo(parentAnnotation, upgradedParentAnnotation);
|
||||||
|
updateAnnotationAppearanceStreams(popupAnnotation);
|
||||||
return popupAnnotation;
|
return popupAnnotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1457,6 +1908,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationSquare(PDFObjectReference
|
|||||||
objectBuilder.endDictionary();
|
objectBuilder.endDictionary();
|
||||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||||
appendTo(page, pageAnnots);
|
appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;
|
return annotationObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1520,6 +1972,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationSquiggly(PDFObjectReferen
|
|||||||
objectBuilder.endDictionary();
|
objectBuilder.endDictionary();
|
||||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||||
appendTo(page, pageAnnots);
|
appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;
|
return annotationObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1568,6 +2021,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationSquiggly(PDFObjectReferen
|
|||||||
objectBuilder.endDictionary();
|
objectBuilder.endDictionary();
|
||||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||||
appendTo(page, pageAnnots);
|
appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;
|
return annotationObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1631,6 +2085,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationStrikeout(PDFObjectRefere
|
|||||||
objectBuilder.endDictionary();
|
objectBuilder.endDictionary();
|
||||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||||
appendTo(page, pageAnnots);
|
appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;
|
return annotationObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1679,6 +2134,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationStrikeout(PDFObjectRefere
|
|||||||
objectBuilder.endDictionary();
|
objectBuilder.endDictionary();
|
||||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||||
appendTo(page, pageAnnots);
|
appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;
|
return annotationObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1751,6 +2207,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationText(PDFObjectReference p
|
|||||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||||
mergeTo(annotationObject, updateAnnotationPopup);
|
mergeTo(annotationObject, updateAnnotationPopup);
|
||||||
appendTo(page, pageAnnots);
|
appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;
|
return annotationObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1814,6 +2271,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationUnderline(PDFObjectRefere
|
|||||||
objectBuilder.endDictionary();
|
objectBuilder.endDictionary();
|
||||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||||
appendTo(page, pageAnnots);
|
appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;
|
return annotationObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1862,6 +2320,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationUnderline(PDFObjectRefere
|
|||||||
objectBuilder.endDictionary();
|
objectBuilder.endDictionary();
|
||||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||||
appendTo(page, pageAnnots);
|
appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;
|
return annotationObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#include "pdfdocument.h"
|
#include "pdfdocument.h"
|
||||||
#include "pdfannotation.h"
|
#include "pdfannotation.h"
|
||||||
|
|
||||||
|
class QPdfWriter;
|
||||||
|
|
||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -108,6 +110,7 @@ public:
|
|||||||
PDFObjectFactory& operator<<(const QPointF& point);
|
PDFObjectFactory& operator<<(const QPointF& point);
|
||||||
PDFObjectFactory& operator<<(const QDateTime& dateTime);
|
PDFObjectFactory& operator<<(const QDateTime& dateTime);
|
||||||
PDFObjectFactory& operator<<(AnnotationBorderStyle style);
|
PDFObjectFactory& operator<<(AnnotationBorderStyle style);
|
||||||
|
PDFObjectFactory& operator<<(const PDFObject& object);
|
||||||
|
|
||||||
/// Treat containers - write them as array
|
/// Treat containers - write them as array
|
||||||
template<typename Container, typename ValueType = decltype(*std::begin(std::declval<Container>()))>
|
template<typename Container, typename ValueType = decltype(*std::begin(std::declval<Container>()))>
|
||||||
@ -174,6 +177,63 @@ private:
|
|||||||
std::vector<Item> m_items;
|
std::vector<Item> m_items;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// This class can create content streams, using the Qt's QPainter
|
||||||
|
/// to draw graphics elements on it. Content stream can have various
|
||||||
|
/// resources, which can, if selected be dereferenced, so content
|
||||||
|
/// stream is encapsulated and doesn't contain references.
|
||||||
|
class PDFFORQTLIBSHARED_EXPORT PDFContentStreamBuilder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum class CoordinateSystem
|
||||||
|
{
|
||||||
|
Qt, ///< Qt's coordinate system, (0, 0) is top left
|
||||||
|
PDF ///< PDF's coordinate system, (0, 0) is top right
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Create new content stream builder, with given size and given coordinate system.
|
||||||
|
explicit PDFContentStreamBuilder(QSizeF size, CoordinateSystem coordinateSystem);
|
||||||
|
~PDFContentStreamBuilder();
|
||||||
|
|
||||||
|
struct ContentStream
|
||||||
|
{
|
||||||
|
/// Page object, which has been created by this content stream builder
|
||||||
|
PDFObjectReference pageObject;
|
||||||
|
|
||||||
|
/// Contents of the created page
|
||||||
|
PDFObject contents;
|
||||||
|
|
||||||
|
/// Resources of the created page
|
||||||
|
PDFObject resources;
|
||||||
|
|
||||||
|
/// Temporary document, which has been created by this builder
|
||||||
|
PDFDocument document;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Starts painting on a new content stream. This function returns painter,
|
||||||
|
/// onto which can be graphics drawn. Painter respects selected coordinate system.
|
||||||
|
/// Calling begin multiple times, without subsequent calls to end function,
|
||||||
|
/// is invalid and can result in undefined behaviour.
|
||||||
|
/// \return Painter, onto which can be graphic content drawn
|
||||||
|
QPainter* begin();
|
||||||
|
|
||||||
|
/// Finishes painting on a new content stream. This function returns content
|
||||||
|
/// stream object, which is associated with this page. This function
|
||||||
|
/// must be called with painter, which has been returned with call to begin function.
|
||||||
|
/// \param painter Painter, which was returned with function begin()
|
||||||
|
ContentStream end(QPainter* painter);
|
||||||
|
|
||||||
|
/// Returns actually used coordinate system
|
||||||
|
CoordinateSystem getCoordinateSystem() const { return m_coordinateSystem; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSizeF m_size;
|
||||||
|
CoordinateSystem m_coordinateSystem;
|
||||||
|
QBuffer* m_buffer;
|
||||||
|
QPdfWriter* m_pdfWriter;
|
||||||
|
QPainter* m_painter;
|
||||||
|
};
|
||||||
|
|
||||||
class PDFFORQTLIBSHARED_EXPORT PDFDocumentBuilder
|
class PDFFORQTLIBSHARED_EXPORT PDFDocumentBuilder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -212,6 +272,11 @@ public:
|
|||||||
/// Returns annotation bounding rectangle
|
/// Returns annotation bounding rectangle
|
||||||
std::array<PDFReal, 4> getAnnotationReductionRectangle(const QRectF& boundingRect, const QRectF& innerRect) const;
|
std::array<PDFReal, 4> getAnnotationReductionRectangle(const QRectF& boundingRect, const QRectF& innerRect) const;
|
||||||
|
|
||||||
|
/// If reference \p annotationReference points to supported annotation,
|
||||||
|
/// then this function updates annotation's appearance streams.
|
||||||
|
/// \param annotationReference Reference to the annotation
|
||||||
|
void updateAnnotationAppearanceStreams(PDFObjectReference annotationReference);
|
||||||
|
|
||||||
/* START GENERATED CODE */
|
/* START GENERATED CODE */
|
||||||
|
|
||||||
/// Appends a new page after last page.
|
/// Appends a new page after last page.
|
||||||
@ -763,6 +828,15 @@ private:
|
|||||||
PDFObjectReference getCatalogReference() const;
|
PDFObjectReference getCatalogReference() const;
|
||||||
void updateDocumentInfo(PDFObject info);
|
void updateDocumentInfo(PDFObject info);
|
||||||
|
|
||||||
|
/// Copies objects from another storage. Objects have adjusted references to match
|
||||||
|
/// this storage references and objects are added after the last objects of active storage.
|
||||||
|
/// This function can also automatically create references from direct objects passed
|
||||||
|
/// by parameter \p objects, if \p createReferences is set to true.
|
||||||
|
/// \param objects Objects, which we want to copy from another storage
|
||||||
|
/// \param storage Storage, from which we are copying from
|
||||||
|
/// \param createReferences Create references from \p objects
|
||||||
|
std::vector<PDFObject> copyFrom(const std::vector<PDFObject>& objects, const PDFObjectStorage& storage, bool createReferences);
|
||||||
|
|
||||||
PDFObjectStorage m_storage;
|
PDFObjectStorage m_storage;
|
||||||
PDFVersion m_version;
|
PDFVersion m_version;
|
||||||
};
|
};
|
||||||
|
@ -104,10 +104,10 @@ const PDFEmbeddedFile* PDFFileSpecification::getPlatformFile() const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFFileSpecification PDFFileSpecification::parse(const PDFDocument* document, PDFObject object)
|
PDFFileSpecification PDFFileSpecification::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
PDFFileSpecification result;
|
PDFFileSpecification result;
|
||||||
object = document->getObject(object);
|
object = storage->getObject(object);
|
||||||
|
|
||||||
if (object.isString())
|
if (object.isString())
|
||||||
{
|
{
|
||||||
@ -115,7 +115,7 @@ PDFFileSpecification PDFFileSpecification::parse(const PDFDocument* document, PD
|
|||||||
}
|
}
|
||||||
else if (object.isDictionary())
|
else if (object.isDictionary())
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
const PDFDictionary* dictionary = object.getDictionary();
|
const PDFDictionary* dictionary = object.getDictionary();
|
||||||
PDFObject collectionObject = dictionary->get("Cl");
|
PDFObject collectionObject = dictionary->get("Cl");
|
||||||
|
|
||||||
@ -129,13 +129,13 @@ PDFFileSpecification PDFFileSpecification::parse(const PDFDocument* document, PD
|
|||||||
result.m_description = loader.readTextStringFromDictionary(dictionary, "Desc", QString());
|
result.m_description = loader.readTextStringFromDictionary(dictionary, "Desc", QString());
|
||||||
result.m_collection = collectionObject.isReference() ? collectionObject.getReference() : PDFObjectReference();
|
result.m_collection = collectionObject.isReference() ? collectionObject.getReference() : PDFObjectReference();
|
||||||
|
|
||||||
PDFObject embeddedFiles = document->getObject(dictionary->get("EF"));
|
PDFObject embeddedFiles = storage->getObject(dictionary->get("EF"));
|
||||||
if (embeddedFiles.isDictionary())
|
if (embeddedFiles.isDictionary())
|
||||||
{
|
{
|
||||||
const PDFDictionary* embeddedFilesDictionary = embeddedFiles.getDictionary();
|
const PDFDictionary* embeddedFilesDictionary = embeddedFiles.getDictionary();
|
||||||
for (size_t i = 0; i < embeddedFilesDictionary->getCount(); ++i)
|
for (size_t i = 0; i < embeddedFilesDictionary->getCount(); ++i)
|
||||||
{
|
{
|
||||||
result.m_embeddedFiles[embeddedFilesDictionary->getKey(i)] = PDFEmbeddedFile::parse(document, embeddedFilesDictionary->getValue(i));
|
result.m_embeddedFiles[embeddedFilesDictionary->getKey(i)] = PDFEmbeddedFile::parse(storage, embeddedFilesDictionary->getValue(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,20 +143,20 @@ PDFFileSpecification PDFFileSpecification::parse(const PDFDocument* document, PD
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFEmbeddedFile PDFEmbeddedFile::parse(const PDFDocument* document, PDFObject object)
|
PDFEmbeddedFile PDFEmbeddedFile::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
PDFEmbeddedFile result;
|
PDFEmbeddedFile result;
|
||||||
object = document->getObject(object);
|
object = storage->getObject(object);
|
||||||
|
|
||||||
if (object.isStream())
|
if (object.isStream())
|
||||||
{
|
{
|
||||||
const PDFStream* stream = object.getStream();
|
const PDFStream* stream = object.getStream();
|
||||||
const PDFDictionary* dictionary = stream->getDictionary();
|
const PDFDictionary* dictionary = stream->getDictionary();
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
result.m_stream = object;
|
result.m_stream = object;
|
||||||
result.m_subtype = loader.readNameFromDictionary(dictionary, "Subtype");
|
result.m_subtype = loader.readNameFromDictionary(dictionary, "Subtype");
|
||||||
|
|
||||||
const PDFObject& paramsObject = document->getObject(dictionary->get("Params"));
|
const PDFObject& paramsObject = storage->getObject(dictionary->get("Params"));
|
||||||
if (paramsObject.isDictionary())
|
if (paramsObject.isDictionary())
|
||||||
{
|
{
|
||||||
const PDFDictionary* paramsDictionary = paramsObject.getDictionary();
|
const PDFDictionary* paramsDictionary = paramsObject.getDictionary();
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
class PDFDocument;
|
class PDFObjectStorage;
|
||||||
|
|
||||||
class PDFEmbeddedFile
|
class PDFEmbeddedFile
|
||||||
{
|
{
|
||||||
@ -39,7 +39,7 @@ public:
|
|||||||
const QByteArray& getChecksum() const { return m_checksum; }
|
const QByteArray& getChecksum() const { return m_checksum; }
|
||||||
const PDFStream* getStream() const { return m_stream.getStream(); }
|
const PDFStream* getStream() const { return m_stream.getStream(); }
|
||||||
|
|
||||||
static PDFEmbeddedFile parse(const PDFDocument* document, PDFObject object);
|
static PDFEmbeddedFile parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFObject m_stream;
|
PDFObject m_stream;
|
||||||
@ -75,7 +75,7 @@ public:
|
|||||||
PDFObjectReference getCollection() const { return m_collection; }
|
PDFObjectReference getCollection() const { return m_collection; }
|
||||||
const std::map<QByteArray, PDFEmbeddedFile>& getEmbeddedFiles() const { return m_embeddedFiles; }
|
const std::map<QByteArray, PDFEmbeddedFile>& getEmbeddedFiles() const { return m_embeddedFiles; }
|
||||||
|
|
||||||
static PDFFileSpecification parse(const PDFDocument* document, PDFObject object);
|
static PDFFileSpecification parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Name of the file system used to interpret this file specification,
|
/// Name of the file system used to interpret this file specification,
|
||||||
|
@ -23,11 +23,11 @@
|
|||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
|
|
||||||
PDFSound PDFSound::parse(const PDFDocument* document, PDFObject object)
|
PDFSound PDFSound::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
PDFSound result;
|
PDFSound result;
|
||||||
|
|
||||||
object = document->getObject(object);
|
object = storage->getObject(object);
|
||||||
if (object.isStream())
|
if (object.isStream())
|
||||||
{
|
{
|
||||||
const PDFStream* stream = object.getStream();
|
const PDFStream* stream = object.getStream();
|
||||||
@ -41,24 +41,24 @@ PDFSound PDFSound::parse(const PDFDocument* document, PDFObject object)
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Jakub Melka: parse the sound without exceptions
|
// Jakub Melka: parse the sound without exceptions
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
result.m_fileSpecification = PDFFileSpecification::parse(document, dictionary->get("F"));
|
result.m_fileSpecification = PDFFileSpecification::parse(storage, dictionary->get("F"));
|
||||||
result.m_samplingRate = loader.readNumberFromDictionary(dictionary, "R", 0.0);
|
result.m_samplingRate = loader.readNumberFromDictionary(dictionary, "R", 0.0);
|
||||||
result.m_channels = loader.readIntegerFromDictionary(dictionary, "C", 1);
|
result.m_channels = loader.readIntegerFromDictionary(dictionary, "C", 1);
|
||||||
result.m_bitsPerSample = loader.readIntegerFromDictionary(dictionary, "B", 8);
|
result.m_bitsPerSample = loader.readIntegerFromDictionary(dictionary, "B", 8);
|
||||||
result.m_format = loader.readEnumByName(dictionary->get("E"), formats.cbegin(), formats.cend(), Format::Raw);
|
result.m_format = loader.readEnumByName(dictionary->get("E"), formats.cbegin(), formats.cend(), Format::Raw);
|
||||||
result.m_soundCompression = loader.readNameFromDictionary(dictionary, "CO");
|
result.m_soundCompression = loader.readNameFromDictionary(dictionary, "CO");
|
||||||
result.m_soundCompressionParameters = document->getObject(dictionary->get("CP"));
|
result.m_soundCompressionParameters = storage->getObject(dictionary->get("CP"));
|
||||||
result.m_streamObject = object;
|
result.m_streamObject = object;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFRendition PDFRendition::parse(const PDFDocument* document, PDFObject object)
|
PDFRendition PDFRendition::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
PDFRendition result;
|
PDFRendition result;
|
||||||
object = document->getObject(object);
|
object = storage->getObject(object);
|
||||||
const PDFDictionary* renditionDictionary = nullptr;
|
const PDFDictionary* renditionDictionary = nullptr;
|
||||||
if (object.isDictionary())
|
if (object.isDictionary())
|
||||||
{
|
{
|
||||||
@ -76,17 +76,17 @@ PDFRendition PDFRendition::parse(const PDFDocument* document, PDFObject object)
|
|||||||
std::pair<const char*, Type>{ "SR", Type::Selector }
|
std::pair<const char*, Type>{ "SR", Type::Selector }
|
||||||
};
|
};
|
||||||
|
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
result.m_type = loader.readEnumByName(renditionDictionary->get("S"), types.cbegin(), types.cend(), Type::Invalid);
|
result.m_type = loader.readEnumByName(renditionDictionary->get("S"), types.cbegin(), types.cend(), Type::Invalid);
|
||||||
result.m_name = loader.readTextStringFromDictionary(renditionDictionary, "N", QString());
|
result.m_name = loader.readTextStringFromDictionary(renditionDictionary, "N", QString());
|
||||||
|
|
||||||
auto readMediaCriteria = [renditionDictionary, document](const char* entry)
|
auto readMediaCriteria = [renditionDictionary, storage](const char* entry)
|
||||||
{
|
{
|
||||||
PDFObject dictionaryObject = document->getObject(renditionDictionary->get(entry));
|
PDFObject dictionaryObject = storage->getObject(renditionDictionary->get(entry));
|
||||||
if (dictionaryObject.isDictionary())
|
if (dictionaryObject.isDictionary())
|
||||||
{
|
{
|
||||||
const PDFDictionary* dictionary = dictionaryObject.getDictionary();
|
const PDFDictionary* dictionary = dictionaryObject.getDictionary();
|
||||||
return PDFMediaCriteria::parse(document, dictionary->get("C"));
|
return PDFMediaCriteria::parse(storage, dictionary->get("C"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return PDFMediaCriteria();
|
return PDFMediaCriteria();
|
||||||
@ -100,9 +100,9 @@ PDFRendition PDFRendition::parse(const PDFDocument* document, PDFObject object)
|
|||||||
case Type::Media:
|
case Type::Media:
|
||||||
{
|
{
|
||||||
MediaRenditionData data;
|
MediaRenditionData data;
|
||||||
data.clip = PDFMediaClip::parse(document, renditionDictionary->get("C"));
|
data.clip = PDFMediaClip::parse(storage, renditionDictionary->get("C"));
|
||||||
data.playParameters = PDFMediaPlayParameters::parse(document, renditionDictionary->get("P"));
|
data.playParameters = PDFMediaPlayParameters::parse(storage, renditionDictionary->get("P"));
|
||||||
data.screenParameters = PDFMediaScreenParameters::parse(document, renditionDictionary->get("SP"));
|
data.screenParameters = PDFMediaScreenParameters::parse(storage, renditionDictionary->get("SP"));
|
||||||
|
|
||||||
result.m_data = qMove(data);
|
result.m_data = qMove(data);
|
||||||
break;
|
break;
|
||||||
@ -122,22 +122,22 @@ PDFRendition PDFRendition::parse(const PDFDocument* document, PDFObject object)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFMediaMinimumBitDepth PDFMediaMinimumBitDepth::parse(const PDFDocument* document, PDFObject object)
|
PDFMediaMinimumBitDepth PDFMediaMinimumBitDepth::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
return PDFMediaMinimumBitDepth(loader.readIntegerFromDictionary(dictionary, "V", -1), loader.readIntegerFromDictionary(dictionary, "M", 0));
|
return PDFMediaMinimumBitDepth(loader.readIntegerFromDictionary(dictionary, "V", -1), loader.readIntegerFromDictionary(dictionary, "M", 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
return PDFMediaMinimumBitDepth(-1, -1);
|
return PDFMediaMinimumBitDepth(-1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFMediaMinimumScreenSize PDFMediaMinimumScreenSize::parse(const PDFDocument* document, PDFObject object)
|
PDFMediaMinimumScreenSize PDFMediaMinimumScreenSize::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
std::vector<PDFInteger> values = loader.readIntegerArrayFromDictionary(dictionary, "V");
|
std::vector<PDFInteger> values = loader.readIntegerArrayFromDictionary(dictionary, "V");
|
||||||
if (values.size() == 2)
|
if (values.size() == 2)
|
||||||
{
|
{
|
||||||
@ -148,11 +148,11 @@ PDFMediaMinimumScreenSize PDFMediaMinimumScreenSize::parse(const PDFDocument* do
|
|||||||
return PDFMediaMinimumScreenSize(-1, -1, -1);
|
return PDFMediaMinimumScreenSize(-1, -1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFMediaSoftwareIdentifier PDFMediaSoftwareIdentifier::parse(const PDFDocument* document, PDFObject object)
|
PDFMediaSoftwareIdentifier PDFMediaSoftwareIdentifier::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
return PDFMediaSoftwareIdentifier(loader.readTextStringFromDictionary(dictionary, "U", QString()).toLatin1(),
|
return PDFMediaSoftwareIdentifier(loader.readTextStringFromDictionary(dictionary, "U", QString()).toLatin1(),
|
||||||
loader.readIntegerArrayFromDictionary(dictionary, "L"),
|
loader.readIntegerArrayFromDictionary(dictionary, "L"),
|
||||||
loader.readIntegerArrayFromDictionary(dictionary, "H"),
|
loader.readIntegerArrayFromDictionary(dictionary, "H"),
|
||||||
@ -164,13 +164,13 @@ PDFMediaSoftwareIdentifier PDFMediaSoftwareIdentifier::parse(const PDFDocument*
|
|||||||
return PDFMediaSoftwareIdentifier(QByteArray(), { }, { }, true, true, { });
|
return PDFMediaSoftwareIdentifier(QByteArray(), { }, { }, true, true, { });
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFMediaCriteria PDFMediaCriteria::parse(const PDFDocument* document, PDFObject object)
|
PDFMediaCriteria PDFMediaCriteria::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
PDFMediaCriteria criteria;
|
PDFMediaCriteria criteria;
|
||||||
|
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
auto readBoolean = [&loader, dictionary](const char* name, std::optional<bool>& value)
|
auto readBoolean = [&loader, dictionary](const char* name, std::optional<bool>& value)
|
||||||
{
|
{
|
||||||
if (dictionary->hasKey(name))
|
if (dictionary->hasKey(name))
|
||||||
@ -189,15 +189,15 @@ PDFMediaCriteria PDFMediaCriteria::parse(const PDFDocument* document, PDFObject
|
|||||||
}
|
}
|
||||||
if (dictionary->hasKey("D"))
|
if (dictionary->hasKey("D"))
|
||||||
{
|
{
|
||||||
criteria.m_minimumBitDepth = PDFMediaMinimumBitDepth::parse(document, dictionary->get("D"));
|
criteria.m_minimumBitDepth = PDFMediaMinimumBitDepth::parse(storage, dictionary->get("D"));
|
||||||
}
|
}
|
||||||
if (dictionary->hasKey("Z"))
|
if (dictionary->hasKey("Z"))
|
||||||
{
|
{
|
||||||
criteria.m_minimumScreenSize = PDFMediaMinimumScreenSize::parse(document, dictionary->get("Z"));
|
criteria.m_minimumScreenSize = PDFMediaMinimumScreenSize::parse(storage, dictionary->get("Z"));
|
||||||
}
|
}
|
||||||
if (dictionary->hasKey("V"))
|
if (dictionary->hasKey("V"))
|
||||||
{
|
{
|
||||||
const PDFObject& viewerObject = document->getObject(dictionary->get("V"));
|
const PDFObject& viewerObject = storage->getObject(dictionary->get("V"));
|
||||||
if (viewerObject.isArray())
|
if (viewerObject.isArray())
|
||||||
{
|
{
|
||||||
std::vector<PDFMediaSoftwareIdentifier> viewers;
|
std::vector<PDFMediaSoftwareIdentifier> viewers;
|
||||||
@ -205,7 +205,7 @@ PDFMediaCriteria PDFMediaCriteria::parse(const PDFDocument* document, PDFObject
|
|||||||
viewers.reserve(viewersArray->getCount());
|
viewers.reserve(viewersArray->getCount());
|
||||||
for (size_t i = 0; i < viewersArray->getCount(); ++i)
|
for (size_t i = 0; i < viewersArray->getCount(); ++i)
|
||||||
{
|
{
|
||||||
viewers.emplace_back(PDFMediaSoftwareIdentifier::parse(document, viewersArray->getItem(i)));
|
viewers.emplace_back(PDFMediaSoftwareIdentifier::parse(storage, viewersArray->getItem(i)));
|
||||||
}
|
}
|
||||||
criteria.m_viewers = qMove(viewers);
|
criteria.m_viewers = qMove(viewers);
|
||||||
}
|
}
|
||||||
@ -228,11 +228,11 @@ PDFMediaCriteria PDFMediaCriteria::parse(const PDFDocument* document, PDFObject
|
|||||||
return criteria;
|
return criteria;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFMediaPermissions PDFMediaPermissions::parse(const PDFDocument* document, PDFObject object)
|
PDFMediaPermissions PDFMediaPermissions::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
constexpr const std::array<std::pair<const char*, Permission>, 4> types = {
|
constexpr const std::array<std::pair<const char*, Permission>, 4> types = {
|
||||||
std::pair<const char*, Permission>{ "TEMPNEVER", Permission::Never },
|
std::pair<const char*, Permission>{ "TEMPNEVER", Permission::Never },
|
||||||
std::pair<const char*, Permission>{ "TEMPEXTRACT", Permission::Extract },
|
std::pair<const char*, Permission>{ "TEMPEXTRACT", Permission::Extract },
|
||||||
@ -246,15 +246,15 @@ PDFMediaPermissions PDFMediaPermissions::parse(const PDFDocument* document, PDFO
|
|||||||
return PDFMediaPermissions(Permission::Never);
|
return PDFMediaPermissions(Permission::Never);
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFMediaPlayers PDFMediaPlayers::parse(const PDFDocument* document, PDFObject object)
|
PDFMediaPlayers PDFMediaPlayers::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
auto readPlayers = [document, dictionary](const char* key)
|
auto readPlayers = [storage, dictionary](const char* key)
|
||||||
{
|
{
|
||||||
std::vector<PDFMediaPlayer> result;
|
std::vector<PDFMediaPlayer> result;
|
||||||
|
|
||||||
const PDFObject& playersArrayObject = document->getObject(dictionary->get(key));
|
const PDFObject& playersArrayObject = storage->getObject(dictionary->get(key));
|
||||||
if (playersArrayObject.isArray())
|
if (playersArrayObject.isArray())
|
||||||
{
|
{
|
||||||
const PDFArray* playersArray = playersArrayObject.getArray();
|
const PDFArray* playersArray = playersArrayObject.getArray();
|
||||||
@ -262,7 +262,7 @@ PDFMediaPlayers PDFMediaPlayers::parse(const PDFDocument* document, PDFObject ob
|
|||||||
|
|
||||||
for (size_t i = 0; i < playersArray->getCount(); ++i)
|
for (size_t i = 0; i < playersArray->getCount(); ++i)
|
||||||
{
|
{
|
||||||
result.emplace_back(PDFMediaPlayer::parse(document, playersArray->getItem(i)));
|
result.emplace_back(PDFMediaPlayer::parse(storage, playersArray->getItem(i)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,24 +275,24 @@ PDFMediaPlayers PDFMediaPlayers::parse(const PDFDocument* document, PDFObject ob
|
|||||||
return PDFMediaPlayers({ }, { }, { });
|
return PDFMediaPlayers({ }, { }, { });
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFMediaPlayer PDFMediaPlayer::parse(const PDFDocument* document, PDFObject object)
|
PDFMediaPlayer PDFMediaPlayer::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
return PDFMediaPlayer(PDFMediaSoftwareIdentifier::parse(document, dictionary->get("PID")));
|
return PDFMediaPlayer(PDFMediaSoftwareIdentifier::parse(storage, dictionary->get("PID")));
|
||||||
}
|
}
|
||||||
return PDFMediaPlayer(PDFMediaSoftwareIdentifier(QByteArray(), { }, { }, true, true, { }));
|
return PDFMediaPlayer(PDFMediaSoftwareIdentifier(QByteArray(), { }, { }, true, true, { }));
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFMediaOffset PDFMediaOffset::parse(const PDFDocument* document, PDFObject object)
|
PDFMediaOffset PDFMediaOffset::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
QByteArray S = loader.readNameFromDictionary(dictionary, "S");
|
QByteArray S = loader.readNameFromDictionary(dictionary, "S");
|
||||||
if (S == "T")
|
if (S == "T")
|
||||||
{
|
{
|
||||||
if (const PDFDictionary* timespanDictionary = document->getDictionaryFromObject(dictionary->get("T")))
|
if (const PDFDictionary* timespanDictionary = storage->getDictionaryFromObject(dictionary->get("T")))
|
||||||
{
|
{
|
||||||
return PDFMediaOffset(Type::Time, TimeData{ loader.readIntegerFromDictionary(timespanDictionary, "V", 0) });
|
return PDFMediaOffset(Type::Time, TimeData{ loader.readIntegerFromDictionary(timespanDictionary, "V", 0) });
|
||||||
}
|
}
|
||||||
@ -310,14 +310,14 @@ PDFMediaOffset PDFMediaOffset::parse(const PDFDocument* document, PDFObject obje
|
|||||||
return PDFMediaOffset(Type::Invalid, std::monostate());
|
return PDFMediaOffset(Type::Invalid, std::monostate());
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFMediaClip PDFMediaClip::parse(const PDFDocument* document, PDFObject object)
|
PDFMediaClip PDFMediaClip::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
MediaClipData clipData;
|
MediaClipData clipData;
|
||||||
std::vector<MediaSectionData> sections;
|
std::vector<MediaSectionData> sections;
|
||||||
|
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
std::set<PDFObjectReference> usedReferences;
|
std::set<PDFObjectReference> usedReferences;
|
||||||
while (dictionary)
|
while (dictionary)
|
||||||
{
|
{
|
||||||
@ -326,23 +326,23 @@ PDFMediaClip PDFMediaClip::parse(const PDFDocument* document, PDFObject object)
|
|||||||
{
|
{
|
||||||
clipData.name = loader.readTextStringFromDictionary(dictionary, "N", QString());
|
clipData.name = loader.readTextStringFromDictionary(dictionary, "N", QString());
|
||||||
|
|
||||||
PDFObject fileSpecificationOrStreamObject = document->getObject(dictionary->get("D"));
|
PDFObject fileSpecificationOrStreamObject = storage->getObject(dictionary->get("D"));
|
||||||
if (fileSpecificationOrStreamObject.isStream())
|
if (fileSpecificationOrStreamObject.isStream())
|
||||||
{
|
{
|
||||||
clipData.dataStream = fileSpecificationOrStreamObject;
|
clipData.dataStream = fileSpecificationOrStreamObject;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
clipData.fileSpecification = PDFFileSpecification::parse(document, fileSpecificationOrStreamObject);
|
clipData.fileSpecification = PDFFileSpecification::parse(storage, fileSpecificationOrStreamObject);
|
||||||
}
|
}
|
||||||
clipData.contentType = loader.readStringFromDictionary(dictionary, "CT");
|
clipData.contentType = loader.readStringFromDictionary(dictionary, "CT");
|
||||||
clipData.permissions = PDFMediaPermissions::parse(document, dictionary->get("P"));
|
clipData.permissions = PDFMediaPermissions::parse(storage, dictionary->get("P"));
|
||||||
clipData.alternateTextDescriptions = PDFMediaMultiLanguageTexts::parse(document, dictionary->get("Alt"));
|
clipData.alternateTextDescriptions = PDFMediaMultiLanguageTexts::parse(storage, dictionary->get("Alt"));
|
||||||
clipData.players = PDFMediaPlayers::parse(document, dictionary->get("PL"));
|
clipData.players = PDFMediaPlayers::parse(storage, dictionary->get("PL"));
|
||||||
|
|
||||||
auto getBaseUrl = [&loader, document, dictionary](const char* name)
|
auto getBaseUrl = [&loader, storage, dictionary](const char* name)
|
||||||
{
|
{
|
||||||
if (const PDFDictionary* subdictionary = document->getDictionaryFromObject(dictionary->get(name)))
|
if (const PDFDictionary* subdictionary = storage->getDictionaryFromObject(dictionary->get(name)))
|
||||||
{
|
{
|
||||||
return loader.readStringFromDictionary(subdictionary, "BU");
|
return loader.readStringFromDictionary(subdictionary, "BU");
|
||||||
}
|
}
|
||||||
@ -357,16 +357,16 @@ PDFMediaClip PDFMediaClip::parse(const PDFDocument* document, PDFObject object)
|
|||||||
{
|
{
|
||||||
MediaSectionData sectionData;
|
MediaSectionData sectionData;
|
||||||
sectionData.name = loader.readTextStringFromDictionary(dictionary, "N", QString());
|
sectionData.name = loader.readTextStringFromDictionary(dictionary, "N", QString());
|
||||||
sectionData.alternateTextDescriptions = PDFMediaMultiLanguageTexts::parse(document, dictionary->get("Alt"));
|
sectionData.alternateTextDescriptions = PDFMediaMultiLanguageTexts::parse(storage, dictionary->get("Alt"));
|
||||||
|
|
||||||
auto readMediaSectionBeginEnd = [document, dictionary](const char* name)
|
auto readMediaSectionBeginEnd = [storage, dictionary](const char* name)
|
||||||
{
|
{
|
||||||
MediaSectionBeginEnd result;
|
MediaSectionBeginEnd result;
|
||||||
|
|
||||||
if (const PDFDictionary* subdictionary = document->getDictionaryFromObject(dictionary->get(name)))
|
if (const PDFDictionary* subdictionary = storage->getDictionaryFromObject(dictionary->get(name)))
|
||||||
{
|
{
|
||||||
result.offsetBegin = PDFMediaOffset::parse(document, subdictionary->get("B"));
|
result.offsetBegin = PDFMediaOffset::parse(storage, subdictionary->get("B"));
|
||||||
result.offsetEnd = PDFMediaOffset::parse(document, subdictionary->get("E"));
|
result.offsetEnd = PDFMediaOffset::parse(storage, subdictionary->get("E"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -384,7 +384,7 @@ PDFMediaClip PDFMediaClip::parse(const PDFDocument* document, PDFObject object)
|
|||||||
}
|
}
|
||||||
usedReferences.insert(next.getReference());
|
usedReferences.insert(next.getReference());
|
||||||
}
|
}
|
||||||
dictionary = document->getDictionaryFromObject(next);
|
dictionary = storage->getDictionaryFromObject(next);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,21 +395,21 @@ PDFMediaClip PDFMediaClip::parse(const PDFDocument* document, PDFObject object)
|
|||||||
return PDFMediaClip(qMove(clipData), qMove(sections));
|
return PDFMediaClip(qMove(clipData), qMove(sections));
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFMediaMultiLanguageTexts PDFMediaMultiLanguageTexts::parse(const PDFDocument* document, PDFObject object)
|
PDFMediaMultiLanguageTexts PDFMediaMultiLanguageTexts::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
PDFMediaMultiLanguageTexts texts;
|
PDFMediaMultiLanguageTexts texts;
|
||||||
|
|
||||||
object = document->getObject(object);
|
object = storage->getObject(object);
|
||||||
if (object.isArray())
|
if (object.isArray())
|
||||||
{
|
{
|
||||||
const PDFArray* array = object.getArray();
|
const PDFArray* array = object.getArray();
|
||||||
if (array->getCount() % 2 == 0)
|
if (array->getCount() % 2 == 0)
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
const size_t pairs = array->getCount() / 2;
|
const size_t pairs = array->getCount() / 2;
|
||||||
for (size_t i = 0; i < pairs; ++i)
|
for (size_t i = 0; i < pairs; ++i)
|
||||||
{
|
{
|
||||||
const PDFObject& languageName = document->getObject(array->getItem(2 * i));
|
const PDFObject& languageName = storage->getObject(array->getItem(2 * i));
|
||||||
const PDFObject& text = array->getItem(2 * i + 1);
|
const PDFObject& text = array->getItem(2 * i + 1);
|
||||||
|
|
||||||
if (languageName.isString())
|
if (languageName.isString())
|
||||||
@ -423,28 +423,28 @@ PDFMediaMultiLanguageTexts PDFMediaMultiLanguageTexts::parse(const PDFDocument*
|
|||||||
return texts;
|
return texts;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFMediaPlayParameters PDFMediaPlayParameters::parse(const PDFDocument* document, PDFObject object)
|
PDFMediaPlayParameters PDFMediaPlayParameters::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
PDFMediaPlayParameters result;
|
PDFMediaPlayParameters result;
|
||||||
|
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
result.m_players = PDFMediaPlayers::parse(document, dictionary->get("PL"));
|
result.m_players = PDFMediaPlayers::parse(storage, dictionary->get("PL"));
|
||||||
|
|
||||||
auto getPlayParameters = [document, dictionary](const char* name)
|
auto getPlayParameters = [storage, dictionary](const char* name)
|
||||||
{
|
{
|
||||||
PlayParameters parameters;
|
PlayParameters parameters;
|
||||||
|
|
||||||
if (const PDFDictionary* subdictionary = document->getDictionaryFromObject(dictionary->get(name)))
|
if (const PDFDictionary* subdictionary = storage->getDictionaryFromObject(dictionary->get(name)))
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
parameters.volume = loader.readIntegerFromDictionary(subdictionary, "V", 100);
|
parameters.volume = loader.readIntegerFromDictionary(subdictionary, "V", 100);
|
||||||
parameters.controllerUserInterface = loader.readBooleanFromDictionary(subdictionary, "C", false);
|
parameters.controllerUserInterface = loader.readBooleanFromDictionary(subdictionary, "C", false);
|
||||||
parameters.fitMode = static_cast<FitMode>(loader.readIntegerFromDictionary(subdictionary, "F", 5));
|
parameters.fitMode = static_cast<FitMode>(loader.readIntegerFromDictionary(subdictionary, "F", 5));
|
||||||
parameters.playAutomatically = loader.readBooleanFromDictionary(subdictionary, "A", true);
|
parameters.playAutomatically = loader.readBooleanFromDictionary(subdictionary, "A", true);
|
||||||
parameters.repeat = loader.readNumberFromDictionary(dictionary, "RC", 1.0);
|
parameters.repeat = loader.readNumberFromDictionary(dictionary, "RC", 1.0);
|
||||||
|
|
||||||
if (const PDFDictionary* durationDictionary = document->getDictionaryFromObject(subdictionary->get("D")))
|
if (const PDFDictionary* durationDictionary = storage->getDictionaryFromObject(subdictionary->get("D")))
|
||||||
{
|
{
|
||||||
constexpr const std::array<std::pair<const char*, Duration>, 3> durations = {
|
constexpr const std::array<std::pair<const char*, Duration>, 3> durations = {
|
||||||
std::pair<const char*, Duration>{ "I", Duration::Intrinsic },
|
std::pair<const char*, Duration>{ "I", Duration::Intrinsic },
|
||||||
@ -453,7 +453,7 @@ PDFMediaPlayParameters PDFMediaPlayParameters::parse(const PDFDocument* document
|
|||||||
};
|
};
|
||||||
parameters.duration = loader.readEnumByName(durationDictionary->get("S"), durations.cbegin(), durations.cend(), Duration::Intrinsic);
|
parameters.duration = loader.readEnumByName(durationDictionary->get("S"), durations.cbegin(), durations.cend(), Duration::Intrinsic);
|
||||||
|
|
||||||
if (const PDFDictionary* timeDictionary = document->getDictionaryFromObject(durationDictionary->get("T")))
|
if (const PDFDictionary* timeDictionary = storage->getDictionaryFromObject(durationDictionary->get("T")))
|
||||||
{
|
{
|
||||||
parameters.durationSeconds = loader.readNumberFromDictionary(timeDictionary, "V", 0.0);
|
parameters.durationSeconds = loader.readNumberFromDictionary(timeDictionary, "V", 0.0);
|
||||||
}
|
}
|
||||||
@ -469,16 +469,16 @@ PDFMediaPlayParameters PDFMediaPlayParameters::parse(const PDFDocument* document
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFMediaScreenParameters PDFMediaScreenParameters::parse(const PDFDocument* document, PDFObject object)
|
PDFMediaScreenParameters PDFMediaScreenParameters::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
auto getScreenParameters = [document, dictionary](const char* name)
|
auto getScreenParameters = [storage, dictionary](const char* name)
|
||||||
{
|
{
|
||||||
ScreenParameters result;
|
ScreenParameters result;
|
||||||
if (const PDFDictionary* screenDictionary = document->getDictionaryFromObject(dictionary->get(name)))
|
if (const PDFDictionary* screenDictionary = storage->getDictionaryFromObject(dictionary->get(name)))
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
result.windowType = static_cast<WindowType>(loader.readIntegerFromDictionary(screenDictionary, "W", 3));
|
result.windowType = static_cast<WindowType>(loader.readIntegerFromDictionary(screenDictionary, "W", 3));
|
||||||
result.opacity = loader.readNumberFromDictionary(screenDictionary, "O", 1.0);
|
result.opacity = loader.readNumberFromDictionary(screenDictionary, "O", 1.0);
|
||||||
result.monitorSpecification = loader.readIntegerFromDictionary(screenDictionary, "M", 0);
|
result.monitorSpecification = loader.readIntegerFromDictionary(screenDictionary, "M", 0);
|
||||||
@ -486,7 +486,7 @@ PDFMediaScreenParameters PDFMediaScreenParameters::parse(const PDFDocument* docu
|
|||||||
rgb.resize(3, 1.0);
|
rgb.resize(3, 1.0);
|
||||||
result.backgroundColor.setRgbF(rgb[0], rgb[1], rgb[2]);
|
result.backgroundColor.setRgbF(rgb[0], rgb[1], rgb[2]);
|
||||||
|
|
||||||
if (const PDFDictionary* floatWindowDictionary = document->getDictionaryFromObject(screenDictionary->get("F")))
|
if (const PDFDictionary* floatWindowDictionary = storage->getDictionaryFromObject(screenDictionary->get("F")))
|
||||||
{
|
{
|
||||||
std::vector<PDFInteger> sizeArray = loader.readIntegerArrayFromDictionary(floatWindowDictionary, "D");
|
std::vector<PDFInteger> sizeArray = loader.readIntegerArrayFromDictionary(floatWindowDictionary, "D");
|
||||||
sizeArray.resize(2, 0);
|
sizeArray.resize(2, 0);
|
||||||
@ -496,7 +496,7 @@ PDFMediaScreenParameters PDFMediaScreenParameters::parse(const PDFDocument* docu
|
|||||||
result.floatingWindowHasTitleBar = loader.readBooleanFromDictionary(floatWindowDictionary, "T", true);
|
result.floatingWindowHasTitleBar = loader.readBooleanFromDictionary(floatWindowDictionary, "T", true);
|
||||||
result.floatingWindowCloseable = loader.readBooleanFromDictionary(floatWindowDictionary, "UC", true);
|
result.floatingWindowCloseable = loader.readBooleanFromDictionary(floatWindowDictionary, "UC", true);
|
||||||
result.floatingWindowResizeMode = static_cast<ResizeMode>(loader.readIntegerFromDictionary(floatWindowDictionary, "R", 0));
|
result.floatingWindowResizeMode = static_cast<ResizeMode>(loader.readIntegerFromDictionary(floatWindowDictionary, "R", 0));
|
||||||
result.floatingWindowTitle = PDFMediaMultiLanguageTexts::parse(document, floatWindowDictionary->get("TT"));
|
result.floatingWindowTitle = PDFMediaMultiLanguageTexts::parse(storage, floatWindowDictionary->get("TT"));
|
||||||
switch (loader.readIntegerFromDictionary(floatWindowDictionary, "P", 4))
|
switch (loader.readIntegerFromDictionary(floatWindowDictionary, "P", 4))
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
@ -539,14 +539,14 @@ PDFMediaScreenParameters PDFMediaScreenParameters::parse(const PDFDocument* docu
|
|||||||
return PDFMediaScreenParameters();
|
return PDFMediaScreenParameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFMovie PDFMovie::parse(const PDFDocument* document, PDFObject object)
|
PDFMovie PDFMovie::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
PDFMovie result;
|
PDFMovie result;
|
||||||
|
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
result.m_movieFile = PDFFileSpecification::parse(document, dictionary->get("F"));
|
result.m_movieFile = PDFFileSpecification::parse(storage, dictionary->get("F"));
|
||||||
std::vector<PDFInteger> windowSizeArray = loader.readIntegerArrayFromDictionary(dictionary, "Aspect");
|
std::vector<PDFInteger> windowSizeArray = loader.readIntegerArrayFromDictionary(dictionary, "Aspect");
|
||||||
if (windowSizeArray.size() == 2)
|
if (windowSizeArray.size() == 2)
|
||||||
{
|
{
|
||||||
@ -554,7 +554,7 @@ PDFMovie PDFMovie::parse(const PDFDocument* document, PDFObject object)
|
|||||||
}
|
}
|
||||||
result.m_rotationAngle = loader.readIntegerFromDictionary(dictionary, "Rotate", 0);
|
result.m_rotationAngle = loader.readIntegerFromDictionary(dictionary, "Rotate", 0);
|
||||||
|
|
||||||
PDFObject posterObject = document->getObject(dictionary->get("Poster"));
|
PDFObject posterObject = storage->getObject(dictionary->get("Poster"));
|
||||||
if (posterObject.isBool())
|
if (posterObject.isBool())
|
||||||
{
|
{
|
||||||
result.m_showPoster = posterObject.getBool();
|
result.m_showPoster = posterObject.getBool();
|
||||||
@ -571,13 +571,13 @@ PDFMovie PDFMovie::parse(const PDFDocument* document, PDFObject object)
|
|||||||
return PDFMovie();
|
return PDFMovie();
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFMovieActivation PDFMovieActivation::parse(const PDFDocument* document, PDFObject object)
|
PDFMovieActivation PDFMovieActivation::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
PDFMovieActivation result;
|
PDFMovieActivation result;
|
||||||
|
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
|
|
||||||
constexpr const std::array<std::pair<const char*, Mode>, 4> modes = {
|
constexpr const std::array<std::pair<const char*, Mode>, 4> modes = {
|
||||||
std::pair<const char*, Mode>{ "Once", Mode::Once },
|
std::pair<const char*, Mode>{ "Once", Mode::Once },
|
||||||
@ -597,8 +597,8 @@ PDFMovieActivation PDFMovieActivation::parse(const PDFDocument* document, PDFObj
|
|||||||
relativePosition.resize(2, 0.5);
|
relativePosition.resize(2, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
result.m_start = parseMovieTime(document, dictionary->get("Start"));
|
result.m_start = parseMovieTime(storage, dictionary->get("Start"));
|
||||||
result.m_duration = parseMovieTime(document, dictionary->get("Duration"));
|
result.m_duration = parseMovieTime(storage, dictionary->get("Duration"));
|
||||||
result.m_rate = loader.readNumberFromDictionary(dictionary, "Rate", 1.0);
|
result.m_rate = loader.readNumberFromDictionary(dictionary, "Rate", 1.0);
|
||||||
result.m_volume = loader.readNumberFromDictionary(dictionary, "Volume", 1.0);
|
result.m_volume = loader.readNumberFromDictionary(dictionary, "Volume", 1.0);
|
||||||
result.m_showControls = loader.readBooleanFromDictionary(dictionary, "ShowControls", false);
|
result.m_showControls = loader.readBooleanFromDictionary(dictionary, "ShowControls", false);
|
||||||
@ -612,11 +612,11 @@ PDFMovieActivation PDFMovieActivation::parse(const PDFDocument* document, PDFObj
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFMovieActivation::MovieTime PDFMovieActivation::parseMovieTime(const PDFDocument* document, PDFObject object)
|
PDFMovieActivation::MovieTime PDFMovieActivation::parseMovieTime(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
MovieTime result;
|
MovieTime result;
|
||||||
|
|
||||||
object = document->getObject(object);
|
object = storage->getObject(object);
|
||||||
if (object.isInt())
|
if (object.isInt())
|
||||||
{
|
{
|
||||||
result.value = object.getInteger();
|
result.value = object.getInteger();
|
||||||
@ -630,10 +630,10 @@ PDFMovieActivation::MovieTime PDFMovieActivation::parseMovieTime(const PDFDocume
|
|||||||
const PDFArray* objectArray = object.getArray();
|
const PDFArray* objectArray = object.getArray();
|
||||||
if (objectArray->getCount() == 2)
|
if (objectArray->getCount() == 2)
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
result.unitsPerSecond = loader.readInteger(objectArray->getItem(1), 0);
|
result.unitsPerSecond = loader.readInteger(objectArray->getItem(1), 0);
|
||||||
|
|
||||||
object = document->getObject(objectArray->getItem(0));
|
object = storage->getObject(objectArray->getItem(0));
|
||||||
if (object.isInt())
|
if (object.isInt())
|
||||||
{
|
{
|
||||||
result.value = object.getInteger();
|
result.value = object.getInteger();
|
||||||
|
@ -28,11 +28,11 @@
|
|||||||
|
|
||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
class PDFDocument;
|
class PDFObjectStorage;
|
||||||
|
|
||||||
struct PDFMediaMultiLanguageTexts
|
struct PDFMediaMultiLanguageTexts
|
||||||
{
|
{
|
||||||
static PDFMediaMultiLanguageTexts parse(const PDFDocument* document, PDFObject object);
|
static PDFMediaMultiLanguageTexts parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
std::map<QByteArray, QString> texts;
|
std::map<QByteArray, QString> texts;
|
||||||
};
|
};
|
||||||
@ -78,7 +78,7 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PDFMediaOffset parse(const PDFDocument* document, PDFObject object);
|
static PDFMediaOffset parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
const TimeData* getTimeData() const { return std::holds_alternative<TimeData>(m_data) ? &std::get<TimeData>(m_data) : nullptr; }
|
const TimeData* getTimeData() const { return std::holds_alternative<TimeData>(m_data) ? &std::get<TimeData>(m_data) : nullptr; }
|
||||||
const FrameData* getFrameData() const { return std::holds_alternative<FrameData>(m_data) ? &std::get<FrameData>(m_data) : nullptr; }
|
const FrameData* getFrameData() const { return std::holds_alternative<FrameData>(m_data) ? &std::get<FrameData>(m_data) : nullptr; }
|
||||||
@ -104,7 +104,7 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PDFMediaSoftwareIdentifier parse(const PDFDocument* document, PDFObject object);
|
static PDFMediaSoftwareIdentifier parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
const QByteArray& getSoftware() const { return m_software; }
|
const QByteArray& getSoftware() const { return m_software; }
|
||||||
const std::vector<PDFInteger>& getLowVersion() const { return m_lowVersion; }
|
const std::vector<PDFInteger>& getLowVersion() const { return m_lowVersion; }
|
||||||
@ -131,7 +131,7 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PDFMediaPlayer parse(const PDFDocument* document, PDFObject object);
|
static PDFMediaPlayer parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
const PDFMediaSoftwareIdentifier* getSoftwareIdentifier() const { return &m_softwareIdentifier; }
|
const PDFMediaSoftwareIdentifier* getSoftwareIdentifier() const { return &m_softwareIdentifier; }
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PDFMediaPlayers parse(const PDFDocument* document, PDFObject object);
|
static PDFMediaPlayers parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
const std::vector<PDFMediaPlayer>& getPlayersMustUsed() const { return m_playersMustUsed; }
|
const std::vector<PDFMediaPlayer>& getPlayersMustUsed() const { return m_playersMustUsed; }
|
||||||
const std::vector<PDFMediaPlayer>& getPlayersAlternate() const { return m_playersAlternate; }
|
const std::vector<PDFMediaPlayer>& getPlayersAlternate() const { return m_playersAlternate; }
|
||||||
@ -191,7 +191,7 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PDFMediaPermissions parse(const PDFDocument* document, PDFObject object);
|
static PDFMediaPermissions parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
Permission getPermission() const { return m_permission; }
|
Permission getPermission() const { return m_permission; }
|
||||||
|
|
||||||
@ -232,7 +232,7 @@ public:
|
|||||||
PDFReal durationSeconds = 0.0;
|
PDFReal durationSeconds = 0.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
static PDFMediaPlayParameters parse(const PDFDocument* document, PDFObject object);
|
static PDFMediaPlayParameters parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
const PDFMediaPlayers* getPlayers() const { return &m_players; }
|
const PDFMediaPlayers* getPlayers() const { return &m_players; }
|
||||||
const PlayParameters* getPlayParametersMustHonored() const { return &m_mustHonored; }
|
const PlayParameters* getPlayParametersMustHonored() const { return &m_mustHonored; }
|
||||||
@ -303,7 +303,7 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PDFMediaScreenParameters parse(const PDFDocument* document, PDFObject object);
|
static PDFMediaScreenParameters parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
const ScreenParameters* getScreenParametersMustHonored() const { return &m_mustHonored; }
|
const ScreenParameters* getScreenParametersMustHonored() const { return &m_mustHonored; }
|
||||||
const ScreenParameters* getScreenParametersBestEffort() const { return &m_bestEffort; }
|
const ScreenParameters* getScreenParametersBestEffort() const { return &m_bestEffort; }
|
||||||
@ -352,7 +352,7 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PDFMediaClip parse(const PDFDocument* document, PDFObject object);
|
static PDFMediaClip parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
const MediaClipData& getMediaClipData() const { return m_mediaClipData; }
|
const MediaClipData& getMediaClipData() const { return m_mediaClipData; }
|
||||||
const std::vector<MediaSectionData>& getClipSections() const { return m_sections; }
|
const std::vector<MediaSectionData>& getClipSections() const { return m_sections; }
|
||||||
@ -372,7 +372,7 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PDFMediaMinimumBitDepth parse(const PDFDocument* document, PDFObject object);
|
static PDFMediaMinimumBitDepth parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
PDFInteger getScreenMinimumBitDepth() const { return m_screenMinimumBitDepth; }
|
PDFInteger getScreenMinimumBitDepth() const { return m_screenMinimumBitDepth; }
|
||||||
PDFInteger getMonitorSpecifier() const { return m_monitorSpecifier; }
|
PDFInteger getMonitorSpecifier() const { return m_monitorSpecifier; }
|
||||||
@ -393,7 +393,7 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PDFMediaMinimumScreenSize parse(const PDFDocument* document, PDFObject object);
|
static PDFMediaMinimumScreenSize parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFInteger m_minimumWidth;
|
PDFInteger m_minimumWidth;
|
||||||
@ -409,7 +409,7 @@ class PDFMediaCriteria
|
|||||||
public:
|
public:
|
||||||
explicit inline PDFMediaCriteria() = default;
|
explicit inline PDFMediaCriteria() = default;
|
||||||
|
|
||||||
static PDFMediaCriteria parse(const PDFDocument* document, PDFObject object);
|
static PDFMediaCriteria parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
bool hasAudioDescriptions() const { return m_audioDescriptions.has_value(); }
|
bool hasAudioDescriptions() const { return m_audioDescriptions.has_value(); }
|
||||||
bool hasTextCaptions() const { return m_textCaptions.has_value(); }
|
bool hasTextCaptions() const { return m_textCaptions.has_value(); }
|
||||||
@ -473,7 +473,7 @@ public:
|
|||||||
PDFObject renditions;
|
PDFObject renditions;
|
||||||
};
|
};
|
||||||
|
|
||||||
static PDFRendition parse(const PDFDocument* document, PDFObject object);
|
static PDFRendition parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
Type getType() const { return m_type; }
|
Type getType() const { return m_type; }
|
||||||
const QString& getName() const { return m_name; }
|
const QString& getName() const { return m_name; }
|
||||||
@ -519,7 +519,7 @@ public:
|
|||||||
|
|
||||||
/// Creates a new sound from the object. If data are invalid, then invalid object
|
/// Creates a new sound from the object. If data are invalid, then invalid object
|
||||||
/// is returned, no exception is thrown.
|
/// is returned, no exception is thrown.
|
||||||
static PDFSound parse(const PDFDocument* document, PDFObject object);
|
static PDFSound parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFFileSpecification m_fileSpecification;
|
PDFFileSpecification m_fileSpecification;
|
||||||
@ -546,7 +546,7 @@ public:
|
|||||||
|
|
||||||
/// Creates a new movie from the object. If data are invalid, then invalid object
|
/// Creates a new movie from the object. If data are invalid, then invalid object
|
||||||
/// is returned, no exception is thrown.
|
/// is returned, no exception is thrown.
|
||||||
static PDFMovie parse(const PDFDocument* document, PDFObject object);
|
static PDFMovie parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFFileSpecification m_movieFile;
|
PDFFileSpecification m_movieFile;
|
||||||
@ -590,10 +590,10 @@ public:
|
|||||||
|
|
||||||
/// Creates a new moview from the object. If data are invalid, then invalid object
|
/// Creates a new moview from the object. If data are invalid, then invalid object
|
||||||
/// is returned, no exception is thrown.
|
/// is returned, no exception is thrown.
|
||||||
static PDFMovieActivation parse(const PDFDocument* document, PDFObject object);
|
static PDFMovieActivation parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static MovieTime parseMovieTime(const PDFDocument* document, PDFObject object);
|
static MovieTime parseMovieTime(const PDFObjectStorage* storage, PDFObject object);
|
||||||
static PDFInteger parseMovieTimeFromString(const QByteArray& string);
|
static PDFInteger parseMovieTimeFromString(const QByteArray& string);
|
||||||
|
|
||||||
MovieTime m_start;
|
MovieTime m_start;
|
||||||
|
@ -34,27 +34,27 @@ public:
|
|||||||
explicit PDFNameTreeLoader() = delete;
|
explicit PDFNameTreeLoader() = delete;
|
||||||
|
|
||||||
using MappedObjects = std::map<QByteArray, Type>;
|
using MappedObjects = std::map<QByteArray, Type>;
|
||||||
using LoadMethod = std::function<Type(const PDFDocument*, const PDFObject&)>;
|
using LoadMethod = std::function<Type(const PDFObjectStorage*, const PDFObject&)>;
|
||||||
|
|
||||||
/// Parses the name tree and loads its items into the map. Some errors are ignored,
|
/// Parses the name tree and loads its items into the map. Some errors are ignored,
|
||||||
/// e.g. when kid is null. Objects are retrieved by \p loadMethod.
|
/// e.g. when kid is null. Objects are retrieved by \p loadMethod.
|
||||||
/// \param document Document
|
/// \param storage Object storage
|
||||||
/// \param root Root of the name tree
|
/// \param root Root of the name tree
|
||||||
/// \param loadMethod Parsing method, which retrieves parsed object
|
/// \param loadMethod Parsing method, which retrieves parsed object
|
||||||
static MappedObjects parse(const PDFDocument* document, const PDFObject& root, const LoadMethod& loadMethod)
|
static MappedObjects parse(const PDFObjectStorage* storage, const PDFObject& root, const LoadMethod& loadMethod)
|
||||||
{
|
{
|
||||||
MappedObjects result;
|
MappedObjects result;
|
||||||
parseImpl(result, document, root, loadMethod);
|
parseImpl(result, storage, root, loadMethod);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void parseImpl(MappedObjects& objects, const PDFDocument* document, const PDFObject& root, const LoadMethod& loadMethod)
|
static void parseImpl(MappedObjects& objects, const PDFObjectStorage* storage, const PDFObject& root, const LoadMethod& loadMethod)
|
||||||
{
|
{
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(root))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(root))
|
||||||
{
|
{
|
||||||
// Jakub Melka: First, load the objects into the map
|
// Jakub Melka: First, load the objects into the map
|
||||||
const PDFObject& namedItems = document->getObject(dictionary->get("Names"));
|
const PDFObject& namedItems = storage->getObject(dictionary->get("Names"));
|
||||||
if (namedItems.isArray())
|
if (namedItems.isArray())
|
||||||
{
|
{
|
||||||
const PDFArray* namedItemsArray = namedItems.getArray();
|
const PDFArray* namedItemsArray = namedItems.getArray();
|
||||||
@ -64,25 +64,25 @@ private:
|
|||||||
const size_t numberIndex = 2 * i;
|
const size_t numberIndex = 2 * i;
|
||||||
const size_t valueIndex = 2 * i + 1;
|
const size_t valueIndex = 2 * i + 1;
|
||||||
|
|
||||||
const PDFObject& name = document->getObject(namedItemsArray->getItem(numberIndex));
|
const PDFObject& name = storage->getObject(namedItemsArray->getItem(numberIndex));
|
||||||
if (!name.isString())
|
if (!name.isString())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
objects[name.getString()] = loadMethod(document, namedItemsArray->getItem(valueIndex));
|
objects[name.getString()] = loadMethod(storage, namedItemsArray->getItem(valueIndex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then, follow the kids
|
// Then, follow the kids
|
||||||
const PDFObject& kids = document->getObject(dictionary->get("Kids"));
|
const PDFObject& kids = storage->getObject(dictionary->get("Kids"));
|
||||||
if (kids.isArray())
|
if (kids.isArray())
|
||||||
{
|
{
|
||||||
const PDFArray* kidsArray = kids.getArray();
|
const PDFArray* kidsArray = kids.getArray();
|
||||||
const size_t count = kidsArray->getCount();
|
const size_t count = kidsArray->getCount();
|
||||||
for (size_t i = 0; i < count; ++i)
|
for (size_t i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
parseImpl(objects, document, kidsArray->getItem(i), loadMethod);
|
parseImpl(objects, storage, kidsArray->getItem(i), loadMethod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,10 +70,10 @@ void PDFOutlineItem::parseImpl(const PDFDocument* document,
|
|||||||
{
|
{
|
||||||
currentOutlineItem->setTitle(PDFEncoding::convertTextString(titleObject.getString()));
|
currentOutlineItem->setTitle(PDFEncoding::convertTextString(titleObject.getString()));
|
||||||
}
|
}
|
||||||
currentOutlineItem->setAction(PDFAction::parse(document, dictionary->get("A")));
|
currentOutlineItem->setAction(PDFAction::parse(&document->getStorage(), dictionary->get("A")));
|
||||||
if (!currentOutlineItem->getAction() && dictionary->hasKey("Dest"))
|
if (!currentOutlineItem->getAction() && dictionary->hasKey("Dest"))
|
||||||
{
|
{
|
||||||
currentOutlineItem->setAction(PDFActionPtr(new PDFActionGoTo(PDFDestination::parse(document, dictionary->get("Dest")))));
|
currentOutlineItem->setAction(PDFActionPtr(new PDFActionGoTo(PDFDestination::parse(&document->getStorage(), dictionary->get("Dest")))));
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(document);
|
||||||
|
@ -44,6 +44,37 @@ class PDFOptionalContentActivity;
|
|||||||
|
|
||||||
static constexpr const char* PDF_RESOURCE_EXTGSTATE = "ExtGState";
|
static constexpr const char* PDF_RESOURCE_EXTGSTATE = "ExtGState";
|
||||||
|
|
||||||
|
class PDFLineDashPattern
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit inline PDFLineDashPattern() = default;
|
||||||
|
explicit inline PDFLineDashPattern(const std::vector<PDFReal>& dashArray, PDFReal dashOffset) :
|
||||||
|
m_dashArray(dashArray),
|
||||||
|
m_dashOffset(dashOffset)
|
||||||
|
{
|
||||||
|
if (m_dashArray.size() % 2 == 1)
|
||||||
|
{
|
||||||
|
m_dashArray.push_back(m_dashArray.back());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const std::vector<PDFReal>& getDashArray() const { return m_dashArray; }
|
||||||
|
inline void setDashArray(const std::vector<PDFReal>& dashArray) { m_dashArray = dashArray; }
|
||||||
|
|
||||||
|
inline PDFReal getDashOffset() const { return m_dashOffset; }
|
||||||
|
inline void setDashOffset(PDFReal dashOffset) { m_dashOffset = dashOffset; }
|
||||||
|
|
||||||
|
inline bool operator==(const PDFLineDashPattern& other) const { return m_dashArray == other.m_dashArray && m_dashOffset == other.m_dashOffset; }
|
||||||
|
inline bool operator!=(const PDFLineDashPattern& other) const { return !(*this == other); }
|
||||||
|
|
||||||
|
/// Is line solid? Function returns true, if yes.
|
||||||
|
bool isSolid() const { return m_dashArray.empty(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<PDFReal> m_dashArray;
|
||||||
|
PDFReal m_dashOffset = 0.0;
|
||||||
|
};
|
||||||
|
|
||||||
/// Process the contents of the page.
|
/// Process the contents of the page.
|
||||||
class PDFPageContentProcessor : public PDFRenderErrorReporter
|
class PDFPageContentProcessor : public PDFRenderErrorReporter
|
||||||
{
|
{
|
||||||
@ -193,34 +224,6 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
class PDFLineDashPattern
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit inline PDFLineDashPattern() = default;
|
|
||||||
explicit inline PDFLineDashPattern(const std::vector<PDFReal>& dashArray, PDFReal dashOffset) :
|
|
||||||
m_dashArray(dashArray),
|
|
||||||
m_dashOffset(dashOffset)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const std::vector<PDFReal>& getDashArray() const { return m_dashArray; }
|
|
||||||
inline void setDashArray(const std::vector<PDFReal>& dashArray) { m_dashArray = dashArray; }
|
|
||||||
|
|
||||||
inline PDFReal getDashOffset() const { return m_dashOffset; }
|
|
||||||
inline void setDashOffset(PDFReal dashOffset) { m_dashOffset = dashOffset; }
|
|
||||||
|
|
||||||
inline bool operator==(const PDFLineDashPattern& other) const { return m_dashArray == other.m_dashArray && m_dashOffset == other.m_dashOffset; }
|
|
||||||
inline bool operator!=(const PDFLineDashPattern& other) const { return !(*this == other); }
|
|
||||||
|
|
||||||
/// Is line solid? Function returns true, if yes.
|
|
||||||
bool isSolid() const { return m_dashArray.empty(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<PDFReal> m_dashArray;
|
|
||||||
PDFReal m_dashOffset = 0.0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PDFTransparencyGroup
|
struct PDFTransparencyGroup
|
||||||
{
|
{
|
||||||
PDFColorSpacePointer colorSpacePointer;
|
PDFColorSpacePointer colorSpacePointer;
|
||||||
|
@ -21,13 +21,13 @@
|
|||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
|
|
||||||
PDFPageTransition PDFPageTransition::parse(const PDFDocument* document, PDFObject object)
|
PDFPageTransition PDFPageTransition::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
PDFPageTransition result;
|
PDFPageTransition result;
|
||||||
|
|
||||||
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
{
|
{
|
||||||
PDFDocumentDataLoaderDecorator loader(document);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
|
|
||||||
constexpr const std::array<std::pair<const char*, Style>, 12> styles = {
|
constexpr const std::array<std::pair<const char*, Style>, 12> styles = {
|
||||||
std::pair<const char*, Style>{ "Split", Style::Split },
|
std::pair<const char*, Style>{ "Split", Style::Split },
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
class PDFDocument;
|
class PDFObjectStorage;
|
||||||
|
|
||||||
/// Page transition during presentation settings.
|
/// Page transition during presentation settings.
|
||||||
class PDFPageTransition
|
class PDFPageTransition
|
||||||
@ -57,7 +57,7 @@ public:
|
|||||||
Outward
|
Outward
|
||||||
};
|
};
|
||||||
|
|
||||||
static PDFPageTransition parse(const PDFDocument* document, PDFObject object);
|
static PDFPageTransition parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
Style getStyle() const { return m_style; }
|
Style getStyle() const { return m_style; }
|
||||||
PDFReal getDuration() const { return m_duration; }
|
PDFReal getDuration() const { return m_duration; }
|
||||||
|
@ -398,6 +398,7 @@ return pageReference;</property>
|
|||||||
<property name="variableName"></property>
|
<property name="variableName"></property>
|
||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">appendTo(page, pageAnnots);
|
<property name="code">appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;</property>
|
return annotationObject;</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
@ -600,6 +601,7 @@ return annotationObject;</property>
|
|||||||
<property name="variableName"></property>
|
<property name="variableName"></property>
|
||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">appendTo(page, pageAnnots);
|
<property name="code">appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;</property>
|
return annotationObject;</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
@ -874,6 +876,7 @@ return annotationObject;</property>
|
|||||||
<property name="variableName"></property>
|
<property name="variableName"></property>
|
||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">appendTo(page, pageAnnots);
|
<property name="code">appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;</property>
|
return annotationObject;</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
@ -1077,6 +1080,7 @@ return annotationObject;</property>
|
|||||||
<property name="variableName"></property>
|
<property name="variableName"></property>
|
||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">appendTo(page, pageAnnots);
|
<property name="code">appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;</property>
|
return annotationObject;</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
@ -1231,6 +1235,7 @@ return annotationObject;</property>
|
|||||||
<property name="variableName"></property>
|
<property name="variableName"></property>
|
||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">appendTo(page, pageAnnots);
|
<property name="code">appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;</property>
|
return annotationObject;</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
@ -1520,6 +1525,7 @@ return annotationObject;</property>
|
|||||||
<property name="variableName"></property>
|
<property name="variableName"></property>
|
||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">appendTo(page, pageAnnots);
|
<property name="code">appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;</property>
|
return annotationObject;</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
@ -1879,6 +1885,7 @@ return annotationObject;</property>
|
|||||||
<property name="variableName"></property>
|
<property name="variableName"></property>
|
||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">appendTo(page, pageAnnots);
|
<property name="code">appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;</property>
|
return annotationObject;</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
@ -2025,6 +2032,7 @@ return annotationObject;</property>
|
|||||||
<property name="variableName"></property>
|
<property name="variableName"></property>
|
||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">appendTo(page, pageAnnots);
|
<property name="code">appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationReference);
|
||||||
return annotationReference;</property>
|
return annotationReference;</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
@ -2317,6 +2325,7 @@ return annotationReference;</property>
|
|||||||
<property name="variableName"></property>
|
<property name="variableName"></property>
|
||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">appendTo(page, pageAnnots);
|
<property name="code">appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;</property>
|
return annotationObject;</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
@ -2584,6 +2593,7 @@ return annotationObject;</property>
|
|||||||
<property name="variableName"></property>
|
<property name="variableName"></property>
|
||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">appendTo(page, pageAnnots);
|
<property name="code">appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;</property>
|
return annotationObject;</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
@ -2722,6 +2732,7 @@ return annotationObject;</property>
|
|||||||
<property name="variableName"></property>
|
<property name="variableName"></property>
|
||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">mergeTo(parentAnnotation, upgradedParentAnnotation);
|
<property name="code">mergeTo(parentAnnotation, upgradedParentAnnotation);
|
||||||
|
updateAnnotationAppearanceStreams(popupAnnotation);
|
||||||
return popupAnnotation;</property>
|
return popupAnnotation;</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
@ -2953,6 +2964,7 @@ return popupAnnotation;</property>
|
|||||||
<property name="variableName"></property>
|
<property name="variableName"></property>
|
||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">appendTo(page, pageAnnots);
|
<property name="code">appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;</property>
|
return annotationObject;</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
@ -3156,6 +3168,7 @@ return annotationObject;</property>
|
|||||||
<property name="variableName"></property>
|
<property name="variableName"></property>
|
||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">appendTo(page, pageAnnots);
|
<property name="code">appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;</property>
|
return annotationObject;</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
@ -3310,6 +3323,7 @@ return annotationObject;</property>
|
|||||||
<property name="variableName"></property>
|
<property name="variableName"></property>
|
||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">appendTo(page, pageAnnots);
|
<property name="code">appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;</property>
|
return annotationObject;</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
@ -3513,6 +3527,7 @@ return annotationObject;</property>
|
|||||||
<property name="variableName"></property>
|
<property name="variableName"></property>
|
||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">appendTo(page, pageAnnots);
|
<property name="code">appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;</property>
|
return annotationObject;</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
@ -3667,6 +3682,7 @@ return annotationObject;</property>
|
|||||||
<property name="variableName"></property>
|
<property name="variableName"></property>
|
||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">appendTo(page, pageAnnots);
|
<property name="code">appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;</property>
|
return annotationObject;</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
@ -3909,6 +3925,7 @@ return annotationObject;</property>
|
|||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">mergeTo(annotationObject, updateAnnotationPopup);
|
<property name="code">mergeTo(annotationObject, updateAnnotationPopup);
|
||||||
appendTo(page, pageAnnots);
|
appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;</property>
|
return annotationObject;</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
@ -4112,6 +4129,7 @@ return annotationObject;</property>
|
|||||||
<property name="variableName"></property>
|
<property name="variableName"></property>
|
||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">appendTo(page, pageAnnots);
|
<property name="code">appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;</property>
|
return annotationObject;</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
@ -4266,6 +4284,7 @@ return annotationObject;</property>
|
|||||||
<property name="variableName"></property>
|
<property name="variableName"></property>
|
||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">appendTo(page, pageAnnots);
|
<property name="code">appendTo(page, pageAnnots);
|
||||||
|
updateAnnotationAppearanceStreams(annotationObject);
|
||||||
return annotationObject;</property>
|
return annotationObject;</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
|
Reference in New Issue
Block a user