Annotations

This commit is contained in:
Jakub Melka
2020-03-03 19:58:51 +01:00
parent 7db167eea3
commit de9e6b9807
3 changed files with 373 additions and 0 deletions

View File

@ -0,0 +1,153 @@
// Copyright (C) 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 "pdfannotation.h"
#include "pdfdocument.h"
namespace pdf
{
PDFAnnotation::PDFAnnotation() :
m_structParent(0)
{
}
PDFAnnotationBorder PDFAnnotationBorder::parseBorder(const PDFDocument* document, PDFObject object)
{
PDFAnnotationBorder result;
object = document->getObject(object);
if (object.isArray())
{
const PDFArray* array = object.getArray();
if (array->getCount() >= 3)
{
PDFDocumentDataLoaderDecorator loader(document);
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);
result.m_width = loader.readNumber(array->getItem(2), 1.0);
if (array->getCount() >= 4)
{
result.m_dashPattern = loader.readNumberArray(array->getItem(3));
}
}
}
return result;
}
PDFAnnotationBorder PDFAnnotationBorder::parseBS(const PDFDocument* document, PDFObject object)
{
PDFAnnotationBorder result;
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
{
PDFDocumentDataLoaderDecorator loader(document);
result.m_definition = Definition::BorderStyle;
result.m_width = loader.readNumberFromDictionary(dictionary, "W", 1.0);
constexpr const std::array<std::pair<const char*, Style>, 6> styles = {
std::pair<const char*, Style>{ "S", Style::Solid },
std::pair<const char*, Style>{ "D", Style::Dashed },
std::pair<const char*, Style>{ "B", Style::Beveled },
std::pair<const char*, Style>{ "I", Style::Inset },
std::pair<const char*, Style>{ "U", Style::Underline }
};
result.m_style = loader.readEnumByName(dictionary->get("S"), styles.begin(), styles.end(), Style::Solid);
}
return result;
}
PDFAnnotationBorderEffect PDFAnnotationBorderEffect::parse(const PDFDocument* document, PDFObject object)
{
PDFAnnotationBorderEffect result;
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
{
PDFDocumentDataLoaderDecorator loader(document);
result.m_intensity = loader.readNumberFromDictionary(dictionary, "I", 0.0);
constexpr const std::array<std::pair<const char*, Effect>, 2> effects = {
std::pair<const char*, Effect>{ "S", Effect::None },
std::pair<const char*, Effect>{ "C", Effect::Cloudy }
};
result.m_effect = loader.readEnumByName(dictionary->get("S"), effects.begin(), effects.end(), Effect::None);
}
return result;
}
PDFAppeareanceStreams PDFAppeareanceStreams::parse(const PDFDocument* document, PDFObject object)
{
PDFAppeareanceStreams result;
auto processSubdicitonary = [&result, document](Appearance appearance, PDFObject subdictionaryObject)
{
if (const PDFDictionary* subdictionary = document->getDictionaryFromObject(subdictionaryObject))
{
for (size_t i = 0; i < subdictionary->getCount(); ++i)
{
result.m_appearanceStreams[std::make_pair(appearance, subdictionary->getKey(i))] = subdictionary->getValue(i);
}
}
else if (!subdictionaryObject.isNull())
{
result.m_appearanceStreams[std::make_pair(appearance, QByteArray())] = subdictionaryObject;
}
};
if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object))
{
processSubdicitonary(Appearance::Normal, dictionary->get("N"));
processSubdicitonary(Appearance::Rollover, dictionary->get("R"));
processSubdicitonary(Appearance::Down, dictionary->get("D"));
}
return result;
}
PDFObject PDFAppeareanceStreams::getAppearance(Appearance appearance, const QByteArray& state) const
{
Key key(appearance, state);
auto it = m_appearanceStreams.find(key);
if (it == m_appearanceStreams.cend() && appearance != Appearance::Normal)
{
key.first = Appearance::Normal;
it = m_appearanceStreams.find(key);
}
if (it == m_appearanceStreams.cend() && !state.isEmpty())
{
key.second = QByteArray();
it = m_appearanceStreams.find(key);
}
if (it != m_appearanceStreams.cend())
{
return it->second;
}
return PDFObject();
}
} // namespace pdf