Update file specification according the PDF 2.0 compliance

This commit is contained in:
Jakub Melka 2020-08-02 17:28:08 +02:00
parent a2c5de0fe4
commit 6814e2755e
4 changed files with 55 additions and 4 deletions

View File

@ -125,6 +125,7 @@ PDFFileSpecification PDFFileSpecification::parse(const PDFObjectStorage* storage
result.m_DOS = loader.readStringFromDictionary(dictionary, "DOS");
result.m_Mac = loader.readStringFromDictionary(dictionary, "Mac");
result.m_Unix = loader.readStringFromDictionary(dictionary, "Unix");
result.m_id = PDFFileIdentifier::parse(storage, dictionary->get("ID"));
result.m_volatile = loader.readBooleanFromDictionary(dictionary, "V", false);
result.m_description = loader.readTextStringFromDictionary(dictionary, "Desc", QString());
result.m_collection = collectionObject.isReference() ? collectionObject.getReference() : PDFObjectReference();
@ -180,4 +181,23 @@ PDFEmbeddedFile PDFEmbeddedFile::parse(const PDFObjectStorage* storage, PDFObjec
return result;
}
PDFFileIdentifier PDFFileIdentifier::parse(const PDFObjectStorage* storage, PDFObject object)
{
PDFFileIdentifier result;
PDFDocumentDataLoaderDecorator loader(storage);
std::vector<QByteArray> identifiers = loader.readStringArray(object);
if (identifiers.size() >= 1)
{
result.m_permanentIdentifier = qMove(identifiers[0]);
}
if (identifiers.size() >= 2)
{
result.m_changingIdentifier = qMove(identifiers[1]);
}
return result;
}
} // namespace pdf

View File

@ -26,6 +26,25 @@ namespace pdf
{
class PDFObjectStorage;
/// File identifier according section 14.4 of PDF 2.0 specification.
/// Each identifier consists of two parts - permanent identifier, which
/// is unique identifier based on original document, and changing identifier,
/// which is updated when document is being modified.
class PDFFileIdentifier
{
public:
explicit inline PDFFileIdentifier() = default;
const QByteArray& getPermanentIdentifier() const { return m_permanentIdentifier; }
const QByteArray& getChangingIdentifier() const { return m_changingIdentifier; }
static PDFFileIdentifier parse(const PDFObjectStorage* storage, PDFObject object);
private:
QByteArray m_permanentIdentifier;
QByteArray m_changingIdentifier;
};
class PDFEmbeddedFile
{
public:
@ -70,6 +89,7 @@ public:
const QByteArray& getDOS() const { return m_DOS; }
const QByteArray& getMac() const { return m_Mac; }
const QByteArray& getUnix() const { return m_Unix; }
const PDFFileIdentifier& getFileIdentifier() const { return m_id; }
bool isVolatile() const { return m_volatile; }
const QString& getDescription() const { return m_description; }
PDFObjectReference getCollection() const { return m_collection; }
@ -93,6 +113,8 @@ private:
QByteArray m_Mac;
QByteArray m_Unix;
PDFFileIdentifier m_id;
/// Is file volatile? I.e it is, for example, link to a video file from online camera?
/// If this boolean is true, then file should never be cached.
bool m_volatile = false;

View File

@ -182,7 +182,7 @@ PDFFunctionPtr PDFFunction::createFunctionImpl(const PDFDocument* document, cons
std::vector<uint32_t> sizeAsUint;
std::transform(size.cbegin(), size.cend(), std::back_inserter(sizeAsUint), [](PDFInteger integer) { return static_cast<uint32_t>(integer); });
return std::make_shared<PDFSampledFunction>(static_cast<uint32_t>(m), static_cast<uint32_t>(n), std::move(domain), std::move(range), std::move(sizeAsUint), std::move(samples), std::move(encode), std::move(decode), sampleMaxValue);
return std::make_shared<PDFSampledFunction>(static_cast<uint32_t>(m), static_cast<uint32_t>(n), std::move(domain), std::move(range), std::move(sizeAsUint), std::move(samples), std::move(encode), std::move(decode), sampleMaxValue, loader.readIntegerFromDictionary(dictionary, "Order", 1));
}
case 2:
{
@ -336,14 +336,16 @@ PDFSampledFunction::PDFSampledFunction(uint32_t m, uint32_t n,
std::vector<PDFReal>&& samples,
std::vector<PDFReal>&& encoder,
std::vector<PDFReal>&& decoder,
PDFReal sampleMaximalValue) :
PDFReal sampleMaximalValue,
PDFInteger order) :
PDFFunction(m, n, std::move(domain), std::move(range)),
m_hypercubeNodeCount(1 << m_m),
m_size(std::move(size)),
m_samples(std::move(samples)),
m_encoder(std::move(encoder)),
m_decoder(std::move(decoder)),
m_sampleMaximalValue(sampleMaximalValue)
m_sampleMaximalValue(sampleMaximalValue),
m_order(order)
{
// Asserts, that we get sane input
Q_ASSERT(m > 0);

View File

@ -162,6 +162,7 @@ public:
/// \param encoder Array of 2 x m variables of encoding range - [x1 min, x1 max, x2 min, x2 max, ... ]
/// \param decoder Array of 2 x n variables of decoding range - [y1 min, y1 max, y2 min, y2 max, ... ]
/// \param sampleMaximalValue Maximal value of the sample
/// \param order Interpolation order
explicit PDFSampledFunction(uint32_t m,
uint32_t n,
std::vector<PDFReal>&& domain,
@ -170,7 +171,8 @@ public:
std::vector<PDFReal>&& samples,
std::vector<PDFReal>&& encoder,
std::vector<PDFReal>&& decoder,
PDFReal sampleMaximalValue);
PDFReal sampleMaximalValue,
PDFInteger order);
virtual ~PDFSampledFunction() = default;
/// Transforms input values to the output values.
@ -180,6 +182,8 @@ public:
/// \param y_n Iterator to the end of the output values (one item after last value)
virtual FunctionResult apply(const_iterator x_1, const_iterator x_m, iterator y_1, iterator y_n) const override;
PDFInteger getOrder() const { return m_order; }
private:
/// Number of nodes in m-dimensional hypercube (it is 2^m).
uint32_t m_hypercubeNodeCount;
@ -203,6 +207,9 @@ private:
/// Maximal value of the sample (determined by number of the bits of the sample)
PDFReal m_sampleMaximalValue;
/// Interpolation order (1 = linear, 2 = quadratic, 3 = cubic)
PDFInteger m_order;
};
/// Exponential function (Type 2 function)