mirror of https://github.com/JakubMelka/PDF4QT.git
235 lines
6.8 KiB
C++
235 lines
6.8 KiB
C++
// Copyright (C) 2018-2020 Jakub Melka
|
|
//
|
|
// This file is part of PdfForQt.
|
|
//
|
|
// PdfForQt is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// PdfForQt is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
// along with PDFForQt. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
#include "pdfobject.h"
|
|
#include "pdfvisitor.h"
|
|
|
|
namespace pdf
|
|
{
|
|
|
|
QByteArray PDFObject::getString() const
|
|
{
|
|
const PDFObjectContentPointer& objectContent = std::get<PDFObjectContentPointer>(m_data);
|
|
|
|
Q_ASSERT(dynamic_cast<PDFString*>(objectContent.get()));
|
|
const PDFString* string = static_cast<PDFString*>(objectContent.get());
|
|
return string->getString();
|
|
}
|
|
|
|
const PDFDictionary* PDFObject::getDictionary() const
|
|
{
|
|
const PDFObjectContentPointer& objectContent = std::get<PDFObjectContentPointer>(m_data);
|
|
|
|
Q_ASSERT(dynamic_cast<const PDFDictionary*>(objectContent.get()));
|
|
return static_cast<const PDFDictionary*>(objectContent.get());
|
|
}
|
|
|
|
const PDFString* PDFObject::getStringObject() const
|
|
{
|
|
const PDFObjectContentPointer& objectContent = std::get<PDFObjectContentPointer>(m_data);
|
|
|
|
Q_ASSERT(dynamic_cast<const PDFString*>(objectContent.get()));
|
|
return static_cast<const PDFString*>(objectContent.get());
|
|
}
|
|
|
|
const PDFStream* PDFObject::getStream() const
|
|
{
|
|
const PDFObjectContentPointer& objectContent = std::get<PDFObjectContentPointer>(m_data);
|
|
|
|
Q_ASSERT(dynamic_cast<const PDFStream*>(objectContent.get()));
|
|
return static_cast<const PDFStream*>(objectContent.get());
|
|
}
|
|
|
|
const PDFArray* PDFObject::getArray() const
|
|
{
|
|
const PDFObjectContentPointer& objectContent = std::get<PDFObjectContentPointer>(m_data);
|
|
|
|
Q_ASSERT(dynamic_cast<const PDFArray*>(objectContent.get()));
|
|
return static_cast<const PDFArray*>(objectContent.get());
|
|
}
|
|
|
|
bool PDFObject::operator==(const PDFObject &other) const
|
|
{
|
|
if (m_type == other.m_type)
|
|
{
|
|
Q_ASSERT(std::holds_alternative<PDFObjectContentPointer>(m_data) == std::holds_alternative<PDFObjectContentPointer>(other.m_data));
|
|
|
|
// If we have content object defined, then use its equal operator,
|
|
// otherwise use default compare operator. The only problem with
|
|
// default compare operator can occur, when we have a double
|
|
// with NaN value. Then operator == can return false, even if
|
|
// values are "equal" (NaN == NaN returns false)
|
|
if (std::holds_alternative<PDFObjectContentPointer>(m_data))
|
|
{
|
|
Q_ASSERT(std::get<PDFObjectContentPointer>(m_data));
|
|
return std::get<PDFObjectContentPointer>(m_data)->equals(std::get<PDFObjectContentPointer>(other.m_data).get());
|
|
}
|
|
|
|
return m_data == other.m_data;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void PDFObject::accept(PDFAbstractVisitor* visitor) const
|
|
{
|
|
switch (m_type)
|
|
{
|
|
case Type::Null:
|
|
visitor->visitNull();
|
|
break;
|
|
|
|
case Type::Bool:
|
|
visitor->visitBool(getBool());
|
|
break;
|
|
|
|
case Type::Int:
|
|
visitor->visitInt(getInteger());
|
|
break;
|
|
|
|
case Type::Real:
|
|
visitor->visitReal(getReal());
|
|
break;
|
|
|
|
case Type::String:
|
|
visitor->visitString(getStringObject());
|
|
break;
|
|
|
|
case Type::Name:
|
|
visitor->visitName(getStringObject());
|
|
break;
|
|
|
|
case Type::Array:
|
|
visitor->visitArray(getArray());
|
|
break;
|
|
|
|
case Type::Dictionary:
|
|
visitor->visitDictionary(getDictionary());
|
|
break;
|
|
|
|
case Type::Stream:
|
|
visitor->visitStream(getStream());
|
|
break;
|
|
|
|
case Type::Reference:
|
|
visitor->visitReference(getReference());
|
|
break;
|
|
|
|
default:
|
|
Q_ASSERT(false);
|
|
}
|
|
}
|
|
|
|
bool PDFString::equals(const PDFObjectContent* other) const
|
|
{
|
|
Q_ASSERT(dynamic_cast<const PDFString*>(other));
|
|
const PDFString* otherString = static_cast<const PDFString*>(other);
|
|
return m_string == otherString->m_string;
|
|
}
|
|
|
|
void PDFString::setString(const QByteArray& string)
|
|
{
|
|
m_string = string;
|
|
}
|
|
|
|
void PDFString::optimize()
|
|
{
|
|
m_string.shrink_to_fit();
|
|
}
|
|
|
|
bool PDFArray::equals(const PDFObjectContent* other) const
|
|
{
|
|
Q_ASSERT(dynamic_cast<const PDFArray*>(other));
|
|
const PDFArray* otherArray = static_cast<const PDFArray*>(other);
|
|
return m_objects == otherArray->m_objects;
|
|
}
|
|
|
|
void PDFArray::appendItem(PDFObject object)
|
|
{
|
|
m_objects.push_back(std::move(object));
|
|
}
|
|
|
|
void PDFArray::optimize()
|
|
{
|
|
m_objects.shrink_to_fit();
|
|
}
|
|
|
|
bool PDFDictionary::equals(const PDFObjectContent* other) const
|
|
{
|
|
Q_ASSERT(dynamic_cast<const PDFDictionary*>(other));
|
|
const PDFDictionary* otherStream = static_cast<const PDFDictionary*>(other);
|
|
return m_dictionary == otherStream->m_dictionary;
|
|
}
|
|
|
|
const PDFObject& PDFDictionary::get(const QByteArray& key) const
|
|
{
|
|
auto it = find(key);
|
|
if (it != m_dictionary.cend())
|
|
{
|
|
return it->second;
|
|
}
|
|
else
|
|
{
|
|
static PDFObject dummy;
|
|
return dummy;
|
|
}
|
|
}
|
|
|
|
const PDFObject& PDFDictionary::get(const char* key) const
|
|
{
|
|
auto it = find(key);
|
|
if (it != m_dictionary.cend())
|
|
{
|
|
return it->second;
|
|
}
|
|
else
|
|
{
|
|
static PDFObject dummy;
|
|
return dummy;
|
|
}
|
|
}
|
|
|
|
void PDFDictionary::optimize()
|
|
{
|
|
m_dictionary.shrink_to_fit();
|
|
|
|
for (DictionaryEntry& entry : m_dictionary)
|
|
{
|
|
entry.first.shrink_to_fit();
|
|
}
|
|
}
|
|
|
|
std::vector<PDFDictionary::DictionaryEntry>::const_iterator PDFDictionary::find(const QByteArray& key) const
|
|
{
|
|
return std::find_if(m_dictionary.cbegin(), m_dictionary.cend(), [&key](const DictionaryEntry& entry) { return entry.first == key; });
|
|
}
|
|
|
|
std::vector<PDFDictionary::DictionaryEntry>::const_iterator PDFDictionary::find(const char* key) const
|
|
{
|
|
return std::find_if(m_dictionary.cbegin(), m_dictionary.cend(), [&key](const DictionaryEntry& entry) { return entry.first == key; });
|
|
}
|
|
|
|
bool PDFStream::equals(const PDFObjectContent* other) const
|
|
{
|
|
Q_ASSERT(dynamic_cast<const PDFStream*>(other));
|
|
const PDFStream* otherStream = static_cast<const PDFStream*>(other);
|
|
return m_dictionary.equals(&otherStream->m_dictionary) && m_content == otherStream->m_content;
|
|
}
|
|
|
|
} // namespace pdf
|