You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
762 lines
30 KiB
762 lines
30 KiB
/*************************************************************************** |
|
* Copyright (C) 2008 by Pino Toscano <pino@kde.org> * |
|
* Copyright (C) 2012 by Guillermo A. Amaral B. <gamaral@kde.org> * |
|
* Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group * |
|
* company, info@kdab.com. Work sponsored by the * |
|
* LiMux project of the city of Munich * |
|
* * |
|
* This program is free software; you can redistribute it and/or modify * |
|
* it under the terms of the GNU General Public License as published by * |
|
* the Free Software Foundation; either version 2 of the License, or * |
|
* (at your option) any later version. * |
|
***************************************************************************/ |
|
|
|
#include "annots.h" |
|
|
|
#include <poppler-annotation.h> |
|
|
|
// qt/kde includes |
|
#include <QLoggingCategory> |
|
#include <QVariant> |
|
|
|
#include <core/annotations.h> |
|
#include <core/area.h> |
|
|
|
#include "config-okular-poppler.h" |
|
#include "debug_pdf.h" |
|
#include "generator_pdf.h" |
|
#include "popplerembeddedfile.h" |
|
|
|
Q_DECLARE_METATYPE(Poppler::Annotation *) |
|
|
|
extern Okular::Sound *createSoundFromPopplerSound(const Poppler::SoundObject *popplerSound); |
|
extern Okular::Movie *createMovieFromPopplerMovie(const Poppler::MovieObject *popplerMovie); |
|
extern Okular::Movie *createMovieFromPopplerScreen(const Poppler::LinkRendition *popplerScreen); |
|
extern QPair<Okular::Movie *, Okular::EmbeddedFile *> createMovieFromPopplerRichMedia(const Poppler::RichMediaAnnotation *popplerRichMedia); |
|
|
|
static void disposeAnnotation(const Okular::Annotation *ann) |
|
{ |
|
Poppler::Annotation *popplerAnn = qvariant_cast<Poppler::Annotation *>(ann->nativeId()); |
|
delete popplerAnn; |
|
} |
|
|
|
static QPointF normPointToPointF(const Okular::NormalizedPoint &pt) |
|
{ |
|
return QPointF(pt.x, pt.y); |
|
} |
|
|
|
static QRectF normRectToRectF(const Okular::NormalizedRect &rect) |
|
{ |
|
return QRectF(QPointF(rect.left, rect.top), QPointF(rect.right, rect.bottom)); |
|
} |
|
|
|
// Poppler and Okular share the same flag values, but we don't want to export internal flags |
|
static int maskExportedFlags(int flags) |
|
{ |
|
return flags & |
|
(Okular::Annotation::Hidden | Okular::Annotation::FixedSize | Okular::Annotation::FixedRotation | Okular::Annotation::DenyPrint | Okular::Annotation::DenyWrite | Okular::Annotation::DenyDelete | |
|
Okular::Annotation::ToggleHidingOnMouse); |
|
} |
|
|
|
// BEGIN PopplerAnnotationProxy implementation |
|
PopplerAnnotationProxy::PopplerAnnotationProxy(Poppler::Document *doc, QMutex *userMutex, QHash<Okular::Annotation *, Poppler::Annotation *> *annotsOnOpenHash) |
|
: ppl_doc(doc) |
|
, mutex(userMutex) |
|
, annotationsOnOpenHash(annotsOnOpenHash) |
|
{ |
|
} |
|
|
|
PopplerAnnotationProxy::~PopplerAnnotationProxy() |
|
{ |
|
} |
|
|
|
bool PopplerAnnotationProxy::supports(Capability cap) const |
|
{ |
|
switch (cap) { |
|
case Addition: |
|
case Modification: |
|
case Removal: |
|
return true; |
|
default: |
|
return false; |
|
} |
|
} |
|
|
|
void PopplerAnnotationProxy::notifyAddition(Okular::Annotation *okl_ann, int page) |
|
{ |
|
// Export annotation to DOM |
|
QDomDocument doc; |
|
QDomElement dom_ann = doc.createElement(QStringLiteral("root")); |
|
Okular::AnnotationUtils::storeAnnotation(okl_ann, dom_ann, doc); |
|
|
|
QMutexLocker ml(mutex); |
|
|
|
// Create poppler annotation |
|
Poppler::Annotation *ppl_ann = Poppler::AnnotationUtils::createAnnotation(dom_ann); |
|
|
|
// Poppler doesn't render StampAnnotations yet |
|
if (ppl_ann->subType() != Poppler::Annotation::AStamp) |
|
okl_ann->setFlags(okl_ann->flags() | Okular::Annotation::ExternallyDrawn); |
|
|
|
// Poppler stores highlight points in swapped order |
|
if (ppl_ann->subType() == Poppler::Annotation::AHighlight) { |
|
Poppler::HighlightAnnotation *hlann = static_cast<Poppler::HighlightAnnotation *>(ppl_ann); |
|
QList<Poppler::HighlightAnnotation::Quad> quads = hlann->highlightQuads(); |
|
QMutableListIterator<Poppler::HighlightAnnotation::Quad> it(quads); |
|
while (it.hasNext()) { |
|
Poppler::HighlightAnnotation::Quad &q = it.next(); |
|
QPointF t; |
|
t = q.points[3]; |
|
q.points[3] = q.points[0]; |
|
q.points[0] = t; |
|
t = q.points[2]; |
|
q.points[2] = q.points[1]; |
|
q.points[1] = t; |
|
} |
|
hlann->setHighlightQuads(quads); |
|
} |
|
|
|
// Bind poppler object to page |
|
Poppler::Page *ppl_page = ppl_doc->page(page); |
|
ppl_page->addAnnotation(ppl_ann); |
|
delete ppl_page; |
|
|
|
// Set pointer to poppler annotation as native Id |
|
okl_ann->setNativeId(QVariant::fromValue(ppl_ann)); |
|
okl_ann->setDisposeDataFunction(disposeAnnotation); |
|
|
|
qCDebug(OkularPdfDebug) << okl_ann->uniqueName(); |
|
} |
|
|
|
void PopplerAnnotationProxy::notifyModification(const Okular::Annotation *okl_ann, int page, bool appearanceChanged) |
|
{ |
|
Q_UNUSED(page); |
|
Q_UNUSED(appearanceChanged); |
|
|
|
Poppler::Annotation *ppl_ann = qvariant_cast<Poppler::Annotation *>(okl_ann->nativeId()); |
|
|
|
if (!ppl_ann) // Ignore non-native annotations |
|
return; |
|
|
|
QMutexLocker ml(mutex); |
|
|
|
if (okl_ann->flags() & (Okular::Annotation::BeingMoved | Okular::Annotation::BeingResized)) { |
|
// Okular ui already renders the annotation on its own |
|
ppl_ann->setFlags(Poppler::Annotation::Hidden); |
|
return; |
|
} |
|
|
|
// Set basic properties |
|
// Note: flags and boundary must be set first in order to correctly handle |
|
// FixedRotation annotations. |
|
ppl_ann->setFlags(maskExportedFlags(okl_ann->flags())); |
|
ppl_ann->setBoundary(normRectToRectF(okl_ann->boundingRectangle())); |
|
|
|
ppl_ann->setAuthor(okl_ann->author()); |
|
ppl_ann->setContents(okl_ann->contents()); |
|
|
|
// Set style |
|
Poppler::Annotation::Style s; |
|
s.setColor(okl_ann->style().color()); |
|
s.setWidth(okl_ann->style().width()); |
|
s.setOpacity(okl_ann->style().opacity()); |
|
ppl_ann->setStyle(s); |
|
|
|
// Set type-specific properties (if any) |
|
switch (ppl_ann->subType()) { |
|
case Poppler::Annotation::AText: { |
|
const Okular::TextAnnotation *okl_txtann = static_cast<const Okular::TextAnnotation *>(okl_ann); |
|
Poppler::TextAnnotation *ppl_txtann = static_cast<Poppler::TextAnnotation *>(ppl_ann); |
|
ppl_txtann->setTextIcon(okl_txtann->textIcon()); |
|
ppl_txtann->setTextFont(okl_txtann->textFont()); |
|
ppl_txtann->setTextColor(okl_txtann->textColor()); |
|
ppl_txtann->setInplaceAlign(okl_txtann->inplaceAlignment()); |
|
ppl_txtann->setCalloutPoints(QVector<QPointF>()); |
|
ppl_txtann->setInplaceIntent((Poppler::TextAnnotation::InplaceIntent)okl_txtann->inplaceIntent()); |
|
break; |
|
} |
|
case Poppler::Annotation::ALine: { |
|
const Okular::LineAnnotation *okl_lineann = static_cast<const Okular::LineAnnotation *>(okl_ann); |
|
Poppler::LineAnnotation *ppl_lineann = static_cast<Poppler::LineAnnotation *>(ppl_ann); |
|
QLinkedList<QPointF> points; |
|
const QLinkedList<Okular::NormalizedPoint> annotPoints = okl_lineann->linePoints(); |
|
for (const Okular::NormalizedPoint &p : annotPoints) { |
|
points.append(normPointToPointF(p)); |
|
} |
|
ppl_lineann->setLinePoints(points); |
|
ppl_lineann->setLineStartStyle((Poppler::LineAnnotation::TermStyle)okl_lineann->lineStartStyle()); |
|
ppl_lineann->setLineEndStyle((Poppler::LineAnnotation::TermStyle)okl_lineann->lineEndStyle()); |
|
ppl_lineann->setLineClosed(okl_lineann->lineClosed()); |
|
ppl_lineann->setLineInnerColor(okl_lineann->lineInnerColor()); |
|
ppl_lineann->setLineLeadingForwardPoint(okl_lineann->lineLeadingForwardPoint()); |
|
ppl_lineann->setLineLeadingBackPoint(okl_lineann->lineLeadingBackwardPoint()); |
|
ppl_lineann->setLineShowCaption(okl_lineann->showCaption()); |
|
ppl_lineann->setLineIntent((Poppler::LineAnnotation::LineIntent)okl_lineann->lineIntent()); |
|
break; |
|
} |
|
case Poppler::Annotation::AGeom: { |
|
const Okular::GeomAnnotation *okl_geomann = static_cast<const Okular::GeomAnnotation *>(okl_ann); |
|
Poppler::GeomAnnotation *ppl_geomann = static_cast<Poppler::GeomAnnotation *>(ppl_ann); |
|
ppl_geomann->setGeomType((Poppler::GeomAnnotation::GeomType)okl_geomann->geometricalType()); |
|
ppl_geomann->setGeomInnerColor(okl_geomann->geometricalInnerColor()); |
|
break; |
|
} |
|
case Poppler::Annotation::AHighlight: { |
|
const Okular::HighlightAnnotation *okl_hlann = static_cast<const Okular::HighlightAnnotation *>(okl_ann); |
|
Poppler::HighlightAnnotation *ppl_hlann = static_cast<Poppler::HighlightAnnotation *>(ppl_ann); |
|
ppl_hlann->setHighlightType((Poppler::HighlightAnnotation::HighlightType)okl_hlann->highlightType()); |
|
break; |
|
} |
|
case Poppler::Annotation::AStamp: { |
|
const Okular::StampAnnotation *okl_stampann = static_cast<const Okular::StampAnnotation *>(okl_ann); |
|
Poppler::StampAnnotation *ppl_stampann = static_cast<Poppler::StampAnnotation *>(ppl_ann); |
|
ppl_stampann->setStampIconName(okl_stampann->stampIconName()); |
|
break; |
|
} |
|
case Poppler::Annotation::AInk: { |
|
const Okular::InkAnnotation *okl_inkann = static_cast<const Okular::InkAnnotation *>(okl_ann); |
|
Poppler::InkAnnotation *ppl_inkann = static_cast<Poppler::InkAnnotation *>(ppl_ann); |
|
QList<QLinkedList<QPointF>> paths; |
|
const QList<QLinkedList<Okular::NormalizedPoint>> inkPathsList = okl_inkann->inkPaths(); |
|
for (const QLinkedList<Okular::NormalizedPoint> &path : inkPathsList) { |
|
QLinkedList<QPointF> points; |
|
for (const Okular::NormalizedPoint &p : path) { |
|
points.append(normPointToPointF(p)); |
|
} |
|
paths.append(points); |
|
} |
|
ppl_inkann->setInkPaths(paths); |
|
break; |
|
} |
|
default: |
|
qCDebug(OkularPdfDebug) << "Type-specific property modification is not implemented for this annotation type"; |
|
break; |
|
} |
|
|
|
qCDebug(OkularPdfDebug) << okl_ann->uniqueName(); |
|
} |
|
|
|
void PopplerAnnotationProxy::notifyRemoval(Okular::Annotation *okl_ann, int page) |
|
{ |
|
Poppler::Annotation *ppl_ann = qvariant_cast<Poppler::Annotation *>(okl_ann->nativeId()); |
|
|
|
if (!ppl_ann) // Ignore non-native annotations |
|
return; |
|
|
|
QMutexLocker ml(mutex); |
|
|
|
Poppler::Page *ppl_page = ppl_doc->page(page); |
|
annotationsOnOpenHash->remove(okl_ann); |
|
ppl_page->removeAnnotation(ppl_ann); // Also destroys ppl_ann |
|
delete ppl_page; |
|
|
|
okl_ann->setNativeId(QVariant::fromValue(0)); // So that we don't double-free in disposeAnnotation |
|
|
|
qCDebug(OkularPdfDebug) << okl_ann->uniqueName(); |
|
} |
|
// END PopplerAnnotationProxy implementation |
|
|
|
static Okular::Annotation::LineStyle popplerToOkular(Poppler::Annotation::LineStyle s) |
|
{ |
|
switch (s) { |
|
case Poppler::Annotation::Solid: |
|
return Okular::Annotation::Solid; |
|
case Poppler::Annotation::Dashed: |
|
return Okular::Annotation::Dashed; |
|
case Poppler::Annotation::Beveled: |
|
return Okular::Annotation::Beveled; |
|
case Poppler::Annotation::Inset: |
|
return Okular::Annotation::Inset; |
|
case Poppler::Annotation::Underline: |
|
return Okular::Annotation::Underline; |
|
default: |
|
qWarning() << Q_FUNC_INFO << "unknown value" << s; |
|
} |
|
|
|
return Okular::Annotation::Solid; |
|
} |
|
|
|
static Okular::Annotation::LineEffect popplerToOkular(Poppler::Annotation::LineEffect e) |
|
{ |
|
switch (e) { |
|
case Poppler::Annotation::NoEffect: |
|
return Okular::Annotation::NoEffect; |
|
case Poppler::Annotation::Cloudy: |
|
return Okular::Annotation::Cloudy; |
|
default: |
|
qWarning() << Q_FUNC_INFO << "unknown value" << e; |
|
} |
|
|
|
return Okular::Annotation::NoEffect; |
|
} |
|
|
|
static Okular::Annotation::RevisionScope popplerToOkular(Poppler::Annotation::RevScope s) |
|
{ |
|
switch (s) { |
|
case Poppler::Annotation::Root: |
|
Q_UNREACHABLE(); |
|
case Poppler::Annotation::Reply: |
|
return Okular::Annotation::Reply; |
|
case Poppler::Annotation::Group: |
|
return Okular::Annotation::Group; |
|
case Poppler::Annotation::Delete: |
|
return Okular::Annotation::Delete; |
|
default: |
|
qWarning() << Q_FUNC_INFO << "unknown value" << s; |
|
} |
|
|
|
return Okular::Annotation::Reply; |
|
} |
|
|
|
static Okular::Annotation::RevisionType popplerToOkular(Poppler::Annotation::RevType t) |
|
{ |
|
switch (t) { |
|
case Poppler::Annotation::None: |
|
return Okular::Annotation::None; |
|
case Poppler::Annotation::Marked: |
|
return Okular::Annotation::Marked; |
|
case Poppler::Annotation::Unmarked: |
|
return Okular::Annotation::Unmarked; |
|
case Poppler::Annotation::Accepted: |
|
return Okular::Annotation::Accepted; |
|
case Poppler::Annotation::Rejected: |
|
return Okular::Annotation::Rejected; |
|
case Poppler::Annotation::Cancelled: |
|
return Okular::Annotation::Cancelled; |
|
case Poppler::Annotation::Completed: |
|
return Okular::Annotation::Completed; |
|
default: |
|
qWarning() << Q_FUNC_INFO << "unknown value" << t; |
|
} |
|
|
|
return Okular::Annotation::None; |
|
} |
|
|
|
static Okular::TextAnnotation::TextType popplerToOkular(Poppler::TextAnnotation::TextType ptt) |
|
{ |
|
switch (ptt) { |
|
case Poppler::TextAnnotation::Linked: |
|
return Okular::TextAnnotation::Linked; |
|
case Poppler::TextAnnotation::InPlace: |
|
return Okular::TextAnnotation::Linked; |
|
default: |
|
qWarning() << Q_FUNC_INFO << "unknown value" << ptt; |
|
} |
|
|
|
return Okular::TextAnnotation::Linked; |
|
} |
|
|
|
static Okular::TextAnnotation::InplaceIntent popplerToOkular(Poppler::TextAnnotation::InplaceIntent pii) |
|
{ |
|
switch (pii) { |
|
case Poppler::TextAnnotation::Unknown: |
|
return Okular::TextAnnotation::Unknown; |
|
case Poppler::TextAnnotation::Callout: |
|
return Okular::TextAnnotation::Callout; |
|
case Poppler::TextAnnotation::TypeWriter: |
|
return Okular::TextAnnotation::TypeWriter; |
|
default: |
|
qWarning() << Q_FUNC_INFO << "unknown value" << pii; |
|
} |
|
|
|
return Okular::TextAnnotation::Unknown; |
|
} |
|
|
|
static Okular::LineAnnotation::TermStyle popplerToOkular(Poppler::LineAnnotation::TermStyle pts) |
|
{ |
|
switch (pts) { |
|
case Poppler::LineAnnotation::Square: |
|
return Okular::LineAnnotation::Square; |
|
case Poppler::LineAnnotation::Circle: |
|
return Okular::LineAnnotation::Circle; |
|
case Poppler::LineAnnotation::Diamond: |
|
return Okular::LineAnnotation::Diamond; |
|
case Poppler::LineAnnotation::OpenArrow: |
|
return Okular::LineAnnotation::OpenArrow; |
|
case Poppler::LineAnnotation::ClosedArrow: |
|
return Okular::LineAnnotation::ClosedArrow; |
|
case Poppler::LineAnnotation::None: |
|
return Okular::LineAnnotation::None; |
|
case Poppler::LineAnnotation::Butt: |
|
return Okular::LineAnnotation::Butt; |
|
case Poppler::LineAnnotation::ROpenArrow: |
|
return Okular::LineAnnotation::ROpenArrow; |
|
case Poppler::LineAnnotation::RClosedArrow: |
|
return Okular::LineAnnotation::RClosedArrow; |
|
case Poppler::LineAnnotation::Slash: |
|
return Okular::LineAnnotation::Slash; |
|
default: |
|
qWarning() << Q_FUNC_INFO << "unknown value" << pts; |
|
} |
|
|
|
return Okular::LineAnnotation::None; |
|
} |
|
|
|
static Okular::LineAnnotation::LineIntent popplerToOkular(Poppler::LineAnnotation::LineIntent pli) |
|
{ |
|
switch (pli) { |
|
case Poppler::LineAnnotation::Unknown: |
|
return Okular::LineAnnotation::Unknown; |
|
case Poppler::LineAnnotation::Arrow: |
|
return Okular::LineAnnotation::Arrow; |
|
case Poppler::LineAnnotation::Dimension: |
|
return Okular::LineAnnotation::Dimension; |
|
case Poppler::LineAnnotation::PolygonCloud: |
|
return Okular::LineAnnotation::PolygonCloud; |
|
default: |
|
qWarning() << Q_FUNC_INFO << "unknown value" << pli; |
|
} |
|
|
|
return Okular::LineAnnotation::Unknown; |
|
} |
|
|
|
static Okular::GeomAnnotation::GeomType popplerToOkular(Poppler::GeomAnnotation::GeomType pgt) |
|
{ |
|
switch (pgt) { |
|
case Poppler::GeomAnnotation::InscribedSquare: |
|
return Okular::GeomAnnotation::InscribedSquare; |
|
case Poppler::GeomAnnotation::InscribedCircle: |
|
return Okular::GeomAnnotation::InscribedCircle; |
|
default: |
|
qWarning() << Q_FUNC_INFO << "unknown value" << pgt; |
|
} |
|
|
|
return Okular::GeomAnnotation::InscribedSquare; |
|
} |
|
|
|
static Okular::HighlightAnnotation::HighlightType popplerToOkular(Poppler::HighlightAnnotation::HighlightType pht) |
|
{ |
|
switch (pht) { |
|
case Poppler::HighlightAnnotation::Highlight: |
|
return Okular::HighlightAnnotation::Highlight; |
|
case Poppler::HighlightAnnotation::Squiggly: |
|
return Okular::HighlightAnnotation::Squiggly; |
|
case Poppler::HighlightAnnotation::Underline: |
|
return Okular::HighlightAnnotation::Underline; |
|
case Poppler::HighlightAnnotation::StrikeOut: |
|
return Okular::HighlightAnnotation::StrikeOut; |
|
default: |
|
qWarning() << Q_FUNC_INFO << "unknown value" << pht; |
|
} |
|
|
|
return Okular::HighlightAnnotation::Highlight; |
|
} |
|
|
|
static Okular::CaretAnnotation::CaretSymbol popplerToOkular(Poppler::CaretAnnotation::CaretSymbol pcs) |
|
{ |
|
switch (pcs) { |
|
case Poppler::CaretAnnotation::None: |
|
return Okular::CaretAnnotation::None; |
|
case Poppler::CaretAnnotation::P: |
|
return Okular::CaretAnnotation::P; |
|
default: |
|
qWarning() << Q_FUNC_INFO << "unknown value" << pcs; |
|
} |
|
|
|
return Okular::CaretAnnotation::None; |
|
} |
|
|
|
static Okular::Annotation *createAnnotationFromPopplerAnnotation(Poppler::TextAnnotation *popplerAnnotation) |
|
{ |
|
Okular::TextAnnotation *oTextAnn = new Okular::TextAnnotation(); |
|
|
|
oTextAnn->setTextType(popplerToOkular(popplerAnnotation->textType())); |
|
oTextAnn->setTextIcon(popplerAnnotation->textIcon()); |
|
oTextAnn->setTextFont(popplerAnnotation->textFont()); |
|
oTextAnn->setTextColor(popplerAnnotation->textColor()); |
|
// this works because we use the same 0:left, 1:center, 2:right meaning both in poppler and okular |
|
oTextAnn->setInplaceAlignment(popplerAnnotation->inplaceAlign()); |
|
oTextAnn->setInplaceIntent(popplerToOkular(popplerAnnotation->inplaceIntent())); |
|
for (int i = 0; i < 3; ++i) { |
|
const QPointF p = popplerAnnotation->calloutPoint(i); |
|
oTextAnn->setInplaceCallout({p.x(), p.y()}, i); |
|
} |
|
|
|
return oTextAnn; |
|
} |
|
|
|
static Okular::Annotation *createAnnotationFromPopplerAnnotation(const Poppler::LineAnnotation *popplerAnnotation) |
|
{ |
|
Okular::LineAnnotation *oLineAnn = new Okular::LineAnnotation(); |
|
|
|
oLineAnn->setLineStartStyle(popplerToOkular(popplerAnnotation->lineStartStyle())); |
|
oLineAnn->setLineEndStyle(popplerToOkular(popplerAnnotation->lineEndStyle())); |
|
oLineAnn->setLineClosed(popplerAnnotation->isLineClosed()); |
|
oLineAnn->setLineInnerColor(popplerAnnotation->lineInnerColor()); |
|
oLineAnn->setLineLeadingForwardPoint(popplerAnnotation->lineLeadingForwardPoint()); |
|
oLineAnn->setLineLeadingBackwardPoint(popplerAnnotation->lineLeadingBackPoint()); |
|
oLineAnn->setShowCaption(popplerAnnotation->lineShowCaption()); |
|
oLineAnn->setLineIntent(popplerToOkular(popplerAnnotation->lineIntent())); |
|
|
|
QLinkedList<Okular::NormalizedPoint> points; |
|
const QLinkedList<QPointF> popplerPoints = popplerAnnotation->linePoints(); |
|
for (const QPointF &p : popplerPoints) { |
|
points << Okular::NormalizedPoint(p.x(), p.y()); |
|
} |
|
oLineAnn->setLinePoints(points); |
|
|
|
return oLineAnn; |
|
} |
|
|
|
static Okular::Annotation *createAnnotationFromPopplerAnnotation(const Poppler::GeomAnnotation *popplerAnnotation) |
|
{ |
|
Okular::GeomAnnotation *oGeomAnn = new Okular::GeomAnnotation(); |
|
|
|
oGeomAnn->setGeometricalType(popplerToOkular(popplerAnnotation->geomType())); |
|
oGeomAnn->setGeometricalInnerColor(popplerAnnotation->geomInnerColor()); |
|
|
|
return oGeomAnn; |
|
} |
|
|
|
static Okular::Annotation *createAnnotationFromPopplerAnnotation(const Poppler::HighlightAnnotation *popplerAnnotation) |
|
{ |
|
Okular::HighlightAnnotation *oHighlightAnn = new Okular::HighlightAnnotation(); |
|
|
|
oHighlightAnn->setHighlightType(popplerToOkular(popplerAnnotation->highlightType())); |
|
|
|
const QList<Poppler::HighlightAnnotation::Quad> popplerHq = popplerAnnotation->highlightQuads(); |
|
QList<Okular::HighlightAnnotation::Quad> &okularHq = oHighlightAnn->highlightQuads(); |
|
|
|
for (const Poppler::HighlightAnnotation::Quad &popplerQ : popplerHq) { |
|
Okular::HighlightAnnotation::Quad q; |
|
|
|
// Poppler stores highlight points in swapped order |
|
q.setPoint(Okular::NormalizedPoint(popplerQ.points[0].x(), popplerQ.points[0].y()), 3); |
|
q.setPoint(Okular::NormalizedPoint(popplerQ.points[1].x(), popplerQ.points[1].y()), 2); |
|
q.setPoint(Okular::NormalizedPoint(popplerQ.points[2].x(), popplerQ.points[2].y()), 1); |
|
q.setPoint(Okular::NormalizedPoint(popplerQ.points[3].x(), popplerQ.points[3].y()), 0); |
|
|
|
q.setCapStart(popplerQ.capStart); |
|
q.setCapEnd(popplerQ.capEnd); |
|
q.setFeather(popplerQ.feather); |
|
okularHq << q; |
|
} |
|
|
|
return oHighlightAnn; |
|
} |
|
|
|
static Okular::Annotation *createAnnotationFromPopplerAnnotation(const Poppler::InkAnnotation *popplerAnnotation) |
|
{ |
|
Okular::InkAnnotation *oInkAnn = new Okular::InkAnnotation(); |
|
|
|
const QList<QLinkedList<QPointF>> popplerInkPaths = popplerAnnotation->inkPaths(); |
|
QList<QLinkedList<Okular::NormalizedPoint>> okularInkPaths; |
|
for (const QLinkedList<QPointF> &popplerInkPath : popplerInkPaths) { |
|
QLinkedList<Okular::NormalizedPoint> okularInkPath; |
|
for (const QPointF &popplerPoint : popplerInkPath) { |
|
okularInkPath << Okular::NormalizedPoint(popplerPoint.x(), popplerPoint.y()); |
|
} |
|
okularInkPaths << okularInkPath; |
|
} |
|
|
|
oInkAnn->setInkPaths(okularInkPaths); |
|
|
|
return oInkAnn; |
|
} |
|
|
|
static Okular::Annotation *createAnnotationFromPopplerAnnotation(const Poppler::CaretAnnotation *popplerAnnotation) |
|
{ |
|
Okular::CaretAnnotation *oCaretAnn = new Okular::CaretAnnotation(); |
|
|
|
oCaretAnn->setCaretSymbol(popplerToOkular(popplerAnnotation->caretSymbol())); |
|
|
|
return oCaretAnn; |
|
} |
|
|
|
static Okular::Annotation *createAnnotationFromPopplerAnnotation(const Poppler::StampAnnotation *popplerAnnotation) |
|
{ |
|
Okular::StampAnnotation *oStampAnn = new Okular::StampAnnotation(); |
|
|
|
oStampAnn->setStampIconName(popplerAnnotation->stampIconName()); |
|
|
|
return oStampAnn; |
|
} |
|
|
|
Okular::Annotation *createAnnotationFromPopplerAnnotation(Poppler::Annotation *popplerAnnotation, const Poppler::Page &popplerPage, bool *doDelete) |
|
{ |
|
Okular::Annotation *okularAnnotation = nullptr; |
|
*doDelete = true; |
|
bool tieToOkularAnn = false; |
|
bool externallyDrawn = false; |
|
switch (popplerAnnotation->subType()) { |
|
case Poppler::Annotation::AFileAttachment: { |
|
Poppler::FileAttachmentAnnotation *attachann = static_cast<Poppler::FileAttachmentAnnotation *>(popplerAnnotation); |
|
Okular::FileAttachmentAnnotation *f = new Okular::FileAttachmentAnnotation(); |
|
okularAnnotation = f; |
|
tieToOkularAnn = true; |
|
*doDelete = false; |
|
|
|
f->setFileIconName(attachann->fileIconName()); |
|
f->setEmbeddedFile(new PDFEmbeddedFile(attachann->embeddedFile())); |
|
|
|
break; |
|
} |
|
case Poppler::Annotation::ASound: { |
|
Poppler::SoundAnnotation *soundann = static_cast<Poppler::SoundAnnotation *>(popplerAnnotation); |
|
Okular::SoundAnnotation *s = new Okular::SoundAnnotation(); |
|
okularAnnotation = s; |
|
|
|
s->setSoundIconName(soundann->soundIconName()); |
|
s->setSound(createSoundFromPopplerSound(soundann->sound())); |
|
|
|
break; |
|
} |
|
case Poppler::Annotation::AMovie: { |
|
Poppler::MovieAnnotation *movieann = static_cast<Poppler::MovieAnnotation *>(popplerAnnotation); |
|
Okular::MovieAnnotation *m = new Okular::MovieAnnotation(); |
|
okularAnnotation = m; |
|
tieToOkularAnn = true; |
|
*doDelete = false; |
|
|
|
m->setMovie(createMovieFromPopplerMovie(movieann->movie())); |
|
|
|
break; |
|
} |
|
case Poppler::Annotation::AWidget: { |
|
okularAnnotation = new Okular::WidgetAnnotation(); |
|
break; |
|
} |
|
case Poppler::Annotation::AScreen: { |
|
Okular::ScreenAnnotation *m = new Okular::ScreenAnnotation(); |
|
okularAnnotation = m; |
|
tieToOkularAnn = true; |
|
*doDelete = false; |
|
break; |
|
} |
|
case Poppler::Annotation::ARichMedia: { |
|
Poppler::RichMediaAnnotation *richmediaann = static_cast<Poppler::RichMediaAnnotation *>(popplerAnnotation); |
|
const QPair<Okular::Movie *, Okular::EmbeddedFile *> result = createMovieFromPopplerRichMedia(richmediaann); |
|
|
|
if (result.first) { |
|
Okular::RichMediaAnnotation *r = new Okular::RichMediaAnnotation(); |
|
tieToOkularAnn = true; |
|
*doDelete = false; |
|
okularAnnotation = r; |
|
|
|
r->setMovie(result.first); |
|
r->setEmbeddedFile(result.second); |
|
} |
|
|
|
break; |
|
} |
|
case Poppler::Annotation::AText: { |
|
externallyDrawn = true; |
|
tieToOkularAnn = true; |
|
*doDelete = false; |
|
okularAnnotation = createAnnotationFromPopplerAnnotation(static_cast<Poppler::TextAnnotation *>(popplerAnnotation)); |
|
break; |
|
} |
|
case Poppler::Annotation::ALine: { |
|
externallyDrawn = true; |
|
tieToOkularAnn = true; |
|
*doDelete = false; |
|
okularAnnotation = createAnnotationFromPopplerAnnotation(static_cast<Poppler::LineAnnotation *>(popplerAnnotation)); |
|
break; |
|
} |
|
case Poppler::Annotation::AGeom: { |
|
externallyDrawn = true; |
|
tieToOkularAnn = true; |
|
*doDelete = false; |
|
okularAnnotation = createAnnotationFromPopplerAnnotation(static_cast<Poppler::GeomAnnotation *>(popplerAnnotation)); |
|
break; |
|
} |
|
case Poppler::Annotation::AHighlight: { |
|
externallyDrawn = true; |
|
tieToOkularAnn = true; |
|
*doDelete = false; |
|
okularAnnotation = createAnnotationFromPopplerAnnotation(static_cast<Poppler::HighlightAnnotation *>(popplerAnnotation)); |
|
break; |
|
} |
|
case Poppler::Annotation::AInk: { |
|
externallyDrawn = true; |
|
tieToOkularAnn = true; |
|
*doDelete = false; |
|
okularAnnotation = createAnnotationFromPopplerAnnotation(static_cast<Poppler::InkAnnotation *>(popplerAnnotation)); |
|
break; |
|
} |
|
case Poppler::Annotation::ACaret: { |
|
externallyDrawn = true; |
|
tieToOkularAnn = true; |
|
*doDelete = false; |
|
okularAnnotation = createAnnotationFromPopplerAnnotation(static_cast<Poppler::CaretAnnotation *>(popplerAnnotation)); |
|
break; |
|
} |
|
case Poppler::Annotation::AStamp: |
|
tieToOkularAnn = true; |
|
*doDelete = false; |
|
okularAnnotation = createAnnotationFromPopplerAnnotation(static_cast<Poppler::StampAnnotation *>(popplerAnnotation)); |
|
break; |
|
default: { |
|
break; |
|
} |
|
} |
|
if (okularAnnotation) { |
|
// the Contents field might have lines separated by \r |
|
QString contents = popplerAnnotation->contents(); |
|
contents.replace(QLatin1Char('\r'), QLatin1Char('\n')); |
|
|
|
okularAnnotation->setAuthor(popplerAnnotation->author()); |
|
okularAnnotation->setContents(contents); |
|
okularAnnotation->setUniqueName(popplerAnnotation->uniqueName()); |
|
okularAnnotation->setModificationDate(popplerAnnotation->modificationDate()); |
|
okularAnnotation->setCreationDate(popplerAnnotation->creationDate()); |
|
okularAnnotation->setFlags(popplerAnnotation->flags() | Okular::Annotation::External); |
|
okularAnnotation->setBoundingRectangle(Okular::NormalizedRect::fromQRectF(popplerAnnotation->boundary())); |
|
|
|
if (externallyDrawn) |
|
okularAnnotation->setFlags(okularAnnotation->flags() | Okular::Annotation::ExternallyDrawn); |
|
|
|
// Convert the poppler annotation style to Okular annotation style |
|
Okular::Annotation::Style &okularStyle = okularAnnotation->style(); |
|
const Poppler::Annotation::Style popplerStyle = popplerAnnotation->style(); |
|
okularStyle.setColor(popplerStyle.color()); |
|
okularStyle.setOpacity(popplerStyle.opacity()); |
|
okularStyle.setWidth(popplerStyle.width()); |
|
okularStyle.setLineStyle(popplerToOkular(popplerStyle.lineStyle())); |
|
okularStyle.setXCorners(popplerStyle.xCorners()); |
|
okularStyle.setYCorners(popplerStyle.yCorners()); |
|
const QVector<double> &dashArray = popplerStyle.dashArray(); |
|
if (dashArray.size() > 0) |
|
okularStyle.setMarks(dashArray[0]); |
|
if (dashArray.size() > 1) |
|
okularStyle.setSpaces(dashArray[1]); |
|
okularStyle.setLineEffect(popplerToOkular(popplerStyle.lineEffect())); |
|
okularStyle.setEffectIntensity(popplerStyle.effectIntensity()); |
|
|
|
// Convert the poppler annotation popup to Okular annotation window |
|
Okular::Annotation::Window &okularWindow = okularAnnotation->window(); |
|
const Poppler::Annotation::Popup popplerPopup = popplerAnnotation->popup(); |
|
// This assumes that both "flags" int mean the same, but since we don't use the flags in okular anywhere it's not really that important |
|
okularWindow.setFlags(popplerPopup.flags()); |
|
const QRectF popplerGeometry = popplerPopup.geometry(); |
|
const QSize popplerPageSize = popplerPage.pageSize(); |
|
okularWindow.setTopLeft(Okular::NormalizedPoint(popplerGeometry.top(), popplerGeometry.left(), popplerPageSize.width(), popplerPageSize.height())); |
|
okularWindow.setWidth(popplerGeometry.width()); |
|
okularWindow.setHeight(popplerGeometry.height()); |
|
okularWindow.setTitle(popplerPopup.title()); |
|
okularWindow.setSummary(popplerPopup.summary()); |
|
|
|
// Convert the poppler revisions to Okular revisions |
|
QLinkedList<Okular::Annotation::Revision> &okularRevisions = okularAnnotation->revisions(); |
|
okularRevisions.clear(); // We can remove this once we stop calling Okular::AnnotationUtils::createAnnotation |
|
const QList<Poppler::Annotation *> popplerRevisions = popplerAnnotation->revisions(); |
|
for (Poppler::Annotation *popplerRevision : popplerRevisions) { |
|
bool deletePopplerRevision; |
|
Okular::Annotation::Revision okularRevision; |
|
okularRevision.setAnnotation(createAnnotationFromPopplerAnnotation(popplerRevision, popplerPage, &deletePopplerRevision)); |
|
okularRevision.setScope(popplerToOkular(popplerRevision->revisionScope())); |
|
okularRevision.setType(popplerToOkular(popplerRevision->revisionType())); |
|
okularRevisions << okularRevision; |
|
|
|
if (deletePopplerRevision) { |
|
delete popplerRevision; |
|
} |
|
} |
|
|
|
if (tieToOkularAnn) { |
|
okularAnnotation->setNativeId(QVariant::fromValue(popplerAnnotation)); |
|
okularAnnotation->setDisposeDataFunction(disposeAnnotation); |
|
} |
|
} |
|
return okularAnnotation; |
|
}
|
|
|