| //======================================================================== |
| // |
| // Link.h |
| // |
| // Copyright 1996-2003 Glyph & Cog, LLC |
| // |
| //======================================================================== |
| |
| //======================================================================== |
| // |
| // Modified under the Poppler project - http://poppler.freedesktop.org |
| // |
| // All changes made under the Poppler project to this file are licensed |
| // under GPL version 2 or later |
| // |
| // Copyright (C) 2006, 2008 Pino Toscano <pino@kde.org> |
| // Copyright (C) 2008 Hugo Mercier <hmercier31@gmail.com> |
| // Copyright (C) 2010, 2011 Carlos Garcia Campos <carlosgc@gnome.org> |
| // Copyright (C) 2012 Tobias Koening <tobias.koenig@kdab.com> |
| // Copyright (C) 2018, 2019 Albert Astals Cid <aacid@kde.org> |
| // Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by the LiMux project of the city of Munich |
| // Copyright (C) 2018 Intevation GmbH <intevation@intevation.de> |
| // Copyright (C) 2019 Oliver Sander <oliver.sander@tu-dresden.de> |
| // |
| // To see a description of the changes please see the Changelog file that |
| // came with your tarball or type make ChangeLog if you are building from git |
| // |
| //======================================================================== |
| |
| #ifndef LINK_H |
| #define LINK_H |
| |
| #include "Object.h" |
| #include <memory> |
| #include <set> |
| |
| class GooString; |
| class Array; |
| class Dict; |
| class Sound; |
| class MediaRendition; |
| class AnnotLink; |
| class Annots; |
| |
| //------------------------------------------------------------------------ |
| // LinkAction |
| //------------------------------------------------------------------------ |
| |
| enum LinkActionKind { |
| actionGoTo, // go to destination |
| actionGoToR, // go to destination in new file |
| actionLaunch, // launch app (or open document) |
| actionURI, // URI |
| actionNamed, // named action |
| actionMovie, // movie action |
| actionRendition, // rendition action |
| actionSound, // sound action |
| actionJavaScript, // JavaScript action |
| actionOCGState, // Set-OCG-State action |
| actionHide, // Hide action |
| actionUnknown // anything else |
| }; |
| |
| class LinkAction { |
| public: |
| |
| LinkAction(); |
| LinkAction(const LinkAction &) = delete; |
| LinkAction& operator=(const LinkAction &other) = delete; |
| |
| // Destructor. |
| virtual ~LinkAction(); |
| |
| // Was the LinkAction created successfully? |
| virtual bool isOk() const = 0; |
| |
| // Check link action type. |
| virtual LinkActionKind getKind() const = 0; |
| |
| // Parse a destination (old-style action) name, string, or array. |
| static LinkAction *parseDest(const Object *obj); |
| |
| // Parse an action dictionary. |
| static LinkAction *parseAction(const Object *obj, const GooString *baseURI = nullptr); |
| |
| // A List of the next actions to execute in order. |
| // The list contains pointer to LinkAction objects. |
| const std::vector<LinkAction*> *nextActions() const; |
| |
| // Sets the next action list. Takes ownership of the actions. |
| void setNextActions(std::vector<LinkAction*> *actions); |
| |
| private: |
| static LinkAction *parseAction(const Object *obj, const GooString *baseURI, std::set<int> *seenNextActions); |
| |
| std::vector<LinkAction*> *nextActionList; |
| }; |
| |
| //------------------------------------------------------------------------ |
| // LinkDest |
| //------------------------------------------------------------------------ |
| |
| enum LinkDestKind { |
| destXYZ, |
| destFit, |
| destFitH, |
| destFitV, |
| destFitR, |
| destFitB, |
| destFitBH, |
| destFitBV |
| }; |
| |
| class LinkDest { |
| public: |
| |
| // Build a LinkDest from the array. |
| LinkDest(const Array *a); |
| |
| // Copy a LinkDest. |
| LinkDest *copy() const { return new LinkDest(this); } |
| |
| // Was the LinkDest created successfully? |
| bool isOk() const { return ok; } |
| |
| // Accessors. |
| LinkDestKind getKind() const { return kind; } |
| bool isPageRef() const { return pageIsRef; } |
| int getPageNum() const { return pageNum; } |
| Ref getPageRef() const { return pageRef; } |
| double getLeft() const { return left; } |
| double getBottom() const { return bottom; } |
| double getRight() const { return right; } |
| double getTop() const { return top; } |
| double getZoom() const { return zoom; } |
| bool getChangeLeft() const { return changeLeft; } |
| bool getChangeTop() const { return changeTop; } |
| bool getChangeZoom() const { return changeZoom; } |
| |
| private: |
| |
| LinkDestKind kind; // destination type |
| bool pageIsRef; // is the page a reference or number? |
| union { |
| Ref pageRef; // reference to page |
| int pageNum; // one-relative page number |
| }; |
| double left, bottom; // position |
| double right, top; |
| double zoom; // zoom factor |
| bool changeLeft, changeTop; // which position components to change: |
| bool changeZoom; // destXYZ uses all three; |
| // destFitH/BH use changeTop; |
| // destFitV/BV use changeLeft |
| bool ok; // set if created successfully |
| |
| LinkDest(const LinkDest *dest); |
| }; |
| |
| //------------------------------------------------------------------------ |
| // LinkGoTo |
| //------------------------------------------------------------------------ |
| |
| class LinkGoTo: public LinkAction { |
| public: |
| |
| // Build a LinkGoTo from a destination (dictionary, name, or string). |
| LinkGoTo(const Object *destObj); |
| |
| // Destructor. |
| ~LinkGoTo(); |
| |
| // Was the LinkGoTo created successfully? |
| bool isOk() const override { return dest || namedDest; } |
| |
| // Accessors. |
| LinkActionKind getKind() const override { return actionGoTo; } |
| const LinkDest *getDest() const { return dest; } |
| const GooString *getNamedDest() const { return namedDest; } |
| |
| private: |
| |
| LinkDest *dest; // regular destination (nullptr for remote |
| // link with bad destination) |
| GooString *namedDest; // named destination (only one of dest and |
| // and namedDest may be non-nullptr) |
| }; |
| |
| //------------------------------------------------------------------------ |
| // LinkGoToR |
| //------------------------------------------------------------------------ |
| |
| class LinkGoToR: public LinkAction { |
| public: |
| |
| // Build a LinkGoToR from a file spec (dictionary) and destination |
| // (dictionary, name, or string). |
| LinkGoToR(Object *fileSpecObj, Object *destObj); |
| |
| // Destructor. |
| ~LinkGoToR(); |
| |
| // Was the LinkGoToR created successfully? |
| bool isOk() const override { return fileName && (dest || namedDest); } |
| |
| // Accessors. |
| LinkActionKind getKind() const override { return actionGoToR; } |
| const GooString *getFileName() const { return fileName; } |
| const LinkDest *getDest() const { return dest; } |
| const GooString *getNamedDest() const { return namedDest; } |
| |
| private: |
| |
| GooString *fileName; // file name |
| LinkDest *dest; // regular destination (nullptr for remote |
| // link with bad destination) |
| GooString *namedDest; // named destination (only one of dest and |
| // and namedDest may be non-nullptr) |
| }; |
| |
| //------------------------------------------------------------------------ |
| // LinkLaunch |
| //------------------------------------------------------------------------ |
| |
| class LinkLaunch: public LinkAction { |
| public: |
| |
| // Build a LinkLaunch from an action dictionary. |
| LinkLaunch(const Object *actionObj); |
| |
| // Destructor. |
| ~LinkLaunch(); |
| |
| // Was the LinkLaunch created successfully? |
| bool isOk() const override { return fileName != nullptr; } |
| |
| // Accessors. |
| LinkActionKind getKind() const override { return actionLaunch; } |
| const GooString *getFileName() const { return fileName; } |
| const GooString *getParams() const { return params; } |
| |
| private: |
| |
| GooString *fileName; // file name |
| GooString *params; // parameters |
| }; |
| |
| //------------------------------------------------------------------------ |
| // LinkURI |
| //------------------------------------------------------------------------ |
| |
| class LinkURI: public LinkAction { |
| public: |
| |
| // Build a LinkURI given the URI (string) and base URI. |
| LinkURI(const Object *uriObj, const GooString *baseURI); |
| |
| // Destructor. |
| ~LinkURI(); |
| |
| // Was the LinkURI created successfully? |
| bool isOk() const override { return uri != nullptr; } |
| |
| // Accessors. |
| LinkActionKind getKind() const override { return actionURI; } |
| const GooString *getURI() const { return uri; } |
| |
| private: |
| |
| GooString *uri; // the URI |
| }; |
| |
| //------------------------------------------------------------------------ |
| // LinkNamed |
| //------------------------------------------------------------------------ |
| |
| class LinkNamed: public LinkAction { |
| public: |
| |
| // Build a LinkNamed given the action name. |
| LinkNamed(const Object *nameObj); |
| |
| ~LinkNamed(); |
| |
| bool isOk() const override { return name != nullptr; } |
| |
| LinkActionKind getKind() const override { return actionNamed; } |
| const GooString *getName() const { return name; } |
| |
| private: |
| |
| GooString *name; |
| }; |
| |
| |
| //------------------------------------------------------------------------ |
| // LinkMovie |
| //------------------------------------------------------------------------ |
| |
| class LinkMovie: public LinkAction { |
| public: |
| |
| enum OperationType { |
| operationTypePlay, |
| operationTypePause, |
| operationTypeResume, |
| operationTypeStop |
| }; |
| |
| LinkMovie(const Object *obj); |
| ~LinkMovie(); |
| |
| bool isOk() const override { return hasAnnotRef() || hasAnnotTitle(); } |
| LinkActionKind getKind() const override { return actionMovie; } |
| |
| // a movie action stores either an indirect reference to a movie annotation |
| // or the movie annotation title |
| |
| bool hasAnnotRef() const { return annotRef != Ref::INVALID(); } |
| bool hasAnnotTitle() const { return annotTitle != nullptr; } |
| const Ref *getAnnotRef() const { return &annotRef; } |
| const GooString *getAnnotTitle() const { return annotTitle; } |
| |
| OperationType getOperation() const { return operation; } |
| |
| private: |
| |
| Ref annotRef; // Annotation |
| GooString *annotTitle; // T |
| |
| OperationType operation; // Operation |
| }; |
| |
| |
| //------------------------------------------------------------------------ |
| // LinkRendition |
| //------------------------------------------------------------------------ |
| |
| class LinkRendition: public LinkAction { |
| public: |
| /** |
| * Describes the possible rendition operations. |
| */ |
| enum RenditionOperation { |
| NoRendition, |
| PlayRendition, |
| StopRendition, |
| PauseRendition, |
| ResumeRendition |
| }; |
| |
| LinkRendition(const Object *Obj); |
| |
| ~LinkRendition(); |
| |
| bool isOk() const override { return true; } |
| |
| LinkActionKind getKind() const override { return actionRendition; } |
| |
| bool hasRenditionObject() const { return renditionObj.isDict(); } |
| const Object* getRenditionObject() const { return &renditionObj; } |
| |
| bool hasScreenAnnot() const { return screenRef != Ref::INVALID(); } |
| Ref getScreenAnnot() const { return screenRef; } |
| |
| RenditionOperation getOperation() const { return operation; } |
| |
| const MediaRendition* getMedia() const { return media; } |
| |
| const GooString *getScript() const { return js; } |
| |
| private: |
| |
| Ref screenRef; |
| Object renditionObj; |
| RenditionOperation operation; |
| |
| MediaRendition* media; |
| |
| GooString *js; |
| }; |
| |
| //------------------------------------------------------------------------ |
| // LinkSound |
| //------------------------------------------------------------------------ |
| |
| class LinkSound: public LinkAction { |
| public: |
| |
| LinkSound(const Object *soundObj); |
| |
| ~LinkSound(); |
| |
| bool isOk() const override { return sound != nullptr; } |
| |
| LinkActionKind getKind() const override { return actionSound; } |
| |
| double getVolume() const { return volume; } |
| bool getSynchronous() const { return sync; } |
| bool getRepeat() const { return repeat; } |
| bool getMix() const { return mix; } |
| Sound *getSound() const { return sound; } |
| |
| private: |
| |
| double volume; |
| bool sync; |
| bool repeat; |
| bool mix; |
| Sound *sound; |
| }; |
| |
| //------------------------------------------------------------------------ |
| // LinkJavaScript |
| //------------------------------------------------------------------------ |
| |
| class LinkJavaScript: public LinkAction { |
| public: |
| |
| // Build a LinkJavaScript given the action name. |
| LinkJavaScript(Object *jsObj); |
| |
| ~LinkJavaScript(); |
| |
| bool isOk() const override { return js != nullptr; } |
| |
| LinkActionKind getKind() const override { return actionJavaScript; } |
| const GooString *getScript() const { return js; } |
| |
| static Object createObject(XRef *xref, const GooString &js); |
| |
| private: |
| |
| GooString *js; |
| }; |
| |
| //------------------------------------------------------------------------ |
| // LinkOCGState |
| //------------------------------------------------------------------------ |
| class LinkOCGState: public LinkAction { |
| public: |
| LinkOCGState(const Object *obj); |
| |
| ~LinkOCGState(); |
| |
| bool isOk() const override { return stateList != nullptr; } |
| |
| LinkActionKind getKind() const override { return actionOCGState; } |
| |
| enum State { On, Off, Toggle}; |
| struct StateList { |
| StateList() { list = nullptr; } |
| ~StateList(); |
| StateList(const StateList &) = delete; |
| StateList& operator=(const StateList &) = delete; |
| State st; |
| std::vector<Ref*> *list; |
| }; |
| |
| const std::vector<StateList*> *getStateList() const { return stateList; } |
| bool getPreserveRB() const { return preserveRB; } |
| |
| private: |
| std::vector<StateList*> *stateList; |
| bool preserveRB; |
| }; |
| |
| //------------------------------------------------------------------------ |
| // LinkHide |
| //------------------------------------------------------------------------ |
| |
| class LinkHide: public LinkAction { |
| public: |
| LinkHide(const Object *hideObj); |
| |
| ~LinkHide(); |
| |
| bool isOk() const override { return targetName != nullptr; } |
| LinkActionKind getKind() const override { return actionHide; } |
| |
| // According to spec the target can be either: |
| // a) A text string containing the fully qualified name of the target |
| // field. |
| // b) An indirect reference to an annotation dictionary. |
| // c) An array of "such dictionaries or text strings". |
| // |
| // While b / c appear to be very uncommon and can't easily be |
| // created with Adobe Acrobat DC. So only support hide |
| // actions with named targets (yet). |
| bool hasTargetName() const { return targetName != nullptr; } |
| const GooString *getTargetName() const { return targetName; } |
| |
| // Should this action show or hide. |
| bool isShowAction() const { return show; } |
| |
| private: |
| GooString *targetName; |
| bool show; |
| }; |
| |
| //------------------------------------------------------------------------ |
| // LinkUnknown |
| //------------------------------------------------------------------------ |
| |
| class LinkUnknown: public LinkAction { |
| public: |
| |
| // Build a LinkUnknown with the specified action type. |
| LinkUnknown(const char *actionA); |
| |
| // Destructor. |
| ~LinkUnknown(); |
| |
| // Was the LinkUnknown create successfully? |
| bool isOk() const override { return action != nullptr; } |
| |
| // Accessors. |
| LinkActionKind getKind() const override { return actionUnknown; } |
| const GooString *getAction() const { return action; } |
| |
| private: |
| |
| GooString *action; // action subtype |
| }; |
| |
| //------------------------------------------------------------------------ |
| // Links |
| //------------------------------------------------------------------------ |
| |
| class Links { |
| public: |
| |
| // Extract links from array of annotations. |
| Links(Annots *annots); |
| |
| // Destructor. |
| ~Links(); |
| |
| Links(const Links &) = delete; |
| Links& operator=(const Links &) = delete; |
| |
| // Iterate through list of links. |
| int getNumLinks() const { return numLinks; } |
| AnnotLink *getLink(int i) const { return links[i]; } |
| |
| // If point <x>,<y> is in a link, return the associated action; |
| // else return nullptr. |
| LinkAction *find(double x, double y) const; |
| |
| // Return true if <x>,<y> is in a link. |
| bool onLink(double x, double y) const; |
| |
| private: |
| |
| AnnotLink **links; |
| int numLinks; |
| }; |
| |
| #endif |