mirror of https://github.com/JakubMelka/PDF4QT.git
1532 lines
58 KiB
C++
1532 lines
58 KiB
C++
// 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/>.
|
|
|
|
#ifndef PDFANNOTATION_H
|
|
#define PDFANNOTATION_H
|
|
|
|
#include "pdfutils.h"
|
|
#include "pdfobject.h"
|
|
#include "pdfaction.h"
|
|
#include "pdffile.h"
|
|
#include "pdfcms.h"
|
|
#include "pdfmultimedia.h"
|
|
#include "pdfmeshqualitysettings.h"
|
|
#include "pdfdocumentdrawinterface.h"
|
|
#include "pdfrenderer.h"
|
|
|
|
#include <QCursor>
|
|
#include <QPainterPath>
|
|
|
|
#include <array>
|
|
|
|
class QKeyEvent;
|
|
class QMouseEvent;
|
|
class QWheelEvent;
|
|
|
|
namespace pdf
|
|
{
|
|
class PDFWidget;
|
|
class PDFObjectStorage;
|
|
class PDFDrawWidgetProxy;
|
|
class PDFFontCache;
|
|
class PDFFormManager;
|
|
class PDFModifiedDocument;
|
|
class PDFOptionalContentActivity;
|
|
class PDFFormFieldWidgetEditor;
|
|
|
|
using TextAlignment = Qt::Alignment;
|
|
using Polygons = std::vector<QPolygonF>;
|
|
|
|
enum class AnnotationType
|
|
{
|
|
Invalid,
|
|
Text,
|
|
Link,
|
|
FreeText,
|
|
Line,
|
|
Square,
|
|
Circle,
|
|
Polygon,
|
|
Polyline,
|
|
Highlight,
|
|
Underline,
|
|
Squiggly,
|
|
StrikeOut,
|
|
Stamp,
|
|
Caret,
|
|
Ink,
|
|
Popup,
|
|
FileAttachment,
|
|
Sound,
|
|
Movie,
|
|
Widget,
|
|
Screen,
|
|
PrinterMark,
|
|
TrapNet,
|
|
Watermark,
|
|
_3D,
|
|
RichMedia
|
|
};
|
|
|
|
enum class AnnotationLineEnding
|
|
{
|
|
None,
|
|
Square,
|
|
Circle,
|
|
Diamond,
|
|
OpenArrow,
|
|
ClosedArrow,
|
|
Butt,
|
|
ROpenArrow,
|
|
RClosedArrow,
|
|
Slash
|
|
};
|
|
|
|
/// Represents annotation's border. Two main definition exists, one is older,
|
|
/// called \p Simple, the other one is defined in BS dictionary of the annotation.
|
|
class PDFAnnotationBorder
|
|
{
|
|
public:
|
|
explicit inline PDFAnnotationBorder() = default;
|
|
|
|
enum class Definition
|
|
{
|
|
Invalid,
|
|
Simple,
|
|
BorderStyle
|
|
};
|
|
|
|
enum class Style
|
|
{
|
|
Solid,
|
|
Dashed,
|
|
Beveled,
|
|
Inset,
|
|
Underline
|
|
};
|
|
|
|
/// Parses the annotation border from the array. If object contains invalid annotation border,
|
|
/// then default annotation border is returned. If object is empty, empty annotation border is returned.
|
|
/// \param storage Object storage
|
|
/// \param object Border object
|
|
static PDFAnnotationBorder parseBorder(const PDFObjectStorage* storage, PDFObject object);
|
|
|
|
/// Parses the annotation border from the BS dictionary. If object contains invalid annotation border,
|
|
/// then default annotation border is returned. If object is empty, empty annotation border is returned.
|
|
/// \param storage Object storage
|
|
/// \param object Border object
|
|
static PDFAnnotationBorder parseBS(const PDFObjectStorage* storage, PDFObject object);
|
|
|
|
/// Returns true, if object is correctly defined
|
|
bool isValid() const { return m_definition != Definition::Invalid; }
|
|
|
|
Definition getDefinition() const { return m_definition; }
|
|
Style getStyle() const { return m_style; }
|
|
PDFReal getHorizontalCornerRadius() const { return m_hCornerRadius; }
|
|
PDFReal getVerticalCornerRadius() const { return m_vCornerRadius; }
|
|
PDFReal getWidth() const { return m_width; }
|
|
const std::vector<PDFReal>& getDashPattern() const { return m_dashPattern; }
|
|
|
|
private:
|
|
Definition m_definition = Definition::Invalid;
|
|
Style m_style = Style::Solid;
|
|
PDFReal m_hCornerRadius = 0.0;
|
|
PDFReal m_vCornerRadius = 0.0;
|
|
PDFReal m_width = 1.0;
|
|
std::vector<PDFReal> m_dashPattern;
|
|
};
|
|
|
|
using AnnotationBorderStyle = PDFAnnotationBorder::Style;
|
|
|
|
/// Annotation border effect
|
|
class PDFAnnotationBorderEffect
|
|
{
|
|
public:
|
|
explicit inline PDFAnnotationBorderEffect() = default;
|
|
|
|
enum class Effect
|
|
{
|
|
None,
|
|
Cloudy
|
|
};
|
|
|
|
/// Parses the annotation border effect from the object. If object contains invalid annotation border effect,
|
|
/// then default annotation border effect is returned. If object is empty, also default annotation border effect is returned.
|
|
/// \param storage Object storage
|
|
/// \param object Border effect object
|
|
static PDFAnnotationBorderEffect parse(const PDFObjectStorage* storage, PDFObject object);
|
|
|
|
private:
|
|
Effect m_effect = Effect::None;
|
|
PDFReal m_intensity = 0.0;
|
|
};
|
|
|
|
/// Storage which handles appearance streams of annotations. Appeareance streams are divided
|
|
/// to three main categories - normal, rollower and down. Each category can have different
|
|
/// states, for example, checkbox can have on/off state. This container can also resolve
|
|
/// queries to obtain appropriate appearance stream.
|
|
class PDFAppeareanceStreams
|
|
{
|
|
public:
|
|
explicit inline PDFAppeareanceStreams() = default;
|
|
|
|
enum class Appearance
|
|
{
|
|
Normal,
|
|
Rollover,
|
|
Down
|
|
};
|
|
|
|
using Key = std::pair<Appearance, QByteArray>;
|
|
|
|
/// Parses annotation appearance streams from the object. If object is invalid, then
|
|
/// empty appearance stream is constructed.
|
|
/// \param storage Object storage
|
|
/// \param object Appearance streams object
|
|
static PDFAppeareanceStreams parse(const PDFObjectStorage* storage, PDFObject object);
|
|
|
|
/// Tries to search for appearance stream for given appearance. If no appearance is found,
|
|
/// then null object is returned.
|
|
/// \param appearance Appearance type
|
|
PDFObject getAppearance(Appearance appearance = Appearance::Normal) const { return getAppearance(appearance, QByteArray()); }
|
|
|
|
/// Tries to resolve appearance stream for given appearance and state. If no appearance is found,
|
|
/// then null object is returned.
|
|
/// \param appearance Appearance type
|
|
/// \param state State name
|
|
PDFObject getAppearance(Appearance appearance, const QByteArray& state) const;
|
|
|
|
/// Returns list of appearance states for given appearance
|
|
/// \param appearance Appearance
|
|
QByteArrayList getAppearanceStates(Appearance appearance) const;
|
|
|
|
/// Returns list of appearance keys
|
|
std::vector<Key> getAppearanceKeys() const;
|
|
|
|
private:
|
|
std::map<Key, PDFObject> m_appearanceStreams;
|
|
};
|
|
|
|
/// Represents annotation's active region, it is used also to
|
|
/// determine underline lines.
|
|
class PDFAnnotationQuadrilaterals
|
|
{
|
|
public:
|
|
using Quadrilateral = std::array<QPointF, 4>;
|
|
using Quadrilaterals = std::vector<Quadrilateral>;
|
|
|
|
inline explicit PDFAnnotationQuadrilaterals() = default;
|
|
inline explicit PDFAnnotationQuadrilaterals(QPainterPath&& path, Quadrilaterals&& quadrilaterals) :
|
|
m_path(qMove(path)),
|
|
m_quadrilaterals(qMove(quadrilaterals))
|
|
{
|
|
|
|
}
|
|
|
|
const QPainterPath& getPath() const { return m_path; }
|
|
const Quadrilaterals& getQuadrilaterals() const { return m_quadrilaterals; }
|
|
bool isEmpty() const { return m_path.isEmpty(); }
|
|
|
|
private:
|
|
QPainterPath m_path;
|
|
Quadrilaterals m_quadrilaterals;
|
|
};
|
|
|
|
/// Represents callout line (line from annotation to some point)
|
|
class PDFAnnotationCalloutLine
|
|
{
|
|
public:
|
|
|
|
enum class Type
|
|
{
|
|
Invalid,
|
|
StartEnd,
|
|
StartKneeEnd
|
|
};
|
|
|
|
inline explicit PDFAnnotationCalloutLine() = default;
|
|
inline explicit PDFAnnotationCalloutLine(QPointF start, QPointF end) :
|
|
m_type(Type::StartEnd),
|
|
m_points({start, end})
|
|
{
|
|
|
|
}
|
|
|
|
inline explicit PDFAnnotationCalloutLine(QPointF start, QPointF knee, QPointF end) :
|
|
m_type(Type::StartKneeEnd),
|
|
m_points({start, knee, end})
|
|
{
|
|
|
|
}
|
|
|
|
/// Parses annotation callout line from the object. If object is invalid, then
|
|
/// invalid callout line is constructed.
|
|
/// \param storage Object storage
|
|
/// \param object Callout line object
|
|
static PDFAnnotationCalloutLine parse(const PDFObjectStorage* storage, PDFObject object);
|
|
|
|
bool isValid() const { return m_type != Type::Invalid; }
|
|
Type getType() const { return m_type; }
|
|
|
|
QPointF getPoint(int index) const { return m_points.at(index); }
|
|
|
|
private:
|
|
Type m_type = Type::Invalid;
|
|
std::array<QPointF, 3> m_points;
|
|
};
|
|
|
|
/// Information about annotation icon fitting (in the widget)
|
|
class PDFAnnotationIconFitInfo
|
|
{
|
|
public:
|
|
inline explicit PDFAnnotationIconFitInfo() = default;
|
|
|
|
enum class ScaleCondition
|
|
{
|
|
Always,
|
|
ScaleBigger,
|
|
ScaleSmaller,
|
|
Never
|
|
};
|
|
|
|
enum class ScaleType
|
|
{
|
|
Anamorphic, ///< Do not keep aspect ratio, fit whole annotation rectangle
|
|
Proportional ///< Keep aspect ratio, annotation rectangle may not be filled fully with icon
|
|
};
|
|
|
|
/// Parses annotation appearance icon fit info from the object. If object is invalid, then
|
|
/// default appearance icon fit info is constructed.
|
|
/// \param storage Object storage
|
|
/// \param object Appearance icon fit info object
|
|
static PDFAnnotationIconFitInfo parse(const PDFObjectStorage* storage, PDFObject object);
|
|
|
|
private:
|
|
ScaleCondition m_scaleCondition = ScaleCondition::Always;
|
|
ScaleType m_scaleType = ScaleType::Proportional;
|
|
QPointF m_relativeProportionalPosition = QPointF(0.5, 0.5);
|
|
bool m_fullBox = false;
|
|
};
|
|
|
|
/// Additional appearance characteristics used for constructing of appearance
|
|
/// stream to display annotation on the screen (or just paint it).
|
|
class PDFAnnotationAppearanceCharacteristics
|
|
{
|
|
public:
|
|
inline explicit PDFAnnotationAppearanceCharacteristics() = default;
|
|
|
|
enum class PushButtonMode
|
|
{
|
|
NoIcon,
|
|
NoCaption,
|
|
IconWithCaptionBelow,
|
|
IconWithCaptionAbove,
|
|
IconWithCaptionRight,
|
|
IconWithCaptionLeft,
|
|
IconWithCaptionOverlaid
|
|
};
|
|
|
|
/// Number of degrees by which the widget annotation is rotated
|
|
/// counterclockwise relative to the page.
|
|
PDFInteger getRotation() const { return m_rotation; }
|
|
const std::vector<PDFReal>& getBorderColor() const { return m_borderColor; }
|
|
const std::vector<PDFReal>& getBackgroundColor() const { return m_backgroundColor; }
|
|
const QString& getNormalCaption() const { return m_normalCaption; }
|
|
const QString& getRolloverCaption() const { return m_rolloverCaption; }
|
|
const QString& getDownCaption() const { return m_downCaption; }
|
|
const PDFObject& getNormalIcon() const { return m_normalIcon; }
|
|
const PDFObject& getRolloverIcon() const { return m_rolloverIcon; }
|
|
const PDFObject& getDownIcon() const { return m_downIcon; }
|
|
const PDFAnnotationIconFitInfo& getIconFit() const { return m_iconFit; }
|
|
PushButtonMode getPushButtonMode() const { return m_pushButtonMode; }
|
|
|
|
/// Parses annotation appearance characteristics from the object. If object is invalid, then
|
|
/// default appearance characteristics is constructed.
|
|
/// \param storage Object storage
|
|
/// \param object Appearance characteristics object
|
|
static PDFAnnotationAppearanceCharacteristics parse(const PDFObjectStorage* storage, PDFObject object);
|
|
|
|
private:
|
|
PDFInteger m_rotation = 0;
|
|
std::vector<PDFReal> m_borderColor;
|
|
std::vector<PDFReal> m_backgroundColor;
|
|
QString m_normalCaption;
|
|
QString m_rolloverCaption;
|
|
QString m_downCaption;
|
|
PDFObject m_normalIcon;
|
|
PDFObject m_rolloverIcon;
|
|
PDFObject m_downIcon;
|
|
PDFAnnotationIconFitInfo m_iconFit;
|
|
PushButtonMode m_pushButtonMode = PushButtonMode::NoIcon;
|
|
};
|
|
|
|
/// Storage for annotation additional actions
|
|
class PDFAnnotationAdditionalActions
|
|
{
|
|
public:
|
|
|
|
enum Action
|
|
{
|
|
CursorEnter,
|
|
CursorLeave,
|
|
MousePressed,
|
|
MouseReleased,
|
|
FocusIn,
|
|
FocusOut,
|
|
PageOpened,
|
|
PageClosed,
|
|
PageShow,
|
|
PageHide,
|
|
Default,
|
|
End
|
|
};
|
|
|
|
inline explicit PDFAnnotationAdditionalActions() = default;
|
|
|
|
/// Returns action for given type. If action is invalid,
|
|
/// or not present, nullptr is returned.
|
|
/// \param action Action type
|
|
const PDFAction* getAction(Action action) const { return m_actions.at(action).get(); }
|
|
|
|
/// Parses annotation additional actions from the object. If object is invalid, then
|
|
/// empty additional actions is constructed.
|
|
/// \param storage Object storage
|
|
/// \param object Additional actions object
|
|
/// \param defaultAction Default action of object (defined in "A" entry of annotation dictionary)
|
|
static PDFAnnotationAdditionalActions parse(const PDFObjectStorage* storage, PDFObject object, PDFObject defaultAction);
|
|
|
|
private:
|
|
std::array<PDFActionPtr, End> m_actions;
|
|
};
|
|
|
|
/// Annotation default appearance
|
|
class PDFAnnotationDefaultAppearance
|
|
{
|
|
public:
|
|
explicit inline PDFAnnotationDefaultAppearance() = default;
|
|
|
|
/// Parses appearance string. If error occurs, then default appearance
|
|
/// string is constructed.
|
|
static PDFAnnotationDefaultAppearance parse(const QByteArray& string);
|
|
|
|
const QByteArray& getFontName() const { return m_fontName; }
|
|
PDFReal getFontSize() const { return m_fontSize; }
|
|
QColor getFontColor() const { return m_fontColor; }
|
|
|
|
private:
|
|
QByteArray m_fontName;
|
|
PDFReal m_fontSize = 8.0;
|
|
QColor m_fontColor = Qt::black;
|
|
};
|
|
|
|
class PDFAnnotation;
|
|
class PDFMarkupAnnotation;
|
|
class PDFTextAnnotation;
|
|
|
|
using PDFAnnotationPtr = QSharedPointer<PDFAnnotation>;
|
|
|
|
struct AnnotationDrawParameters
|
|
{
|
|
/// Painter, onto which is annotation graphics drawn
|
|
QPainter* painter = nullptr;
|
|
|
|
/// Pointer to annotation (if draw is delegated to other objects,
|
|
/// for example, form manager, then maybe pointer to annotation
|
|
/// is needed).
|
|
PDFAnnotation* annotation = nullptr;
|
|
|
|
/// Pointer to form manager (if forms are drawn)
|
|
const PDFFormManager* formManager = nullptr;
|
|
|
|
/// Output parameter. Marks annotation's graphics bounding
|
|
/// rectangle (it can be different/adjusted from original
|
|
/// annotation bounding rectangle, in that case, it must be adjusted).
|
|
/// If this rectangle is invalid, then appearance content stream
|
|
/// is assumed to be empty.
|
|
QRectF boundingRectangle;
|
|
|
|
/// Appeareance mode (normal/rollover/down, and appearance state)
|
|
PDFAppeareanceStreams::Key key;
|
|
|
|
/// Invert colors?
|
|
bool invertColors = false;
|
|
};
|
|
|
|
/// Base class for all annotation types. Represents PDF annotation object.
|
|
/// Annotations are various enhancements to pages graphical representation,
|
|
/// such as graphics, text, highlight or multimedia content, such as sounds,
|
|
/// videos and 3D annotations.
|
|
class PDFAnnotation
|
|
{
|
|
public:
|
|
explicit PDFAnnotation();
|
|
virtual ~PDFAnnotation() = default;
|
|
|
|
enum Flag : uint
|
|
{
|
|
None = 0x0000,
|
|
Invisible = 0x0001, ///< If set, do not display unknown annotations using their AP dictionary
|
|
Hidden = 0x0002, ///< If set, do not display annotation and do not show popup windows (completely hidden)
|
|
Print = 0x0004, ///< If set, print annotation
|
|
NoZoom = 0x0008, ///< Do not apply page zoom while displaying annotation rectangle
|
|
NoRotate = 0x0010, ///< Do not rotate annotation's appearance to match orientation of the page
|
|
NoView = 0x0020, ///< Do not display annotation on the screen (it still can be printed)
|
|
ReadOnly = 0x0040, ///< Do not allow interacting with the user (and disallow also mouse interaction)
|
|
Locked = 0x0080, ///< Do not allow to delete/modify annotation by user
|
|
ToggleNoView = 0x0100, ///< If set, invert the interpretation of NoView flag
|
|
LockedContents = 0x0200, ///< Do not allow to modify contents of the annotation
|
|
};
|
|
Q_DECLARE_FLAGS(Flags, Flag)
|
|
|
|
virtual AnnotationType getType() const = 0;
|
|
|
|
virtual PDFMarkupAnnotation* asMarkupAnnotation() { return nullptr; }
|
|
virtual const PDFMarkupAnnotation* asMarkupAnnotation() const { return nullptr; }
|
|
virtual bool isReplyTo() const { return false; }
|
|
|
|
/// Draws the annotation using parameters. Annotation is drawn onto painter,
|
|
/// but actual graphics can be drawn outside of annotation's rectangle.
|
|
/// In that case, adjusted annotation's rectangle is passed to the parameters.
|
|
/// Painter must use annotation's coordinate system (for example, line points
|
|
/// must match in both in painter and this annotation).
|
|
/// \param parameters Graphics parameters
|
|
virtual void draw(AnnotationDrawParameters& parameters) const;
|
|
|
|
/// Returns a list of appearance states, which must be created for this annotation
|
|
virtual std::vector<PDFAppeareanceStreams::Key> getDrawKeys(const PDFFormManager* formManager) const;
|
|
|
|
/// Returns effective flags (some annotations can behave as they have always
|
|
/// set some flags, such as NoZoom and NoRotate)
|
|
virtual Flags getEffectiveFlags() const { return getFlags(); }
|
|
|
|
PDFObjectReference getSelfReference() const { return m_selfReference; }
|
|
const QRectF& getRectangle() const { return m_rectangle; }
|
|
const QString& getContents() const { return m_contents; }
|
|
PDFObjectReference getPageReference() const { return m_pageReference; }
|
|
const QString& getName() const { return m_name; }
|
|
const QDateTime& getLastModifiedDateTime() const { return m_lastModified; }
|
|
const QString& getLastModifiedString() const { return m_lastModifiedString; }
|
|
Flags getFlags() const { return m_flags; }
|
|
const PDFAppeareanceStreams& getAppearanceStreams() const { return m_appearanceStreams; }
|
|
const QByteArray& getAppearanceState() const { return m_appearanceState; }
|
|
const PDFAnnotationBorder& getBorder() const { return m_annotationBorder; }
|
|
const std::vector<PDFReal>& getColor() const { return m_color; }
|
|
PDFInteger getStructuralParent() const { return m_structParent; }
|
|
PDFObjectReference getOptionalContent() const { return m_optionalContentReference; }
|
|
|
|
/// Parses annotation from the object. If error occurs, then nullptr is returned.
|
|
/// \param storage Object storage
|
|
/// \param reference Annotation object reference
|
|
static PDFAnnotationPtr parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
/// Parses quadrilaterals and fills them in the painter path. If no quadrilaterals are defined,
|
|
/// then annotation rectangle is used. If annotation rectangle is also invalid,
|
|
/// then empty painter path is used.
|
|
/// \param storage Object storage
|
|
/// \param quadrilateralsObject Object with quadrilaterals definition
|
|
/// \param annotationRect Annotation rectangle
|
|
static PDFAnnotationQuadrilaterals parseQuadrilaterals(const PDFObjectStorage* storage, PDFObject quadrilateralsObject, const QRectF annotationRect);
|
|
|
|
/// Converts name to line ending. If appropriate line ending for name is not found,
|
|
/// then None line ending is returned.
|
|
/// \param name Name of the line ending
|
|
static AnnotationLineEnding convertNameToLineEnding(const QByteArray& name);
|
|
|
|
/// Returns draw color from defined annotation color
|
|
static QColor getDrawColorFromAnnotationColor(const std::vector<PDFReal>& color);
|
|
|
|
protected:
|
|
virtual QColor getStrokeColor() const;
|
|
virtual QColor getFillColor() const;
|
|
|
|
struct LineGeometryInfo
|
|
{
|
|
/// Original line
|
|
QLineF originalLine;
|
|
|
|
/// Transformed line
|
|
QLineF transformedLine;
|
|
|
|
/// Matrix LCStoGCS is local coordinate system of line originalLine. It transforms
|
|
/// points on the line to the global coordinate system. So, point (0, 0) will
|
|
/// map onto p1 and point (originalLine.length(), 0) will map onto p2.
|
|
QMatrix LCStoGCS;
|
|
|
|
/// Inverted matrix of LCStoGCS. It maps global coordinate system to local
|
|
/// coordinate system of the original line.
|
|
QMatrix GCStoLCS;
|
|
|
|
static LineGeometryInfo create(QLineF line);
|
|
};
|
|
|
|
/// Returns pen from border settings and annotation color
|
|
QPen getPen() const;
|
|
|
|
/// Returns brush from interior color. If annotation doesn't have
|
|
/// a brush, then empty brush is returned.
|
|
QBrush getBrush() const;
|
|
|
|
/// Draw line using given parameters and painter. Line is specified
|
|
/// by its geometry information. Painter must be set to global coordinates.
|
|
/// Bounding path is also updated, it is specified in global coordinates,
|
|
/// not in line local coordinate system. We consider p1 as start point of
|
|
/// the line, and p2 as the end point. The painter must have proper QPen
|
|
/// and QBrush setted, this function uses current pen/brush to paint the line.
|
|
/// \param info Line geometry info
|
|
/// \param painter Painter
|
|
/// \param lineEndingSize Line ending size
|
|
/// \param p1Ending Line endpoint graphics at p1
|
|
/// \param p2Ending Line endpoint graphics at p2
|
|
/// \param boundingPath Bounding path in global coordinate system
|
|
/// \param textOffset Additional text offset
|
|
/// \param text Text, which should be printed along the line
|
|
/// \param textIsAboveLine Text should be printed above line
|
|
void drawLine(const LineGeometryInfo& info,
|
|
QPainter& painter,
|
|
PDFReal lineEndingSize,
|
|
AnnotationLineEnding p1Ending,
|
|
AnnotationLineEnding p2Ending,
|
|
QPainterPath& boundingPath,
|
|
QPointF textOffset,
|
|
const QString& text,
|
|
bool textIsAboveLine) const;
|
|
|
|
/// Draws character unicode symbol using text
|
|
/// \param text Text to be drawn
|
|
/// \param opacity Opacity
|
|
/// \param parameters Draw parameters
|
|
void drawCharacterSymbol(QString text, PDFReal opacity, AnnotationDrawParameters& parameters) const;
|
|
|
|
private:
|
|
PDFObjectReference m_selfReference; ///< Reference to self
|
|
QRectF m_rectangle; ///< Annotation rectangle, in page coordinates, "Rect" entry
|
|
QString m_contents; ///< Text to be displayed to the user (or alternate text), "Content" entry
|
|
PDFObjectReference m_pageReference; ///< Reference to annotation's page, "P" entry
|
|
QString m_name; ///< Unique name (in page context) for the annotation, "NM" entry
|
|
QDateTime m_lastModified; ///< Date and time, when annotation was last modified, "M" entry
|
|
QString m_lastModifiedString; ///< Date and time, in text format
|
|
Flags m_flags; ///< Annotation flags
|
|
PDFAppeareanceStreams m_appearanceStreams; ///< Appearance streams, "AP" entry
|
|
QByteArray m_appearanceState; ///< Appearance state, "AS" entry
|
|
PDFAnnotationBorder m_annotationBorder; ///< Annotation border, "Border" entry
|
|
std::vector<PDFReal> m_color; ///< Color (for example, title bar of popup window), "C" entry
|
|
PDFInteger m_structParent; ///< Structural parent identifier, "StructParent" entry
|
|
PDFObjectReference m_optionalContentReference; ///< Reference to optional content, "OC" entry
|
|
};
|
|
|
|
/// Markup annotation object, used to mark up contents of PDF documents. Markup annotations
|
|
/// can have various types, as free text (just text displayed on page), annotations with popup
|
|
/// windows, and special annotations, such as multimedia annotations.
|
|
class PDFMarkupAnnotation : public PDFAnnotation
|
|
{
|
|
public:
|
|
explicit inline PDFMarkupAnnotation() = default;
|
|
|
|
virtual PDFMarkupAnnotation* asMarkupAnnotation() override { return this; }
|
|
virtual const PDFMarkupAnnotation* asMarkupAnnotation() const override { return this; }
|
|
virtual bool isReplyTo() const override;
|
|
|
|
enum class ReplyType
|
|
{
|
|
Reply,
|
|
Group
|
|
};
|
|
|
|
const QString& getWindowTitle() const { return m_windowTitle; }
|
|
PDFObjectReference getPopupAnnotation() const { return m_popupAnnotation; }
|
|
PDFReal getOpacity() const { return m_opacity; }
|
|
const QString& getRichTextString() const { return m_richTextString; }
|
|
const QDateTime& getCreationDate() const { return m_creationDate; }
|
|
PDFObjectReference getInReplyTo() const { return m_inReplyTo; }
|
|
const QString& getSubject() const { return m_subject; }
|
|
ReplyType getReplyType() const { return m_replyType; }
|
|
const QByteArray& getIntent() const { return m_intent; }
|
|
const PDFObject& getExternalData() const { return m_externalData; }
|
|
|
|
protected:
|
|
virtual QColor getStrokeColor() const override;
|
|
virtual QColor getFillColor() const override;
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
QString m_windowTitle;
|
|
PDFObjectReference m_popupAnnotation;
|
|
PDFReal m_opacity = 1.0;
|
|
QString m_richTextString;
|
|
QDateTime m_creationDate;
|
|
PDFObjectReference m_inReplyTo;
|
|
QString m_subject;
|
|
ReplyType m_replyType = ReplyType::Reply;
|
|
QByteArray m_intent;
|
|
PDFObject m_externalData;
|
|
};
|
|
|
|
enum class TextAnnotationIcon
|
|
{
|
|
Comment,
|
|
Help,
|
|
Insert,
|
|
Key,
|
|
NewParagraph,
|
|
Note,
|
|
Paragraph
|
|
};
|
|
|
|
/// Text annotation represents note attached to a specific point in the PDF
|
|
/// document. It appears as icon, and it is not zoomed, or rotated (behaves
|
|
/// as if flag NoZoom and NoRotate were set). When this annotation is opened,
|
|
/// it displays popup window containing the text of the note, font and size
|
|
/// is implementation dependent by viewer application.
|
|
class PDFTextAnnotation : public PDFMarkupAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDFTextAnnotation() = default;
|
|
|
|
virtual AnnotationType getType() const override { return AnnotationType::Text; }
|
|
virtual std::vector<PDFAppeareanceStreams::Key> getDrawKeys(const PDFFormManager* formManager) const override;
|
|
virtual void draw(AnnotationDrawParameters& parameters) const override;
|
|
virtual Flags getEffectiveFlags() const override;
|
|
|
|
bool isOpen() const { return m_open; }
|
|
const QByteArray& getIconName() const { return m_iconName; }
|
|
const QString& getState() const { return m_state; }
|
|
const QString& getStateModel() const { return m_stateModel; }
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
bool m_open = false;
|
|
QByteArray m_iconName;
|
|
QString m_state;
|
|
QString m_stateModel;
|
|
};
|
|
|
|
enum class LinkHighlightMode
|
|
{
|
|
None,
|
|
Invert,
|
|
Outline,
|
|
Push
|
|
};
|
|
|
|
/// Link annotation represents hypertext link to a destination to elsewhere
|
|
/// in the document, or action to be performed.
|
|
class PDFLinkAnnotation : public PDFAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDFLinkAnnotation() = default;
|
|
|
|
virtual AnnotationType getType() const override { return AnnotationType::Link; }
|
|
virtual std::vector<PDFAppeareanceStreams::Key> getDrawKeys(const PDFFormManager* formManager) const override;
|
|
virtual void draw(AnnotationDrawParameters& parameters) const override;
|
|
|
|
const PDFAction* getAction() const { return m_action.data(); }
|
|
LinkHighlightMode getHighlightMode() const { return m_highlightMode; }
|
|
const PDFAction* getURIAction() const { return m_previousAction.data(); }
|
|
const PDFAnnotationQuadrilaterals& getActivationRegion() const { return m_activationRegion; }
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
PDFActionPtr m_action;
|
|
LinkHighlightMode m_highlightMode = LinkHighlightMode::Invert;
|
|
PDFActionPtr m_previousAction;
|
|
PDFAnnotationQuadrilaterals m_activationRegion;
|
|
};
|
|
|
|
/// Free text annotation displays text directly on the page. Free text doesn't have
|
|
/// open/close state, text is always visible.
|
|
class PDFFreeTextAnnotation : public PDFMarkupAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDFFreeTextAnnotation() = default;
|
|
|
|
virtual AnnotationType getType() const override { return AnnotationType::FreeText; }
|
|
virtual void draw(AnnotationDrawParameters& parameters) const override;
|
|
|
|
enum class Justification
|
|
{
|
|
Left,
|
|
Centered,
|
|
Right
|
|
};
|
|
|
|
enum class Intent
|
|
{
|
|
None,
|
|
Callout,
|
|
TypeWriter
|
|
};
|
|
|
|
const QByteArray& getDefaultAppearance() const { return m_defaultAppearance; }
|
|
Justification getJustification() const { return m_justification; }
|
|
const QString& getDefaultStyle() const { return m_defaultStyleString; }
|
|
const PDFAnnotationCalloutLine& getCalloutLine() const { return m_calloutLine; }
|
|
Intent getIntent() const { return m_intent; }
|
|
const QRectF& getTextRectangle() const { return m_textRectangle; }
|
|
const PDFAnnotationBorderEffect& getBorderEffect() const { return m_effect; }
|
|
AnnotationLineEnding getStartLineEnding() const { return m_startLineEnding; }
|
|
AnnotationLineEnding getEndLineEnding() const { return m_endLineEnding; }
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
QByteArray m_defaultAppearance;
|
|
Justification m_justification = Justification::Left;
|
|
QString m_defaultStyleString;
|
|
PDFAnnotationCalloutLine m_calloutLine;
|
|
Intent m_intent = Intent::None;
|
|
QRectF m_textRectangle;
|
|
PDFAnnotationBorderEffect m_effect;
|
|
AnnotationLineEnding m_startLineEnding = AnnotationLineEnding::None;
|
|
AnnotationLineEnding m_endLineEnding = AnnotationLineEnding::None;
|
|
};
|
|
|
|
/// Line annotation, draws straight line on the page (in most simple form), or
|
|
/// it can display, for example, dimensions with perpendicular lines at the line
|
|
/// endings. Caption text can also be displayed.
|
|
class PDFLineAnnotation : public PDFMarkupAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDFLineAnnotation() = default;
|
|
|
|
virtual AnnotationType getType() const override { return AnnotationType::Line; }
|
|
virtual void draw(AnnotationDrawParameters& parameters) const override;
|
|
|
|
enum class Intent
|
|
{
|
|
Arrow,
|
|
Dimension
|
|
};
|
|
|
|
enum class CaptionPosition
|
|
{
|
|
Inline,
|
|
Top
|
|
};
|
|
|
|
const QLineF& getLine() const { return m_line; }
|
|
AnnotationLineEnding getStartLineEnding() const { return m_startLineEnding; }
|
|
AnnotationLineEnding getEndLineEnding() const { return m_endLineEnding; }
|
|
const std::vector<PDFReal>& getInteriorColor() const { return m_interiorColor; }
|
|
PDFReal getLeaderLineLength() const { return m_leaderLineLength; }
|
|
PDFReal getLeaderLineExtension() const { return m_leaderLineExtension; }
|
|
PDFReal getLeaderLineOffset() const { return m_leaderLineOffset; }
|
|
bool isCaptionRendered() const { return m_captionRendered; }
|
|
Intent getIntent() const { return m_intent; }
|
|
CaptionPosition getCaptionPosition() const { return m_captionPosition; }
|
|
const PDFObject& getMeasureDictionary() const { return m_measureDictionary; }
|
|
const QPointF& getCaptionOffset() const { return m_captionOffset; }
|
|
|
|
protected:
|
|
virtual QColor getFillColor() const override;
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
QLineF m_line;
|
|
AnnotationLineEnding m_startLineEnding = AnnotationLineEnding::None;
|
|
AnnotationLineEnding m_endLineEnding = AnnotationLineEnding::None;
|
|
std::vector<PDFReal> m_interiorColor;
|
|
PDFReal m_leaderLineLength = 0.0;
|
|
PDFReal m_leaderLineExtension = 0.0;
|
|
PDFReal m_leaderLineOffset = 0.0;
|
|
bool m_captionRendered = false;
|
|
Intent m_intent = Intent::Arrow;
|
|
CaptionPosition m_captionPosition = CaptionPosition::Inline;
|
|
PDFObject m_measureDictionary;
|
|
QPointF m_captionOffset;
|
|
};
|
|
|
|
/// Simple geometry annotation.
|
|
/// Square and circle annotations displays rectangle or ellipse on the page.
|
|
/// Name is a bit strange (because rectangle may not be a square or circle is not ellipse),
|
|
/// but it is defined in PDF specification, so we will use these terms.
|
|
class PDFSimpleGeometryAnnotation : public PDFMarkupAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDFSimpleGeometryAnnotation(AnnotationType type) :
|
|
m_type(type)
|
|
{
|
|
|
|
}
|
|
|
|
virtual AnnotationType getType() const override { return m_type; }
|
|
virtual void draw(AnnotationDrawParameters& parameters) const override;
|
|
|
|
const std::vector<PDFReal>& getInteriorColor() const { return m_interiorColor; }
|
|
const PDFAnnotationBorderEffect& getBorderEffect() const { return m_effect; }
|
|
const QRectF& getGeometryRectangle() const { return m_geometryRectangle; }
|
|
|
|
protected:
|
|
virtual QColor getFillColor() const override;
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
AnnotationType m_type;
|
|
std::vector<PDFReal> m_interiorColor;
|
|
PDFAnnotationBorderEffect m_effect;
|
|
QRectF m_geometryRectangle;
|
|
};
|
|
|
|
/// Polygonal geometry, consists of polygon or polyline geometry. Polygon annotation
|
|
/// displays closed polygon (potentially filled), polyline annotation displays
|
|
/// polyline, which is not closed.
|
|
class PDFPolygonalGeometryAnnotation : public PDFMarkupAnnotation
|
|
{
|
|
public:
|
|
enum class Intent
|
|
{
|
|
None,
|
|
Cloud,
|
|
Dimension
|
|
};
|
|
|
|
inline explicit PDFPolygonalGeometryAnnotation(AnnotationType type) :
|
|
m_type(type),
|
|
m_intent(Intent::None)
|
|
{
|
|
|
|
}
|
|
|
|
virtual AnnotationType getType() const override { return m_type; }
|
|
virtual void draw(AnnotationDrawParameters& parameters) const override;
|
|
|
|
const std::vector<QPointF>& getVertices() const { return m_vertices; }
|
|
AnnotationLineEnding getStartLineEnding() const { return m_startLineEnding; }
|
|
AnnotationLineEnding getEndLineEnding() const { return m_endLineEnding; }
|
|
const std::vector<PDFReal>& getInteriorColor() const { return m_interiorColor; }
|
|
const PDFAnnotationBorderEffect& getBorderEffect() const { return m_effect; }
|
|
Intent getIntent() const { return m_intent; }
|
|
const PDFObject& getMeasure() const { return m_measure; }
|
|
|
|
protected:
|
|
virtual QColor getFillColor() const override;
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
AnnotationType m_type;
|
|
std::vector<QPointF> m_vertices;
|
|
AnnotationLineEnding m_startLineEnding = AnnotationLineEnding::None;
|
|
AnnotationLineEnding m_endLineEnding = AnnotationLineEnding::None;
|
|
std::vector<PDFReal> m_interiorColor;
|
|
PDFAnnotationBorderEffect m_effect;
|
|
Intent m_intent;
|
|
PDFObject m_measure;
|
|
};
|
|
|
|
/// Annotation for text highlighting. Can highlight, underline, strikeout,
|
|
/// or squiggly underline the text.
|
|
class PDFHighlightAnnotation : public PDFMarkupAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDFHighlightAnnotation(AnnotationType type) :
|
|
m_type(type)
|
|
{
|
|
|
|
}
|
|
|
|
virtual AnnotationType getType() const override { return m_type; }
|
|
virtual void draw(AnnotationDrawParameters& parameters) const override;
|
|
|
|
const PDFAnnotationQuadrilaterals& getHiglightArea() const { return m_highlightArea; }
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
AnnotationType m_type;
|
|
PDFAnnotationQuadrilaterals m_highlightArea;
|
|
};
|
|
|
|
/// Annotation for visual symbol that indicates presence of text edits.
|
|
class PDFCaretAnnotation : public PDFMarkupAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDFCaretAnnotation() = default;
|
|
|
|
enum class Symbol
|
|
{
|
|
None,
|
|
Paragraph
|
|
};
|
|
|
|
virtual AnnotationType getType() const override { return AnnotationType::Caret; }
|
|
virtual void draw(AnnotationDrawParameters& parameters) const override;
|
|
|
|
const QRectF& getCaretRectangle() const { return m_caretRectangle; }
|
|
Symbol getSymbol() const { return m_symbol; }
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
QRectF m_caretRectangle;
|
|
Symbol m_symbol = Symbol::None;
|
|
};
|
|
|
|
enum class Stamp
|
|
{
|
|
Approved,
|
|
AsIs,
|
|
Confidential,
|
|
Departmental,
|
|
Draft,
|
|
Experimental,
|
|
Expired,
|
|
Final,
|
|
ForComment,
|
|
ForPublicRelease,
|
|
NotApproved,
|
|
NotForPublicRelease,
|
|
Sold,
|
|
TopSecret
|
|
};
|
|
|
|
/// Annotation for stamps. Displays text or graphics intended to look
|
|
/// as if they were stamped on the paper.
|
|
class PDFStampAnnotation : public PDFMarkupAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDFStampAnnotation() = default;
|
|
|
|
virtual AnnotationType getType() const override { return AnnotationType::Stamp; }
|
|
virtual void draw(AnnotationDrawParameters& parameters) const override;
|
|
|
|
Stamp getStamp() const { return m_stamp; }
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
Stamp m_stamp = Stamp::Draft;
|
|
};
|
|
|
|
/// Ink annotation. Represents a path composed of disjoint polygons.
|
|
class PDFInkAnnotation : public PDFMarkupAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDFInkAnnotation() = default;
|
|
|
|
virtual AnnotationType getType() const override { return AnnotationType::Ink; }
|
|
virtual void draw(AnnotationDrawParameters& parameters) const override;
|
|
|
|
const QPainterPath& getInkPath() const { return m_inkPath; }
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
QPainterPath m_inkPath;
|
|
};
|
|
|
|
/// Popup annotation. Displays text in popup window for markup annotations.
|
|
/// This annotation contains field to associated annotation, for which
|
|
/// is window displayed, and window state (open/closed).
|
|
class PDFPopupAnnotation : public PDFAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDFPopupAnnotation() = default;
|
|
|
|
virtual AnnotationType getType() const override { return AnnotationType::Popup; }
|
|
|
|
bool isOpened() const { return m_opened; }
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
bool m_opened = false;
|
|
};
|
|
|
|
enum class FileAttachmentIcon
|
|
{
|
|
Graph,
|
|
Paperclip,
|
|
PushPin,
|
|
Tag
|
|
};
|
|
|
|
/// File attachment annotation contains reference to (embedded or external) file.
|
|
/// So it is a link to specified file. Activating annotation enables user to view
|
|
/// or store attached file in the filesystem.
|
|
class PDFFileAttachmentAnnotation : public PDFMarkupAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDFFileAttachmentAnnotation() = default;
|
|
|
|
virtual AnnotationType getType() const override { return AnnotationType::FileAttachment; }
|
|
virtual void draw(AnnotationDrawParameters& parameters) const override;
|
|
|
|
const PDFFileSpecification& getFileSpecification() const { return m_fileSpecification; }
|
|
FileAttachmentIcon getIcon() const { return m_icon; }
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
PDFFileSpecification m_fileSpecification;
|
|
FileAttachmentIcon m_icon = FileAttachmentIcon::PushPin;
|
|
};
|
|
|
|
/// Sound annotation contains sound, which is played, when
|
|
/// annotation is activated.
|
|
class PDFSoundAnnotation : public PDFMarkupAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDFSoundAnnotation() = default;
|
|
|
|
enum class Icon
|
|
{
|
|
Speaker,
|
|
Microphone
|
|
};
|
|
|
|
virtual AnnotationType getType() const override { return AnnotationType::Sound; }
|
|
virtual void draw(AnnotationDrawParameters& parameters) const override;
|
|
|
|
const PDFSound& getSound() const { return m_sound; }
|
|
Icon getIcon() const { return m_icon; }
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
PDFSound m_sound;
|
|
Icon m_icon = Icon::Speaker;
|
|
};
|
|
|
|
/// Movie annotation contains movie or sound, which is played, when
|
|
/// annotation is activated.
|
|
class PDFMovieAnnotation : public PDFAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDFMovieAnnotation() = default;
|
|
|
|
virtual AnnotationType getType() const override { return AnnotationType::Movie; }
|
|
|
|
const QString& getMovieTitle() const { return m_movieTitle; }
|
|
bool isMovieToBePlayed() const { return m_playMovie; }
|
|
const PDFMovie& getMovie() const { return m_movie; }
|
|
const PDFMovieActivation& getMovieActivation() const { return m_movieActivation; }
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
QString m_movieTitle;
|
|
bool m_playMovie = true;
|
|
PDFMovie m_movie;
|
|
PDFMovieActivation m_movieActivation;
|
|
};
|
|
|
|
/// Screen action represents area of page in which is media played.
|
|
/// See also Rendition actions and their relationship to this annotation.
|
|
class PDFScreenAnnotation : public PDFAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDFScreenAnnotation() = default;
|
|
|
|
virtual AnnotationType getType() const override { return AnnotationType::Screen; }
|
|
|
|
const QString& getScreenTitle() const { return m_screenTitle; }
|
|
const PDFAnnotationAppearanceCharacteristics& getAppearanceCharacteristics() const { return m_appearanceCharacteristics; }
|
|
const PDFAction* getAction() const { return m_action.get(); }
|
|
const PDFAnnotationAdditionalActions& getAdditionalActions() const { return m_additionalActions; }
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
QString m_screenTitle;
|
|
PDFAnnotationAppearanceCharacteristics m_appearanceCharacteristics;
|
|
PDFActionPtr m_action;
|
|
PDFAnnotationAdditionalActions m_additionalActions;
|
|
};
|
|
|
|
/// Widget annotation represents form fields for interactive forms.
|
|
/// Annotation's dictionary is merged with form field dictionary,
|
|
/// it can be done, because dictionaries doesn't overlap.
|
|
class PDFWidgetAnnotation : public PDFAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDFWidgetAnnotation() = default;
|
|
|
|
enum class HighlightMode
|
|
{
|
|
None,
|
|
Invert,
|
|
Outline,
|
|
Push,
|
|
Toggle
|
|
};
|
|
|
|
virtual AnnotationType getType() const override { return AnnotationType::Widget; }
|
|
virtual void draw(AnnotationDrawParameters& parameters) const override;
|
|
virtual std::vector<PDFAppeareanceStreams::Key> getDrawKeys(const PDFFormManager* formManager) const override;
|
|
|
|
HighlightMode getHighlightMode() const { return m_highlightMode; }
|
|
const PDFAnnotationAppearanceCharacteristics& getAppearanceCharacteristics() const { return m_appearanceCharacteristics; }
|
|
const PDFAction* getAction() const { return m_action.get(); }
|
|
const PDFAnnotationAdditionalActions& getAdditionalActions() const { return m_additionalActions; }
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
HighlightMode m_highlightMode = HighlightMode::Invert;
|
|
PDFAnnotationAppearanceCharacteristics m_appearanceCharacteristics;
|
|
PDFActionPtr m_action;
|
|
PDFAnnotationAdditionalActions m_additionalActions;
|
|
};
|
|
|
|
/// Printer mark annotation represents graphics symbol, mark, or other
|
|
/// graphic feature to assist printing production.
|
|
class PDFPrinterMarkAnnotation : public PDFAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDFPrinterMarkAnnotation() = default;
|
|
|
|
virtual AnnotationType getType() const override { return AnnotationType::PrinterMark; }
|
|
};
|
|
|
|
/// Trapping characteristics for the page
|
|
class PDFTrapNetworkAnnotation : public PDFAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDFTrapNetworkAnnotation() = default;
|
|
|
|
virtual AnnotationType getType() const override { return AnnotationType::TrapNet; }
|
|
};
|
|
|
|
/// Watermark annotation represents watermark displayed on the page,
|
|
/// for example, if it is printed. Watermarks are displayed at fixed
|
|
/// position and size on the page.
|
|
class PDFWatermarkAnnotation : public PDFAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDFWatermarkAnnotation() = default;
|
|
|
|
virtual AnnotationType getType() const override { return AnnotationType::Watermark; }
|
|
|
|
const QMatrix& getMatrix() const { return m_matrix; }
|
|
PDFReal getRelativeHorizontalOffset() const { return m_relativeHorizontalOffset; }
|
|
PDFReal getRelativeVerticalOffset() const { return m_relativeVerticalOffset; }
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
QMatrix m_matrix;
|
|
PDFReal m_relativeHorizontalOffset = 0.0;
|
|
PDFReal m_relativeVerticalOffset = 0.0;
|
|
};
|
|
|
|
/// 3D annotations represents 3D scene, which can be viewed in the application.
|
|
class PDF3DAnnotation : public PDFAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDF3DAnnotation() = default;
|
|
|
|
virtual AnnotationType getType() const override { return AnnotationType::_3D; }
|
|
|
|
const PDF3DStream& getStream() const { return m_stream; }
|
|
const std::optional<PDF3DView>& getDefaultView() const { return m_defaultView; }
|
|
const PDF3DActivation& getActivation() const { return m_activation; }
|
|
bool isInteractive() const { return m_interactive; }
|
|
QRectF getViewBox() const { return m_viewBox; }
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
PDF3DStream m_stream;
|
|
std::optional<PDF3DView> m_defaultView;
|
|
PDF3DActivation m_activation;
|
|
bool m_interactive = true;
|
|
QRectF m_viewBox;
|
|
};
|
|
|
|
/// Rich media annotations can be video, audio, or other multimedia presentations.
|
|
/// The application should provide additional functionality to control rich media,
|
|
/// such as buttons to play/pause/stop video etc. This annotation consists
|
|
/// of contents and settings, settings are optional.
|
|
class PDFRichMediaAnnotation : public PDFAnnotation
|
|
{
|
|
public:
|
|
inline explicit PDFRichMediaAnnotation() = default;
|
|
|
|
virtual AnnotationType getType() const override { return AnnotationType::RichMedia; }
|
|
|
|
const PDFRichMediaContent* getContent() const { return &m_content; }
|
|
const PDFRichMediaSettings* getSettings() const { return &m_settings; }
|
|
|
|
private:
|
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
|
|
|
PDFRichMediaContent m_content;
|
|
PDFRichMediaSettings m_settings;
|
|
};
|
|
|
|
/// Annotation manager manages annotations for document's pages. Each page
|
|
/// can have multiple annotations, and this object caches them. Also,
|
|
/// this object builds annotation's appearance streams, if necessary. This
|
|
/// manager is intended to non-gui rendering. If widget annotation manager is used,
|
|
/// then this object is not thread safe.
|
|
class PDFFORQTLIBSHARED_EXPORT PDFAnnotationManager : public QObject, public IDocumentDrawInterface
|
|
{
|
|
Q_OBJECT
|
|
|
|
private:
|
|
using BaseClass = QObject;
|
|
|
|
void drawWidgetAnnotationHighlight(QRectF annotationRectangle, PDFObjectReference annotationReference, QPainter* painter, QMatrix userSpaceToDeviceSpace) const;
|
|
|
|
public:
|
|
|
|
enum class Target
|
|
{
|
|
View,
|
|
Print
|
|
};
|
|
|
|
explicit PDFAnnotationManager(PDFFontCache* fontCache,
|
|
const PDFCMSManager* cmsManager,
|
|
const PDFOptionalContentActivity* optionalActivity,
|
|
PDFMeshQualitySettings meshQualitySettings,
|
|
PDFRenderer::Features features,
|
|
Target target,
|
|
QObject* parent);
|
|
virtual ~PDFAnnotationManager() override;
|
|
|
|
virtual void drawPage(QPainter* painter,
|
|
PDFInteger pageIndex,
|
|
const PDFPrecompiledPage* compiledPage,
|
|
PDFTextLayoutGetter& layoutGetter,
|
|
const QMatrix& pagePointToDevicePointMatrix,
|
|
QList<PDFRenderError>& errors) const override;
|
|
|
|
/// Set document
|
|
/// \param document New document
|
|
void setDocument(const PDFModifiedDocument& document);
|
|
|
|
Target getTarget() const;
|
|
void setTarget(Target target);
|
|
|
|
const PDFOptionalContentActivity* getOptionalActivity() const;
|
|
void setOptionalActivity(const PDFOptionalContentActivity* optionalActivity);
|
|
|
|
PDFFontCache* getFontCache() const;
|
|
void setFontCache(PDFFontCache* fontCache);
|
|
|
|
PDFMeshQualitySettings getMeshQualitySettings() const;
|
|
void setMeshQualitySettings(const PDFMeshQualitySettings& meshQualitySettings);
|
|
|
|
PDFRenderer::Features getFeatures() const;
|
|
void setFeatures(PDFRenderer::Features features);
|
|
|
|
PDFFormManager* getFormManager() const;
|
|
void setFormManager(PDFFormManager* formManager);
|
|
|
|
struct PageAnnotation
|
|
{
|
|
PDFAppeareanceStreams::Appearance appearance = PDFAppeareanceStreams::Appearance::Normal;
|
|
PDFAnnotationPtr annotation;
|
|
|
|
/// This mutable appearance stream is protected by main mutex
|
|
mutable PDFCachedItem<PDFObject> appearanceStream;
|
|
};
|
|
|
|
struct PageAnnotations
|
|
{
|
|
bool isEmpty() const { return annotations.empty(); }
|
|
|
|
/// Returns popup annotation for given annotation, if annotation doesn't have
|
|
/// popup annotation attached, then nullptr is returned.
|
|
/// \param pageAnnotation Page annotation
|
|
/// \returns Popup annotation or nullptr
|
|
const PageAnnotation* getPopupAnnotation(const PageAnnotation& pageAnnotation) const;
|
|
|
|
/// Returns a list of page annotations, which are replies to this page annotation.
|
|
/// If page annotation doesn't have any replies, then empty list is returned. Replies
|
|
/// are returned in order, in which they were created.
|
|
/// \param pageAnnotation Page annotation
|
|
/// \returns List of replies
|
|
std::vector<const PageAnnotation*> getReplies(const PageAnnotation& pageAnnotation) const;
|
|
|
|
std::vector<PageAnnotation> annotations;
|
|
};
|
|
|
|
/// Prepares annotation transformations for rendering
|
|
/// \param pagePointToDevicePointMatrix Page point to device point matrix
|
|
/// \param device Paint device, onto which will be annotation rendered
|
|
/// \param annotationFlags Annotation flags
|
|
/// \param page Page
|
|
/// \param[in,out] annotationRectangle Input/output annotation rectangle
|
|
QMatrix prepareTransformations(const QMatrix& pagePointToDevicePointMatrix,
|
|
QPaintDevice* device,
|
|
const PDFAnnotation::Flags annotationFlags,
|
|
const PDFPage* page,
|
|
QRectF& annotationRectangle) const;
|
|
|
|
/// Returns current appearance stream for given page annotation
|
|
/// \param pageAnnotation Page annotation
|
|
PDFObject getAppearanceStream(const PageAnnotation& pageAnnotation) const;
|
|
|
|
/// Returns constant reference to page annotation for given page index.
|
|
/// This function requires, that pointer to m_document is valid.
|
|
/// \param pageIndex Page index (must point to valid page)
|
|
const PageAnnotations& getPageAnnotations(PDFInteger pageIndex) const;
|
|
|
|
/// Returns reference to page annotation for given page index.
|
|
/// This function requires, that pointer to m_document is valid.
|
|
/// \param pageIndex Page index (must point to valid page)
|
|
PageAnnotations& getPageAnnotations(PDFInteger pageIndex);
|
|
|
|
/// Returns true, if given page has any annotation
|
|
bool hasAnnotation(PDFInteger pageIndex) const;
|
|
|
|
/// Returns true, if any page in the given indices has annotation
|
|
bool hasAnyPageAnnotation(const std::vector<PDFInteger>& pageIndices) const;
|
|
|
|
protected:
|
|
void drawWidgetAnnotationHighlight(QRectF annotationRectangle,
|
|
const PDFAnnotation* annotation,
|
|
QPainter* painter,
|
|
QMatrix userSpaceToDeviceSpace) const;
|
|
|
|
/// Returns true, if given annotation should be drawn
|
|
/// \param annotation Annotation
|
|
bool isAnnotationDrawEnabled(const PageAnnotation& annotation) const;
|
|
|
|
/// Returns true, if annotation is drawn by editor (from form widget)
|
|
/// \param annotation Annotation
|
|
bool isAnnotationDrawnByEditor(const PageAnnotation& annotation) const;
|
|
|
|
/// Draws annotation
|
|
/// \param pageAnnotation Page annotation
|
|
/// \param pagePointToDevicePointMatrix Page point to device point matrix
|
|
/// \param page Page
|
|
/// \param cms Color management system
|
|
/// \param isEditorDrawEnabled Is editor draw enabled?
|
|
/// \param errors Errors list (where draw errors are stored)
|
|
/// \param painter Painter
|
|
void drawAnnotation(const PageAnnotation& annotation,
|
|
const QMatrix& pagePointToDevicePointMatrix,
|
|
const PDFPage* page,
|
|
const PDFCMS* cms,
|
|
bool isEditorDrawEnabled,
|
|
QList<PDFRenderError>& errors,
|
|
QPainter* painter) const;
|
|
|
|
/// Draws annotation by direct drawing, not using annotation's
|
|
/// appearance stream.
|
|
/// \param pageAnnotation Page annotation
|
|
/// \param pagePointToDevicePointMatrix Page point to device point matrix
|
|
/// \param page Page
|
|
/// \param cms Color management system
|
|
/// \param isEditorDrawEnabled Is annotation drawn by form widget editor?
|
|
/// \param painter Painter
|
|
void drawAnnotationDirect(const PageAnnotation& annotation,
|
|
const QMatrix& pagePointToDevicePointMatrix,
|
|
const PDFPage* page,
|
|
const PDFCMS* cms,
|
|
bool isEditorDrawEnabled,
|
|
QPainter* painter) const;
|
|
|
|
/// Draws annotation using annotation's appearance stream.
|
|
/// \param pageAnnotation Page annotation
|
|
/// \param appearanceStreamObject Object with appearance stream
|
|
/// \param pagePointToDevicePointMatrix Page point to device point matrix
|
|
/// \param page Page
|
|
/// \param cms Color management system
|
|
/// \param painter Painter
|
|
void drawAnnotationUsingAppearanceStream(const PageAnnotation& annotation,
|
|
const PDFObject& appearanceStreamObject,
|
|
const QMatrix& pagePointToDevicePointMatrix,
|
|
const PDFPage* page,
|
|
const PDFCMS* cms,
|
|
QPainter* painter) const;
|
|
|
|
const PDFDocument* m_document;
|
|
|
|
PDFFontCache* m_fontCache;
|
|
const PDFCMSManager* m_cmsManager;
|
|
const PDFOptionalContentActivity* m_optionalActivity;
|
|
PDFFormManager* m_formManager;
|
|
PDFMeshQualitySettings m_meshQualitySettings;
|
|
PDFRenderer::Features m_features;
|
|
|
|
mutable QMutex m_mutex;
|
|
mutable std::map<PDFInteger, PageAnnotations> m_pageAnnotations;
|
|
Target m_target = Target::View;
|
|
};
|
|
|
|
/// Annotation manager for GUI rendering, it also manages annotations widgets
|
|
/// for parent widget.
|
|
class PDFFORQTLIBSHARED_EXPORT PDFWidgetAnnotationManager : public PDFAnnotationManager, public IDrawWidgetInputInterface
|
|
{
|
|
Q_OBJECT
|
|
|
|
private:
|
|
using BaseClass = PDFAnnotationManager;
|
|
|
|
public:
|
|
explicit PDFWidgetAnnotationManager(PDFDrawWidgetProxy* proxy, QObject* parent);
|
|
virtual ~PDFWidgetAnnotationManager() override;
|
|
|
|
virtual void shortcutOverrideEvent(QWidget* widget, QKeyEvent* event) override;
|
|
virtual void keyPressEvent(QWidget* widget, QKeyEvent* event) override;
|
|
virtual void keyReleaseEvent(QWidget* widget, QKeyEvent* event) override;
|
|
virtual void mousePressEvent(QWidget* widget, QMouseEvent* event) override;
|
|
virtual void mouseDoubleClickEvent(QWidget* widget, QMouseEvent* event) override;
|
|
virtual void mouseReleaseEvent(QWidget* widget, QMouseEvent* event) override;
|
|
virtual void mouseMoveEvent(QWidget* widget, QMouseEvent* event) override;
|
|
virtual void wheelEvent(QWidget* widget, QWheelEvent* event) override;
|
|
|
|
/// Returns tooltip generated from annotation
|
|
virtual QString getTooltip() const override { return m_tooltip; }
|
|
|
|
/// Returns current cursor
|
|
virtual const std::optional<QCursor>& getCursor() const override { return m_cursor; }
|
|
|
|
virtual int getInputPriority() const override { return AnnotationPriority; }
|
|
|
|
signals:
|
|
void actionTriggered(const PDFAction* action);
|
|
|
|
private:
|
|
void updateFromMouseEvent(QMouseEvent* event);
|
|
|
|
/// Creates dialog for markup annotations. This function is used only for markup annotations,
|
|
/// do not use them for other annotations (function can crash).
|
|
/// \param widget Dialog's parent widget
|
|
/// \param pageAnnotation Markup annotation
|
|
/// \param pageAnnotations Page annotations
|
|
QDialog* createDialogForMarkupAnnotations(PDFWidget* widget,
|
|
const PageAnnotation& pageAnnotation,
|
|
const PageAnnotations& pageAnnotations);
|
|
|
|
/// Creates widgets for markup annotation main popup widget. Also sets
|
|
/// default size of parent widget.
|
|
/// \param parentWidget Parent widget, where widgets are created
|
|
/// \param pageAnnotation Markup annotation
|
|
/// \param pageAnnotations Page annotations
|
|
void createWidgetsForMarkupAnnotations(QWidget* parentWidget,
|
|
const PageAnnotation& pageAnnotation,
|
|
const PageAnnotations& pageAnnotations);
|
|
|
|
PDFDrawWidgetProxy* m_proxy;
|
|
QString m_tooltip;
|
|
std::optional<QCursor> m_cursor;
|
|
};
|
|
|
|
} // namespace pdf
|
|
|
|
#endif // PDFANNOTATION_H
|