mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-02-26 08:27:49 +01:00
Annotation painting, first part
This commit is contained in:
parent
8bce1bc1e5
commit
232832e753
@ -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");
|
||||
builder.setAnnotationBorderStyle(annotation, pdf::PDFAnnotationBorder::Style::Inset, 2.718);
|
||||
builder.setAnnotationBorder(annotation, 5.0, 3.0, 2.0);
|
||||
builder.setAnnotationColor(annotation, Qt::black);
|
||||
}
|
||||
}
|
||||
|
@ -23,10 +23,10 @@
|
||||
namespace pdf
|
||||
{
|
||||
|
||||
PDFActionPtr PDFAction::parse(const PDFDocument* document, PDFObject object)
|
||||
PDFActionPtr PDFAction::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
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)
|
||||
@ -46,7 +46,7 @@ std::vector<const PDFAction*> PDFAction::getActionList() const
|
||||
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())
|
||||
{
|
||||
@ -56,7 +56,7 @@ PDFActionPtr PDFAction::parseImpl(const PDFDocument* document, PDFObject object,
|
||||
throw PDFException(PDFTranslationContext::tr("Circular dependence in actions found."));
|
||||
}
|
||||
usedReferences.insert(reference);
|
||||
object = document->getObjectByReference(reference);
|
||||
object = storage->getObjectByReference(reference);
|
||||
}
|
||||
|
||||
if (object.isNull())
|
||||
@ -69,34 +69,34 @@ PDFActionPtr PDFAction::parseImpl(const PDFDocument* document, PDFObject object,
|
||||
throw PDFException(PDFTranslationContext::tr("Invalid action."));
|
||||
}
|
||||
|
||||
PDFDocumentDataLoaderDecorator loader(document);
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
const PDFDictionary* dictionary = object.getDictionary();
|
||||
QByteArray name = loader.readNameFromDictionary(dictionary, "S");
|
||||
|
||||
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)));
|
||||
}
|
||||
else if (name == "GoToR")
|
||||
{
|
||||
PDFDestination destination = PDFDestination::parse(document, dictionary->get("D"));
|
||||
PDFFileSpecification fileSpecification = PDFFileSpecification::parse(document, dictionary->get("F"));
|
||||
PDFDestination destination = PDFDestination::parse(storage, dictionary->get("D"));
|
||||
PDFFileSpecification fileSpecification = PDFFileSpecification::parse(storage, dictionary->get("F"));
|
||||
return PDFActionPtr(new PDFActionGoToR(qMove(destination), qMove(fileSpecification), loader.readBooleanFromDictionary(dictionary, "NewWindow", false)));
|
||||
}
|
||||
else if (name == "GoToE")
|
||||
{
|
||||
PDFDestination destination = PDFDestination::parse(document, dictionary->get("D"));
|
||||
PDFFileSpecification fileSpecification = PDFFileSpecification::parse(document, dictionary->get("F"));
|
||||
return PDFActionPtr(new PDFActionGoToE(qMove(destination), qMove(fileSpecification), loader.readBooleanFromDictionary(dictionary, "NewWindow", false), document->getObject(dictionary->get("T"))));
|
||||
PDFDestination destination = PDFDestination::parse(storage, dictionary->get("D"));
|
||||
PDFFileSpecification fileSpecification = PDFFileSpecification::parse(storage, dictionary->get("F"));
|
||||
return PDFActionPtr(new PDFActionGoToE(qMove(destination), qMove(fileSpecification), loader.readBooleanFromDictionary(dictionary, "NewWindow", false), storage->getObject(dictionary->get("T"))));
|
||||
}
|
||||
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);
|
||||
PDFActionLaunch::Win win;
|
||||
|
||||
const PDFObject& winDictionaryObject = document->getObject(dictionary->get("Win"));
|
||||
const PDFObject& winDictionaryObject = storage->getObject(dictionary->get("Win"));
|
||||
if (winDictionaryObject.isDictionary())
|
||||
{
|
||||
const PDFDictionary* winDictionary = winDictionaryObject.getDictionary();
|
||||
@ -110,7 +110,7 @@ PDFActionPtr PDFAction::parseImpl(const PDFDocument* document, PDFObject object,
|
||||
}
|
||||
else if (name == "Thread")
|
||||
{
|
||||
PDFFileSpecification fileSpecification = PDFFileSpecification::parse(document, dictionary->get("F"));
|
||||
PDFFileSpecification fileSpecification = PDFFileSpecification::parse(storage, dictionary->get("F"));
|
||||
PDFActionThread::Thread thread;
|
||||
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 isRepeat = loader.readBooleanFromDictionary(dictionary, "Repeat", 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")
|
||||
{
|
||||
@ -220,7 +220,7 @@ PDFActionPtr PDFAction::parseImpl(const PDFDocument* document, PDFObject object,
|
||||
const bool isRadioButtonsPreserved = loader.readBooleanFromDictionary(dictionary, "PreserveRB", true);
|
||||
PDFActionSetOCGState::StateChangeItems items;
|
||||
|
||||
PDFObject stateArrayObject = document->getObject(dictionary->get("State"));
|
||||
PDFObject stateArrayObject = storage->getObject(dictionary->get("State"));
|
||||
if (stateArrayObject.isArray())
|
||||
{
|
||||
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"))
|
||||
{
|
||||
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())
|
||||
{
|
||||
javascript = PDFEncoding::convertTextString(javascriptObject.getString());
|
||||
}
|
||||
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)));
|
||||
}
|
||||
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")
|
||||
{
|
||||
@ -283,14 +283,14 @@ PDFActionPtr PDFAction::parseImpl(const PDFDocument* document, PDFObject object,
|
||||
else if (name == "JavaScript")
|
||||
{
|
||||
QByteArray textJavaScript;
|
||||
const PDFObject& javaScriptObject = document->getObject(dictionary->get("JS"));
|
||||
const PDFObject& javaScriptObject = storage->getObject(dictionary->get("JS"));
|
||||
if (javaScriptObject.isString())
|
||||
{
|
||||
textJavaScript = javaScriptObject.getString();
|
||||
}
|
||||
else if (javaScriptObject.isStream())
|
||||
{
|
||||
textJavaScript = document->getDecodedStream(javaScriptObject.getStream());
|
||||
textJavaScript = storage->getDecodedStream(javaScriptObject.getStream());
|
||||
}
|
||||
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;
|
||||
object = document->getObject(object);
|
||||
object = storage->getObject(object);
|
||||
|
||||
if (object.isName() || object.isString())
|
||||
{
|
||||
@ -330,7 +330,7 @@ PDFDestination PDFDestination::parse(const PDFDocument* document, PDFObject obje
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFDocumentDataLoaderDecorator loader(document);
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
|
||||
// First parse page number/page index
|
||||
PDFObject pageNumberObject = array->getItem(0);
|
||||
|
@ -34,6 +34,7 @@ namespace pdf
|
||||
{
|
||||
class PDFAction;
|
||||
class PDFDocument;
|
||||
class PDFObjectStorage;
|
||||
|
||||
enum class ActionType
|
||||
{
|
||||
@ -87,9 +88,9 @@ public:
|
||||
|
||||
/// Parses the destination from the object. If object contains invalid destination,
|
||||
/// then empty destination is returned. If object is empty, empty destination is returned.
|
||||
/// \param document Document
|
||||
/// \param storage Object storage
|
||||
/// \param object Destination object
|
||||
static PDFDestination parse(const PDFDocument* document, PDFObject object);
|
||||
static PDFDestination parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
private:
|
||||
DestinationType m_destinationType = DestinationType::Invalid;
|
||||
@ -120,9 +121,9 @@ public:
|
||||
|
||||
/// Tries to parse the action. If serious error occurs, then exception is thrown.
|
||||
/// If \p object is null object, then nullptr is returned.
|
||||
/// \param document Document
|
||||
/// \param storage Object storage
|
||||
/// \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
|
||||
/// the 'Next' entry, as described by PDF 1.7 specification.
|
||||
@ -132,7 +133,7 @@ public:
|
||||
std::vector<const PDFAction*> getActionList() const;
|
||||
|
||||
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;
|
||||
|
||||
|
@ -22,21 +22,22 @@
|
||||
#include "pdfdrawspacecontroller.h"
|
||||
#include "pdfcms.h"
|
||||
#include "pdfwidgetutils.h"
|
||||
#include "pdfpagecontentprocessor.h"
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
|
||||
PDFAnnotationBorder PDFAnnotationBorder::parseBorder(const PDFDocument* document, PDFObject object)
|
||||
PDFAnnotationBorder PDFAnnotationBorder::parseBorder(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
PDFAnnotationBorder result;
|
||||
object = document->getObject(object);
|
||||
object = storage->getObject(object);
|
||||
|
||||
if (object.isArray())
|
||||
{
|
||||
const PDFArray* array = object.getArray();
|
||||
if (array->getCount() >= 3)
|
||||
{
|
||||
PDFDocumentDataLoaderDecorator loader(document);
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
result.m_definition = Definition::Simple;
|
||||
result.m_hCornerRadius = loader.readNumber(array->getItem(0), 0.0);
|
||||
result.m_vCornerRadius = loader.readNumber(array->getItem(1), 0.0);
|
||||
@ -52,13 +53,13 @@ PDFAnnotationBorder PDFAnnotationBorder::parseBorder(const PDFDocument* document
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFAnnotationBorder PDFAnnotationBorder::parseBS(const PDFDocument* document, PDFObject object)
|
||||
PDFAnnotationBorder PDFAnnotationBorder::parseBS(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
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_width = loader.readNumberFromDictionary(dictionary, "W", 1.0);
|
||||
|
||||
@ -76,13 +77,13 @@ PDFAnnotationBorder PDFAnnotationBorder::parseBS(const PDFDocument* document, PD
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFAnnotationBorderEffect PDFAnnotationBorderEffect::parse(const PDFDocument* document, PDFObject object)
|
||||
PDFAnnotationBorderEffect PDFAnnotationBorderEffect::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
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);
|
||||
|
||||
constexpr const std::array<std::pair<const char*, Effect>, 2> effects = {
|
||||
@ -96,16 +97,16 @@ PDFAnnotationBorderEffect PDFAnnotationBorderEffect::parse(const PDFDocument* do
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFAppeareanceStreams PDFAppeareanceStreams::parse(const PDFDocument* document, PDFObject object)
|
||||
PDFAppeareanceStreams PDFAppeareanceStreams::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
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())
|
||||
{
|
||||
const PDFDictionary* subdictionary = document->getDictionaryFromObject(subdictionaryObject);
|
||||
const PDFDictionary* subdictionary = storage->getDictionaryFromObject(subdictionaryObject);
|
||||
for (size_t i = 0; i < subdictionary->getCount(); ++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::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;
|
||||
|
||||
const PDFDictionary* dictionary = document->getDictionaryFromObject(object);
|
||||
const PDFDictionary* dictionary = storage->getDictionaryFromObject(object);
|
||||
if (!dictionary)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFDocumentDataLoaderDecorator loader(document);
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
|
||||
QRectF annotationsRectangle = loader.readRectangle(dictionary->get("Rect"), QRectF());
|
||||
|
||||
@ -189,13 +200,13 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
||||
PDFLinkAnnotation* linkAnnotation = new PDFLinkAnnotation;
|
||||
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)
|
||||
{
|
||||
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_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 = {
|
||||
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_activationRegion = parseQuadrilaterals(document, dictionary->get("QuadPoints"), annotationsRectangle);
|
||||
linkAnnotation->m_activationRegion = parseQuadrilaterals(storage, dictionary->get("QuadPoints"), annotationsRectangle);
|
||||
}
|
||||
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_justification = static_cast<PDFFreeTextAnnotation::Justification>(loader.readIntegerFromDictionary(dictionary, "Q", 0));
|
||||
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_effect = PDFAnnotationBorderEffect::parse(document, dictionary->get("BE"));
|
||||
freeTextAnnotation->m_effect = PDFAnnotationBorderEffect::parse(storage, dictionary->get("BE"));
|
||||
|
||||
std::vector<PDFReal> differenceRectangle = loader.readNumberArrayFromDictionary(dictionary, "RD");
|
||||
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_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_measureDictionary = document->getObject(dictionary->get("Measure"));
|
||||
lineAnnotation->m_measureDictionary = storage->getObject(dictionary->get("Measure"));
|
||||
|
||||
std::vector<PDFReal> captionOffset = loader.readNumberArrayFromDictionary(dictionary, "CO");
|
||||
if (captionOffset.size() == 2)
|
||||
@ -280,7 +291,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
||||
result.reset(annotation);
|
||||
|
||||
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");
|
||||
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_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 = {
|
||||
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_measure = document->getObject(dictionary->get("Measure"));
|
||||
annotation->m_measure = storage->getObject(dictionary->get("Measure"));
|
||||
}
|
||||
else if (subtype == "Highlight" ||
|
||||
subtype == "Underline" ||
|
||||
@ -346,7 +357,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
||||
PDFHighlightAnnotation* annotation = new PDFHighlightAnnotation(type);
|
||||
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")
|
||||
{
|
||||
@ -394,7 +405,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
||||
PDFInkAnnotation* annotation = new PDFInkAnnotation();
|
||||
result.reset(annotation);
|
||||
|
||||
PDFObject inkList = document->getObject(dictionary->get("InkList"));
|
||||
PDFObject inkList = storage->getObject(dictionary->get("InkList"));
|
||||
if (inkList.isArray())
|
||||
{
|
||||
const PDFArray* inkListArray = inkList.getArray();
|
||||
@ -432,7 +443,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
||||
PDFFileAttachmentAnnotation* annotation = new PDFFileAttachmentAnnotation();
|
||||
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 = {
|
||||
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();
|
||||
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 = {
|
||||
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);
|
||||
|
||||
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())
|
||||
{
|
||||
annotation->m_playMovie = activation.getBool();
|
||||
@ -473,7 +484,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
||||
else if (activation.isDictionary())
|
||||
{
|
||||
annotation->m_playMovie = true;
|
||||
annotation->m_movieActivation = PDFMovieActivation::parse(document, activation);
|
||||
annotation->m_movieActivation = PDFMovieActivation::parse(storage, activation);
|
||||
}
|
||||
}
|
||||
else if (subtype == "Screen")
|
||||
@ -482,9 +493,9 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
||||
result.reset(annotation);
|
||||
|
||||
annotation->m_screenTitle = loader.readTextStringFromDictionary(dictionary, "T", QString());
|
||||
annotation->m_appearanceCharacteristics = PDFAnnotationAppearanceCharacteristics::parse(document, dictionary->get("MK"));
|
||||
annotation->m_action = PDFAction::parse(document, dictionary->get("A"));
|
||||
annotation->m_additionalActions = PDFAnnotationAdditionalActions::parse(document, dictionary->get("AA"));
|
||||
annotation->m_appearanceCharacteristics = PDFAnnotationAppearanceCharacteristics::parse(storage, dictionary->get("MK"));
|
||||
annotation->m_action = PDFAction::parse(storage, dictionary->get("A"));
|
||||
annotation->m_additionalActions = PDFAnnotationAdditionalActions::parse(storage, dictionary->get("AA"));
|
||||
}
|
||||
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_appearanceCharacteristics = PDFAnnotationAppearanceCharacteristics::parse(document, dictionary->get("MK"));
|
||||
annotation->m_action = PDFAction::parse(document, dictionary->get("A"));
|
||||
annotation->m_additionalActions = PDFAnnotationAdditionalActions::parse(document, dictionary->get("AA"));
|
||||
annotation->m_appearanceCharacteristics = PDFAnnotationAppearanceCharacteristics::parse(storage, dictionary->get("MK"));
|
||||
annotation->m_action = PDFAction::parse(storage, dictionary->get("A"));
|
||||
annotation->m_additionalActions = PDFAnnotationAdditionalActions::parse(storage, dictionary->get("AA"));
|
||||
}
|
||||
else if (subtype == "PrinterMark")
|
||||
{
|
||||
@ -519,7 +530,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject obj
|
||||
PDFWatermarkAnnotation* annotation = new PDFWatermarkAnnotation();
|
||||
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_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_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_annotationBorder = PDFAnnotationBorder::parseBS(document, dictionary->get("BS"));
|
||||
result->m_annotationBorder = PDFAnnotationBorder::parseBS(storage, dictionary->get("BS"));
|
||||
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_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_replyType = (loader.readNameFromDictionary(dictionary, "RT") == "Group") ? PDFMarkupAnnotation::ReplyType::Group : PDFMarkupAnnotation::ReplyType::Reply;
|
||||
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;
|
||||
}
|
||||
|
||||
PDFAnnotationQuadrilaterals PDFAnnotation::parseQuadrilaterals(const PDFDocument* document, PDFObject quadrilateralsObject, const QRectF annotationRect)
|
||||
PDFAnnotationQuadrilaterals PDFAnnotation::parseQuadrilaterals(const PDFObjectStorage* storage, PDFObject quadrilateralsObject, const QRectF annotationRect)
|
||||
{
|
||||
QPainterPath path;
|
||||
std::vector<QLineF> underlines;
|
||||
|
||||
PDFDocumentDataLoaderDecorator loader(document);
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
std::vector<PDFReal> points = loader.readNumberArray(quadrilateralsObject);
|
||||
const size_t quadrilateralCount = points.size() % 8;
|
||||
path.reserve(int(quadrilateralCount) + 5);
|
||||
@ -639,9 +650,89 @@ AnnotationLineEnding PDFAnnotation::convertNameToLineEnding(const QByteArray& na
|
||||
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);
|
||||
|
||||
switch (points.size())
|
||||
@ -659,13 +750,13 @@ PDFAnnotationCalloutLine PDFAnnotationCalloutLine::parse(const PDFDocument* docu
|
||||
return PDFAnnotationCalloutLine();
|
||||
}
|
||||
|
||||
PDFAnnotationAppearanceCharacteristics PDFAnnotationAppearanceCharacteristics::parse(const PDFDocument* document, PDFObject object)
|
||||
PDFAnnotationAppearanceCharacteristics PDFAnnotationAppearanceCharacteristics::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
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_borderColor = loader.readNumberArrayFromDictionary(dictionary, "BC");
|
||||
@ -673,22 +764,22 @@ PDFAnnotationAppearanceCharacteristics PDFAnnotationAppearanceCharacteristics::p
|
||||
result.m_normalCaption = loader.readTextStringFromDictionary(dictionary, "CA", QString());
|
||||
result.m_rolloverCaption = loader.readTextStringFromDictionary(dictionary, "RC", QString());
|
||||
result.m_downCaption = loader.readTextStringFromDictionary(dictionary, "AC", QString());
|
||||
result.m_normalIcon = document->getObject(dictionary->get("I"));
|
||||
result.m_rolloverIcon = document->getObject(dictionary->get("RI"));
|
||||
result.m_downIcon = document->getObject(dictionary->get("IX"));
|
||||
result.m_iconFit = PDFAnnotationIconFitInfo::parse(document, dictionary->get("IF"));
|
||||
result.m_normalIcon = storage->getObject(dictionary->get("I"));
|
||||
result.m_rolloverIcon = storage->getObject(dictionary->get("RI"));
|
||||
result.m_downIcon = storage->getObject(dictionary->get("IX"));
|
||||
result.m_iconFit = PDFAnnotationIconFitInfo::parse(storage, dictionary->get("IF"));
|
||||
result.m_pushButtonMode = static_cast<PushButtonMode>(loader.readIntegerFromDictionary(dictionary, "TP", PDFInteger(PDFAnnotationAppearanceCharacteristics::PushButtonMode::NoIcon)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFAnnotationIconFitInfo PDFAnnotationIconFitInfo::parse(const PDFDocument* document, PDFObject object)
|
||||
PDFAnnotationIconFitInfo PDFAnnotationIconFitInfo::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
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 = {
|
||||
std::pair<const char*, PDFAnnotationIconFitInfo::ScaleCondition>{ "A", PDFAnnotationIconFitInfo::ScaleCondition::Always },
|
||||
@ -717,22 +808,22 @@ PDFAnnotationIconFitInfo PDFAnnotationIconFitInfo::parse(const PDFDocument* docu
|
||||
return info;
|
||||
}
|
||||
|
||||
PDFAnnotationAdditionalActions PDFAnnotationAdditionalActions::parse(const PDFDocument* document, PDFObject object)
|
||||
PDFAnnotationAdditionalActions PDFAnnotationAdditionalActions::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
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[CursorLeave] = PDFAction::parse(document, dictionary->get("X"));
|
||||
result.m_actions[MousePressed] = PDFAction::parse(document, dictionary->get("D"));
|
||||
result.m_actions[MouseReleased] = PDFAction::parse(document, dictionary->get("U"));
|
||||
result.m_actions[FocusIn] = PDFAction::parse(document, dictionary->get("Fo"));
|
||||
result.m_actions[FocusOut] = PDFAction::parse(document, dictionary->get("Bl"));
|
||||
result.m_actions[PageOpened] = PDFAction::parse(document, dictionary->get("PO"));
|
||||
result.m_actions[PageClosed] = PDFAction::parse(document, dictionary->get("PC"));
|
||||
result.m_actions[PageShow] = PDFAction::parse(document, dictionary->get("PV"));
|
||||
result.m_actions[PageHide] = PDFAction::parse(document, dictionary->get("PI"));
|
||||
result.m_actions[CursorEnter] = PDFAction::parse(storage, dictionary->get("E"));
|
||||
result.m_actions[CursorLeave] = PDFAction::parse(storage, dictionary->get("X"));
|
||||
result.m_actions[MousePressed] = PDFAction::parse(storage, dictionary->get("D"));
|
||||
result.m_actions[MouseReleased] = PDFAction::parse(storage, dictionary->get("U"));
|
||||
result.m_actions[FocusIn] = PDFAction::parse(storage, dictionary->get("Fo"));
|
||||
result.m_actions[FocusOut] = PDFAction::parse(storage, dictionary->get("Bl"));
|
||||
result.m_actions[PageOpened] = PDFAction::parse(storage, dictionary->get("PO"));
|
||||
result.m_actions[PageClosed] = PDFAction::parse(storage, dictionary->get("PC"));
|
||||
result.m_actions[PageShow] = PDFAction::parse(storage, dictionary->get("PV"));
|
||||
result.m_actions[PageHide] = PDFAction::parse(storage, dictionary->get("PI"));
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -931,7 +1022,7 @@ PDFAnnotationManager::PageAnnotations& PDFAnnotationManager::getPageAnnotations(
|
||||
annotations.annotations.reserve(pageAnnotations.size());
|
||||
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)
|
||||
{
|
||||
PageAnnotation annotation;
|
||||
@ -956,4 +1047,78 @@ void PDFAnnotationManager::setTarget(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
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
class PDFDocument;
|
||||
class PDFObjectStorage;
|
||||
class PDFDrawWidgetProxy;
|
||||
|
||||
using TextAlignment = Qt::Alignment;
|
||||
@ -105,15 +105,15 @@ public:
|
||||
|
||||
/// 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.
|
||||
/// \param document Document
|
||||
/// \param storage Object storage
|
||||
/// \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,
|
||||
/// 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
|
||||
static PDFAnnotationBorder parseBS(const PDFDocument* document, PDFObject object);
|
||||
static PDFAnnotationBorder parseBS(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
/// Returns true, if object is correctly defined
|
||||
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,
|
||||
/// 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
|
||||
static PDFAnnotationBorderEffect parse(const PDFDocument* document, PDFObject object);
|
||||
static PDFAnnotationBorderEffect parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
private:
|
||||
Effect m_effect = Effect::None;
|
||||
@ -179,9 +179,9 @@ public:
|
||||
|
||||
/// Parses annotation appearance streams from the object. If object is invalid, then
|
||||
/// empty appearance stream is constructed.
|
||||
/// \param document Document
|
||||
/// \param storage Object storage
|
||||
/// \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,
|
||||
/// then null object is returned.
|
||||
@ -248,9 +248,9 @@ public:
|
||||
|
||||
/// Parses annotation callout line from the object. If object is invalid, then
|
||||
/// invalid callout line is constructed.
|
||||
/// \param document Document
|
||||
/// \param storage Object storage
|
||||
/// \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; }
|
||||
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
|
||||
/// default appearance icon fit info is constructed.
|
||||
/// \param document Document
|
||||
/// \param storage Object storage
|
||||
/// \param object Appearance icon fit info object
|
||||
static PDFAnnotationIconFitInfo parse(const PDFDocument* document, PDFObject object);
|
||||
static PDFAnnotationIconFitInfo parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
private:
|
||||
ScaleCondition m_scaleCondition = ScaleCondition::Always;
|
||||
@ -329,9 +329,9 @@ public:
|
||||
|
||||
/// Parses annotation appearance characteristics from the object. If object is invalid, then
|
||||
/// default appearance characteristics is constructed.
|
||||
/// \param document Document
|
||||
/// \param storage Object storage
|
||||
/// \param object Appearance characteristics object
|
||||
static PDFAnnotationAppearanceCharacteristics parse(const PDFDocument* document, PDFObject object);
|
||||
static PDFAnnotationAppearanceCharacteristics parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
private:
|
||||
PDFInteger m_rotation = 0;
|
||||
@ -376,9 +376,9 @@ public:
|
||||
|
||||
/// Parses annotation additional actions from the object. If object is invalid, then
|
||||
/// empty additional actions is constructed.
|
||||
/// \param document Document
|
||||
/// \param storage Object storage
|
||||
/// \param object Additional actions object
|
||||
static PDFAnnotationAdditionalActions parse(const PDFDocument* document, PDFObject object);
|
||||
static PDFAnnotationAdditionalActions parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
private:
|
||||
std::array<PDFActionPtr, End> m_actions;
|
||||
@ -390,6 +390,22 @@ class PDFTextAnnotation;
|
||||
|
||||
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.
|
||||
/// Annotations are various enhancements to pages graphical representation,
|
||||
/// such as graphics, text, highlight or multimedia content, such as sounds,
|
||||
@ -421,6 +437,17 @@ public:
|
||||
virtual PDFMarkupAnnotation* asMarkupAnnotation() { 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 QString& getContents() const { return m_contents; }
|
||||
PDFObjectReference getPageReference() const { return m_pageReference; }
|
||||
@ -436,24 +463,39 @@ public:
|
||||
PDFObjectReference getOptionalContent() const { return m_optionalContentReference; }
|
||||
|
||||
/// Parses annotation from the object. If error occurs, then nullptr is returned.
|
||||
/// \param document Document
|
||||
/// \param storage Object storage
|
||||
/// \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,
|
||||
/// then annotation rectangle is used. If annotation rectangle is also invalid,
|
||||
/// then empty painter path is used.
|
||||
/// \param document Document
|
||||
/// \param storage Object storage
|
||||
/// \param quadrilateralsObject Object with quadrilaterals definition
|
||||
/// \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,
|
||||
/// then None line ending is returned.
|
||||
/// \param name Name of the line ending
|
||||
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:
|
||||
|
||||
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
|
||||
PDFObjectReference m_pageReference; ///< Reference to annotation's page, "P" entry
|
||||
@ -497,8 +539,12 @@ public:
|
||||
const QByteArray& getIntent() const { return m_intent; }
|
||||
const PDFObject& getExternalData() const { return m_externalData; }
|
||||
|
||||
protected:
|
||||
virtual QColor getStrokeColor() const override;
|
||||
virtual QColor getFillColor() const override;
|
||||
|
||||
private:
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
QString m_windowTitle;
|
||||
PDFObjectReference m_popupAnnotation;
|
||||
@ -541,7 +587,7 @@ public:
|
||||
const QString& getStateModel() const { return m_stateModel; }
|
||||
|
||||
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;
|
||||
QByteArray m_iconName;
|
||||
@ -572,7 +618,7 @@ public:
|
||||
const PDFAnnotationQuadrilaterals& getActivationRegion() const { return m_activationRegion; }
|
||||
|
||||
private:
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
PDFActionPtr m_action;
|
||||
LinkHighlightMode m_highlightMode = LinkHighlightMode::Invert;
|
||||
@ -614,7 +660,7 @@ public:
|
||||
AnnotationLineEnding getEndLineEnding() const { return m_endLineEnding; }
|
||||
|
||||
private:
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
QByteArray m_defaultAppearance;
|
||||
Justification m_justification = Justification::Left;
|
||||
@ -663,7 +709,7 @@ public:
|
||||
const QPointF& getCaptionOffset() const { return m_captionOffset; }
|
||||
|
||||
private:
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
QLineF m_line;
|
||||
AnnotationLineEnding m_startLineEnding = AnnotationLineEnding::None;
|
||||
@ -693,13 +739,17 @@ public:
|
||||
}
|
||||
|
||||
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 PDFAnnotationBorderEffect& getBorderEffect() const { return m_effect; }
|
||||
const QRectF& getGeometryRectangle() const { return m_geometryRectangle; }
|
||||
|
||||
protected:
|
||||
virtual QColor getFillColor() const override;
|
||||
|
||||
private:
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
AnnotationType m_type;
|
||||
std::vector<PDFReal> m_interiorColor;
|
||||
@ -738,7 +788,7 @@ public:
|
||||
const PDFObject& getMeasure() const { return m_measure; }
|
||||
|
||||
private:
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
AnnotationType m_type;
|
||||
std::vector<QPointF> m_vertices;
|
||||
@ -766,7 +816,7 @@ public:
|
||||
const PDFAnnotationQuadrilaterals& getHiglightArea() const { return m_highlightArea; }
|
||||
|
||||
private:
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
AnnotationType m_type;
|
||||
PDFAnnotationQuadrilaterals m_highlightArea;
|
||||
@ -790,7 +840,7 @@ public:
|
||||
Symbol getSymbol() const { return m_symbol; }
|
||||
|
||||
private:
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
QRectF m_caretRectangle;
|
||||
Symbol m_symbol = Symbol::None;
|
||||
@ -826,7 +876,7 @@ public:
|
||||
Stamp getStamp() const { return m_stamp; }
|
||||
|
||||
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;
|
||||
};
|
||||
@ -842,7 +892,7 @@ public:
|
||||
const QPainterPath& getInkPath() const { return m_inkPath; }
|
||||
|
||||
private:
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
QPainterPath m_inkPath;
|
||||
};
|
||||
@ -860,7 +910,7 @@ public:
|
||||
bool isOpened() const { return m_opened; }
|
||||
|
||||
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;
|
||||
};
|
||||
@ -887,7 +937,7 @@ public:
|
||||
Icon getIcon() const { return m_icon; }
|
||||
|
||||
private:
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
PDFFileSpecification m_fileSpecification;
|
||||
Icon m_icon = Icon::PushPin;
|
||||
@ -912,7 +962,7 @@ public:
|
||||
Icon getIcon() const { return m_icon; }
|
||||
|
||||
private:
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
PDFSound m_sound;
|
||||
Icon m_icon = Icon::Speaker;
|
||||
@ -933,7 +983,7 @@ public:
|
||||
const PDFMovieActivation& getMovieActivation() const { return m_movieActivation; }
|
||||
|
||||
private:
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
QString m_movieTitle;
|
||||
bool m_playMovie = true;
|
||||
@ -956,7 +1006,7 @@ public:
|
||||
const PDFAnnotationAdditionalActions& getAdditionalActions() const { return m_additionalActions; }
|
||||
|
||||
private:
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
QString m_screenTitle;
|
||||
PDFAnnotationAppearanceCharacteristics m_appearanceCharacteristics;
|
||||
@ -989,7 +1039,7 @@ public:
|
||||
const PDFAnnotationAdditionalActions& getAdditionalActions() const { return m_additionalActions; }
|
||||
|
||||
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;
|
||||
PDFAnnotationAppearanceCharacteristics m_appearanceCharacteristics;
|
||||
@ -1031,7 +1081,7 @@ public:
|
||||
PDFReal getRelativeVerticalOffset() const { return m_relativeVerticalOffset; }
|
||||
|
||||
private:
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFDocument* document, PDFObject object);
|
||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
QMatrix m_matrix;
|
||||
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"));
|
||||
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())
|
||||
{
|
||||
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")))
|
||||
{
|
||||
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())
|
||||
{
|
||||
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_javaScriptActions = PDFNameTreeLoader<PDFActionPtr>::parse(document, namesDictionary->get("JavaScript"), &PDFAction::parse);
|
||||
catalogObject.m_embeddedFiles = PDFNameTreeLoader<PDFFileSpecification>::parse(document, namesDictionary->get("EmbeddedFiles"), &PDFFileSpecification::parse);
|
||||
catalogObject.m_destinations = PDFNameTreeLoader<PDFDestination>::parse(&document->getStorage(), namesDictionary->get("Dests"), parseDestination);
|
||||
catalogObject.m_javaScriptActions = PDFNameTreeLoader<PDFActionPtr>::parse(&document->getStorage(), namesDictionary->get("JavaScript"), &PDFAction::parse);
|
||||
catalogObject.m_embeddedFiles = PDFNameTreeLoader<PDFFileSpecification>::parse(&document->getStorage(), namesDictionary->get("EmbeddedFiles"), &PDFFileSpecification::parse);
|
||||
}
|
||||
|
||||
// Examine "Dests" dictionary
|
||||
@ -158,7 +158,7 @@ PDFCatalog PDFCatalog::parse(const PDFObject& catalog, const PDFDocument* docume
|
||||
const size_t count = destsDictionary->getCount();
|
||||
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_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
|
||||
{
|
||||
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
|
||||
@ -242,9 +247,15 @@ void PDFObjectStorage::updateTrailerDictionary(PDFObject trailerDictionary)
|
||||
m_trailerDictionary = PDFObjectManipulator::merge(m_trailerDictionary, trailerDictionary, PDFObjectManipulator::RemoveNullObjects);
|
||||
}
|
||||
|
||||
PDFDocumentDataLoaderDecorator::PDFDocumentDataLoaderDecorator(const PDFDocument* document)
|
||||
: m_storage(&document->getStorage())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QByteArray PDFDocumentDataLoaderDecorator::readName(const PDFObject& object)
|
||||
{
|
||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
||||
const PDFObject& dereferencedObject = m_storage->getObject(object);
|
||||
if (dereferencedObject.isName())
|
||||
{
|
||||
return dereferencedObject.getString();
|
||||
@ -255,7 +266,7 @@ QByteArray PDFDocumentDataLoaderDecorator::readName(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())
|
||||
{
|
||||
return dereferencedObject.getString();
|
||||
@ -266,7 +277,7 @@ QByteArray PDFDocumentDataLoaderDecorator::readString(const PDFObject& object)
|
||||
|
||||
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())
|
||||
{
|
||||
return dereferencedObject.getInteger();
|
||||
@ -277,7 +288,7 @@ PDFInteger PDFDocumentDataLoaderDecorator::readInteger(const PDFObject& object,
|
||||
|
||||
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())
|
||||
{
|
||||
@ -292,7 +303,7 @@ PDFReal PDFDocumentDataLoaderDecorator::readNumber(const PDFObject& object, PDFR
|
||||
|
||||
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())
|
||||
{
|
||||
@ -304,7 +315,7 @@ bool PDFDocumentDataLoaderDecorator::readBoolean(const PDFObject& object, bool d
|
||||
|
||||
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())
|
||||
{
|
||||
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
|
||||
{
|
||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
||||
const PDFObject& dereferencedObject = m_storage->getObject(object);
|
||||
if (dereferencedObject.isArray())
|
||||
{
|
||||
const PDFArray* array = dereferencedObject.getArray();
|
||||
@ -324,7 +335,7 @@ QRectF PDFDocumentDataLoaderDecorator::readRectangle(const PDFObject& object, co
|
||||
std::array<PDFReal, 4> items;
|
||||
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())
|
||||
{
|
||||
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
|
||||
{
|
||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
||||
const PDFObject& dereferencedObject = m_storage->getObject(object);
|
||||
if (dereferencedObject.isArray())
|
||||
{
|
||||
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
|
||||
{
|
||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
||||
const PDFObject& dereferencedObject = m_storage->getObject(object);
|
||||
if (dereferencedObject.isArray())
|
||||
{
|
||||
const PDFArray* array = dereferencedObject.getArray();
|
||||
@ -512,7 +523,7 @@ PDFObjectReference PDFDocumentDataLoaderDecorator::readReferenceFromDictionary(c
|
||||
|
||||
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())
|
||||
{
|
||||
const PDFArray* array = dereferencedObject.getArray();
|
||||
@ -544,7 +555,7 @@ std::vector<PDFObjectReference> PDFDocumentDataLoaderDecorator::readReferenceArr
|
||||
|
||||
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())
|
||||
{
|
||||
const PDFArray* array = dereferencedObject.getArray();
|
||||
@ -626,7 +637,7 @@ std::vector<QByteArray> PDFDocumentDataLoaderDecorator::readStringArrayFromDicti
|
||||
|
||||
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())
|
||||
{
|
||||
const PDFArray* array = dereferencedObject.getArray();
|
||||
|
@ -69,6 +69,20 @@ public:
|
||||
/// then null object is returned (no exception is thrown).
|
||||
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
|
||||
const PDFObjects& getObjects() const { return m_objects; }
|
||||
|
||||
@ -98,6 +112,11 @@ public:
|
||||
/// \param trailerDictionary New trailer dictionary
|
||||
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:
|
||||
PDFObjects m_objects;
|
||||
PDFObject m_trailerDictionary;
|
||||
@ -112,7 +131,8 @@ private:
|
||||
class PDFDocumentDataLoaderDecorator
|
||||
{
|
||||
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;
|
||||
|
||||
/// 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>
|
||||
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())
|
||||
{
|
||||
QByteArray name = dereferencedObject.getString();
|
||||
@ -184,7 +204,7 @@ public:
|
||||
template<typename T>
|
||||
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())
|
||||
{
|
||||
const PDFArray* array = dereferencedObject.getArray();
|
||||
@ -318,7 +338,7 @@ public:
|
||||
std::vector<QByteArray> readStringArrayFromDictionary(const PDFDictionary* dictionary, const char* key) const;
|
||||
|
||||
private:
|
||||
const PDFDocument* m_document;
|
||||
const PDFObjectStorage* m_storage;
|
||||
};
|
||||
|
||||
/// PDF document main class.
|
||||
@ -458,6 +478,40 @@ const PDFObject& PDFDocument::getObjectByReference(PDFObjectReference 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
|
||||
|
||||
#endif // PDFDOCUMENT_H
|
||||
|
@ -18,10 +18,165 @@
|
||||
#include "pdfdocumentbuilder.h"
|
||||
#include "pdfencoding.h"
|
||||
#include "pdfconstants.h"
|
||||
#include "pdfdocumentreader.h"
|
||||
#include "pdfvisitor.h"
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QPainter>
|
||||
#include <QPdfWriter>
|
||||
|
||||
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()
|
||||
{
|
||||
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)));
|
||||
}
|
||||
|
||||
PDFObjectFactory& PDFObjectFactory::operator<<(const PDFObject& object)
|
||||
{
|
||||
addObject(object);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PDFObjectFactory& PDFObjectFactory::operator<<(AnnotationBorderStyle 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()) };
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return m_storage.addObject(PDFObjectManipulator::removeNullObjects(object));
|
||||
@ -585,6 +897,134 @@ void PDFDocumentBuilder::updateDocumentInfo(PDFObject 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 */
|
||||
|
||||
PDFObjectReference PDFDocumentBuilder::appendPage(QRectF mediaBox)
|
||||
@ -701,6 +1141,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationCircle(PDFObjectReference
|
||||
objectBuilder.endDictionary();
|
||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||
appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;
|
||||
}
|
||||
|
||||
@ -762,6 +1203,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationFreeText(PDFObjectReferen
|
||||
objectBuilder.endDictionary();
|
||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||
appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;
|
||||
}
|
||||
|
||||
@ -845,6 +1287,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationFreeText(PDFObjectReferen
|
||||
objectBuilder.endDictionary();
|
||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||
appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;
|
||||
}
|
||||
|
||||
@ -908,6 +1351,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationHighlight(PDFObjectRefere
|
||||
objectBuilder.endDictionary();
|
||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||
appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;
|
||||
}
|
||||
|
||||
@ -956,6 +1400,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationHighlight(PDFObjectRefere
|
||||
objectBuilder.endDictionary();
|
||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||
appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;
|
||||
}
|
||||
|
||||
@ -1042,6 +1487,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationLine(PDFObjectReference p
|
||||
objectBuilder.endDictionary();
|
||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||
appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;
|
||||
}
|
||||
|
||||
@ -1148,6 +1594,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationLine(PDFObjectReference p
|
||||
objectBuilder.endDictionary();
|
||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||
appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;
|
||||
}
|
||||
|
||||
@ -1189,6 +1636,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationLink(PDFObjectReference p
|
||||
objectBuilder.endDictionary();
|
||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||
appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationReference);
|
||||
return annotationReference;
|
||||
}
|
||||
|
||||
@ -1271,6 +1719,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationPolygon(PDFObjectReferenc
|
||||
objectBuilder.endDictionary();
|
||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||
appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;
|
||||
}
|
||||
|
||||
@ -1350,6 +1799,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationPolyline(PDFObjectReferen
|
||||
objectBuilder.endDictionary();
|
||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||
appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;
|
||||
}
|
||||
|
||||
@ -1389,6 +1839,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationPopup(PDFObjectReference
|
||||
objectBuilder.endDictionary();
|
||||
PDFObject upgradedParentAnnotation = objectBuilder.takeObject();
|
||||
mergeTo(parentAnnotation, upgradedParentAnnotation);
|
||||
updateAnnotationAppearanceStreams(popupAnnotation);
|
||||
return popupAnnotation;
|
||||
}
|
||||
|
||||
@ -1457,6 +1908,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationSquare(PDFObjectReference
|
||||
objectBuilder.endDictionary();
|
||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||
appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;
|
||||
}
|
||||
|
||||
@ -1520,6 +1972,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationSquiggly(PDFObjectReferen
|
||||
objectBuilder.endDictionary();
|
||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||
appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;
|
||||
}
|
||||
|
||||
@ -1568,6 +2021,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationSquiggly(PDFObjectReferen
|
||||
objectBuilder.endDictionary();
|
||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||
appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;
|
||||
}
|
||||
|
||||
@ -1631,6 +2085,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationStrikeout(PDFObjectRefere
|
||||
objectBuilder.endDictionary();
|
||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||
appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;
|
||||
}
|
||||
|
||||
@ -1679,6 +2134,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationStrikeout(PDFObjectRefere
|
||||
objectBuilder.endDictionary();
|
||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||
appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;
|
||||
}
|
||||
|
||||
@ -1751,6 +2207,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationText(PDFObjectReference p
|
||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||
mergeTo(annotationObject, updateAnnotationPopup);
|
||||
appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;
|
||||
}
|
||||
|
||||
@ -1814,6 +2271,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationUnderline(PDFObjectRefere
|
||||
objectBuilder.endDictionary();
|
||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||
appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;
|
||||
}
|
||||
|
||||
@ -1862,6 +2320,7 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationUnderline(PDFObjectRefere
|
||||
objectBuilder.endDictionary();
|
||||
PDFObject pageAnnots = objectBuilder.takeObject();
|
||||
appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include "pdfdocument.h"
|
||||
#include "pdfannotation.h"
|
||||
|
||||
class QPdfWriter;
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
|
||||
@ -108,6 +110,7 @@ public:
|
||||
PDFObjectFactory& operator<<(const QPointF& point);
|
||||
PDFObjectFactory& operator<<(const QDateTime& dateTime);
|
||||
PDFObjectFactory& operator<<(AnnotationBorderStyle style);
|
||||
PDFObjectFactory& operator<<(const PDFObject& object);
|
||||
|
||||
/// Treat containers - write them as array
|
||||
template<typename Container, typename ValueType = decltype(*std::begin(std::declval<Container>()))>
|
||||
@ -174,6 +177,63 @@ private:
|
||||
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
|
||||
{
|
||||
public:
|
||||
@ -212,6 +272,11 @@ public:
|
||||
/// Returns annotation bounding rectangle
|
||||
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 */
|
||||
|
||||
/// Appends a new page after last page.
|
||||
@ -763,6 +828,15 @@ private:
|
||||
PDFObjectReference getCatalogReference() const;
|
||||
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;
|
||||
PDFVersion m_version;
|
||||
};
|
||||
|
@ -104,10 +104,10 @@ const PDFEmbeddedFile* PDFFileSpecification::getPlatformFile() const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PDFFileSpecification PDFFileSpecification::parse(const PDFDocument* document, PDFObject object)
|
||||
PDFFileSpecification PDFFileSpecification::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
PDFFileSpecification result;
|
||||
object = document->getObject(object);
|
||||
object = storage->getObject(object);
|
||||
|
||||
if (object.isString())
|
||||
{
|
||||
@ -115,7 +115,7 @@ PDFFileSpecification PDFFileSpecification::parse(const PDFDocument* document, PD
|
||||
}
|
||||
else if (object.isDictionary())
|
||||
{
|
||||
PDFDocumentDataLoaderDecorator loader(document);
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
const PDFDictionary* dictionary = object.getDictionary();
|
||||
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_collection = collectionObject.isReference() ? collectionObject.getReference() : PDFObjectReference();
|
||||
|
||||
PDFObject embeddedFiles = document->getObject(dictionary->get("EF"));
|
||||
PDFObject embeddedFiles = storage->getObject(dictionary->get("EF"));
|
||||
if (embeddedFiles.isDictionary())
|
||||
{
|
||||
const PDFDictionary* embeddedFilesDictionary = embeddedFiles.getDictionary();
|
||||
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;
|
||||
}
|
||||
|
||||
PDFEmbeddedFile PDFEmbeddedFile::parse(const PDFDocument* document, PDFObject object)
|
||||
PDFEmbeddedFile PDFEmbeddedFile::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
PDFEmbeddedFile result;
|
||||
object = document->getObject(object);
|
||||
object = storage->getObject(object);
|
||||
|
||||
if (object.isStream())
|
||||
{
|
||||
const PDFStream* stream = object.getStream();
|
||||
const PDFDictionary* dictionary = stream->getDictionary();
|
||||
PDFDocumentDataLoaderDecorator loader(document);
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
result.m_stream = object;
|
||||
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())
|
||||
{
|
||||
const PDFDictionary* paramsDictionary = paramsObject.getDictionary();
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
class PDFDocument;
|
||||
class PDFObjectStorage;
|
||||
|
||||
class PDFEmbeddedFile
|
||||
{
|
||||
@ -39,7 +39,7 @@ public:
|
||||
const QByteArray& getChecksum() const { return m_checksum; }
|
||||
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:
|
||||
PDFObject m_stream;
|
||||
@ -75,7 +75,7 @@ public:
|
||||
PDFObjectReference getCollection() const { return m_collection; }
|
||||
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:
|
||||
/// Name of the file system used to interpret this file specification,
|
||||
|
@ -23,11 +23,11 @@
|
||||
namespace pdf
|
||||
{
|
||||
|
||||
PDFSound PDFSound::parse(const PDFDocument* document, PDFObject object)
|
||||
PDFSound PDFSound::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
PDFSound result;
|
||||
|
||||
object = document->getObject(object);
|
||||
object = storage->getObject(object);
|
||||
if (object.isStream())
|
||||
{
|
||||
const PDFStream* stream = object.getStream();
|
||||
@ -41,24 +41,24 @@ PDFSound PDFSound::parse(const PDFDocument* document, PDFObject object)
|
||||
};
|
||||
|
||||
// Jakub Melka: parse the sound without exceptions
|
||||
PDFDocumentDataLoaderDecorator loader(document);
|
||||
result.m_fileSpecification = PDFFileSpecification::parse(document, dictionary->get("F"));
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
result.m_fileSpecification = PDFFileSpecification::parse(storage, dictionary->get("F"));
|
||||
result.m_samplingRate = loader.readNumberFromDictionary(dictionary, "R", 0.0);
|
||||
result.m_channels = loader.readIntegerFromDictionary(dictionary, "C", 1);
|
||||
result.m_bitsPerSample = loader.readIntegerFromDictionary(dictionary, "B", 8);
|
||||
result.m_format = loader.readEnumByName(dictionary->get("E"), formats.cbegin(), formats.cend(), Format::Raw);
|
||||
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;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFRendition PDFRendition::parse(const PDFDocument* document, PDFObject object)
|
||||
PDFRendition PDFRendition::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
PDFRendition result;
|
||||
object = document->getObject(object);
|
||||
object = storage->getObject(object);
|
||||
const PDFDictionary* renditionDictionary = nullptr;
|
||||
if (object.isDictionary())
|
||||
{
|
||||
@ -76,17 +76,17 @@ PDFRendition PDFRendition::parse(const PDFDocument* document, PDFObject object)
|
||||
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_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())
|
||||
{
|
||||
const PDFDictionary* dictionary = dictionaryObject.getDictionary();
|
||||
return PDFMediaCriteria::parse(document, dictionary->get("C"));
|
||||
return PDFMediaCriteria::parse(storage, dictionary->get("C"));
|
||||
}
|
||||
|
||||
return PDFMediaCriteria();
|
||||
@ -100,9 +100,9 @@ PDFRendition PDFRendition::parse(const PDFDocument* document, PDFObject object)
|
||||
case Type::Media:
|
||||
{
|
||||
MediaRenditionData data;
|
||||
data.clip = PDFMediaClip::parse(document, renditionDictionary->get("C"));
|
||||
data.playParameters = PDFMediaPlayParameters::parse(document, renditionDictionary->get("P"));
|
||||
data.screenParameters = PDFMediaScreenParameters::parse(document, renditionDictionary->get("SP"));
|
||||
data.clip = PDFMediaClip::parse(storage, renditionDictionary->get("C"));
|
||||
data.playParameters = PDFMediaPlayParameters::parse(storage, renditionDictionary->get("P"));
|
||||
data.screenParameters = PDFMediaScreenParameters::parse(storage, renditionDictionary->get("SP"));
|
||||
|
||||
result.m_data = qMove(data);
|
||||
break;
|
||||
@ -122,22 +122,22 @@ PDFRendition PDFRendition::parse(const PDFDocument* document, PDFObject object)
|
||||
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(-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");
|
||||
if (values.size() == 2)
|
||||
{
|
||||
@ -148,11 +148,11 @@ PDFMediaMinimumScreenSize PDFMediaMinimumScreenSize::parse(const PDFDocument* do
|
||||
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(),
|
||||
loader.readIntegerArrayFromDictionary(dictionary, "L"),
|
||||
loader.readIntegerArrayFromDictionary(dictionary, "H"),
|
||||
@ -164,13 +164,13 @@ PDFMediaSoftwareIdentifier PDFMediaSoftwareIdentifier::parse(const PDFDocument*
|
||||
return PDFMediaSoftwareIdentifier(QByteArray(), { }, { }, true, true, { });
|
||||
}
|
||||
|
||||
PDFMediaCriteria PDFMediaCriteria::parse(const PDFDocument* document, PDFObject object)
|
||||
PDFMediaCriteria PDFMediaCriteria::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (dictionary->hasKey(name))
|
||||
@ -189,15 +189,15 @@ PDFMediaCriteria PDFMediaCriteria::parse(const PDFDocument* document, PDFObject
|
||||
}
|
||||
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"))
|
||||
{
|
||||
criteria.m_minimumScreenSize = PDFMediaMinimumScreenSize::parse(document, dictionary->get("Z"));
|
||||
criteria.m_minimumScreenSize = PDFMediaMinimumScreenSize::parse(storage, dictionary->get("Z"));
|
||||
}
|
||||
if (dictionary->hasKey("V"))
|
||||
{
|
||||
const PDFObject& viewerObject = document->getObject(dictionary->get("V"));
|
||||
const PDFObject& viewerObject = storage->getObject(dictionary->get("V"));
|
||||
if (viewerObject.isArray())
|
||||
{
|
||||
std::vector<PDFMediaSoftwareIdentifier> viewers;
|
||||
@ -205,7 +205,7 @@ PDFMediaCriteria PDFMediaCriteria::parse(const PDFDocument* document, PDFObject
|
||||
viewers.reserve(viewersArray->getCount());
|
||||
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);
|
||||
}
|
||||
@ -228,11 +228,11 @@ PDFMediaCriteria PDFMediaCriteria::parse(const PDFDocument* document, PDFObject
|
||||
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 = {
|
||||
std::pair<const char*, Permission>{ "TEMPNEVER", Permission::Never },
|
||||
std::pair<const char*, Permission>{ "TEMPEXTRACT", Permission::Extract },
|
||||
@ -246,15 +246,15 @@ PDFMediaPermissions PDFMediaPermissions::parse(const PDFDocument* document, PDFO
|
||||
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;
|
||||
|
||||
const PDFObject& playersArrayObject = document->getObject(dictionary->get(key));
|
||||
const PDFObject& playersArrayObject = storage->getObject(dictionary->get(key));
|
||||
if (playersArrayObject.isArray())
|
||||
{
|
||||
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)
|
||||
{
|
||||
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({ }, { }, { });
|
||||
}
|
||||
|
||||
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, { }));
|
||||
}
|
||||
|
||||
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");
|
||||
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) });
|
||||
}
|
||||
@ -310,14 +310,14 @@ PDFMediaOffset PDFMediaOffset::parse(const PDFDocument* document, PDFObject obje
|
||||
return PDFMediaOffset(Type::Invalid, std::monostate());
|
||||
}
|
||||
|
||||
PDFMediaClip PDFMediaClip::parse(const PDFDocument* document, PDFObject object)
|
||||
PDFMediaClip PDFMediaClip::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
MediaClipData clipData;
|
||||
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;
|
||||
while (dictionary)
|
||||
{
|
||||
@ -326,23 +326,23 @@ PDFMediaClip PDFMediaClip::parse(const PDFDocument* document, PDFObject object)
|
||||
{
|
||||
clipData.name = loader.readTextStringFromDictionary(dictionary, "N", QString());
|
||||
|
||||
PDFObject fileSpecificationOrStreamObject = document->getObject(dictionary->get("D"));
|
||||
PDFObject fileSpecificationOrStreamObject = storage->getObject(dictionary->get("D"));
|
||||
if (fileSpecificationOrStreamObject.isStream())
|
||||
{
|
||||
clipData.dataStream = fileSpecificationOrStreamObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
clipData.fileSpecification = PDFFileSpecification::parse(document, fileSpecificationOrStreamObject);
|
||||
clipData.fileSpecification = PDFFileSpecification::parse(storage, fileSpecificationOrStreamObject);
|
||||
}
|
||||
clipData.contentType = loader.readStringFromDictionary(dictionary, "CT");
|
||||
clipData.permissions = PDFMediaPermissions::parse(document, dictionary->get("P"));
|
||||
clipData.alternateTextDescriptions = PDFMediaMultiLanguageTexts::parse(document, dictionary->get("Alt"));
|
||||
clipData.players = PDFMediaPlayers::parse(document, dictionary->get("PL"));
|
||||
clipData.permissions = PDFMediaPermissions::parse(storage, dictionary->get("P"));
|
||||
clipData.alternateTextDescriptions = PDFMediaMultiLanguageTexts::parse(storage, dictionary->get("Alt"));
|
||||
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");
|
||||
}
|
||||
@ -357,16 +357,16 @@ PDFMediaClip PDFMediaClip::parse(const PDFDocument* document, PDFObject object)
|
||||
{
|
||||
MediaSectionData sectionData;
|
||||
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;
|
||||
|
||||
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.offsetEnd = PDFMediaOffset::parse(document, subdictionary->get("E"));
|
||||
result.offsetBegin = PDFMediaOffset::parse(storage, subdictionary->get("B"));
|
||||
result.offsetEnd = PDFMediaOffset::parse(storage, subdictionary->get("E"));
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -384,7 +384,7 @@ PDFMediaClip PDFMediaClip::parse(const PDFDocument* document, PDFObject object)
|
||||
}
|
||||
usedReferences.insert(next.getReference());
|
||||
}
|
||||
dictionary = document->getDictionaryFromObject(next);
|
||||
dictionary = storage->getDictionaryFromObject(next);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -395,21 +395,21 @@ PDFMediaClip PDFMediaClip::parse(const PDFDocument* document, PDFObject object)
|
||||
return PDFMediaClip(qMove(clipData), qMove(sections));
|
||||
}
|
||||
|
||||
PDFMediaMultiLanguageTexts PDFMediaMultiLanguageTexts::parse(const PDFDocument* document, PDFObject object)
|
||||
PDFMediaMultiLanguageTexts PDFMediaMultiLanguageTexts::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
PDFMediaMultiLanguageTexts texts;
|
||||
|
||||
object = document->getObject(object);
|
||||
object = storage->getObject(object);
|
||||
if (object.isArray())
|
||||
{
|
||||
const PDFArray* array = object.getArray();
|
||||
if (array->getCount() % 2 == 0)
|
||||
{
|
||||
PDFDocumentDataLoaderDecorator loader(document);
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
const size_t pairs = array->getCount() / 2;
|
||||
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);
|
||||
|
||||
if (languageName.isString())
|
||||
@ -423,28 +423,28 @@ PDFMediaMultiLanguageTexts PDFMediaMultiLanguageTexts::parse(const PDFDocument*
|
||||
return texts;
|
||||
}
|
||||
|
||||
PDFMediaPlayParameters PDFMediaPlayParameters::parse(const PDFDocument* document, PDFObject object)
|
||||
PDFMediaPlayParameters PDFMediaPlayParameters::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
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;
|
||||
|
||||
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.controllerUserInterface = loader.readBooleanFromDictionary(subdictionary, "C", false);
|
||||
parameters.fitMode = static_cast<FitMode>(loader.readIntegerFromDictionary(subdictionary, "F", 5));
|
||||
parameters.playAutomatically = loader.readBooleanFromDictionary(subdictionary, "A", true);
|
||||
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 = {
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
@ -469,16 +469,16 @@ PDFMediaPlayParameters PDFMediaPlayParameters::parse(const PDFDocument* document
|
||||
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;
|
||||
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.opacity = loader.readNumberFromDictionary(screenDictionary, "O", 1.0);
|
||||
result.monitorSpecification = loader.readIntegerFromDictionary(screenDictionary, "M", 0);
|
||||
@ -486,7 +486,7 @@ PDFMediaScreenParameters PDFMediaScreenParameters::parse(const PDFDocument* docu
|
||||
rgb.resize(3, 1.0);
|
||||
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");
|
||||
sizeArray.resize(2, 0);
|
||||
@ -496,7 +496,7 @@ PDFMediaScreenParameters PDFMediaScreenParameters::parse(const PDFDocument* docu
|
||||
result.floatingWindowHasTitleBar = loader.readBooleanFromDictionary(floatWindowDictionary, "T", true);
|
||||
result.floatingWindowCloseable = loader.readBooleanFromDictionary(floatWindowDictionary, "UC", true);
|
||||
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))
|
||||
{
|
||||
case 0:
|
||||
@ -539,14 +539,14 @@ PDFMediaScreenParameters PDFMediaScreenParameters::parse(const PDFDocument* docu
|
||||
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;
|
||||
|
||||
PDFDocumentDataLoaderDecorator loader(document);
|
||||
result.m_movieFile = PDFFileSpecification::parse(document, dictionary->get("F"));
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
result.m_movieFile = PDFFileSpecification::parse(storage, dictionary->get("F"));
|
||||
std::vector<PDFInteger> windowSizeArray = loader.readIntegerArrayFromDictionary(dictionary, "Aspect");
|
||||
if (windowSizeArray.size() == 2)
|
||||
{
|
||||
@ -554,7 +554,7 @@ PDFMovie PDFMovie::parse(const PDFDocument* document, PDFObject object)
|
||||
}
|
||||
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())
|
||||
{
|
||||
result.m_showPoster = posterObject.getBool();
|
||||
@ -571,13 +571,13 @@ PDFMovie PDFMovie::parse(const PDFDocument* document, PDFObject object)
|
||||
return PDFMovie();
|
||||
}
|
||||
|
||||
PDFMovieActivation PDFMovieActivation::parse(const PDFDocument* document, PDFObject object)
|
||||
PDFMovieActivation PDFMovieActivation::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
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 = {
|
||||
std::pair<const char*, Mode>{ "Once", Mode::Once },
|
||||
@ -597,8 +597,8 @@ PDFMovieActivation PDFMovieActivation::parse(const PDFDocument* document, PDFObj
|
||||
relativePosition.resize(2, 0.5);
|
||||
}
|
||||
|
||||
result.m_start = parseMovieTime(document, dictionary->get("Start"));
|
||||
result.m_duration = parseMovieTime(document, dictionary->get("Duration"));
|
||||
result.m_start = parseMovieTime(storage, dictionary->get("Start"));
|
||||
result.m_duration = parseMovieTime(storage, dictionary->get("Duration"));
|
||||
result.m_rate = loader.readNumberFromDictionary(dictionary, "Rate", 1.0);
|
||||
result.m_volume = loader.readNumberFromDictionary(dictionary, "Volume", 1.0);
|
||||
result.m_showControls = loader.readBooleanFromDictionary(dictionary, "ShowControls", false);
|
||||
@ -612,11 +612,11 @@ PDFMovieActivation PDFMovieActivation::parse(const PDFDocument* document, PDFObj
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFMovieActivation::MovieTime PDFMovieActivation::parseMovieTime(const PDFDocument* document, PDFObject object)
|
||||
PDFMovieActivation::MovieTime PDFMovieActivation::parseMovieTime(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
MovieTime result;
|
||||
|
||||
object = document->getObject(object);
|
||||
object = storage->getObject(object);
|
||||
if (object.isInt())
|
||||
{
|
||||
result.value = object.getInteger();
|
||||
@ -630,10 +630,10 @@ PDFMovieActivation::MovieTime PDFMovieActivation::parseMovieTime(const PDFDocume
|
||||
const PDFArray* objectArray = object.getArray();
|
||||
if (objectArray->getCount() == 2)
|
||||
{
|
||||
PDFDocumentDataLoaderDecorator loader(document);
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
result.unitsPerSecond = loader.readInteger(objectArray->getItem(1), 0);
|
||||
|
||||
object = document->getObject(objectArray->getItem(0));
|
||||
object = storage->getObject(objectArray->getItem(0));
|
||||
if (object.isInt())
|
||||
{
|
||||
result.value = object.getInteger();
|
||||
|
@ -28,11 +28,11 @@
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
class PDFDocument;
|
||||
class PDFObjectStorage;
|
||||
|
||||
struct PDFMediaMultiLanguageTexts
|
||||
{
|
||||
static PDFMediaMultiLanguageTexts parse(const PDFDocument* document, PDFObject object);
|
||||
static PDFMediaMultiLanguageTexts parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
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 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 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; }
|
||||
|
||||
@ -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>& 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; }
|
||||
|
||||
@ -232,7 +232,7 @@ public:
|
||||
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 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* 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 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 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:
|
||||
PDFInteger m_minimumWidth;
|
||||
@ -409,7 +409,7 @@ class PDFMediaCriteria
|
||||
public:
|
||||
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 hasTextCaptions() const { return m_textCaptions.has_value(); }
|
||||
@ -473,7 +473,7 @@ public:
|
||||
PDFObject renditions;
|
||||
};
|
||||
|
||||
static PDFRendition parse(const PDFDocument* document, PDFObject object);
|
||||
static PDFRendition parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
Type getType() const { return m_type; }
|
||||
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
|
||||
/// is returned, no exception is thrown.
|
||||
static PDFSound parse(const PDFDocument* document, PDFObject object);
|
||||
static PDFSound parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
private:
|
||||
PDFFileSpecification m_fileSpecification;
|
||||
@ -546,7 +546,7 @@ public:
|
||||
|
||||
/// Creates a new movie from the object. If data are invalid, then invalid object
|
||||
/// is returned, no exception is thrown.
|
||||
static PDFMovie parse(const PDFDocument* document, PDFObject object);
|
||||
static PDFMovie parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
private:
|
||||
PDFFileSpecification m_movieFile;
|
||||
@ -590,10 +590,10 @@ public:
|
||||
|
||||
/// Creates a new moview from the object. If data are invalid, then invalid object
|
||||
/// is returned, no exception is thrown.
|
||||
static PDFMovieActivation parse(const PDFDocument* document, PDFObject object);
|
||||
static PDFMovieActivation parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
private:
|
||||
static MovieTime parseMovieTime(const PDFDocument* document, PDFObject object);
|
||||
static MovieTime parseMovieTime(const PDFObjectStorage* storage, PDFObject object);
|
||||
static PDFInteger parseMovieTimeFromString(const QByteArray& string);
|
||||
|
||||
MovieTime m_start;
|
||||
|
@ -34,27 +34,27 @@ public:
|
||||
explicit PDFNameTreeLoader() = delete;
|
||||
|
||||
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,
|
||||
/// 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 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;
|
||||
parseImpl(result, document, root, loadMethod);
|
||||
parseImpl(result, storage, root, loadMethod);
|
||||
return result;
|
||||
}
|
||||
|
||||
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
|
||||
const PDFObject& namedItems = document->getObject(dictionary->get("Names"));
|
||||
const PDFObject& namedItems = storage->getObject(dictionary->get("Names"));
|
||||
if (namedItems.isArray())
|
||||
{
|
||||
const PDFArray* namedItemsArray = namedItems.getArray();
|
||||
@ -64,25 +64,25 @@ private:
|
||||
const size_t numberIndex = 2 * i;
|
||||
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())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
objects[name.getString()] = loadMethod(document, namedItemsArray->getItem(valueIndex));
|
||||
objects[name.getString()] = loadMethod(storage, namedItemsArray->getItem(valueIndex));
|
||||
}
|
||||
}
|
||||
|
||||
// Then, follow the kids
|
||||
const PDFObject& kids = document->getObject(dictionary->get("Kids"));
|
||||
const PDFObject& kids = storage->getObject(dictionary->get("Kids"));
|
||||
if (kids.isArray())
|
||||
{
|
||||
const PDFArray* kidsArray = kids.getArray();
|
||||
const size_t count = kidsArray->getCount();
|
||||
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->setAction(PDFAction::parse(document, dictionary->get("A")));
|
||||
currentOutlineItem->setAction(PDFAction::parse(&document->getStorage(), dictionary->get("A")));
|
||||
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);
|
||||
|
@ -44,6 +44,37 @@ class PDFOptionalContentActivity;
|
||||
|
||||
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.
|
||||
class PDFPageContentProcessor : public PDFRenderErrorReporter
|
||||
{
|
||||
@ -193,34 +224,6 @@ public:
|
||||
|
||||
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
|
||||
{
|
||||
PDFColorSpacePointer colorSpacePointer;
|
||||
|
@ -21,13 +21,13 @@
|
||||
namespace pdf
|
||||
{
|
||||
|
||||
PDFPageTransition PDFPageTransition::parse(const PDFDocument* document, PDFObject object)
|
||||
PDFPageTransition PDFPageTransition::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
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 = {
|
||||
std::pair<const char*, Style>{ "Split", Style::Split },
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
class PDFDocument;
|
||||
class PDFObjectStorage;
|
||||
|
||||
/// Page transition during presentation settings.
|
||||
class PDFPageTransition
|
||||
@ -57,7 +57,7 @@ public:
|
||||
Outward
|
||||
};
|
||||
|
||||
static PDFPageTransition parse(const PDFDocument* document, PDFObject object);
|
||||
static PDFPageTransition parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
Style getStyle() const { return m_style; }
|
||||
PDFReal getDuration() const { return m_duration; }
|
||||
|
@ -398,6 +398,7 @@ return pageReference;</property>
|
||||
<property name="variableName"></property>
|
||||
<property name="variableType">_void</property>
|
||||
<property name="code">appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;</property>
|
||||
</QObject>
|
||||
</property>
|
||||
@ -600,6 +601,7 @@ return annotationObject;</property>
|
||||
<property name="variableName"></property>
|
||||
<property name="variableType">_void</property>
|
||||
<property name="code">appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;</property>
|
||||
</QObject>
|
||||
</property>
|
||||
@ -874,6 +876,7 @@ return annotationObject;</property>
|
||||
<property name="variableName"></property>
|
||||
<property name="variableType">_void</property>
|
||||
<property name="code">appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;</property>
|
||||
</QObject>
|
||||
</property>
|
||||
@ -1077,6 +1080,7 @@ return annotationObject;</property>
|
||||
<property name="variableName"></property>
|
||||
<property name="variableType">_void</property>
|
||||
<property name="code">appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;</property>
|
||||
</QObject>
|
||||
</property>
|
||||
@ -1231,6 +1235,7 @@ return annotationObject;</property>
|
||||
<property name="variableName"></property>
|
||||
<property name="variableType">_void</property>
|
||||
<property name="code">appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;</property>
|
||||
</QObject>
|
||||
</property>
|
||||
@ -1520,6 +1525,7 @@ return annotationObject;</property>
|
||||
<property name="variableName"></property>
|
||||
<property name="variableType">_void</property>
|
||||
<property name="code">appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;</property>
|
||||
</QObject>
|
||||
</property>
|
||||
@ -1879,6 +1885,7 @@ return annotationObject;</property>
|
||||
<property name="variableName"></property>
|
||||
<property name="variableType">_void</property>
|
||||
<property name="code">appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;</property>
|
||||
</QObject>
|
||||
</property>
|
||||
@ -2025,6 +2032,7 @@ return annotationObject;</property>
|
||||
<property name="variableName"></property>
|
||||
<property name="variableType">_void</property>
|
||||
<property name="code">appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationReference);
|
||||
return annotationReference;</property>
|
||||
</QObject>
|
||||
</property>
|
||||
@ -2317,6 +2325,7 @@ return annotationReference;</property>
|
||||
<property name="variableName"></property>
|
||||
<property name="variableType">_void</property>
|
||||
<property name="code">appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;</property>
|
||||
</QObject>
|
||||
</property>
|
||||
@ -2584,6 +2593,7 @@ return annotationObject;</property>
|
||||
<property name="variableName"></property>
|
||||
<property name="variableType">_void</property>
|
||||
<property name="code">appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;</property>
|
||||
</QObject>
|
||||
</property>
|
||||
@ -2722,6 +2732,7 @@ return annotationObject;</property>
|
||||
<property name="variableName"></property>
|
||||
<property name="variableType">_void</property>
|
||||
<property name="code">mergeTo(parentAnnotation, upgradedParentAnnotation);
|
||||
updateAnnotationAppearanceStreams(popupAnnotation);
|
||||
return popupAnnotation;</property>
|
||||
</QObject>
|
||||
</property>
|
||||
@ -2953,6 +2964,7 @@ return popupAnnotation;</property>
|
||||
<property name="variableName"></property>
|
||||
<property name="variableType">_void</property>
|
||||
<property name="code">appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;</property>
|
||||
</QObject>
|
||||
</property>
|
||||
@ -3156,6 +3168,7 @@ return annotationObject;</property>
|
||||
<property name="variableName"></property>
|
||||
<property name="variableType">_void</property>
|
||||
<property name="code">appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;</property>
|
||||
</QObject>
|
||||
</property>
|
||||
@ -3310,6 +3323,7 @@ return annotationObject;</property>
|
||||
<property name="variableName"></property>
|
||||
<property name="variableType">_void</property>
|
||||
<property name="code">appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;</property>
|
||||
</QObject>
|
||||
</property>
|
||||
@ -3513,6 +3527,7 @@ return annotationObject;</property>
|
||||
<property name="variableName"></property>
|
||||
<property name="variableType">_void</property>
|
||||
<property name="code">appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;</property>
|
||||
</QObject>
|
||||
</property>
|
||||
@ -3667,6 +3682,7 @@ return annotationObject;</property>
|
||||
<property name="variableName"></property>
|
||||
<property name="variableType">_void</property>
|
||||
<property name="code">appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;</property>
|
||||
</QObject>
|
||||
</property>
|
||||
@ -3909,6 +3925,7 @@ return annotationObject;</property>
|
||||
<property name="variableType">_void</property>
|
||||
<property name="code">mergeTo(annotationObject, updateAnnotationPopup);
|
||||
appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;</property>
|
||||
</QObject>
|
||||
</property>
|
||||
@ -4112,6 +4129,7 @@ return annotationObject;</property>
|
||||
<property name="variableName"></property>
|
||||
<property name="variableType">_void</property>
|
||||
<property name="code">appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;</property>
|
||||
</QObject>
|
||||
</property>
|
||||
@ -4266,6 +4284,7 @@ return annotationObject;</property>
|
||||
<property name="variableName"></property>
|
||||
<property name="variableType">_void</property>
|
||||
<property name="code">appendTo(page, pageAnnots);
|
||||
updateAnnotationAppearanceStreams(annotationObject);
|
||||
return annotationObject;</property>
|
||||
</QObject>
|
||||
</property>
|
||||
|
Loading…
x
Reference in New Issue
Block a user