diff options
author | ZackaryWelch <welch.zackary@gmail.com> | 2018-03-11 21:18:53 -0400 |
---|---|---|
committer | ZackaryWelch <welch.zackary@gmail.com> | 2018-03-11 21:18:53 -0400 |
commit | 4b126da97fe1a6180507b13c36591743b44d0d27 (patch) | |
tree | 3e496f67eab3ddcb5ffd2e8b11a06dbd0665c74c /src-qt5/desktop-utils | |
parent | Merge remote-tracking branch 'origin/master' (diff) | |
download | lumina-4b126da97fe1a6180507b13c36591743b44d0d27.tar.gz lumina-4b126da97fe1a6180507b13c36591743b44d0d27.tar.bz2 lumina-4b126da97fe1a6180507b13c36591743b44d0d27.zip |
Added multithreading support for the MuPDF backend and fixed rendering errors
Diffstat (limited to 'src-qt5/desktop-utils')
-rw-r--r-- | src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp | 16 | ||||
-rw-r--r-- | src-qt5/desktop-utils/lumina-pdf/Renderer-mupdf.cpp | 133 | ||||
-rw-r--r-- | src-qt5/desktop-utils/lumina-pdf/Renderer-poppler.cpp | 4 | ||||
-rw-r--r-- | src-qt5/desktop-utils/lumina-pdf/Renderer.h | 4 | ||||
-rw-r--r-- | src-qt5/desktop-utils/lumina-pdf/mainUI.cpp | 12 | ||||
-rw-r--r-- | src-qt5/desktop-utils/lumina-pdf/mainUI.h | 1 |
6 files changed, 93 insertions, 77 deletions
diff --git a/src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp b/src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp index bece454e..5c7fa1dd 100644 --- a/src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp +++ b/src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp @@ -185,23 +185,23 @@ void PrintWidget::layoutPages() { void PrintWidget::populateScene() { for (int i = 0; i < pages.size(); i++){ - scene->removeItem(pages.at(i)); + scene->removeItem(pages.at(i)); } qDeleteAll(pages); pages.clear(); //qDebug() << "populateScene"; if(pictures==0){ return; } //nothing to show yet int numPages = pictures->count(); - //Replace from loadingHash resolution - QSize paperSize = pictures->value(0).size(); - //qDebug() << "Image paperSize" << paperSize; - - //Changes the paper orientation if rotated by 90 or 270 degrees - if(degrees == 90 or degrees == 270) - paperSize.transpose(); for (int i = 0; i < numPages; i++) { QImage pagePicture = pictures->value(i); + + QSize paperSize = pictures->value(i).size(); + + //Changes the paper orientation if rotated by 90 or 270 degrees + if(degrees == 90 or degrees == 270) + paperSize.transpose(); + if(degrees != 0) { pagePicture = pagePicture.transformed(rotMatrix, Qt::SmoothTransformation); //qDebug() << "Rotating by: " << degrees << " degrees"; diff --git a/src-qt5/desktop-utils/lumina-pdf/Renderer-mupdf.cpp b/src-qt5/desktop-utils/lumina-pdf/Renderer-mupdf.cpp index 279888c6..799f6584 100644 --- a/src-qt5/desktop-utils/lumina-pdf/Renderer-mupdf.cpp +++ b/src-qt5/desktop-utils/lumina-pdf/Renderer-mupdf.cpp @@ -1,23 +1,43 @@ #include "Renderer.h" -#include <mupdf/fitz.h> -#include <mupdf/pdf.h> - #include <QDateTime> +#include <mupdf/fitz.h> +//#include <pthread.h> fz_document *DOC; -pdf_document *PDOC; fz_context *CTX; -inline QString getTextInfo(pdf_obj *info, QString str) { - pdf_obj *obj = pdf_dict_gets(CTX, info, str.toLatin1().data()); - if(obj){ return pdf_to_utf8(CTX, obj); } +inline QString getTextInfo(QString str) { + char infoBuff[1000]; + int size = DOC->lookup_metadata(CTX, DOC, ("info:"+str).toLocal8Bit().data(), infoBuff, 1000); + if(size != -1){ return QString::fromLatin1(infoBuff); } return ""; } +/*void lock_mutex(void *user, int lock) { + pthread_mutex_t *mutex = (pthread_mutex_t *) user; + pthread_mutex_lock(&mutex[lock]); +} + +void unlock_mutex(void *user, int lock) { + pthread_mutex_t *mutex = (pthread_mutex_t *) user; + pthread_mutex_unlock(&mutex[lock]); +}*/ + Renderer::Renderer(){ + /*pthread_mutex_t mutex[FZ_LOCK_MAX]; + fz_locks_context locks; + locks.user = mutex; + locks.lock = lock_mutex; + locks.unlock = unlock_mutex; + + for (int i = 0; i < FZ_LOCK_MAX; i++) + pthread_mutex_init(&mutex[i], NULL);*/ + + mutex = new QMutex(); DOC = 0; + //CTX = fz_new_context(NULL, &locks, FZ_STORE_UNLIMITED); CTX = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED); - PDOC = 0; + qDebug() << "Context created"; needpass = false; } @@ -25,43 +45,45 @@ Renderer::~Renderer(){ } -bool Renderer::loadMultiThread(){ return false; } +//bool Renderer::loadMultiThread(){ return true; } QJsonObject Renderer::properties(){ QJsonObject jobj; - pdf_obj *info = pdf_dict_gets(CTX, pdf_trailer(CTX, PDOC), "Info"); - jobj.insert("title", getTextInfo(info, "Title") ); - jobj.insert("subject", getTextInfo(info, "Subject") ); - jobj.insert("author", getTextInfo(info, "Author") ); - jobj.insert("creator", getTextInfo(info, "Creator") ); - jobj.insert("producer", getTextInfo(info, "Producer") ); - jobj.insert("keywords", getTextInfo(info, "Keywords") ); - jobj.insert("dt_created", QDateTime::fromString( getTextInfo(info, "CreationDate").left(16), "'D:'yyyyMMddHHmmss").toString() ); - jobj.insert("dt_modified", QDateTime::fromString( getTextInfo(info, "ModDate").left(16), "'D:'yyyyMMddHHmmss").toString() ); + jobj.insert("title", getTextInfo("Title") ); + jobj.insert("subject", getTextInfo("Subject") ); + jobj.insert("author", getTextInfo("Author") ); + jobj.insert("creator", getTextInfo("Creator") ); + jobj.insert("producer", getTextInfo("Producer") ); + jobj.insert("keywords", getTextInfo("Keywords") ); + jobj.insert("dt_created", QDateTime::fromString( getTextInfo("CreationDate").left(16), "'D:'yyyyMMddHHmmss").toString() ); + jobj.insert("dt_modified", QDateTime::fromString( getTextInfo("ModDate").left(16), "'D:'yyyyMMddHHmmss").toString() ); return jobj; } bool Renderer::loadDocument(QString path, QString password){ - if(DOC==0){ fz_register_document_handlers(CTX); } //first time through - else if(path!=docpath){ + //first time through + if(DOC==0){ + fz_register_document_handlers(CTX); + qDebug() << "Document handlers registered"; + }else if(path!=docpath){ //fz_close_document(DOC); //Clear out the old document first delete DOC; DOC=0; - if(PDOC!=0){ delete PDOC; PDOC=0; } needpass = false; + docpath = path; } + if(DOC==0){ DOC = fz_open_document(CTX, path.toLocal8Bit().data()); + docpath = path; + qDebug() << "File opened"; if(DOC==0){ qDebug() << "Could not open file:" << path; return false; } needpass = (fz_needs_password(CTX, DOC) != 0); } - if(PDOC==0){ - PDOC = pdf_open_document(CTX, path.toLocal8Bit().data()); - } if(needpass && password.isEmpty()){ return false; } else if(needpass){ @@ -69,48 +91,47 @@ bool Renderer::loadDocument(QString path, QString password){ if(needpass){ return false; } //incorrect password } + qDebug() << "Password Check cleared"; + //Could read/access the PDF - go ahead and load the info now pnum = -1; doctitle.clear(); //qDebug() << "Opening File:" << path; - pdf_obj *info = pdf_dict_gets(CTX, pdf_trailer(CTX, (pdf_document*)DOC), "Info"); - if(info) { - if(pdf_obj *obj = pdf_dict_gets(CTX, info, (char *)"Title")){ doctitle = pdf_to_utf8(CTX, obj); } - } - if(doctitle.isEmpty()){ doctitle = path.section("/",-1); } + QString title = getTextInfo("Subject"); + if(!title.isNull()) + doctitle = title; + else + doctitle = path.section("/",-1); pnum = fz_count_pages(CTX, DOC); //Setup the Document fz_page *PAGE = fz_load_page(CTX, DOC, 0); - if(PAGE!=0){ - /*switch(PAGE->orientation()){ - case Poppler::Page::Landscape: - WIDGET->setOrientation(QPageLayout::Landscape); break; - default: - WIDGET->setOrientation(QPageLayout::Portrait); - }*/ - delete PAGE; - return true; //could see the first page - } - return false; + qDebug() << "Page Loaded"; + //Possibly check Page orientation"; + + return (PAGE); } +//Consider rendering through a display list QImage Renderer::renderPage(int pagenum, QSize DPI){ - //MuPDF uses a scaling factor, not DPI - fz_page *PAGE = fz_load_page(CTX, DOC, pagenum); - QImage img; - if(PAGE!=0){ - fz_matrix matrix; - //double scaleFactorW = dpi.width()/72.0; - //double scaleFactorH = dpi.height()/72.0; - //fz_scale(&matrix, scaleFactorW, scaleFactorH); - fz_scale(&matrix, 4.0, 4.0); //need to adjust this later according to DPI - fz_pre_rotate(&matrix, 0.0); - fz_pixmap *pixmap = fz_new_pixmap_from_page_number(CTX, DOC, pagenum, &matrix, fz_device_rgb(CTX), 0); - //unsigned char *samples = fz_pixmap_samples(CTX, pixmap); - img = QImage(pixmap->samples, pixmap->w, pixmap->h, QImage::Format_RGB888); //make the raw image a bit larger than the end result - delete PAGE; - } - qDebug() << "Render Page:" << pagenum << img.size(); + QImage img; + fz_matrix matrix; + fz_pixmap *pixmap = nullptr; + + fz_scale(&matrix, DPI.width()/96.0, DPI.height()/96.0); + + //fz_context *ctx = fz_clone_context(CTX); + mutex->lock(); + + fz_try(CTX) { + pixmap = fz_new_pixmap_from_page_number(CTX, DOC, pagenum, &matrix, fz_device_rgb(CTX), 0); + }fz_catch(CTX){ + qDebug() << "Error when rendering page using MuPDF"; + } + + mutex->unlock(); + + img = QImage(pixmap->samples, pixmap->w, pixmap->h, pixmap->stride, QImage::Format_RGB888); + qDebug() << "Render Page:" << pagenum; return img; } diff --git a/src-qt5/desktop-utils/lumina-pdf/Renderer-poppler.cpp b/src-qt5/desktop-utils/lumina-pdf/Renderer-poppler.cpp index b2d7dd32..693faa64 100644 --- a/src-qt5/desktop-utils/lumina-pdf/Renderer-poppler.cpp +++ b/src-qt5/desktop-utils/lumina-pdf/Renderer-poppler.cpp @@ -13,7 +13,7 @@ Renderer::~Renderer(){ } -bool Renderer::loadMultiThread(){ return true; } +//bool Renderer::loadMultiThread(){ return true; } QJsonObject Renderer::properties(){ return QJsonObject(); //TO-DO @@ -27,11 +27,13 @@ bool Renderer::loadDocument(QString path, QString password){ DOC=0; needpass = false; pnum=0; + docpath = path; } //Load the Document (if needed); if(DOC==0){ //qDebug() << "Loading Document"; DOC = Poppler::Document::load(path); + docpath = path; } if(DOC==0){ diff --git a/src-qt5/desktop-utils/lumina-pdf/Renderer.h b/src-qt5/desktop-utils/lumina-pdf/Renderer.h index 09e9c425..c9e13c7f 100644 --- a/src-qt5/desktop-utils/lumina-pdf/Renderer.h +++ b/src-qt5/desktop-utils/lumina-pdf/Renderer.h @@ -11,6 +11,7 @@ #include <QImage> #include <QDebug> #include <QJsonObject> +#include <QMutex> #include "textData.h" class Renderer{ @@ -19,10 +20,11 @@ private: bool needpass; QString docpath; //save the path for the currently-loaded document QString doctitle; + QMutex *mutex; public: Renderer(); ~Renderer(); - bool loadMultiThread(); + //bool loadMultiThread(); //Information functions (usually needs to be loaded first) int numPages(){ return pnum; } diff --git a/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp b/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp index 4daf8ec9..03050138 100644 --- a/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp +++ b/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp @@ -15,7 +15,6 @@ #include <QDebug> #include <QApplication> #include <QScreen> -#include <QTimer> #include <iostream> #include <QtConcurrent> @@ -382,10 +381,6 @@ void MainUI::startLoadingPages(){ // Using Qt to scale the image (adjust page value) smooths out the image quite a bit without a lot of performance loss (but cannot scale up without pixelization) // The best approach seams to be to increase the DPI a bit, but match that with the same scaling on the page size (smoothing) - //double scalefactor = 2.5; - //fz_rect page_rect; - //fz_bound_page(CTX, fz_load_page(CTX, DOC, 0), &page_rect); - //pageSize = QSizeF((page_rect.x1 - page_rect.x0)/72.0, (page_rect.y1 - page_rect.y0)/72.0); QSize DPI(300,300); //print-quality (some printers even go to 600 DPI nowdays) /*qDebug() << "Screen Resolutions:"; @@ -393,14 +388,9 @@ void MainUI::startLoadingPages(){ for(int i=0; i<screens.length(); i++){ qDebug() << screens[i]->name() << screens[i]->logicalDotsPerInchX() << screens[i]->logicalDotsPerInchY(); }*/ - bool async = BACKEND->loadMultiThread(); for(int i=0; i<BACKEND->numPages(); i++){ //qDebug() << " - Kickoff page load:" << i; - if(async){ - QtConcurrent::run(this, &MainUI::loadPage, i, this, DPI); - }else{ - loadPage(i, this, DPI); - } + QtConcurrent::run(this, &MainUI::loadPage, i, this, DPI); } //qDebug() << "Finish page loading kickoff"; } diff --git a/src-qt5/desktop-utils/lumina-pdf/mainUI.h b/src-qt5/desktop-utils/lumina-pdf/mainUI.h index 911456aa..74badbfd 100644 --- a/src-qt5/desktop-utils/lumina-pdf/mainUI.h +++ b/src-qt5/desktop-utils/lumina-pdf/mainUI.h @@ -18,6 +18,7 @@ #include <QWheelEvent> #include <QApplication> #include <QMenu> +#include <QTimer> #include "Renderer.h" #include "PresentationLabel.h" |