From a857e061b80bb20a2710f89e230066a74fab7ce7 Mon Sep 17 00:00:00 2001 From: Jakub Melka Date: Sun, 24 Nov 2019 15:43:27 +0100 Subject: [PATCH] Finishing of actions --- PdfForQtLib/PdfForQtLib.pro | 2 + PdfForQtLib/sources/pdfaction.cpp | 32 +++++++++ PdfForQtLib/sources/pdfaction.h | 85 +++++++++++++++++++++-- PdfForQtLib/sources/pdfoutline.cpp | 57 +++++++++++++++ PdfForQtLib/sources/pdfoutline.h | 16 +++++ PdfForQtLib/sources/pdfpagetransition.cpp | 69 ++++++++++++++++++ PdfForQtLib/sources/pdfpagetransition.h | 82 ++++++++++++++++++++++ 7 files changed, 339 insertions(+), 4 deletions(-) create mode 100644 PdfForQtLib/sources/pdfpagetransition.cpp create mode 100644 PdfForQtLib/sources/pdfpagetransition.h diff --git a/PdfForQtLib/PdfForQtLib.pro b/PdfForQtLib/PdfForQtLib.pro index 3c8c85e..419990e 100644 --- a/PdfForQtLib/PdfForQtLib.pro +++ b/PdfForQtLib/PdfForQtLib.pro @@ -46,6 +46,7 @@ SOURCES += \ sources/pdfobject.cpp \ sources/pdfoptionalcontent.cpp \ sources/pdfoutline.cpp \ + sources/pdfpagetransition.cpp \ sources/pdfparser.cpp \ sources/pdfdocument.cpp \ sources/pdfdocumentreader.cpp \ @@ -83,6 +84,7 @@ HEADERS += \ sources/pdfobject.h \ sources/pdfoptionalcontent.h \ sources/pdfoutline.h \ + sources/pdfpagetransition.h \ sources/pdfparser.h \ sources/pdfglobal.h \ sources/pdfconstants.h \ diff --git a/PdfForQtLib/sources/pdfaction.cpp b/PdfForQtLib/sources/pdfaction.cpp index 500433d..d2ca276 100644 --- a/PdfForQtLib/sources/pdfaction.cpp +++ b/PdfForQtLib/sources/pdfaction.cpp @@ -241,6 +241,38 @@ PDFActionPtr PDFAction::parseImpl(const PDFDocument* document, PDFObject object, return PDFActionPtr(new PDFActionSetOCGState(qMove(items), isRadioButtonsPreserved)); } + else if (name == "Rendition") + { + PDFObject annotationObject = dictionary->get("AN"); + std::optional rendition; + PDFObjectReference annotation = annotationObject.isReference() ? annotationObject.getReference() : PDFObjectReference(); + PDFActionRendition::Operation operation = static_cast(loader.readIntegerFromDictionary(dictionary, "OP", 4)); + QString javascript; + + if (dictionary->hasKey("R")) + { + rendition = PDFRendition::parse(document, dictionary->get("R")); + } + PDFObject javascriptObject = document->getObject(dictionary->get("JS")); + if (javascriptObject.isString()) + { + javascript = PDFEncoding::convertTextString(javascriptObject.getString()); + } + else if (javascriptObject.isStream()) + { + javascript = PDFEncoding::convertTextString(document->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")))); + } + else if (name == "GoTo3DView") + { + return PDFActionPtr(new PDFActionGoTo3DView(dictionary->get("TA"), dictionary->get("V"))); + } return PDFActionPtr(); } diff --git a/PdfForQtLib/sources/pdfaction.h b/PdfForQtLib/sources/pdfaction.h index 5bb71cd..5144f46 100644 --- a/PdfForQtLib/sources/pdfaction.h +++ b/PdfForQtLib/sources/pdfaction.h @@ -22,6 +22,7 @@ #include "pdfobject.h" #include "pdffile.h" #include "pdfmultimedia.h" +#include "pdfpagetransition.h" #include @@ -46,7 +47,10 @@ enum class ActionType Movie, Hide, Named, - SetOCGState + SetOCGState, + Rendition, + Transition, + GoTo3DView }; enum class DestinationType @@ -388,9 +392,9 @@ public: enum class SwitchType { - ON, - OFF, - Toggle + ON = 0, + OFF = 1, + Toggle = 2 }; using StateChangeItem = std::pair; @@ -413,6 +417,79 @@ private: bool m_isRadioButtonsPreserved; }; +class PDFActionRendition : public PDFAction +{ +public: + + enum class Operation + { + PlayAndAssociate = 0, + Stop = 1, + Pause = 2, + Resume = 3, + Play = 4 + }; + + explicit inline PDFActionRendition(std::optional&& rendition, PDFObjectReference annotation, Operation operation, QString javascript) : + m_rendition(qMove(rendition)), + m_annotation(annotation), + m_operation(operation), + m_javascript(qMove(javascript)) + { + + } + + virtual ActionType getType() const override { return ActionType::Rendition; } + + const PDFRendition* getRendition() const { return m_rendition.has_value() ? &m_rendition.value() : nullptr; } + PDFObjectReference getAnnotation() const { return m_annotation; } + Operation getOperation() const { return m_operation; } + const QString& getJavascript() const { return m_javascript; } + +private: + std::optional m_rendition; + PDFObjectReference m_annotation; + Operation m_operation; + QString m_javascript; +}; + +class PDFActionTransition : public PDFAction +{ +public: + explicit inline PDFActionTransition(PDFPageTransition&& transition) : + m_transition(qMove(transition)) + { + + } + + virtual ActionType getType() const override { return ActionType::Transition; } + + const PDFPageTransition& getTransition() const { return m_transition; } + +private: + PDFPageTransition m_transition; +}; + +class PDFActionGoTo3DView : public PDFAction +{ +public: + explicit PDFActionGoTo3DView(PDFObject annotation, PDFObject view) : + m_annotation(qMove(annotation)), + m_view(qMove(view)) + { + + } + + virtual ActionType getType() const override { return ActionType::GoTo3DView; } + + const PDFObject& getAnnotation() const { return m_annotation; } + const PDFObject& getView() const { return m_view; } + +private: + PDFObject m_annotation; + PDFObject m_view; +}; + } // namespace pdf #endif // PDFACTION_H diff --git a/PdfForQtLib/sources/pdfoutline.cpp b/PdfForQtLib/sources/pdfoutline.cpp index f6681f4..6395840 100644 --- a/PdfForQtLib/sources/pdfoutline.cpp +++ b/PdfForQtLib/sources/pdfoutline.cpp @@ -71,6 +71,23 @@ void PDFOutlineItem::parseImpl(const PDFDocument* document, currentOutlineItem->setTitle(PDFEncoding::convertTextString(titleObject.getString())); } currentOutlineItem->setAction(PDFAction::parse(document, dictionary->get("A"))); + if (!currentOutlineItem->getAction() && dictionary->hasKey("Dest")) + { + currentOutlineItem->setAction(PDFActionPtr(new PDFActionGoTo(PDFDestination::parse(document, dictionary->get("Dest"))))); + } + + PDFDocumentDataLoaderDecorator loader(document); + std::vector colors = loader.readNumberArrayFromDictionary(dictionary, "C", { 0.0, 0.0, 0.0 }); + colors.resize(3, 0.0); + currentOutlineItem->setTextColor(QColor::fromRgbF(colors[0], colors[1], colors[2])); + PDFInteger flag = loader.readIntegerFromDictionary(dictionary, "F", 0); + currentOutlineItem->setFontItalics(flag & 0x1); + currentOutlineItem->setFontBold(flag & 0x2); + PDFObject structureElementObject = dictionary->get("SE"); + if (structureElementObject.isReference()) + { + currentOutlineItem->setStructureElement(structureElementObject.getReference()); + } // Parse children of this item const PDFObject& firstItem = dictionary->get("First"); @@ -97,6 +114,46 @@ void PDFOutlineItem::parseImpl(const PDFDocument* document, } } +PDFObjectReference PDFOutlineItem::getStructureElement() const +{ + return m_structureElement; +} + +void PDFOutlineItem::setStructureElement(PDFObjectReference structureElement) +{ + m_structureElement = structureElement; +} + +bool PDFOutlineItem::isFontBold() const +{ + return m_fontBold; +} + +void PDFOutlineItem::setFontBold(bool fontBold) +{ + m_fontBold = fontBold; +} + +bool PDFOutlineItem::isFontItalics() const +{ + return m_fontItalics; +} + +void PDFOutlineItem::setFontItalics(bool fontItalics) +{ + m_fontItalics = fontItalics; +} + +QColor PDFOutlineItem::getTextColor() const +{ + return m_textColor; +} + +void PDFOutlineItem::setTextColor(const QColor& textColor) +{ + m_textColor = textColor; +} + const PDFAction* PDFOutlineItem::getAction() const { return m_action.get(); diff --git a/PdfForQtLib/sources/pdfoutline.h b/PdfForQtLib/sources/pdfoutline.h index 2025575..0d80d3a 100644 --- a/PdfForQtLib/sources/pdfoutline.h +++ b/PdfForQtLib/sources/pdfoutline.h @@ -48,6 +48,18 @@ public: const PDFAction* getAction() const; void setAction(const PDFActionPtr& action); + QColor getTextColor() const; + void setTextColor(const QColor& textColor); + + bool isFontItalics() const; + void setFontItalics(bool fontItalics); + + bool isFontBold() const; + void setFontBold(bool fontBold); + + PDFObjectReference getStructureElement() const; + void setStructureElement(PDFObjectReference structureElement); + private: static void parseImpl(const PDFDocument* document, PDFOutlineItem* parent, @@ -57,6 +69,10 @@ private: QString m_title; std::vector> m_children; PDFActionPtr m_action; + PDFObjectReference m_structureElement; + QColor m_textColor; + bool m_fontItalics = false; + bool m_fontBold = false; }; } // namespace pdf diff --git a/PdfForQtLib/sources/pdfpagetransition.cpp b/PdfForQtLib/sources/pdfpagetransition.cpp new file mode 100644 index 0000000..5d1bb82 --- /dev/null +++ b/PdfForQtLib/sources/pdfpagetransition.cpp @@ -0,0 +1,69 @@ +// Copyright (C) 2019 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 . + +#include "pdfpagetransition.h" +#include "pdfdocument.h" + +namespace pdf +{ + +PDFPageTransition PDFPageTransition::parse(const PDFDocument* document, PDFObject object) +{ + PDFPageTransition result; + + if (const PDFDictionary* dictionary = document->getDictionaryFromObject(object)) + { + PDFDocumentDataLoaderDecorator loader(document); + + constexpr const std::array, 12> styles = { + std::pair{ "Split", Style::Split }, + std::pair{ "Blinds", Style::Blinds }, + std::pair{ "Box", Style::Box }, + std::pair{ "Wipe", Style::Wipe }, + std::pair{ "Dissolve", Style::Dissolve }, + std::pair{ "Glitter", Style::Glitter }, + std::pair{ "R", Style::R }, + std::pair{ "Fly", Style::Fly }, + std::pair{ "Push", Style::Push }, + std::pair{ "Cover", Style::Cover }, + std::pair{ "Uncover", Style::Uncover }, + std::pair{ "Fade", Style::Fade } + }; + + constexpr const std::array, 2> orientations = { + std::pair{ "H", Orientation::Horizontal }, + std::pair{ "V", Orientation::Vertical } + }; + + constexpr const std::array, 2> directions = { + std::pair{ "I", Direction::Inward }, + std::pair{ "O", Direction::Outward } + }; + + result.m_style = loader.readEnumByName(dictionary->get("S"), styles.cbegin(), styles.cend(), Style::R); + result.m_duration = loader.readNumberFromDictionary(dictionary, "D", 1.0); + result.m_orientation = loader.readEnumByName(dictionary->get("Dm"), orientations.cbegin(), orientations.cend(), Orientation::Horizontal); + result.m_direction = loader.readEnumByName(dictionary->get("M"), directions.cbegin(), directions.cend(), Direction::Inward); + result.m_angle = loader.readNumberFromDictionary(dictionary, "Di", 0.0); + result.m_scale = loader.readNumberFromDictionary(dictionary, "SS", 1.0); + result.m_rectangular = loader.readBooleanFromDictionary(dictionary, "B", false); + } + + return result; +} + +} // namespace pdf diff --git a/PdfForQtLib/sources/pdfpagetransition.h b/PdfForQtLib/sources/pdfpagetransition.h new file mode 100644 index 0000000..cd822de --- /dev/null +++ b/PdfForQtLib/sources/pdfpagetransition.h @@ -0,0 +1,82 @@ +// Copyright (C) 2019 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 . + +#ifndef PDFPAGETRANSITION_H +#define PDFPAGETRANSITION_H + +#include "pdfobject.h" + +namespace pdf +{ +class PDFDocument; + +/// Page transition during presentation settings. +class PDFPageTransition +{ +public: + + enum class Style + { + Split, + Blinds, + Box, + Wipe, + Dissolve, + Glitter, + R, + Fly, + Push, + Cover, + Uncover, + Fade + }; + + enum class Orientation + { + Horizontal, + Vertical + }; + + enum class Direction + { + Inward, + Outward + }; + + static PDFPageTransition parse(const PDFDocument* document, PDFObject object); + + Style getStyle() const { return m_style; } + PDFReal getDuration() const { return m_duration; } + Orientation getOrientation() const { return m_orientation; } + Direction getDirection() const { return m_direction; } + PDFReal getAngle() const { return m_angle; } + PDFReal getScale() const { return m_scale; } + bool getRectangular() const { return m_rectangular; } + +private: + Style m_style = Style::R; + PDFReal m_duration = 1.0; + Orientation m_orientation = Orientation::Horizontal; + Direction m_direction = Direction::Inward; + PDFReal m_angle = 0.0; + PDFReal m_scale = 1.0; + bool m_rectangular = false; +}; + +} // namespace pdf + +#endif // PDFPAGETRANSITION_H