mirror of
				https://github.com/JakubMelka/PDF4QT.git
				synced 2025-06-05 21:59:17 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			724 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			724 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//    Copyright (C) 2019-2020 Jakub Melka
 | 
						|
//
 | 
						|
//    This file is part of Pdf4Qt.
 | 
						|
//
 | 
						|
//    Pdf4Qt 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.
 | 
						|
//
 | 
						|
//    Pdf4Qt 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 Pdf4Qt.  If not, see <https://www.gnu.org/licenses/>.
 | 
						|
 | 
						|
#include "pdfaction.h"
 | 
						|
#include "pdfdocument.h"
 | 
						|
#include "pdfexception.h"
 | 
						|
#include "pdfencoding.h"
 | 
						|
 | 
						|
namespace pdf
 | 
						|
{
 | 
						|
 | 
						|
PDFActionPtr PDFAction::parse(const PDFObjectStorage* storage, PDFObject object)
 | 
						|
{
 | 
						|
    std::set<PDFObjectReference> usedReferences;
 | 
						|
    return parseImpl(storage, qMove(object), usedReferences);
 | 
						|
}
 | 
						|
 | 
						|
void PDFAction::apply(const std::function<void (const PDFAction*)>& callback)
 | 
						|
{
 | 
						|
    callback(this);
 | 
						|
 | 
						|
    for (const PDFActionPtr& nextAction : m_nextActions)
 | 
						|
    {
 | 
						|
        nextAction->apply(callback);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
std::vector<const PDFAction*> PDFAction::getActionList() const
 | 
						|
{
 | 
						|
    std::vector<const PDFAction*> result;
 | 
						|
    fillActionList(result);
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
PDFActionPtr PDFAction::parseImpl(const PDFObjectStorage* storage, PDFObject object, std::set<PDFObjectReference>& usedReferences)
 | 
						|
{
 | 
						|
    if (object.isReference())
 | 
						|
    {
 | 
						|
        PDFObjectReference reference = object.getReference();
 | 
						|
        if (usedReferences.count(reference))
 | 
						|
        {
 | 
						|
            throw PDFException(PDFTranslationContext::tr("Circular dependence in actions found."));
 | 
						|
        }
 | 
						|
        usedReferences.insert(reference);
 | 
						|
        object = storage->getObjectByReference(reference);
 | 
						|
    }
 | 
						|
 | 
						|
    if (object.isNull())
 | 
						|
    {
 | 
						|
        return PDFActionPtr();
 | 
						|
    }
 | 
						|
 | 
						|
    if (!object.isDictionary())
 | 
						|
    {
 | 
						|
        throw PDFException(PDFTranslationContext::tr("Invalid action."));
 | 
						|
    }
 | 
						|
 | 
						|
    PDFDocumentDataLoaderDecorator loader(storage);
 | 
						|
    const PDFDictionary* dictionary = object.getDictionary();
 | 
						|
    QByteArray name = loader.readNameFromDictionary(dictionary, "S");
 | 
						|
 | 
						|
    if (name == "GoTo") // Goto action
 | 
						|
    {
 | 
						|
        PDFDestination destination = PDFDestination::parse(storage, dictionary->get("D"));
 | 
						|
        PDFDestination structureDestination = PDFDestination::parse(storage, dictionary->get("SD"));
 | 
						|
        return PDFActionPtr(new PDFActionGoTo(qMove(destination), qMove(structureDestination)));
 | 
						|
    }
 | 
						|
    else if (name == "GoToR")
 | 
						|
    {
 | 
						|
        PDFDestination destination = PDFDestination::parse(storage, dictionary->get("D"));
 | 
						|
        PDFDestination structureDestination = PDFDestination::parse(storage, dictionary->get("SD"));
 | 
						|
        PDFFileSpecification fileSpecification = PDFFileSpecification::parse(storage, dictionary->get("F"));
 | 
						|
        return PDFActionPtr(new PDFActionGoToR(qMove(destination), qMove(structureDestination), qMove(fileSpecification), loader.readBooleanFromDictionary(dictionary, "NewWindow", false)));
 | 
						|
    }
 | 
						|
    else if (name == "GoToE")
 | 
						|
    {
 | 
						|
        PDFDestination destination = PDFDestination::parse(storage, dictionary->get("D"));
 | 
						|
        PDFFileSpecification fileSpecification = PDFFileSpecification::parse(storage, dictionary->get("F"));
 | 
						|
        return PDFActionPtr(new PDFActionGoToE(qMove(destination), qMove(fileSpecification), loader.readBooleanFromDictionary(dictionary, "NewWindow", false), storage->getObject(dictionary->get("T"))));
 | 
						|
    }
 | 
						|
    else if (name == "GoToDp")
 | 
						|
    {
 | 
						|
        PDFObjectReference documentPart = loader.readReferenceFromDictionary(dictionary, "Dp");
 | 
						|
        return PDFActionPtr(new PDFActionGoToDp(documentPart));
 | 
						|
    }
 | 
						|
    else if (name == "Launch")
 | 
						|
    {
 | 
						|
        PDFFileSpecification fileSpecification = PDFFileSpecification::parse(storage, dictionary->get("F"));
 | 
						|
        const bool newWindow = loader.readBooleanFromDictionary(dictionary, "NewWindow", false);
 | 
						|
        PDFActionLaunch::Win win;
 | 
						|
 | 
						|
        const PDFObject& winDictionaryObject = storage->getObject(dictionary->get("Win"));
 | 
						|
        if (winDictionaryObject.isDictionary())
 | 
						|
        {
 | 
						|
            const PDFDictionary* winDictionary = winDictionaryObject.getDictionary();
 | 
						|
            win.file = loader.readStringFromDictionary(winDictionary, "F");
 | 
						|
            win.directory = loader.readStringFromDictionary(winDictionary, "D");
 | 
						|
            win.operation = loader.readStringFromDictionary(winDictionary, "O");
 | 
						|
            win.parameters = loader.readStringFromDictionary(winDictionary, "P");
 | 
						|
        }
 | 
						|
 | 
						|
        return PDFActionPtr(new PDFActionLaunch(qMove(fileSpecification), newWindow, qMove(win)));
 | 
						|
    }
 | 
						|
    else if (name == "Thread")
 | 
						|
    {
 | 
						|
        PDFFileSpecification fileSpecification = PDFFileSpecification::parse(storage, dictionary->get("F"));
 | 
						|
        PDFActionThread::Thread thread;
 | 
						|
        PDFActionThread::Bead bead;
 | 
						|
 | 
						|
        const PDFObject& threadObject = dictionary->get("D");
 | 
						|
        if (threadObject.isReference())
 | 
						|
        {
 | 
						|
            thread = threadObject.getReference();
 | 
						|
        }
 | 
						|
        else if (threadObject.isInt())
 | 
						|
        {
 | 
						|
            thread = threadObject.getInteger();
 | 
						|
        }
 | 
						|
        else if (threadObject.isString())
 | 
						|
        {
 | 
						|
            thread = PDFEncoding::convertTextString(threadObject.getString());
 | 
						|
        }
 | 
						|
        const PDFObject& beadObject = dictionary->get("B");
 | 
						|
        if (beadObject.isReference())
 | 
						|
        {
 | 
						|
            bead = beadObject.getReference();
 | 
						|
        }
 | 
						|
        else if (beadObject.isInt())
 | 
						|
        {
 | 
						|
            bead = beadObject.getInteger();
 | 
						|
        }
 | 
						|
 | 
						|
        return PDFActionPtr(new PDFActionThread(qMove(fileSpecification), qMove(thread), qMove(bead)));
 | 
						|
    }
 | 
						|
    else if (name == "URI")
 | 
						|
    {
 | 
						|
        return PDFActionPtr(new PDFActionURI(loader.readStringFromDictionary(dictionary, "URI"), loader.readBooleanFromDictionary(dictionary, "IsMap", false)));
 | 
						|
    }
 | 
						|
    else if (name == "Sound")
 | 
						|
    {
 | 
						|
        const PDFReal volume = loader.readNumberFromDictionary(dictionary, "Volume", 1.0);
 | 
						|
        const bool isSynchronous = loader.readBooleanFromDictionary(dictionary, "Synchronous", false);
 | 
						|
        const bool isRepeat = loader.readBooleanFromDictionary(dictionary, "Repeat", false);
 | 
						|
        const bool isMix = loader.readBooleanFromDictionary(dictionary, "Mix", false);
 | 
						|
        return PDFActionPtr(new PDFActionSound(PDFSound::parse(storage, dictionary->get("Sound")), volume, isSynchronous, isRepeat, isMix));
 | 
						|
    }
 | 
						|
    else if (name == "Movie")
 | 
						|
    {
 | 
						|
        constexpr const std::array<std::pair<const char*, PDFActionMovie::Operation>, 4> operations = {
 | 
						|
            std::pair<const char*, PDFActionMovie::Operation>{ "Play", PDFActionMovie::Operation::Play },
 | 
						|
            std::pair<const char*, PDFActionMovie::Operation>{ "Stop", PDFActionMovie::Operation::Stop },
 | 
						|
            std::pair<const char*, PDFActionMovie::Operation>{ "Pause", PDFActionMovie::Operation::Pause },
 | 
						|
            std::pair<const char*, PDFActionMovie::Operation>{ "Resume", PDFActionMovie::Operation::Resume }
 | 
						|
        };
 | 
						|
 | 
						|
        // Jakub Melka: parse the movie action
 | 
						|
        PDFObject annotationObject = dictionary->get("Annotation");
 | 
						|
        PDFObjectReference annotation = annotationObject.isReference() ? annotationObject.getReference() : PDFObjectReference();
 | 
						|
        QString title = loader.readTextStringFromDictionary(dictionary, "T", QString());
 | 
						|
        PDFActionMovie::Operation operation = loader.readEnumByName(dictionary->get("Operation"), operations.cbegin(), operations.cend(), PDFActionMovie::Operation::Play);
 | 
						|
 | 
						|
        return PDFActionPtr(new PDFActionMovie(annotation, qMove(title), operation));
 | 
						|
    }
 | 
						|
    else if (name == "Hide")
 | 
						|
    {
 | 
						|
        std::vector<PDFObjectReference> annotations;
 | 
						|
        std::vector<QString> fieldNames;
 | 
						|
 | 
						|
        const PDFObject& object = dictionary->get("T");
 | 
						|
        if (object.isReference())
 | 
						|
        {
 | 
						|
            annotations = { object.getReference() };
 | 
						|
        }
 | 
						|
        else if (object.isString())
 | 
						|
        {
 | 
						|
            fieldNames = { loader.readTextString(object, QString()) };
 | 
						|
        }
 | 
						|
        else if (object.isArray())
 | 
						|
        {
 | 
						|
            const PDFArray* items = object.getArray();
 | 
						|
            for (size_t i = 0; i < items->getCount(); ++i)
 | 
						|
            {
 | 
						|
                const PDFObject& itemObject = items->getItem(i);
 | 
						|
                if (itemObject.isReference())
 | 
						|
                {
 | 
						|
                    annotations.push_back(itemObject.getReference());
 | 
						|
                }
 | 
						|
                else if (itemObject.isString())
 | 
						|
                {
 | 
						|
                    fieldNames.push_back(loader.readTextString(itemObject, QString()));
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        const bool hide = loader.readBooleanFromDictionary(dictionary, "H", true);
 | 
						|
        return PDFActionPtr(new PDFActionHide(qMove(annotations), qMove(fieldNames), hide));
 | 
						|
    }
 | 
						|
    else if (name == "Named")
 | 
						|
    {
 | 
						|
        constexpr const std::array<std::pair<const char*, PDFActionNamed::NamedActionType>, 4> types = {
 | 
						|
            std::pair<const char*, PDFActionNamed::NamedActionType>{ "NextPage", PDFActionNamed::NamedActionType::NextPage },
 | 
						|
            std::pair<const char*, PDFActionNamed::NamedActionType>{ "PrevPage", PDFActionNamed::NamedActionType::PrevPage },
 | 
						|
            std::pair<const char*, PDFActionNamed::NamedActionType>{ "FirstPage", PDFActionNamed::NamedActionType::FirstPage },
 | 
						|
            std::pair<const char*, PDFActionNamed::NamedActionType>{ "LastPage", PDFActionNamed::NamedActionType::LastPage }
 | 
						|
        };
 | 
						|
 | 
						|
        QByteArray name = loader.readNameFromDictionary(dictionary, "N");
 | 
						|
        PDFActionNamed::NamedActionType actionType = loader.readEnumByName(dictionary->get("N"), types.cbegin(), types.cend(), PDFActionNamed::NamedActionType::Custom);
 | 
						|
        return PDFActionPtr(new PDFActionNamed(actionType, qMove(name)));
 | 
						|
    }
 | 
						|
    else if (name == "SetOCGState")
 | 
						|
    {
 | 
						|
        const bool isRadioButtonsPreserved = loader.readBooleanFromDictionary(dictionary, "PreserveRB", true);
 | 
						|
        PDFActionSetOCGState::StateChangeItems items;
 | 
						|
 | 
						|
        PDFObject stateArrayObject = storage->getObject(dictionary->get("State"));
 | 
						|
        if (stateArrayObject.isArray())
 | 
						|
        {
 | 
						|
            constexpr const std::array<std::pair<const char*, PDFActionSetOCGState::SwitchType>, 3> types = {
 | 
						|
                std::pair<const char*, PDFActionSetOCGState::SwitchType>{ "ON", PDFActionSetOCGState::SwitchType::ON },
 | 
						|
                std::pair<const char*, PDFActionSetOCGState::SwitchType>{ "OFF", PDFActionSetOCGState::SwitchType::OFF },
 | 
						|
                std::pair<const char*, PDFActionSetOCGState::SwitchType>{ "Toggle", PDFActionSetOCGState::SwitchType::Toggle }
 | 
						|
            };
 | 
						|
 | 
						|
            PDFActionSetOCGState::SwitchType switchType = PDFActionSetOCGState::SwitchType::ON;
 | 
						|
            const PDFArray* stateArray = stateArrayObject.getArray();
 | 
						|
            items.reserve(stateArray->getCount());
 | 
						|
            for (size_t i = 0; i < stateArray->getCount(); ++i)
 | 
						|
            {
 | 
						|
                const PDFObject& item = stateArray->getItem(i);
 | 
						|
                if (item.isName())
 | 
						|
                {
 | 
						|
                    switchType = loader.readEnumByName(item, types.cbegin(), types.cend(), PDFActionSetOCGState::SwitchType::ON);
 | 
						|
                }
 | 
						|
                else if (item.isReference())
 | 
						|
                {
 | 
						|
                    items.emplace_back(switchType, item.getReference());
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        return PDFActionPtr(new PDFActionSetOCGState(qMove(items), isRadioButtonsPreserved));
 | 
						|
    }
 | 
						|
    else if (name == "Rendition")
 | 
						|
    {
 | 
						|
        PDFObject annotationObject = dictionary->get("AN");
 | 
						|
        std::optional<PDFRendition> rendition;
 | 
						|
        PDFObjectReference annotation = annotationObject.isReference() ? annotationObject.getReference() : PDFObjectReference();
 | 
						|
        PDFActionRendition::Operation operation = static_cast<PDFActionRendition::Operation>(loader.readIntegerFromDictionary(dictionary, "OP", 4));
 | 
						|
        QString javascript;
 | 
						|
 | 
						|
        if (dictionary->hasKey("R"))
 | 
						|
        {
 | 
						|
            rendition = PDFRendition::parse(storage, dictionary->get("R"));
 | 
						|
        }
 | 
						|
        PDFObject javascriptObject = storage->getObject(dictionary->get("JS"));
 | 
						|
        if (javascriptObject.isString())
 | 
						|
        {
 | 
						|
            javascript = PDFEncoding::convertTextString(javascriptObject.getString());
 | 
						|
        }
 | 
						|
        else if (javascriptObject.isStream())
 | 
						|
        {
 | 
						|
            javascript = PDFEncoding::convertTextString(storage->getDecodedStream(javascriptObject.getStream()));
 | 
						|
        }
 | 
						|
 | 
						|
        return PDFActionPtr(new PDFActionRendition(qMove(rendition), annotation, operation, qMove(javascript)));
 | 
						|
    }
 | 
						|
    else if (name == "Trans")
 | 
						|
    {
 | 
						|
        return PDFActionPtr(new PDFActionTransition(PDFPageTransition::parse(storage, dictionary->get("Trans"))));
 | 
						|
    }
 | 
						|
    else if (name == "GoTo3DView")
 | 
						|
    {
 | 
						|
        return PDFActionPtr(new PDFActionGoTo3DView(dictionary->get("TA"), dictionary->get("V")));
 | 
						|
    }
 | 
						|
    else if (name == "JavaScript")
 | 
						|
    {
 | 
						|
        QByteArray textJavaScript;
 | 
						|
        const PDFObject& javaScriptObject = storage->getObject(dictionary->get("JS"));
 | 
						|
        if (javaScriptObject.isString())
 | 
						|
        {
 | 
						|
            textJavaScript = javaScriptObject.getString();
 | 
						|
        }
 | 
						|
        else if (javaScriptObject.isStream())
 | 
						|
        {
 | 
						|
            textJavaScript = storage->getDecodedStream(javaScriptObject.getStream());
 | 
						|
        }
 | 
						|
        return PDFActionPtr(new PDFActionJavaScript(PDFEncoding::convertTextString(textJavaScript)));
 | 
						|
    }
 | 
						|
    else if (name == "RichMediaExecute")
 | 
						|
    {
 | 
						|
        PDFObjectReference richMediaAnnotation = loader.readReferenceFromDictionary(dictionary, "TA");
 | 
						|
        PDFObjectReference richMediaInstance = loader.readReferenceFromDictionary(dictionary, "TI");
 | 
						|
 | 
						|
        QString command;
 | 
						|
        PDFObject arguments;
 | 
						|
 | 
						|
        if (const PDFDictionary* commandDictionary = storage->getDictionaryFromObject(dictionary->get("CMD")))
 | 
						|
        {
 | 
						|
            command = loader.readTextStringFromDictionary(commandDictionary, "C", QString());
 | 
						|
            arguments = commandDictionary->get("A");
 | 
						|
        }
 | 
						|
 | 
						|
        return PDFActionPtr(new PDFActionRichMediaExecute(richMediaAnnotation, richMediaInstance, qMove(command), qMove(arguments)));
 | 
						|
    }
 | 
						|
    else if (name == "SubmitForm")
 | 
						|
    {
 | 
						|
        PDFFormAction::FieldScope fieldScope = PDFFormAction::FieldScope::All;
 | 
						|
        PDFFileSpecification url = PDFFileSpecification::parse(storage, dictionary->get("F"));
 | 
						|
        PDFFormAction::FieldList fieldList = PDFFormAction::parseFieldList(storage, dictionary->get("Fields"), fieldScope);
 | 
						|
        PDFActionSubmitForm::SubmitFlags flags = static_cast<PDFActionSubmitForm::SubmitFlags>(loader.readIntegerFromDictionary(dictionary, "Flags", 0));
 | 
						|
        QByteArray charset = loader.readStringFromDictionary(dictionary, "CharSet");
 | 
						|
 | 
						|
        if (fieldScope == PDFFormAction::FieldScope::Include &&
 | 
						|
            flags.testFlag(PDFActionSubmitForm::IncludeExclude))
 | 
						|
        {
 | 
						|
            fieldScope = PDFFormAction::FieldScope::Exclude;
 | 
						|
        }
 | 
						|
 | 
						|
        return PDFActionPtr(new PDFActionSubmitForm(fieldScope, qMove(fieldList), qMove(url), qMove(charset), flags));
 | 
						|
    }
 | 
						|
    else if (name == "ResetForm")
 | 
						|
    {
 | 
						|
        PDFFormAction::FieldScope fieldScope = PDFFormAction::FieldScope::All;
 | 
						|
        PDFFormAction::FieldList fieldList = PDFFormAction::parseFieldList(storage, dictionary->get("Fields"), fieldScope);
 | 
						|
        PDFActionResetForm::ResetFlags flags = static_cast<PDFActionResetForm::ResetFlags>(loader.readIntegerFromDictionary(dictionary, "Flags", 0));
 | 
						|
 | 
						|
        if (fieldScope == PDFFormAction::FieldScope::Include &&
 | 
						|
            flags.testFlag(PDFActionResetForm::IncludeExclude))
 | 
						|
        {
 | 
						|
            fieldScope = PDFFormAction::FieldScope::Exclude;
 | 
						|
        }
 | 
						|
 | 
						|
        return PDFActionPtr(new PDFActionResetForm(fieldScope, qMove(fieldList), flags));
 | 
						|
    }
 | 
						|
    else if (name == "ImportData")
 | 
						|
    {
 | 
						|
        PDFFileSpecification file = PDFFileSpecification::parse(storage, dictionary->get("F"));
 | 
						|
        return PDFActionPtr(new PDFActionImportDataForm(qMove(file)));
 | 
						|
    }
 | 
						|
 | 
						|
    return PDFActionPtr();
 | 
						|
}
 | 
						|
 | 
						|
void PDFAction::fillActionList(std::vector<const PDFAction*>& actionList) const
 | 
						|
{
 | 
						|
    actionList.push_back(this);
 | 
						|
 | 
						|
    for (const PDFActionPtr& actionPointer : m_nextActions)
 | 
						|
    {
 | 
						|
        if (actionPointer)
 | 
						|
        {
 | 
						|
            actionPointer->fillActionList(actionList);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
PDFDestination PDFDestination::parse(const PDFObjectStorage* storage, PDFObject object)
 | 
						|
{
 | 
						|
    PDFDestination result;
 | 
						|
    object = storage->getObject(object);
 | 
						|
 | 
						|
    if (object.isName() || object.isString())
 | 
						|
    {
 | 
						|
        QByteArray name = object.getString();
 | 
						|
        result.m_destinationType = DestinationType::Named;
 | 
						|
        result.m_name = name;
 | 
						|
    }
 | 
						|
    else if (object.isArray())
 | 
						|
    {
 | 
						|
        const PDFArray* array = object.getArray();
 | 
						|
        if (array->getCount() < 2)
 | 
						|
        {
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        PDFDocumentDataLoaderDecorator loader(storage);
 | 
						|
 | 
						|
        // First parse page number/page index
 | 
						|
        PDFObject pageNumberObject = array->getItem(0);
 | 
						|
        if (pageNumberObject.isReference())
 | 
						|
        {
 | 
						|
            result.m_pageReference = pageNumberObject.getReference();
 | 
						|
        }
 | 
						|
        else if (pageNumberObject.isInt())
 | 
						|
        {
 | 
						|
            result.m_pageIndex = pageNumberObject.getInteger();
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        QByteArray name = loader.readName(array->getItem(1));
 | 
						|
 | 
						|
        size_t currentIndex = 2;
 | 
						|
        auto readNumber = [&]()
 | 
						|
        {
 | 
						|
            if (currentIndex < array->getCount())
 | 
						|
            {
 | 
						|
                return loader.readNumber(array->getItem(currentIndex++), 0.0);
 | 
						|
            }
 | 
						|
            return 0.0;
 | 
						|
        };
 | 
						|
 | 
						|
        if (name == "XYZ")
 | 
						|
        {
 | 
						|
            result.m_destinationType = DestinationType::XYZ;
 | 
						|
            result.m_left = readNumber();
 | 
						|
            result.m_top = readNumber();
 | 
						|
            result.m_zoom = readNumber();
 | 
						|
        }
 | 
						|
        else if (name == "Fit")
 | 
						|
        {
 | 
						|
            result.m_destinationType = DestinationType::Fit;
 | 
						|
        }
 | 
						|
        else if (name == "FitH")
 | 
						|
        {
 | 
						|
            result.m_destinationType = DestinationType::FitH;
 | 
						|
            result.m_top = readNumber();
 | 
						|
        }
 | 
						|
        else if (name == "FitV")
 | 
						|
        {
 | 
						|
            result.m_destinationType = DestinationType::FitV;
 | 
						|
            result.m_left = readNumber();
 | 
						|
        }
 | 
						|
        else if (name == "FitR")
 | 
						|
        {
 | 
						|
            result.m_destinationType = DestinationType::FitR;
 | 
						|
            result.m_left = readNumber();
 | 
						|
            result.m_bottom = readNumber();
 | 
						|
            result.m_right = readNumber();
 | 
						|
            result.m_top = readNumber();
 | 
						|
        }
 | 
						|
        else if (name == "FitB")
 | 
						|
        {
 | 
						|
            result.m_destinationType = DestinationType::FitB;
 | 
						|
        }
 | 
						|
        else if (name == "FitBH")
 | 
						|
        {
 | 
						|
            result.m_destinationType = DestinationType::FitBH;
 | 
						|
            result.m_top = readNumber();
 | 
						|
        }
 | 
						|
        else if (name == "FitBV")
 | 
						|
        {
 | 
						|
            result.m_destinationType = DestinationType::FitBV;
 | 
						|
            result.m_left = readNumber();
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
void PDFDestination::setDestinationType(DestinationType destinationType)
 | 
						|
{
 | 
						|
    m_destinationType = destinationType;
 | 
						|
}
 | 
						|
 | 
						|
void PDFDestination::setLeft(PDFReal left)
 | 
						|
{
 | 
						|
    m_left = left;
 | 
						|
}
 | 
						|
 | 
						|
void PDFDestination::setTop(PDFReal top)
 | 
						|
{
 | 
						|
    m_top = top;
 | 
						|
}
 | 
						|
 | 
						|
void PDFDestination::setRight(PDFReal right)
 | 
						|
{
 | 
						|
    m_right = right;
 | 
						|
}
 | 
						|
 | 
						|
void PDFDestination::setBottom(PDFReal bottom)
 | 
						|
{
 | 
						|
    m_bottom = bottom;
 | 
						|
}
 | 
						|
 | 
						|
void PDFDestination::setZoom(PDFReal zoom)
 | 
						|
{
 | 
						|
    m_zoom = zoom;
 | 
						|
}
 | 
						|
 | 
						|
void PDFDestination::setName(const QByteArray& name)
 | 
						|
{
 | 
						|
    m_name = name;
 | 
						|
}
 | 
						|
 | 
						|
void PDFDestination::setPageReference(PDFObjectReference pageReference)
 | 
						|
{
 | 
						|
    m_pageReference = pageReference;
 | 
						|
}
 | 
						|
 | 
						|
void PDFDestination::setPageIndex(PDFInteger pageIndex)
 | 
						|
{
 | 
						|
    m_pageIndex = pageIndex;
 | 
						|
}
 | 
						|
 | 
						|
PDFDestination PDFDestination::createXYZ(PDFObjectReference page, PDFReal left, PDFReal top, PDFReal zoom)
 | 
						|
{
 | 
						|
    PDFDestination result;
 | 
						|
    result.setDestinationType(DestinationType::XYZ);
 | 
						|
    result.setPageReference(page);
 | 
						|
    result.setLeft(left);
 | 
						|
    result.setTop(top);
 | 
						|
    result.setZoom(zoom);
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
PDFDestination PDFDestination::createFit(PDFObjectReference page)
 | 
						|
{
 | 
						|
    PDFDestination result;
 | 
						|
    result.setDestinationType(DestinationType::Fit);
 | 
						|
    result.setPageReference(page);
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
PDFDestination PDFDestination::createFitH(PDFObjectReference page, PDFReal top)
 | 
						|
{
 | 
						|
    PDFDestination result;
 | 
						|
    result.setDestinationType(DestinationType::FitH);
 | 
						|
    result.setPageReference(page);
 | 
						|
    result.setTop(top);
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
PDFDestination PDFDestination::createFitV(PDFObjectReference page, PDFReal left)
 | 
						|
{
 | 
						|
    PDFDestination result;
 | 
						|
    result.setDestinationType(DestinationType::FitV);
 | 
						|
    result.setPageReference(page);
 | 
						|
    result.setLeft(left);
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
PDFDestination PDFDestination::createFitR(PDFObjectReference page, PDFReal left, PDFReal top, PDFReal right, PDFReal bottom)
 | 
						|
{
 | 
						|
    PDFDestination result;
 | 
						|
    result.setDestinationType(DestinationType::FitR);
 | 
						|
    result.setPageReference(page);
 | 
						|
    result.setLeft(left);
 | 
						|
    result.setTop(top);
 | 
						|
    result.setRight(right);
 | 
						|
    result.setBottom(bottom);
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
PDFDestination PDFDestination::createFitB(PDFObjectReference page)
 | 
						|
{
 | 
						|
    PDFDestination result;
 | 
						|
    result.setDestinationType(DestinationType::FitB);
 | 
						|
    result.setPageReference(page);
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
PDFDestination PDFDestination::createFitBH(PDFObjectReference page, PDFReal top)
 | 
						|
{
 | 
						|
    PDFDestination result;
 | 
						|
    result.setDestinationType(DestinationType::FitBH);
 | 
						|
    result.setPageReference(page);
 | 
						|
    result.setTop(top);
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
PDFDestination PDFDestination::createFitBV(PDFObjectReference page, PDFReal left)
 | 
						|
{
 | 
						|
    PDFDestination result;
 | 
						|
    result.setDestinationType(DestinationType::FitBV);
 | 
						|
    result.setPageReference(page);
 | 
						|
    result.setLeft(left);
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
PDFDestination PDFDestination::createNamed(const QByteArray& name)
 | 
						|
{
 | 
						|
    PDFDestination result;
 | 
						|
    result.setDestinationType(DestinationType::Named);
 | 
						|
    result.setName(name);
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
bool PDFDestination::hasLeft() const
 | 
						|
{
 | 
						|
    switch (m_destinationType)
 | 
						|
    {
 | 
						|
        case DestinationType::XYZ:
 | 
						|
        case DestinationType::FitV:
 | 
						|
        case DestinationType::FitBV:
 | 
						|
        case DestinationType::FitR:
 | 
						|
            return true;
 | 
						|
 | 
						|
        default:
 | 
						|
            break;
 | 
						|
    }
 | 
						|
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
bool PDFDestination::hasTop() const
 | 
						|
{
 | 
						|
    switch (m_destinationType)
 | 
						|
    {
 | 
						|
        case DestinationType::XYZ:
 | 
						|
        case DestinationType::FitH:
 | 
						|
        case DestinationType::FitBH:
 | 
						|
        case DestinationType::FitR:
 | 
						|
            return true;
 | 
						|
 | 
						|
        default:
 | 
						|
            break;
 | 
						|
    }
 | 
						|
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
bool PDFDestination::hasRight() const
 | 
						|
{
 | 
						|
    switch (m_destinationType)
 | 
						|
    {
 | 
						|
        case DestinationType::FitR:
 | 
						|
            return true;
 | 
						|
 | 
						|
        default:
 | 
						|
            break;
 | 
						|
    }
 | 
						|
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
bool PDFDestination::hasBottom() const
 | 
						|
{
 | 
						|
    switch (m_destinationType)
 | 
						|
    {
 | 
						|
        case DestinationType::FitR:
 | 
						|
            return true;
 | 
						|
 | 
						|
        default:
 | 
						|
            break;
 | 
						|
    }
 | 
						|
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
bool PDFDestination::hasZoom() const
 | 
						|
{
 | 
						|
    switch (m_destinationType)
 | 
						|
    {
 | 
						|
        case DestinationType::XYZ:
 | 
						|
            return true;
 | 
						|
 | 
						|
        default:
 | 
						|
            break;
 | 
						|
    }
 | 
						|
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
PDFFormAction::FieldList PDFFormAction::parseFieldList(const PDFObjectStorage* storage, PDFObject object, FieldScope& fieldScope)
 | 
						|
{
 | 
						|
    FieldList result;
 | 
						|
 | 
						|
    object = storage->getObject(object);
 | 
						|
    if (object.isArray())
 | 
						|
    {
 | 
						|
        PDFDocumentDataLoaderDecorator loader(storage);
 | 
						|
 | 
						|
        const PDFArray* fieldsArray = object.getArray();
 | 
						|
        for (size_t i = 0, count = fieldsArray->getCount(); i < count; ++i)
 | 
						|
        {
 | 
						|
            PDFObject fieldObject = fieldsArray->getItem(i);
 | 
						|
            if (fieldObject.isReference())
 | 
						|
            {
 | 
						|
                result.fieldReferences.push_back(fieldObject.getReference());
 | 
						|
            }
 | 
						|
            else if (fieldObject.isString())
 | 
						|
            {
 | 
						|
                result.qualifiedNames.push_back(loader.readTextString(fieldObject, QString()));
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (!result.isEmpty())
 | 
						|
    {
 | 
						|
        fieldScope = FieldScope::Include;
 | 
						|
    }
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
QString PDFActionURI::getURIString() const
 | 
						|
{
 | 
						|
    return QString::fromUtf8(m_URI);
 | 
						|
}
 | 
						|
 | 
						|
void PDFActionGoTo::setDestination(const PDFDestination& destination)
 | 
						|
{
 | 
						|
    m_destination = destination;
 | 
						|
}
 | 
						|
 | 
						|
void PDFActionGoTo::setStructureDestination(const PDFDestination& structureDestination)
 | 
						|
{
 | 
						|
    m_structureDestination = structureDestination;
 | 
						|
}
 | 
						|
 | 
						|
}   // namespace pdf
 |