mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Annotations
This commit is contained in:
153
PdfForQtLib/sources/pdfannotation.cpp
Normal file
153
PdfForQtLib/sources/pdfannotation.cpp
Normal 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
|
Reference in New Issue
Block a user