aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZackaryWelch <welch.zackary@gmail.com>2018-04-27 17:26:02 -0400
committerZackaryWelch <welch.zackary@gmail.com>2018-04-27 17:26:02 -0400
commit253bacc6ee0d825564bef6aa507296e79b2611ff (patch)
tree0d87304383654f25f83259cdb0ae776706250c23
parentMerge branch 'master' of http://github.com/trueos/lumina (diff)
downloadlumina-253bacc6ee0d825564bef6aa507296e79b2611ff.tar.gz
lumina-253bacc6ee0d825564bef6aa507296e79b2611ff.tar.bz2
lumina-253bacc6ee0d825564bef6aa507296e79b2611ff.zip
Added more annotation and widget support. Currently incomplete. Updated to MuPDF 1.13.
-rw-r--r--src-qt5/desktop-utils/lumina-pdf/Annotation.h46
-rw-r--r--src-qt5/desktop-utils/lumina-pdf/BookmarkMenu.cpp2
-rw-r--r--src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp58
-rw-r--r--src-qt5/desktop-utils/lumina-pdf/PrintWidget.h83
-rw-r--r--src-qt5/desktop-utils/lumina-pdf/Renderer-mupdf.cpp350
-rw-r--r--src-qt5/desktop-utils/lumina-pdf/Renderer-poppler.cpp39
-rw-r--r--src-qt5/desktop-utils/lumina-pdf/Renderer.h46
-rw-r--r--src-qt5/desktop-utils/lumina-pdf/Widget.h29
-rw-r--r--src-qt5/desktop-utils/lumina-pdf/lumina-pdf.pro4
-rw-r--r--src-qt5/desktop-utils/lumina-pdf/mainUI.cpp13
10 files changed, 520 insertions, 150 deletions
diff --git a/src-qt5/desktop-utils/lumina-pdf/Annotation.h b/src-qt5/desktop-utils/lumina-pdf/Annotation.h
new file mode 100644
index 00000000..60df6a2d
--- /dev/null
+++ b/src-qt5/desktop-utils/lumina-pdf/Annotation.h
@@ -0,0 +1,46 @@
+#include <QList>
+#include <QVector>
+#include <QPointF>
+#include <QPolygonF>
+
+class Annotation{
+ public:
+ Annotation(int _annotType, double _opacity, QRectF _loc = QRectF()) : annotType(_annotType), opacity(_opacity), loc(_loc) { }
+
+ virtual ~Annotation() { }
+
+ virtual int getType() { return annotType; }
+ virtual QRectF getLoc() { return loc; }
+
+ virtual QString getAuthor() { return author; }
+ virtual QString getText() { return text; }
+ virtual QList<QPolygonF> getQuadList() { return quadList; }
+ virtual QVector<QVector<QPointF>> getInkList() { return inkList; }
+ virtual QColor getColor() { return color; }
+ virtual QColor getInternalColor() { return iColor; }
+ virtual double getOpacity() { return opacity; }
+ virtual bool print() { return canPrint; }
+
+ virtual void setAuthor(QString _author) { author = _author; }
+ virtual void setContents(QString _text) { text = _text; }
+ virtual void setColor(QColor _color) { color = _color; };
+ virtual void setInternalColor(QColor _iColor) { iColor = _iColor; };
+ virtual void setQuadList(QList<QPolygonF> _quadList) { quadList = _quadList; };
+ virtual void setInkList(QVector<QVector<QPointF>> _inkList) { inkList = _inkList; };
+ virtual void setPrint(bool _print) { canPrint = _print; }
+
+ virtual QImage renderImage() = 0;
+
+ private:
+ int annotType;
+ double opacity;
+ QRectF loc;
+
+ QString author;
+ QString text;
+ QColor color;
+ QColor iColor;
+ QList<QPolygonF> quadList;
+ QVector<QVector<QPointF>> inkList;
+ bool canPrint;
+};
diff --git a/src-qt5/desktop-utils/lumina-pdf/BookmarkMenu.cpp b/src-qt5/desktop-utils/lumina-pdf/BookmarkMenu.cpp
index a90007d8..902fe0ff 100644
--- a/src-qt5/desktop-utils/lumina-pdf/BookmarkMenu.cpp
+++ b/src-qt5/desktop-utils/lumina-pdf/BookmarkMenu.cpp
@@ -16,7 +16,7 @@ BookmarkMenu::BookmarkMenu(Renderer *Backend, QWidget *parent) : QWidget(parent)
connect(ui->closeButton, &QPushButton::clicked, parent, [=]() { static_cast<QSplitter*>(parent)->setSizes(QList<int>() << 0 << this->width()); });
connect(ui->closeButton, &QPushButton::clicked, parent, [=]() { });
connect(ui->bookmarks, &QTreeWidget::itemClicked, this, [=](QTreeWidgetItem *item) {
- Backend->handleLink(item->data(1, Qt::UserRole).toString()); });
+ Backend->handleLink(parent, item->data(1, Qt::UserRole).toString()); });
}
void BookmarkMenu::loadBookmarks() {
diff --git a/src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp b/src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp
index e9a0ed34..f64106d3 100644
--- a/src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp
+++ b/src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp
@@ -1,4 +1,6 @@
#include "PrintWidget.h"
+#include <QPushButton>
+#include <QGraphicsProxyWidget>
PrintWidget::PrintWidget(Renderer *backend, QWidget *parent) :
QGraphicsView(parent), scene(0), curPage(1), viewMode(SinglePageView),
@@ -226,23 +228,23 @@ void PrintWidget::populateScene()
}
qDeleteAll(pages);
pages.clear();
- //links.clear();
- //annots.clear();
+ links.clear();
+ annots.clear();
int numPages = BACKEND->numPages();
if(BACKEND->hashSize() < numPages){ return; } //nothing to show yet
for (int i = 0; i < numPages; i++) {
QImage pagePicture = BACKEND->imageHash(i);
QSize paperSize = pagePicture.size();
- //QList<QGraphicsItem*> linkLocations;
- //QList<QGraphicsItem*> annotLocations;
+ QList<QGraphicsItem*> linkLocations;
+ QList<QGraphicsItem*> annotLocations;
if(pagePicture.isNull()) {
qDebug() << "NULL IMAGE ON PAGE " << i;
continue;
}
- PageItem* item = new PageItem(i+1, pagePicture, paperSize);
+ PageItem* item = new PageItem(i+1, pagePicture, paperSize, BACKEND);
scene->addItem(item);
pages.append(item);
@@ -250,17 +252,51 @@ void PrintWidget::populateScene()
for(int k = 0; k < BACKEND->linkSize(i); k++) {
LinkItem *lItem = new LinkItem(item, BACKEND->linkList(i, k));
lItem->setOpacity(0.1);
- //linkLocations.append(lItem);
+ linkLocations.append(lItem);
}
//qDebug() << "Creating annotations for:" << i;
for(int k = 0; k < BACKEND->annotSize(i); k++) {
- AnnotItem *aItem = new AnnotItem(item, BACKEND->annotList(i, k), BACKEND->annotLoc(i, k));
- AnnotZone *aZone = new AnnotZone(item, BACKEND->annotLoc(i, k), aItem);
+ Annotation *annot = BACKEND->annotList(i, k);
+ if(annot->getType() == 14) {
+ InkItem *iItem = new InkItem(item, annot);
+ annotLocations.append(iItem);
+ }
+ PopupItem *aItem = new PopupItem(item, annot);
+ AnnotZone *aZone = new AnnotZone(item, annot, aItem);
aItem->setVisible(false);
- //annotLocations.append(aItem);
+ annotLocations.append(aItem);
+ annotLocations.append(aZone);
}
- //links.insert(i, linkLocations);
- //annots.insert(i, annotLocations);
+
+ for(int k = 0; k < BACKEND->widgetSize(i); k++) {
+ Widget *widget = BACKEND->widgetList(i, k);
+ int type = widget->getWidgetType();
+ QRectF loc = widget->getLocation();
+ QString text = widget->getCurrentText();
+ if(type == 0) {
+ QPushButton *button = new QPushButton(widget->getCurrentText());
+ button->setGeometry(loc.toRect());
+ button->setText(text);
+ QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(item);
+ proxy->setWidget(button);
+ }else if(type == 1) {
+
+ }else if(type == 2) {
+
+ }else if(type == 3) {
+
+ }else if(type == 4) {
+
+ }else if(type == 5) {
+
+ }else if(type == 6) {
+
+ }else {
+ qDebug() << "INVALID WIDGET";
+ }
+ }
+ links.insert(i, linkLocations);
+ annots.insert(i, annotLocations);
}
}
}
diff --git a/src-qt5/desktop-utils/lumina-pdf/PrintWidget.h b/src-qt5/desktop-utils/lumina-pdf/PrintWidget.h
index d7e3d92e..c353cb84 100644
--- a/src-qt5/desktop-utils/lumina-pdf/PrintWidget.h
+++ b/src-qt5/desktop-utils/lumina-pdf/PrintWidget.h
@@ -20,12 +20,41 @@
#include <QtMath>
#include <QPageLayout>
#include <QTextDocument>
+#include <QApplication>
#include "Renderer.h"
#include "TextData.h"
-class AnnotItem: public QGraphicsItem {
+class InkItem: public QGraphicsItem {
public:
- AnnotItem(QGraphicsItem *parent, QList<QString> textData, QRectF loc) : QGraphicsItem(parent), author(textData[0]), text(textData[1]) {
+ InkItem(QGraphicsItem *parent, Annotation *_annot) : QGraphicsItem(parent), pointData(_annot->getInkList()), inkColor(_annot->getColor()), annot(_annot) {
+ setCacheMode(DeviceCoordinateCache);
+ bbox = annot->getLoc();
+ }
+
+ QRectF boundingRect() const Q_DECL_OVERRIDE { return bbox; }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) Q_DECL_OVERRIDE
+ {
+ Q_UNUSED(widget);
+ painter->setClipRect(option->exposedRect);
+ QPen inkPen = QPen(inkColor);
+ painter->setPen(inkPen);
+ foreach(QVector<QPointF> pointList, pointData) {
+ painter->drawLines(pointList);
+ }
+ }
+
+private:
+ QRectF bbox;
+ QVector<QVector<QPointF>> pointData;
+ QColor inkColor;
+ Annotation *annot;
+};
+
+class PopupItem: public QGraphicsItem {
+public:
+ PopupItem(QGraphicsItem *parent, Annotation *_annot) : QGraphicsItem(parent), author(_annot->getAuthor()), text(_annot->getText()) {
+ QRectF loc = _annot->getLoc();
setCacheMode(DeviceCoordinateCache);
QString allText = "Author: " + author + "\n\n" + text;
QTextDocument document;
@@ -59,14 +88,22 @@ private:
class AnnotZone: public QGraphicsItem {
public:
- AnnotZone(QGraphicsItem *parent, QRectF _bbox, AnnotItem *_annot) : QGraphicsItem(parent), bbox(_bbox), annot(_annot) { }
+ AnnotZone(QGraphicsItem *parent, Annotation *_annot, PopupItem *_annotItem) : QGraphicsItem(parent), bbox(_annot->getLoc()), annot(_annotItem) {
+ _hasText = !_annot->getText().isEmpty();
+ _hasAuthor = !_annot->getAuthor().isEmpty();
+ }
+
QRectF boundingRect() const Q_DECL_OVERRIDE { return bbox; }
- AnnotItem* annotation() const { return annot; }
+ PopupItem* annotation() const { return annot; }
+ bool hasText() const { return _hasText; }
+ bool hasAuthor() const { return _hasAuthor; }
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) Q_DECL_OVERRIDE { Q_UNUSED(widget); Q_UNUSED(painter); Q_UNUSED(option); }
private:
QRectF bbox;
- AnnotItem *annot;
+ PopupItem *annot;
+ bool _hasText;
+ bool _hasAuthor;
};
class LinkItem: public QGraphicsItem {
@@ -98,8 +135,8 @@ private:
class PageItem : public QGraphicsItem {
public:
- PageItem(int _pageNum, QImage _pagePicture, QSize _paperSize)
- : pageNum(_pageNum), pagePicture(_pagePicture), paperSize(_paperSize)
+ PageItem(int _pageNum, QImage _pagePicture, QSize _paperSize, Renderer *_backend)
+ : pageNum(_pageNum), pagePicture(_pagePicture), paperSize(_paperSize), BACKEND(_backend)
{
brect = QRectF(QPointF(-25, -25),
QSizeF(paperSize)+QSizeF(50, 50));
@@ -146,6 +183,10 @@ public:
painter->setClipRect(paperRect & option->exposedRect);
painter->fillRect(paperRect, Qt::white);
painter->drawImage(QPoint(0,0), pagePicture);
+ for(int k = 0; k < BACKEND->annotSize(pageNum-1); k++) {
+ Annotation *annot = BACKEND->annotList(pageNum-1, k);
+ painter->drawImage(annot->getLoc(), annot->renderImage());
+ }
}
private:
@@ -153,6 +194,7 @@ private:
QImage pagePicture;
QSize paperSize;
QRectF brect;
+ Renderer *BACKEND;
};
class PrintWidget : public QGraphicsView
@@ -187,6 +229,7 @@ private:
bool initialized, fitting;
QList<QGraphicsItem*> pages;
QHash<int, QList<QGraphicsItem*>> links;
+ QHash<int, QList<QGraphicsItem*>> annots;
int degrees;
Renderer *BACKEND;
@@ -239,17 +282,18 @@ protected:
continue;
if(graphicsItem == dynamic_cast<LinkItem*>(graphicsItem))
graphicsItem->setOpacity(0.1);
- if(graphicsItem == dynamic_cast<AnnotItem*>(graphicsItem))
+ if(graphicsItem == dynamic_cast<PopupItem*>(graphicsItem))
graphicsItem->setVisible(false);
}
}
void mouseMoveEvent(QMouseEvent *e) Q_DECL_OVERRIDE {
QGraphicsView::mouseMoveEvent(e);
+ static bool cursorSet = false;
if(QGraphicsItem *item = scene->itemAt(mapToScene(e->pos()), transform())) {
QList<QGraphicsItem*> linkList;
- if(item == dynamic_cast<AnnotItem*>(item))
+ if(item == dynamic_cast<PopupItem*>(item))
item = item->parentItem();
if(PageItem *page = dynamic_cast<PageItem*>(item))
@@ -259,11 +303,19 @@ protected:
if(LinkItem *link = dynamic_cast<LinkItem*>(item)){
item->setOpacity(1);
- }else if(AnnotZone *annotZone = dynamic_cast<AnnotZone*>(item)){
- annotZone->annotation()->setVisible(true);
+ if(!cursorSet) {
+ QApplication::setOverrideCursor(QCursor(Qt::PointingHandCursor));
+ cursorSet = true;
+ }
+ }else if(cursorSet){
+ QApplication::restoreOverrideCursor();
+ cursorSet = false;
+ }
+ if(AnnotZone *annotZone = dynamic_cast<AnnotZone*>(item)){
+ if(annotZone->hasText() or annotZone->hasAuthor())
+ annotZone->annotation()->setVisible(true);
item = annotZone->annotation();
}
-
clearItems(linkList, item);
}
}
@@ -273,12 +325,7 @@ protected:
QPointF scenePoint = mapToScene(e->pos());
QGraphicsItem *item = scene->itemAt(scenePoint, transform());
if(LinkItem *link = dynamic_cast<LinkItem*>(item)) {
- PageItem *page = dynamic_cast<PageItem*>(link->parentItem());
- if(!BACKEND->isExternalLink(page->pageNumber()-1, link->getData()->text())) {
- BACKEND->handleLink(link->getData()->text());
- }else{
- //External Link
- }
+ BACKEND->handleLink(this, link->getData()->text());
link->setOpacity(0.1);
}
}
diff --git a/src-qt5/desktop-utils/lumina-pdf/Renderer-mupdf.cpp b/src-qt5/desktop-utils/lumina-pdf/Renderer-mupdf.cpp
index 31a07e01..a52fd5b4 100644
--- a/src-qt5/desktop-utils/lumina-pdf/Renderer-mupdf.cpp
+++ b/src-qt5/desktop-utils/lumina-pdf/Renderer-mupdf.cpp
@@ -1,34 +1,17 @@
#include "Renderer.h"
#include "TextData.h"
-#include <QDateTime>
#include <mupdf/fitz.h>
#include <mupdf/pdf.h>
+#include <QDateTime>
#include <QMutex>
#include <QFuture>
#include <QtConcurrent>
-class Annot{
- public:
- Annot(fz_context *_ctx, pdf_annot *_fzAnnot, char *_text, char *_author, QRectF _loc = QRectF()) : fzAnnot(_fzAnnot), ctx(_ctx), loc(_loc) {
- author = (_author) ? QString::fromLocal8Bit(_author) : QString();
- text = (_text) ? QString::fromLocal8Bit(_text) : QString();
- }
-
- ~Annot() {
- fz_drop_annot(ctx, (fz_annot*)fzAnnot);
- }
-
- QString getAuthor() { return author; }
- QString getText() { return text; }
- QRectF getLoc() { return loc; }
+class Annot;
- private:
- pdf_annot *fzAnnot;
- fz_context *ctx;
- QString author;
- QString text;
- QRectF loc;
-};
+inline QRectF convertRect(fz_rect bbox, double sf=1.0) {
+ return QRectF(sf*bbox.x0, sf*bbox.y0, sf*(bbox.x1-bbox.x0), sf*(bbox.y1 - bbox.y0));
+}
class Link {
public:
@@ -52,15 +35,14 @@ class Link {
class Data {
public:
- Data(int _pagenum, fz_context *_ctx, fz_display_list *_list, fz_rect _bbox, fz_matrix _ctm, double _sf, fz_link *_link, QList<Annot*> &_annot) : pagenumber(_pagenum), ctx(_ctx), list(_list), bbox(_bbox), ctm(_ctm), sf(_sf), annotList(_annot) {
+ Data(int _pagenum, fz_context *_ctx, fz_display_list *_list, fz_rect _bbox, fz_matrix _ctm, double _sf, fz_link *_link, QList<Annot*> &_annot, QList<Widget*> &_widgets) : pagenumber(_pagenum), ctx(_ctx), list(_list), bbox(_bbox), ctm(_ctm), sf(_sf), annotList(_annot), widgetList(_widgets) {
while(_link) {
- QRectF rect(sf*_link->rect.x0, sf*_link->rect.y0, sf*(_link->rect.x1 - _link->rect.x0), sf*(_link->rect.y1 - _link->rect.y0));
+ QRectF rect = convertRect(_link->rect, sf);
Link *link = new Link(_ctx, _link, _link->uri, _pagenum, rect);
linkList.append(link);
_link = _link->next;
}
-
}
~Data() {
@@ -70,14 +52,19 @@ class Data {
linkList.clear();
qDeleteAll(annotList);
annotList.clear();
+ qDeleteAll(widgetList);
+ widgetList.clear();
}
int getPage() { return pagenumber; }
QList<Link*> getLinkList() { return linkList; }
- QList<Annot*> getAnnotList() { return annotList; }
+ Annot* getAnnotList(int i) { return annotList[i]; }
+ Widget* getWidgetList(int i) { return widgetList[i]; }
+ int getAnnotSize() { return annotList.size(); }
+ int getWidgetSize() { return widgetList.size(); }
fz_context* getContext() { return ctx; }
fz_display_list* getDisplayList() { return list; }
- QRectF getScaledRect() { return QRectF(sf*bbox.x0, sf*bbox.y0, sf*(bbox.x1-bbox.x0), sf*(bbox.y1 - bbox.y0)); }
+ QRectF getScaledRect() { return convertRect(bbox, sf); }
fz_rect getBoundingBox() { return bbox; }
fz_matrix getMatrix() { return ctm; }
QImage getImage() { return img; }
@@ -95,6 +82,7 @@ class Data {
QList<Link*> linkList;
double sf;
QList<Annot*> annotList;
+ QList<Widget*> widgetList;
fz_pixmap *pix;
QImage img;
@@ -107,6 +95,32 @@ QHash<int, Data*> dataHash;
QMutex mutex[FZ_LOCK_MAX];
fz_locks_context locks;
+class Annot : public Annotation{
+ public:
+ Annot(fz_context *_ctx, pdf_annot *_fzAnnot, int _type, int _i, float _opacity, QRectF _loc = QRectF()) : Annotation(_type, _opacity, _loc), ctx(_ctx), fzAnnot(_fzAnnot), pageNum(_i) { }
+ virtual ~Annot() { fz_drop_annot(ctx, (fz_annot*)fzAnnot); }
+
+ virtual QImage renderImage() {
+ fz_rect bbox;
+ fz_irect rbox;
+ pdf_bound_annot(ctx, fzAnnot, &bbox);
+
+ fz_pixmap *pixmap = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), fz_round_rect(&rbox, &bbox), NULL, 0);
+ fz_clear_pixmap_with_value(ctx, pixmap, 0xff);
+ fz_device *dev = fz_new_draw_device(ctx, &fz_identity, pixmap);
+ fz_run_display_list(ctx, dataHash[pageNum]->getDisplayList(), dev, &fz_identity, &bbox, NULL);
+
+ QImage image(pixmap->samples, pixmap->w, pixmap->h, pixmap->stride, QImage::Format_RGB888);
+ return image;
+ }
+
+ private:
+ fz_context *ctx;
+ pdf_annot *fzAnnot;
+
+ int pageNum;
+};
+
inline QString getTextInfo(QString str) {
char infoBuff[1000];
int size = DOC->lookup_metadata(CTX, DOC, ("info:"+str).toLocal8Bit().data(), infoBuff, 1000);
@@ -137,6 +151,7 @@ Renderer::Renderer(){
}
Renderer::~Renderer(){
+ //pdf_clean_page_contents
qDebug() << "Dropping Context";
clearHash();
fz_drop_document(CTX, DOC);
@@ -147,7 +162,7 @@ Renderer::~Renderer(){
bool Renderer::loadMultiThread(){ return false; }
-void Renderer::handleLink(QString link) {
+void Renderer::handleLink(QWidget *obj, QString link) {
float xp = 0.0, yp = 0.0;
int pagenum = 0;
@@ -155,9 +170,13 @@ void Renderer::handleLink(QString link) {
char *uri = linkData.data();
if(!link.isEmpty()) {
- pagenum = fz_resolve_link(CTX, DOC, uri, &xp, &yp);
- if(pagenum != -1)
- emit goToPosition(pagenum+1, xp, yp);
+ if(fz_is_external_link(CTX, uri)) {
+ if(QMessageBox::Yes == QMessageBox::question(obj, tr("Open External Link?"), QString(tr("Do you want to open %1 in the default browser")).arg(link), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ){ QProcess::startDetached("firefox \""+link+"\""); }
+ }else{
+ pagenum = fz_resolve_link(CTX, DOC, uri, &xp, &yp);
+ if(pagenum != -1)
+ emit goToPosition(pagenum+1, xp, yp);
+ }
}
}
@@ -193,6 +212,8 @@ bool Renderer::loadDocument(QString path, QString password){
qDebug() << "Document handlers registered";
}
+ //fz_page_presentation
+
docpath = path;
DOC = fz_open_document(CTX, path.toLocal8Bit().data());
qDebug() << "File opened" << DOC;
@@ -280,49 +301,250 @@ void Renderer::renderPage(int pagenum, QSize DPI, int degrees){
fz_rect bbox;
fz_display_list *list;
- //double pageDPI = 96.0;
- //double sf = DPI.width() / pageDPI;
- double sf = 1;
- //fz_scale(&matrix, sf, sf);
- fz_rotate(&matrix, degrees);
+ double pageDPI = 96.0;
+ double sf = DPI.width() / pageDPI;
+ fz_scale(&matrix, sf, sf);
+ fz_pre_rotate(&matrix, degrees);
- fz_page *PAGE = fz_load_page(CTX, DOC, pagenum);
- fz_bound_page(CTX, PAGE, &bbox);
+ pdf_page *PAGE = pdf_load_page(CTX, (pdf_document*)DOC, pagenum);
+ pdf_bound_page(CTX, PAGE, &bbox);
emit OrigSize(QSizeF(bbox.x1 - bbox.x0, bbox.y1 - bbox.y0));
fz_transform_rect(&bbox, &matrix);
list = fz_new_display_list(CTX, &bbox);
fz_device *dev = fz_new_list_device(CTX, list);
- fz_run_page(CTX, PAGE, dev, &fz_identity, NULL);
+ pdf_run_page_contents(CTX, PAGE, dev, &fz_identity, NULL);
- fz_link *link = fz_load_links(CTX, PAGE);
- pdf_annot *_annot = pdf_first_annot(CTX, (pdf_page*)PAGE);
+ fz_link *link = pdf_load_links(CTX, PAGE);
+ pdf_annot *_annot = pdf_first_annot(CTX, PAGE);
QList<Annot*> annotList;
+ QList<Widget*> widgetList;
//qDebug() << "Starting annotations for:" << pagenum;
while(_annot) {
- pdf_run_annot(CTX, _annot, dev, &fz_identity, NULL);
+ //if(pdf_annot_is_dirty(CTX, _annot))
+ //qDebug() << "DIRTY ANNOT";
+
+ int type = pdf_annot_type(CTX, _annot);
+ /**TYPES
+ 0 = TEXT
+ 1 = LINK
+ 2 = FREE_TEXT
+ 3 = LINE
+ 4 = SQUARE
+ ...
+ 24 = 3D
+ -1 = UNKNOWN
+ **/
+ //qDebug() << "Page Number:" << pagenum+1 << type << pdf_string_from_annot_type(CTX, (enum pdf_annot_type)type);
fz_rect anotBox;
pdf_bound_annot(CTX, _annot, &anotBox);
- QRectF rect(sf*anotBox.x0, sf*anotBox.y0, sf*(anotBox.x1-anotBox.x0), sf*(anotBox.y1 - anotBox.y0));
+ QRectF rect = convertRect(anotBox, sf);
+ float opacity = pdf_annot_opacity(CTX, _annot);
+ /**TYPES
+ 0 = LEFT
+ 1 = CENTER
+ 2 = RIGHT
+ **/
+ int quadding = pdf_annot_quadding(CTX, _annot);
+
+ Annot *annot = new Annot(CTX, _annot, type, pagenum, opacity, rect);
+
+ int flags = pdf_annot_flags(CTX, _annot);
+ /**FLAGS
+ 1 << 0 = INVISIBLE
+ 1 << 1 = HIDDEN
+ 1 << 2 = PRINT
+ 1 << 3 = NO_ZOOM
+ 1 << 4 = NO_ROTATE
+ 1 << 5 = NO_VIEW
+ 1 << 6 = READ_ONLY
+ 1 << 7 = LOCKED
+ 1 << 8 = TOGGLE_NO_VIEW
+ 1 << 9 = LOCKED_CONTENTS
+ **/
+
+ annot->setPrint((flags & PDF_ANNOT_IS_PRINT) == PDF_ANNOT_IS_PRINT);
+
char *contents = NULL, *author = NULL;
- fz_try(CTX)
- contents = pdf_copy_annot_contents(CTX, _annot);
- fz_catch(CTX) { }
- fz_try(CTX)
- author = pdf_copy_annot_author(CTX, _annot);
- fz_catch(CTX) { }
+ if(type != 19 and type != 20) {
+ fz_try(CTX){
+ contents = pdf_copy_annot_contents(CTX, _annot);
+ if(contents)
+ annot->setContents(QString::fromLocal8Bit(contents));
+ }fz_catch(CTX) { }
+ fz_try(CTX){
+ author = pdf_copy_annot_author(CTX, _annot);
+ if(author)
+ annot->setAuthor(QString::fromLocal8Bit(author));
+ }fz_catch(CTX) { }
+ }
+ //pdf_annot_modification_date(CTX, _annot);
+
+ if(pdf_annot_has_ink_list(CTX, _annot)) {
+ int inkCount = pdf_annot_ink_list_count(CTX, _annot);
+ QVector<QVector<QPointF>> inkList;
+ for(int i = 0; i < inkCount; i++) {
+ int strokeCount = pdf_annot_ink_list_stroke_count(CTX, _annot, i);
+ QVector<QPointF> inkPoints;
+ for(int k = 0; k < strokeCount; k++) {
+ fz_point strokeVertex = pdf_annot_ink_list_stroke_vertex(CTX, _annot, i, k);
+ QPointF vertexPoint(strokeVertex.x, strokeVertex.y);
+ inkPoints.append(sf*vertexPoint);
+ }
+ inkList.append(inkPoints);
+ annot->setInkList(inkList);
+ }
+ fz_rect annotRect;
+ pdf_annot_rect(CTX, _annot, &annotRect);
+ //qDebug() << "ANNOT RECT:" << convertRect(annotRect, sf);
+ //qDebug() << "INK LIST:" << inkList;
+ }
+
+ float color[4] = {0, 0, 0, 1};
+ int n;
+ fz_try(CTX) {
+ pdf_annot_color(CTX, _annot, &n, color);
+ QColor inkColor = QColor(color[0]*255, color[1]*255, color[2]*255, color[3]*255);
+ annot->setColor(inkColor);
+ //qDebug() << "COLOR:" << inkColor;
+ }fz_catch(CTX) {
+ //qDebug() << "NO COLOR";
+ annot->setColor(QColor());
+ }
+
+ if(pdf_annot_has_interior_color(CTX, _annot)) {
+ fz_try(CTX) {
+ color[0] = 0; color[1] = 0; color[2] = 0; color[3] = 1;
+ pdf_annot_interior_color(CTX, _annot, &n, color);
+ QColor internalColor = QColor(color[0]*255, color[1]*255, color[2]*255, color[3]*255);
+ //qDebug() << "INTERNAL COLOR:" << internalColor;
+ annot->setInternalColor(internalColor);
+ }fz_catch(CTX) {
+ //qDebug() << "NO INTERNAL COLOR";
+ annot->setInternalColor(QColor());
+ }
+ }
+
+ //qDebug() << "BORDER:" << pdf_annot_border(CTX, _annot);
+
+ if(pdf_annot_has_quad_points(CTX, _annot)) {
+ //qDebug() << "HAS QUAD POINTS" << "Page Number:" << pagenum << type;
+ int pointCount = pdf_annot_quad_point_count(CTX, _annot);
+ QList<QPolygonF> quadList;
+ for(int i = 0; i < pointCount; i++) {
+ float qp[8];
+ pdf_annot_quad_point(CTX, _annot, i, qp);
+ QPolygonF quad = QPolygonF(QVector<QPointF>() << QPointF(qp[0], qp[1]) << QPointF(qp[2], qp[3]) << QPointF(qp[4], qp[5]) << QPointF(qp[6], qp[7]));
+ quadList.append(quad);
+ }
+ annot->setQuadList(quadList);
+ }
- Annot *annot = new Annot(CTX, _annot, contents, author, rect);
+ if(pdf_annot_has_line_ending_styles(CTX, _annot)) {
+ //qDebug() << "HAS LINE ENDING STYLES" << "Page Number:" << pagenum << type;
+ pdf_line_ending start, end;
+ /**LINE ENDING
+ 0 = NONE
+ 1 = SQUARE
+ 2 = CIRCLE
+ ...
+ 9 = SLASH
+ **/
+ pdf_annot_line_ending_styles(CTX, _annot, &start, &end);
+ //qDebug() << "START:" << start << "END:" << end;
+ }
+
+ if(pdf_annot_has_vertices(CTX, _annot)) {
+ //qDebug() << "HAS VERTICIES" << "Page Number:" << pagenum << type;
+ int vertexCount = pdf_annot_vertex_count(CTX, _annot);
+ QList<QPointF> vertexList;
+ for(int i = 0; i < vertexCount; i++) {
+ fz_point v = pdf_annot_vertex(CTX, _annot, i);
+ vertexList.append(sf*QPointF(v.x, v.y));
+ }
+ //qDebug() << vertexList;
+ }
+
+ if(pdf_annot_has_line(CTX, _annot)) {
+ fz_point a, b;
+ pdf_annot_line(CTX, _annot, &a, &b);
+ QPointF pa(a.x, a.y);
+ QPointF pb(b.x, b.y);
+ //qDebug() << pa << pb;
+ }
+
+ if(pdf_annot_has_icon_name(CTX, _annot)) {
+ QString iconName = QString::fromLocal8Bit(pdf_annot_icon_name(CTX, _annot));
+ //qDebug() << iconName;
+ }
+
+ if(!pdf_annot_has_ink_list(CTX, _annot)) {
+ pdf_run_annot(CTX, _annot, dev, &fz_identity, NULL);
+ }
+
annotList.append(annot);
- _annot = _annot->next;
+ _annot = pdf_next_annot(CTX, _annot);
+ }
+
+ pdf_widget *widget = pdf_first_widget(CTX, (pdf_document*)DOC, PAGE);
+ while(widget) {
+ int type = pdf_widget_type(CTX, widget);
+ /**
+ -1 = NOT_WIDGET
+ 0 = PUSHBUTTON
+ 1 = CHECKBOX
+ 2 = RADIOBUTTON
+ 3 = TEXT
+ 4 = LISTBOX
+ 5 = COMBOBOX
+ 6 = SIGNATURE
+ **/
+
+ fz_rect wrect;
+ pdf_bound_widget(CTX, widget, &wrect);
+ QRectF WRECT = convertRect(wrect, sf);
+ char *currText = pdf_text_widget_text(CTX, (pdf_document*)DOC, widget);
+ int maxLen = pdf_text_widget_max_len(CTX, (pdf_document*)DOC, widget);
+ int contentType = pdf_text_widget_content_type(CTX, (pdf_document*)DOC, widget);
+ /**
+ 0 = UNRESTRAINED
+ 1 = NUMBER
+ 2 = SPECIAL
+ 3 = DATE
+ 4 = TIME
+ **/
+
+ Widget *WIDGET = new Widget(type, WRECT, QString::fromLocal8Bit(currText), maxLen, contentType);
+ if(type == 4 or type == 5) {
+ QStringList optionList, exportList;
+ bool multi = pdf_choice_widget_is_multiselect(CTX, (pdf_document*)DOC, widget);
+
+ if(int listS = pdf_choice_widget_options(CTX, (pdf_document*)DOC, widget, 0, NULL)) {
+ char *opts[listS];
+ pdf_choice_widget_options(CTX, (pdf_document*)DOC, widget, 0, opts);
+ for(int i = 0; i < listS; i++) { optionList.append(QString::fromLocal8Bit(opts[i])); }
+ WIDGET->setOptions(optionList);
+ }
+
+ if(int exportS = pdf_choice_widget_options(CTX, (pdf_document*)DOC, widget, 1, NULL)) {
+ char *opts[exportS];
+ pdf_choice_widget_options(CTX, (pdf_document*)DOC, widget, 1, opts);
+ for(int i = 0; i < exportS; i++) { exportList.append(QString::fromLocal8Bit(opts[i])); }
+ WIDGET->setExports(exportList);
+ }
+ }
+
+ widgetList.push_back(WIDGET);
+
+ widget = pdf_next_widget(CTX, widget);
}
fz_close_device(CTX, dev);
fz_drop_device(CTX, dev);
- fz_drop_page(CTX, PAGE);
+ //fz_drop_page(CTX, PAGE);
- data = new Data(pagenum, CTX, list, bbox, matrix, sf, link, annotList);
+ data = new Data(pagenum, CTX, list, bbox, matrix, sf, link, annotList, widgetList);
data->setRenderThread(QtConcurrent::run(&renderer, data, this));
}
@@ -368,26 +590,20 @@ int Renderer::linkSize(int pagenum) {
return dataHash[pagenum]->getLinkList().size();
}
-QList<QString> Renderer::annotList(int pagenum, int entry) {
- return QList<QString>() << dataHash[pagenum]->getAnnotList()[entry]->getAuthor() << dataHash[pagenum]->getAnnotList()[entry]->getText();
+Annotation *Renderer::annotList(int pagenum, int entry) {
+ return static_cast<Annotation*>(dataHash[pagenum]->getAnnotList(entry));
}
-QRectF Renderer::annotLoc(int pagenum, int entry) {
- return dataHash[pagenum]->getAnnotList()[entry]->getLoc();
+int Renderer::annotSize(int pagenum) {
+ return dataHash[pagenum]->getAnnotSize();
}
-int Renderer::annotSize(int pagenum) {
- return dataHash[pagenum]->getAnnotList().size();
+Widget *Renderer::widgetList(int pagenum, int entry) {
+ return dataHash[pagenum]->getWidgetList(entry);
}
-bool Renderer::isExternalLink(int pagenum, QString text) {
- QList<Link*> linkList = dataHash[pagenum]->getLinkList();
- foreach(Link *link, linkList) {
- if(link->getData()->text() == text)
- return fz_is_external_link(CTX, link->getData()->text().toLocal8Bit().data());
- }
- return false;
+int Renderer::widgetSize(int pagenum) {
+ return dataHash[pagenum]->getWidgetSize();
}
bool Renderer::supportsExtraFeatures() { return true; }
-
diff --git a/src-qt5/desktop-utils/lumina-pdf/Renderer-poppler.cpp b/src-qt5/desktop-utils/lumina-pdf/Renderer-poppler.cpp
index 52412871..b8828557 100644
--- a/src-qt5/desktop-utils/lumina-pdf/Renderer-poppler.cpp
+++ b/src-qt5/desktop-utils/lumina-pdf/Renderer-poppler.cpp
@@ -163,7 +163,7 @@ bool Renderer::supportsExtraFeatures() { return false; }
void Renderer::traverseOutline(void *, int) { }
-void Renderer::handleLink(QString linkDest) {
+void Renderer::handleLink(QWidget *obj, QString linkDest) {
Poppler::Link* trueLink;
foreach(QList<Link*> linkArray, linkHash) {
for(int i = 0; i < linkArray.size(); i++) {
@@ -180,6 +180,9 @@ void Renderer::handleLink(QString linkDest) {
if(trueLink) {
if(trueLink->linkType() == Poppler::Link::LinkType::Goto)
emit goToPosition(dynamic_cast<Poppler::LinkGoto*>(trueLink)->destination().pageNumber(), 0, 0);
+ else if(trueLink->linkType() == Poppler::Link::LinkType::Browse) {
+ if(QMessageBox::Yes == QMessageBox::question(obj, tr("Open External Link?"), QString(tr("Do you want to open %1 in the default browser")).arg(linkDest), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ){ QProcess::startDetached("firefox \""+linkDest+"\""); }
+ }
}
}
@@ -190,38 +193,12 @@ TextData* Renderer::linkList(int pageNum, int entry) {
return 0;
}
-QList<QString> Renderer::annotList(int pageNum, int entry) {
- Q_UNUSED(pageNum)
- Q_UNUSED(entry)
- return QList<QString>() << QString() << QString();
-}
-
int Renderer::linkSize(int pageNum) { Q_UNUSED(pageNum) return linkHash[pageNum].size(); }
int Renderer::annotSize(int pageNum) { Q_UNUSED(pageNum) return 0; }
-QRectF Renderer::annotLoc(int pageNum, int entry) { Q_UNUSED(pageNum) Q_UNUSED(entry) return QRectF(); }
+Annotation *Renderer::annotList(int pageNum, int entry) { Q_UNUSED(pageNum) Q_UNUSED(entry) return NULL; }
-bool Renderer::isExternalLink(int pageNum, QString text) {
- Q_UNUSED(pageNum)
- Poppler::Link* trueLink;
- foreach(QList<Link*> linkArray, linkHash) {
- for(int i = 0; i < linkArray.size(); i++) {
- Poppler::Link* link = linkArray[i]->getLink();
- if(link->linkType() == Poppler::Link::LinkType::Browse) {
- if(text == dynamic_cast<Poppler::LinkBrowse*>(link)->url())
- trueLink = link;
- }else if(link->linkType() == Poppler::Link::LinkType::Goto) {
- if(text == dynamic_cast<Poppler::LinkGoto*>(link)->fileName())
- trueLink = link;
- }
- }
- }
- if(trueLink) {
- if(trueLink->linkType() == Poppler::Link::LinkType::Goto)
- return dynamic_cast<Poppler::LinkGoto*>(trueLink)->isExternal();
- if(trueLink->linkType() == Poppler::Link::LinkType::Browse)
- return true;
- }
- return false;
-}
+int Renderer::widgetSize(int pageNum) { Q_UNUSED(pageNum) return 0; }
+
+Widget *Renderer::widgetList(int pageNum, int entry) { Q_UNUSED(pageNum) Q_UNUSED(entry) return NULL; }
diff --git a/src-qt5/desktop-utils/lumina-pdf/Renderer.h b/src-qt5/desktop-utils/lumina-pdf/Renderer.h
index 4dd3e3b1..59d7024b 100644
--- a/src-qt5/desktop-utils/lumina-pdf/Renderer.h
+++ b/src-qt5/desktop-utils/lumina-pdf/Renderer.h
@@ -10,8 +10,12 @@
#include <QImage>
#include <QDebug>
#include <QJsonObject>
+#include <QMessageBox>
+#include <QProcess>
#include "TextData.h"
#include "Bookmark.h"
+#include "Annotation.h"
+#include "Widget.h"
class Renderer : public QObject {
Q_OBJECT
@@ -31,29 +35,29 @@ public:
bool loadMultiThread();
//Information functions (usually needs to be loaded first)
- int numPages(){ return pnum; }
- bool needPassword(){ return needpass; }
- QString title(){ return doctitle; }
- QJsonObject properties() { return jobj; }
- int hashSize();
- QImage imageHash(int pagenum);
- int rotatedDegrees() { return degrees; }
- QList<Bookmark*> getBookmarks() { return bookmarks; }
+ virtual int numPages(){ return pnum; }
+ virtual bool needPassword(){ return needpass; }
+ virtual QString title(){ return doctitle; }
+ virtual QJsonObject properties() { return jobj; }
+ virtual int hashSize();
+ virtual QImage imageHash(int pagenum);
+ virtual int rotatedDegrees() { return degrees; }
+ virtual QList<Bookmark*> getBookmarks() { return bookmarks; }
//Main access functions
- bool loadDocument(QString path, QString password);
- void renderPage(int pagenum, QSize DPI, int degrees=0);
- QList<TextData*> searchDocument(QString text, bool matchCase);
- void traverseOutline(void *, int);
- void handleLink(QString);
- TextData *linkList(int, int);
- int linkSize(int);
- QList<QString> annotList(int, int);
- int annotSize(int);
- QRectF annotLoc(int, int);
- bool isExternalLink(int, QString);
+ virtual bool loadDocument(QString path, QString password);
+ virtual void renderPage(int pagenum, QSize DPI, int degrees=0);
+ virtual QList<TextData*> searchDocument(QString text, bool matchCase);
+ virtual void traverseOutline(void *, int);
+ virtual void handleLink(QWidget*, QString);
+ virtual TextData *linkList(int, int);
+ virtual int linkSize(int);
+ virtual Annotation *annotList(int, int);
+ virtual int annotSize(int);
+ virtual Widget *widgetList(int, int);
+ virtual int widgetSize(int);
- void clearHash();
+ virtual void clearHash();
//Makes sure degrees is between 0 and 360 then rotates the matrix and
void setDegrees(int degrees) {
//Mods by 360, but adds and remods because of how C++ treats negative mods
@@ -61,7 +65,7 @@ public:
emit reloadPages(this->degrees);
}
- bool supportsExtraFeatures();
+ virtual bool supportsExtraFeatures();
signals:
void PageLoaded(int);
diff --git a/src-qt5/desktop-utils/lumina-pdf/Widget.h b/src-qt5/desktop-utils/lumina-pdf/Widget.h
new file mode 100644
index 00000000..0bfe5cdd
--- /dev/null
+++ b/src-qt5/desktop-utils/lumina-pdf/Widget.h
@@ -0,0 +1,29 @@
+#include <QStringList>
+
+class Widget{
+ public:
+ Widget(int _widgetType, QRectF _loc, QString _currText, int _maxLen, int _contentType) : widgetType(_widgetType), loc(_loc), currText(_currText), maxLen(_maxLen), contentType(_contentType) { }
+
+ virtual ~Widget() { }
+
+ virtual int getWidgetType() { return widgetType; }
+ virtual QRectF getLocation() { return loc; }
+ virtual QString getCurrentText() { return currText; }
+ virtual int getMaxLength() { return maxLen; }
+ virtual int getContentType() { return contentType; }
+ virtual QStringList getOptionList() { return optionList; }
+ virtual QStringList getExportList() { return exportList; }
+
+ virtual void setOptions(QStringList _optionList) { optionList = _optionList; }
+ virtual void setExports(QStringList _exportList) { exportList = _exportList; }
+
+ private:
+ int widgetType;
+ QRectF loc;
+ QString currText;
+ int maxLen;
+ int contentType;
+
+ QStringList optionList;
+ QStringList exportList;
+};
diff --git a/src-qt5/desktop-utils/lumina-pdf/lumina-pdf.pro b/src-qt5/desktop-utils/lumina-pdf/lumina-pdf.pro
index c63386c0..80360bb0 100644
--- a/src-qt5/desktop-utils/lumina-pdf/lumina-pdf.pro
+++ b/src-qt5/desktop-utils/lumina-pdf/lumina-pdf.pro
@@ -30,7 +30,9 @@ HEADERS += mainUI.h \
Renderer.h \
TextData.h \
Bookmark.h \
- BookmarkMenu.h
+ BookmarkMenu.h \
+ Annotation.h \
+ Widget.h
FORMS += mainUI.ui \
PropDialog.ui \
diff --git a/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp b/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp
index aa80489d..3d308b2f 100644
--- a/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp
+++ b/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp
@@ -484,6 +484,19 @@ void MainUI::paintToPrinter(QPrinter *PRINTER){
QImage img = BACKEND->imageHash(pageCount[i]).scaled(sz, Qt::KeepAspectRatio, Qt::SmoothTransformation);
//Now draw the image
painter.drawImage(0,0,img);
+ //Also paint the annotations at their locations
+ for(int k = 0; k < BACKEND->annotSize(i); k++) {
+ Annotation *annot = BACKEND->annotList(i, k);
+ if(annot->print()) {
+ if(annot->getType() == 14) {
+ painter.setPen(QPen(annot->getColor()));
+ foreach(QVector<QPointF> pointList, annot->getInkList())
+ painter.drawLines(pointList);
+ }else{
+ painter.drawImage(annot->getLoc(), annot->renderImage());
+ }
+ }
+ }
}
progAct->setVisible(false);
}
bgstack15