mirror of https://github.com/JakubMelka/PDF4QT.git
Rich media and 3D annotations
This commit is contained in:
parent
de1fa4a2da
commit
6d9744886a
|
@ -539,6 +539,14 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject
|
|||
annotation->m_relativeVerticalOffset = loader.readNumberFromDictionary(fixedPrintDictionary, "V", 0.0);
|
||||
}
|
||||
}
|
||||
else if (subtype == "RichMedia")
|
||||
{
|
||||
PDFRichMediaAnnotation* annotation = new PDFRichMediaAnnotation();
|
||||
result.reset(annotation);
|
||||
|
||||
annotation->m_content = PDFRichMediaContent::parse(storage, dictionary->get("RichMediaContent"));
|
||||
annotation->m_settings = PDFRichMediaSettings::parse(storage, dictionary->get("RichMediaSettings"));
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
|
@ -2121,6 +2129,29 @@ void PDFStampAnnotation::draw(AnnotationDrawParameters& parameters) const
|
|||
parameters.boundingRectangle.adjust(-penWidth, -penWidth, penWidth, penWidth);
|
||||
}
|
||||
|
||||
void PDFAnnotation::drawCharacterSymbol(QString text, PDFReal opacity, AnnotationDrawParameters& parameters) const
|
||||
{
|
||||
QColor strokeColor = QColor::fromRgbF(0.0, 0.0, 0.0, opacity);
|
||||
|
||||
constexpr const PDFReal rectSize = 24.0;
|
||||
QPainter& painter = *parameters.painter;
|
||||
QRectF rectangle = getRectangle();
|
||||
rectangle.setSize(QSizeF(rectSize, rectSize));
|
||||
|
||||
QFont font = QApplication::font();
|
||||
font.setPixelSize(16.0);
|
||||
|
||||
QPainterPath textPath;
|
||||
textPath.addText(0.0, 0.0, font, text);
|
||||
textPath = QMatrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0).map(textPath);
|
||||
QRectF textBoundingRect = textPath.boundingRect();
|
||||
QPointF offset = rectangle.center() - textBoundingRect.center();
|
||||
textPath.translate(offset);
|
||||
painter.fillPath(textPath, QBrush(strokeColor, Qt::SolidPattern));
|
||||
|
||||
parameters.boundingRectangle = rectangle;
|
||||
}
|
||||
|
||||
void PDFFileAttachmentAnnotation::draw(AnnotationDrawParameters& parameters) const
|
||||
{
|
||||
QString text = "?";
|
||||
|
@ -2144,26 +2175,27 @@ void PDFFileAttachmentAnnotation::draw(AnnotationDrawParameters& parameters) con
|
|||
break;
|
||||
}
|
||||
|
||||
const PDFReal opacity = getOpacity();
|
||||
QColor strokeColor = QColor::fromRgbF(0.0, 0.0, 0.0, opacity);
|
||||
drawCharacterSymbol(text, getOpacity(), parameters);
|
||||
}
|
||||
|
||||
constexpr const PDFReal rectSize = 24.0;
|
||||
QPainter& painter = *parameters.painter;
|
||||
QRectF rectangle = getRectangle();
|
||||
rectangle.setSize(QSizeF(rectSize, rectSize));
|
||||
void PDFSoundAnnotation::draw(AnnotationDrawParameters& parameters) const
|
||||
{
|
||||
QString text = "?";
|
||||
switch (getIcon())
|
||||
{
|
||||
case Icon::Speaker:
|
||||
text = QString::fromUtf16(u"\U0001F508");
|
||||
break;
|
||||
case Icon::Microphone:
|
||||
text = QString::fromUtf16(u"\U0001F3A4");
|
||||
break;
|
||||
|
||||
QFont font = QApplication::font();
|
||||
font.setPixelSize(16.0);
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
QPainterPath textPath;
|
||||
textPath.addText(0.0, 0.0, font, text);
|
||||
textPath = QMatrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0).map(textPath);
|
||||
QRectF textBoundingRect = textPath.boundingRect();
|
||||
QPointF offset = rectangle.center() - textBoundingRect.center();
|
||||
textPath.translate(offset);
|
||||
painter.fillPath(textPath, QBrush(strokeColor, Qt::SolidPattern));
|
||||
|
||||
parameters.boundingRectangle = rectangle;
|
||||
drawCharacterSymbol(text, getOpacity(), parameters);
|
||||
}
|
||||
|
||||
} // namespace pdf
|
||||
|
|
|
@ -64,7 +64,8 @@ enum class AnnotationType
|
|||
PrinterMark,
|
||||
TrapNet,
|
||||
Watermark,
|
||||
_3D
|
||||
_3D,
|
||||
RichMedia
|
||||
};
|
||||
|
||||
enum class AnnotationLineEnding
|
||||
|
@ -564,6 +565,12 @@ protected:
|
|||
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:
|
||||
|
||||
QRectF m_rectangle; ///< Annotation rectangle, in page coordinates, "Rect" entry
|
||||
|
@ -1044,6 +1051,7 @@ public:
|
|||
};
|
||||
|
||||
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; }
|
||||
|
@ -1175,6 +1183,27 @@ private:
|
|||
PDFReal m_relativeVerticalOffset = 0.0;
|
||||
};
|
||||
|
||||
/// 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, PDFObject object);
|
||||
|
||||
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.
|
||||
|
|
|
@ -17,12 +17,20 @@
|
|||
|
||||
#include "pdfmultimedia.h"
|
||||
#include "pdfdocument.h"
|
||||
#include "pdfnametreeloader.h"
|
||||
|
||||
#include <QtEndian>
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
|
||||
constexpr const std::array<std::pair<const char*, RichMediaType>, 4> richMediaTypes = {
|
||||
std::pair<const char*, RichMediaType>{ "3D", RichMediaType::_3D },
|
||||
std::pair<const char*, RichMediaType>{ "Flash", RichMediaType::Flash },
|
||||
std::pair<const char*, RichMediaType>{ "Sound", RichMediaType::Sound },
|
||||
std::pair<const char*, RichMediaType>{ "Video", RichMediaType::Video }
|
||||
};
|
||||
|
||||
PDFSound PDFSound::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
PDFSound result;
|
||||
|
@ -662,4 +670,242 @@ PDFInteger PDFMovieActivation::parseMovieTimeFromString(const QByteArray& string
|
|||
return 0;
|
||||
}
|
||||
|
||||
PDFRichMediaWindowPosition PDFRichMediaWindowPosition::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
PDFRichMediaWindowPosition result;
|
||||
|
||||
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||
{
|
||||
constexpr const std::array<std::pair<const char*, Alignment>, 3> alignments = {
|
||||
std::pair<const char*, Alignment>{ "Near", Alignment::Near },
|
||||
std::pair<const char*, Alignment>{ "Center", Alignment::Center },
|
||||
std::pair<const char*, Alignment>{ "Far", Alignment::Far }
|
||||
};
|
||||
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
result.m_horizontalAlignment = loader.readEnumByName(dictionary->get("HAlign"), alignments.cbegin(), alignments.cend(), Alignment::Far);
|
||||
result.m_verticalAlignment = loader.readEnumByName(dictionary->get("VAlign"), alignments.cbegin(), alignments.cend(), Alignment::Near);
|
||||
result.m_horizontalOffset = loader.readNumberFromDictionary(dictionary, "HOffset", 18.0);
|
||||
result.m_verticalOffset = loader.readNumberFromDictionary(dictionary, "VOffset", 18.0);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFRichMediaWindow PDFRichMediaWindow::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
PDFRichMediaWindow result;
|
||||
|
||||
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||
{
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
|
||||
// Parse width
|
||||
if (const PDFDictionary* widthDictionary = storage->getDictionaryFromObject(dictionary->get("Width")))
|
||||
{
|
||||
result.m_width[Default] = loader.readNumberFromDictionary(widthDictionary, "Default", 288.0);
|
||||
result.m_width[Max] = loader.readNumberFromDictionary(widthDictionary, "Max", 576.0);
|
||||
result.m_width[Min] = loader.readNumberFromDictionary(widthDictionary, "Min", 72.0);
|
||||
}
|
||||
|
||||
// Parse height
|
||||
if (const PDFDictionary* heightDictionary = storage->getDictionaryFromObject(dictionary->get("Height")))
|
||||
{
|
||||
result.m_height[Default] = loader.readNumberFromDictionary(heightDictionary, "Default", 288.0);
|
||||
result.m_height[Max] = loader.readNumberFromDictionary(heightDictionary, "Max", 576.0);
|
||||
result.m_height[Min] = loader.readNumberFromDictionary(heightDictionary, "Min", 72.0);
|
||||
}
|
||||
|
||||
result.m_richMediaPosition = PDFRichMediaWindowPosition::parse(storage, dictionary->get("Position"));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFRichMediaPresentation PDFRichMediaPresentation::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
PDFRichMediaPresentation result;
|
||||
|
||||
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||
{
|
||||
constexpr const std::array<std::pair<const char*, Style>, 2> styles = {
|
||||
std::pair<const char*, Style>{ "Embedded", Style::Embedded },
|
||||
std::pair<const char*, Style>{ "Windowed", Style::Windowed }
|
||||
};
|
||||
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
result.m_style = loader.readEnumByName(dictionary->get("Style"), styles.cbegin(), styles.cend(), Style::Embedded);
|
||||
result.m_window = PDFRichMediaWindow::parse(storage, dictionary->get("Window"));
|
||||
result.m_isTransparent = loader.readBooleanFromDictionary(dictionary, "Transparent", false);
|
||||
result.m_isNavigationPaneEnabled = loader.readBooleanFromDictionary(dictionary, "NavigationPane", false);
|
||||
result.m_isToolbarEnabled = loader.readBooleanFromDictionary(dictionary, "Toolbar", false);
|
||||
result.m_isContentClickPassed = loader.readBooleanFromDictionary(dictionary, "PassContextClick", false);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFRichMediaAnimation PDFRichMediaAnimation::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
PDFRichMediaAnimation result;
|
||||
|
||||
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||
{
|
||||
constexpr const std::array<std::pair<const char*, Animation>, 3> animations = {
|
||||
std::pair<const char*, Animation>{ "None", Animation::None },
|
||||
std::pair<const char*, Animation>{ "Linear", Animation::Linear },
|
||||
std::pair<const char*, Animation>{ "Oscillating", Animation::Oscillating }
|
||||
};
|
||||
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
result.m_animation = loader.readEnumByName(dictionary->get("Subtype"), animations.cbegin(), animations.cend(), Animation::None);
|
||||
result.m_playCount = loader.readIntegerFromDictionary(dictionary, "PlayCount", -1);
|
||||
result.m_speed = loader.readNumberFromDictionary(dictionary, "Speed", 1.0);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFRichMediaDeactivation PDFRichMediaDeactivation::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
PDFRichMediaDeactivation result;
|
||||
|
||||
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||
{
|
||||
constexpr const std::array<std::pair<const char*, DeactivationMode>, 3> deactivationModes = {
|
||||
std::pair<const char*, DeactivationMode>{ "XD", DeactivationMode::ExplicitlyByUserAction },
|
||||
std::pair<const char*, DeactivationMode>{ "PC", DeactivationMode::PageLoseFocus },
|
||||
std::pair<const char*, DeactivationMode>{ "PI", DeactivationMode::PageHide }
|
||||
};
|
||||
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
result.m_mode = loader.readEnumByName(dictionary->get("Condition"), deactivationModes.cbegin(), deactivationModes.cend(), DeactivationMode::ExplicitlyByUserAction);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFRichMediaActivation PDFRichMediaActivation::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
PDFRichMediaActivation result;
|
||||
|
||||
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||
{
|
||||
constexpr const std::array<std::pair<const char*, ActivationMode>, 3> activationModes = {
|
||||
std::pair<const char*, ActivationMode>{ "XA", ActivationMode::ExplicitlyByUserAction },
|
||||
std::pair<const char*, ActivationMode>{ "PO", ActivationMode::PageEnterFocus },
|
||||
std::pair<const char*, ActivationMode>{ "PV", ActivationMode::PageShow }
|
||||
};
|
||||
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
result.m_mode = loader.readEnumByName(dictionary->get("Condition"), activationModes.cbegin(), activationModes.cend(), ActivationMode::ExplicitlyByUserAction);
|
||||
result.m_animation = PDFRichMediaAnimation::parse(storage, dictionary->get("Animation"));
|
||||
result.m_view = loader.readReferenceFromDictionary(dictionary, "View");
|
||||
result.m_configuration = loader.readReferenceFromDictionary(dictionary, "Configuration");
|
||||
result.m_presentation = PDFRichMediaPresentation::parse(storage, dictionary->get("Presentation"));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFRichMediaSettings PDFRichMediaSettings::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
PDFRichMediaSettings result;
|
||||
|
||||
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||
{
|
||||
result.m_activation = PDFRichMediaActivation::parse(storage, dictionary->get("Activation"));
|
||||
result.m_deactivation = PDFRichMediaDeactivation::parse(storage, dictionary->get("Deactivation"));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFRichMediaContent PDFRichMediaContent::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
PDFRichMediaContent result;
|
||||
|
||||
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||
{
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
result.m_assets = PDFNameTreeLoader<PDFFileSpecification>::parse(storage, dictionary->get("Assets"), &PDFFileSpecification::parse);
|
||||
result.m_configurations = loader.readReferenceArrayFromDictionary(dictionary, "Configurations");
|
||||
result.m_views = loader.readReferenceArrayFromDictionary(dictionary, "Views");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFRichMediaConfiguration PDFRichMediaConfiguration::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
PDFRichMediaConfiguration result;
|
||||
|
||||
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||
{
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
result.m_type = loader.readEnumByName(dictionary->get("Subtype"), richMediaTypes.cbegin(), richMediaTypes.cend(), RichMediaType::Unspecified);
|
||||
result.m_instances = loader.readReferenceArrayFromDictionary(dictionary, "Instances");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFRichMediaInstance PDFRichMediaInstance::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
PDFRichMediaInstance result;
|
||||
|
||||
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||
{
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
result.m_type = loader.readEnumByName(dictionary->get("Subtype"), richMediaTypes.cbegin(), richMediaTypes.cend(), RichMediaType::Unspecified);
|
||||
result.m_asset = loader.readReferenceFromDictionary(dictionary, "Asset");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PDF3DActivation PDF3DActivation::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||
{
|
||||
PDF3DActivation result;
|
||||
|
||||
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||
{
|
||||
constexpr const std::array<std::pair<const char*, TriggerMode>, 3> activationModes = {
|
||||
std::pair<const char*, TriggerMode>{ "XA", TriggerMode::ExplicitlyByUserAction },
|
||||
std::pair<const char*, TriggerMode>{ "PO", TriggerMode::PageFocus },
|
||||
std::pair<const char*, TriggerMode>{ "PV", TriggerMode::PageVisibility }
|
||||
};
|
||||
|
||||
constexpr const std::array<std::pair<const char*, ActivationMode>, 3> deactivationModes = {
|
||||
std::pair<const char*, TriggerMode>{ "XD", TriggerMode::ExplicitlyByUserAction },
|
||||
std::pair<const char*, TriggerMode>{ "PC", TriggerMode::PageFocus },
|
||||
std::pair<const char*, TriggerMode>{ "PI", TriggerMode::PageVisibility }
|
||||
};
|
||||
|
||||
constexpr const std::array<std::pair<const char*, ActivationMode>, 3> stateModes = {
|
||||
std::pair<const char*, ActivationMode>{ "I", ActivationMode::Instantiated },
|
||||
std::pair<const char*, ActivationMode>{ "L", ActivationMode::Live },
|
||||
std::pair<const char*, ActivationMode>{ "U", ActivationMode::Uninstantiated }
|
||||
};
|
||||
|
||||
constexpr const std::array<std::pair<const char*, Style>, 2> styles = {
|
||||
std::pair<const char*, Style>{ "Embedded", Style::Embedded },
|
||||
std::pair<const char*, Style>{ "Windowed", Style::Windowed }
|
||||
};
|
||||
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
result.m_activationTriggerMode = loader.readEnumByName(dictionary->get("A"), activationModes.cbegin(), activationModes.cend(), TriggerMode::ExplicitlyByUserAction);
|
||||
result.m_deactivationTriggerMode = loader.readEnumByName(dictionary->get("D"), deactivationModes.cbegin(), deactivationModes.cend(), TriggerMode::PageVisibility);
|
||||
result.m_activationMode = loader.readEnumByName(dictionary->get("AIS"), stateModes.cbegin(), stateModes.cend(), ActivationMode::Live);
|
||||
result.m_deactivationMode = loader.readEnumByName(dictionary->get("DIS"), stateModes.cbegin(), stateModes.cend(), ActivationMode::Uninstantiated);
|
||||
result.m_toolbar = loader.readBooleanFromDictionary(dictionary, "TB", true);
|
||||
result.m_navigator = loader.readBooleanFromDictionary(dictionary, "NP", false);
|
||||
result.m_style = loader.readEnumByName(dictionary->get("Style"), styles.cbegin(), styles.cend(), Style::Embedded);
|
||||
result.m_window = PDFRichMediaWindow::parse(storage, dictionary->get("Window"));
|
||||
result.m_transparent = loader.readBooleanFromDictionary(dictionary, "Transparent", false);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace pdf
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <QColor>
|
||||
|
||||
#include <map>
|
||||
#include <array>
|
||||
#include <optional>
|
||||
|
||||
namespace pdf
|
||||
|
@ -588,7 +589,7 @@ public:
|
|||
PDFInteger getScaleDenominator() const { return m_scaleDenominator; }
|
||||
QPointF getRelativeWindowPosition() const { return m_relativeWindowPosition; }
|
||||
|
||||
/// Creates a new moview from the object. If data are invalid, then invalid object
|
||||
/// Creates a new movie from the object. If data are invalid, then invalid object
|
||||
/// is returned, no exception is thrown.
|
||||
static PDFMovieActivation parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
|
@ -608,6 +609,322 @@ private:
|
|||
QPointF m_relativeWindowPosition;
|
||||
};
|
||||
|
||||
/// Rich media position of window
|
||||
class PDFRichMediaWindowPosition
|
||||
{
|
||||
public:
|
||||
explicit inline PDFRichMediaWindowPosition() = default;
|
||||
|
||||
enum class Alignment
|
||||
{
|
||||
Near,
|
||||
Center,
|
||||
Far
|
||||
};
|
||||
|
||||
Alignment getHorizontalAlignment() const { return m_horizontalAlignment; }
|
||||
Alignment getVerticalAlignment() const { return m_verticalAlignment; }
|
||||
PDFReal getHorizontalOffset() const { return m_horizontalOffset; }
|
||||
PDFReal getVerticalOffset() const { return m_verticalOffset; }
|
||||
|
||||
/// Creates a new rich media position from the object. If data are invalid, then invalid object
|
||||
/// is returned, no exception is thrown.
|
||||
static PDFRichMediaWindowPosition parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
private:
|
||||
Alignment m_horizontalAlignment = Alignment::Far;
|
||||
Alignment m_verticalAlignment = Alignment::Near;
|
||||
PDFReal m_horizontalOffset = 18.0;
|
||||
PDFReal m_verticalOffset = 18.0;
|
||||
};
|
||||
|
||||
/// Rich media window
|
||||
class PDFRichMediaWindow
|
||||
{
|
||||
public:
|
||||
explicit inline PDFRichMediaWindow() = default;
|
||||
|
||||
enum SizeHintType
|
||||
{
|
||||
Default,
|
||||
Max,
|
||||
Min,
|
||||
End
|
||||
};
|
||||
|
||||
PDFReal getWidth(SizeHintType type) const { return m_width.at(type); }
|
||||
PDFReal getHeight(SizeHintType type) const { return m_height.at(type); }
|
||||
const PDFRichMediaWindowPosition& getRichMediaWindowPosition() const { return m_richMediaPosition; }
|
||||
|
||||
using WindowSize = std::array<PDFReal, End>;
|
||||
|
||||
/// Creates a new rich media window from the object. If data are invalid, then invalid object
|
||||
/// is returned, no exception is thrown.
|
||||
static PDFRichMediaWindow parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
private:
|
||||
WindowSize m_width = { 288.0, 576.0, 72.0 };
|
||||
WindowSize m_height = { 288.0, 576.0, 72.0 };
|
||||
PDFRichMediaWindowPosition m_richMediaPosition;
|
||||
};
|
||||
|
||||
/// Rich media presentation defines, how rich media will appear on the page,
|
||||
/// or if it should be launched in a new window.
|
||||
class PDFRichMediaPresentation
|
||||
{
|
||||
public:
|
||||
explicit inline PDFRichMediaPresentation() = default;
|
||||
|
||||
enum class Style
|
||||
{
|
||||
Embedded,
|
||||
Windowed
|
||||
};
|
||||
|
||||
Style getStyle() const { return m_style; }
|
||||
const PDFRichMediaWindow& getWindow() const { return m_window; }
|
||||
bool isTransparent() const { return m_isTransparent; }
|
||||
bool isNavigationPaneEnabled() const { return m_isNavigationPaneEnabled; }
|
||||
bool isToolbarEnabled() const { return m_isToolbarEnabled; }
|
||||
bool isContentClickPassed() const { return m_isContentClickPassed; }
|
||||
|
||||
/// Creates a new rich media presentation from the object. If data are invalid, then invalid object
|
||||
/// is returned, no exception is thrown.
|
||||
static PDFRichMediaPresentation parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
private:
|
||||
Style m_style = Style::Embedded;
|
||||
PDFRichMediaWindow m_window; ///< Meaningful only when style is windowed
|
||||
bool m_isTransparent = false;
|
||||
bool m_isNavigationPaneEnabled = false;
|
||||
bool m_isToolbarEnabled = false;
|
||||
bool m_isContentClickPassed = false;
|
||||
};
|
||||
|
||||
/// Rich media animation
|
||||
class PDFRichMediaAnimation
|
||||
{
|
||||
public:
|
||||
explicit inline PDFRichMediaAnimation() = default;
|
||||
|
||||
enum class Animation
|
||||
{
|
||||
None,
|
||||
Linear,
|
||||
Oscillating
|
||||
};
|
||||
|
||||
Animation getAnimation() const { return m_animation; }
|
||||
PDFInteger getPlayCount() const { return m_playCount; }
|
||||
PDFReal getSpeed() const { return m_speed; }
|
||||
|
||||
/// Creates a new rich media animation from the object. If data are invalid, then invalid object
|
||||
/// is returned, no exception is thrown.
|
||||
static PDFRichMediaAnimation parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
private:
|
||||
Animation m_animation = Animation::None;
|
||||
PDFInteger m_playCount = -1;
|
||||
PDFReal m_speed = 1;
|
||||
};
|
||||
|
||||
/// Rich media deactivation dictionary
|
||||
class PDFRichMediaDeactivation
|
||||
{
|
||||
public:
|
||||
explicit inline PDFRichMediaDeactivation() = default;
|
||||
|
||||
enum class DeactivationMode
|
||||
{
|
||||
ExplicitlyByUserAction,
|
||||
PageLoseFocus,
|
||||
PageHide
|
||||
};
|
||||
|
||||
DeactivationMode getMode() const { return m_mode; }
|
||||
|
||||
/// Creates a new rich media deactivation from the object. If data are invalid, then invalid object
|
||||
/// is returned, no exception is thrown.
|
||||
static PDFRichMediaDeactivation parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
private:
|
||||
DeactivationMode m_mode = DeactivationMode::ExplicitlyByUserAction;
|
||||
};
|
||||
|
||||
/// Rich media activation dictionary
|
||||
class PDFRichMediaActivation
|
||||
{
|
||||
public:
|
||||
explicit inline PDFRichMediaActivation() = default;
|
||||
|
||||
enum class ActivationMode
|
||||
{
|
||||
ExplicitlyByUserAction,
|
||||
PageEnterFocus,
|
||||
PageShow
|
||||
};
|
||||
|
||||
ActivationMode getActivationMode() const { return m_mode; }
|
||||
const PDFRichMediaAnimation& getAnimation() const { return m_animation; }
|
||||
PDFObjectReference getView() const { return m_view; }
|
||||
PDFObjectReference getConfiguration() const { return m_configuration; }
|
||||
const PDFRichMediaPresentation& getPresentation() const { return m_presentation; }
|
||||
|
||||
/// Creates a new rich media activation from the object. If data are invalid, then invalid object
|
||||
/// is returned, no exception is thrown.
|
||||
static PDFRichMediaActivation parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
private:
|
||||
ActivationMode m_mode = ActivationMode::ExplicitlyByUserAction;
|
||||
PDFRichMediaAnimation m_animation;
|
||||
PDFObjectReference m_view;
|
||||
PDFObjectReference m_configuration;
|
||||
PDFRichMediaPresentation m_presentation;
|
||||
};
|
||||
|
||||
/// Rich media settings
|
||||
class PDFRichMediaSettings
|
||||
{
|
||||
public:
|
||||
explicit inline PDFRichMediaSettings() = default;
|
||||
|
||||
const PDFRichMediaActivation& getActivation() const { return m_activation; }
|
||||
const PDFRichMediaDeactivation& getDeactivation() const { return m_deactivation; }
|
||||
|
||||
/// Creates a new rich media settings from the object. If data are invalid, then invalid object
|
||||
/// is returned, no exception is thrown.
|
||||
static PDFRichMediaSettings parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
private:
|
||||
PDFRichMediaActivation m_activation;
|
||||
PDFRichMediaDeactivation m_deactivation;
|
||||
};
|
||||
|
||||
/// Rich media content dictionary
|
||||
class PDFRichMediaContent
|
||||
{
|
||||
public:
|
||||
explicit inline PDFRichMediaContent() = default;
|
||||
|
||||
using Assets = std::map<QByteArray, PDFFileSpecification>;
|
||||
using Configurations = std::vector<PDFObjectReference>;
|
||||
using Views = std::vector<PDFObjectReference>;
|
||||
|
||||
const Assets& getAssets() const { return m_assets; }
|
||||
const Configurations& getConfigurations() const { return m_configurations; }
|
||||
const Views& getViews() const { return m_views; }
|
||||
|
||||
/// Creates a new rich media content from the object. If data are invalid, then invalid object
|
||||
/// is returned, no exception is thrown.
|
||||
static PDFRichMediaContent parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
private:
|
||||
Assets m_assets;
|
||||
Configurations m_configurations;
|
||||
Views m_views;
|
||||
};
|
||||
|
||||
enum class RichMediaType
|
||||
{
|
||||
Unspecified,
|
||||
_3D,
|
||||
Sound,
|
||||
Flash,
|
||||
Video
|
||||
};
|
||||
|
||||
/// Rich media configuration dictionary
|
||||
class PDFRichMediaConfiguration
|
||||
{
|
||||
public:
|
||||
explicit inline PDFRichMediaConfiguration() = default;
|
||||
|
||||
using Instances = std::vector<PDFObjectReference>;
|
||||
|
||||
RichMediaType getType() const { return m_type; }
|
||||
const Instances& getInstances() const { return m_instances; }
|
||||
|
||||
/// Creates a new rich media configuration from the object. If data are invalid, then invalid object
|
||||
/// is returned, no exception is thrown.
|
||||
static PDFRichMediaConfiguration parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
private:
|
||||
RichMediaType m_type = RichMediaType::Unspecified;
|
||||
Instances m_instances;
|
||||
};
|
||||
|
||||
/// Rich media instance dictionary
|
||||
class PDFRichMediaInstance
|
||||
{
|
||||
public:
|
||||
explicit inline PDFRichMediaInstance() = default;
|
||||
|
||||
RichMediaType getType() const { return m_type; }
|
||||
PDFObjectReference getAsset() const { return m_asset; }
|
||||
|
||||
/// Creates a new rich media instance from the object. If data are invalid, then invalid object
|
||||
/// is returned, no exception is thrown.
|
||||
static PDFRichMediaInstance parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
private:
|
||||
RichMediaType m_type = RichMediaType::Unspecified;
|
||||
PDFObjectReference m_asset;
|
||||
};
|
||||
|
||||
/// 3D PDF activation dictionary
|
||||
class PDF3DActivation
|
||||
{
|
||||
public:
|
||||
|
||||
/// Activation/deactivation mode
|
||||
enum class TriggerMode
|
||||
{
|
||||
ExplicitlyByUserAction, ///< Explicitly turned on/off by user
|
||||
PageFocus, ///< Turned on/off by gain/lose focus
|
||||
PageVisibility ///< Turned on/off by page shown/hidden
|
||||
};
|
||||
|
||||
/// Activation mode
|
||||
enum class ActivationMode
|
||||
{
|
||||
Uninstantiated,
|
||||
Instantiated,
|
||||
Live
|
||||
};
|
||||
|
||||
/// Style
|
||||
enum class Style
|
||||
{
|
||||
Embedded,
|
||||
Windowed
|
||||
};
|
||||
|
||||
TriggerMode getActivationTriggerMode() const { return m_activationMode; }
|
||||
TriggerMode getDeactivationTriggerMode() const { return m_deactivationMode; }
|
||||
ActivationMode getActivationMode() const { return m_activationMode; }
|
||||
ActivationMode getDeactivationMode() const { return m_deactivationMode; }
|
||||
bool hasToolbar() const { return m_toolbar; }
|
||||
bool hasNavigator() const { return m_navigator; }
|
||||
Style getStyle() const { return m_style; }
|
||||
const PDFRichMediaWindow& getWindow() const { return m_window; }
|
||||
bool isTransparent() const { return m_transparent; }
|
||||
|
||||
/// Creates a new 3D annotation activation from the object. If data are invalid, then invalid object
|
||||
/// is returned, no exception is thrown.
|
||||
static PDF3DActivation parse(const PDFObjectStorage* storage, PDFObject object);
|
||||
|
||||
private:
|
||||
TriggerMode m_activationTriggerMode = TriggerMode::ExplicitlyByUserAction;
|
||||
TriggerMode m_deactivationTriggerMode = TriggerMode::PageVisibility;
|
||||
ActivationMode m_activationMode = ActivationMode::Live;
|
||||
ActivationMode m_deactivationMode = ActivationMode::Uninstantiated;
|
||||
bool m_toolbar = true;
|
||||
bool m_navigator = false;
|
||||
Style m_style = Style::Embedded;
|
||||
PDFRichMediaWindow m_window;
|
||||
bool m_transparent = false;
|
||||
};
|
||||
|
||||
} // namespace pdf
|
||||
|
||||
#endif // PDFMULTIMEDIA_H
|
||||
|
|
Loading…
Reference in New Issue