Rich media and 3D annotations

This commit is contained in:
Jakub Melka 2020-04-09 19:49:57 +02:00
parent de1fa4a2da
commit 6d9744886a
4 changed files with 643 additions and 19 deletions

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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