From b93568ad1821adeb76a3cc488a1fb5fb5829a5c8 Mon Sep 17 00:00:00 2001 From: Anton Thomasson Date: Mon, 8 Nov 2021 19:49:47 +0100 Subject: [PATCH] Use pdf2printable --- harbour-seaprint.pro | 11 ++- ppm2pwg | 2 +- rpm/harbour-seaprint.spec | 4 + src/convertworker.cpp | 105 ++++++++------------ src/convertworker.h | 2 +- src/curliodevice.cpp | 124 ------------------------ src/curlrequester.cpp | 71 ++++++++++++++ src/{curliodevice.h => curlrequester.h} | 16 +-- src/curlworker.cpp | 47 +++++++-- src/curlworker.h | 7 +- src/harbour-seaprint.cpp | 10 -- src/ippprinter.h | 2 +- 12 files changed, 181 insertions(+), 220 deletions(-) delete mode 100644 src/curliodevice.cpp create mode 100644 src/curlrequester.cpp rename src/{curliodevice.h => curlrequester.h} (71%) diff --git a/harbour-seaprint.pro b/harbour-seaprint.pro index ab3a12f..1b14372 100644 --- a/harbour-seaprint.pro +++ b/harbour-seaprint.pro @@ -27,8 +27,8 @@ system(lrelease $$PWD/translations/*.ts) CONFIG += sailfishapp QT += svg -PKGCONFIG += mlite5 libcurl -LIBS += -lcurl +PKGCONFIG += mlite5 libcurl poppler glib-2.0 cairo +LIBS += -lcurl -lpoppler -lcairo -lglib-2.0 -lgobject-2.0 -lpoppler-glib # Write version file VERSION_H = \ @@ -40,13 +40,14 @@ write_file($$$$OUT_PWD/seaprint_version.h, VERSION_H) SOURCES += src/harbour-seaprint.cpp \ src/convertchecker.cpp \ src/convertworker.cpp \ - src/curliodevice.cpp \ + src/curlrequester.cpp \ src/curlworker.cpp \ src/ippdiscovery.cpp \ src/ippmsg.cpp \ src/ippprinter.cpp \ src/mimer.cpp \ ppm2pwg/ppm2pwg.cpp \ + ppm2pwg/pdf2printable.cpp \ ppm2pwg/bytestream/bytestream.cpp \ src/overrider.cpp \ src/settings.cpp \ @@ -86,12 +87,14 @@ TRANSLATIONS += translations/harbour-seaprint-de.ts \ HEADERS += \ src/convertchecker.h \ src/convertworker.h \ - src/curliodevice.h \ + src/curlrequester.h \ src/curlworker.h \ src/ippdiscovery.h \ src/ippmsg.h \ src/ippprinter.h \ src/mimer.h \ + ppm2pwg/ppm2pwg.h \ + ppm2pwg/pdf2printable.h \ ppm2pwg/PwgPgHdr.h \ ppm2pwg/PwgPgHdr.codable \ ppm2pwg/UrfPgHdr.h \ diff --git a/ppm2pwg b/ppm2pwg index 331b4b5..6a93de0 160000 --- a/ppm2pwg +++ b/ppm2pwg @@ -1 +1 @@ -Subproject commit 331b4b5270264b604cd642201a7f5a2b6f2c9c1d +Subproject commit 6a93de071f3d2814260da5fe2ea14352483ea0a0 diff --git a/rpm/harbour-seaprint.spec b/rpm/harbour-seaprint.spec index 40304da..849ce83 100644 --- a/rpm/harbour-seaprint.spec +++ b/rpm/harbour-seaprint.spec @@ -16,6 +16,10 @@ BuildRequires: pkgconfig(Qt5Svg) BuildRequires: pkgconfig(mlite5) BuildRequires: desktop-file-utils BuildRequires: pkgconfig(libcurl) +BuildRequires: pkgconfig(poppler) +BuildRequires: pkgconfig(poppler-glib) +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(cairo) %description Network printing for Sailfish OS diff --git a/src/convertworker.cpp b/src/convertworker.cpp index 72a06c0..fb79ec3 100644 --- a/src/convertworker.cpp +++ b/src/convertworker.cpp @@ -11,6 +11,7 @@ #include #include #include "ippprinter.h" +#include "pdf2printable.h" void ppm2PwgEnv(QStringList& env, bool urf, quint32 Quality, QString PaperSize, quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble, @@ -64,7 +65,7 @@ ConvertWorker::ConvertWorker(IppPrinter* parent) // : QObject((QObject*)parent) void ConvertWorker::command(QByteArray msg) { - CurlIODevice cid(_printer->httpUrl()); + CurlRequester cid(_printer->httpUrl()); cid.setFinishedCallback(_printer, &IppPrinter::getPrinterAttributesFinished); qDebug() << "command..."; @@ -75,7 +76,7 @@ void ConvertWorker::command(QByteArray msg) // TODO: de-duplicate void ConvertWorker::getJobs(QByteArray msg) { - CurlIODevice cid(_printer->httpUrl()); + CurlRequester cid(_printer->httpUrl()); cid.setFinishedCallback(_printer, &IppPrinter::getJobsRequestFinished); cid.write(msg.data(), msg.length()); @@ -83,7 +84,7 @@ void ConvertWorker::getJobs(QByteArray msg) void ConvertWorker::cancelJob(QByteArray msg) { - CurlIODevice cid(_printer->httpUrl()); + CurlRequester cid(_printer->httpUrl()); cid.setFinishedCallback(_printer, &IppPrinter::cancelJobFinished); cid.write(msg.data(), msg.length()); @@ -93,11 +94,9 @@ void ConvertWorker::justUpload(QString filename, QByteArray header) { qDebug() << "justupload"; - CurlIODevice cid(_printer->httpUrl()); + CurlRequester cid(_printer->httpUrl()); cid.setFinishedCallback(_printer, &IppPrinter::printRequestFinished); - qDebug() << "justupload cp set"; - QFile file(filename); file.open(QFile::ReadOnly); @@ -113,87 +112,67 @@ void ConvertWorker::convertPdf(QString filename, QByteArray header, quint32 PageRangeLow, quint32 PageRangeHigh, bool BackHFlip, bool BackVFlip) { try { + Format format; - quint32 pages = ConvertChecker::instance()->pdfPages(filename); - if (!pages) - { - qDebug() << "pdfinfo returned 0 pages"; - throw ConvertFailedException(tr("Failed to get info about PDF file")); - } - - if(PageRangeLow==0) - { - PageRangeLow=1; - } - - if(PageRangeHigh==0) - { - PageRangeHigh=pages; - } - - // Actual number of pages to print - pages = PageRangeHigh-PageRangeLow+1; - - qDebug() << "PageRangeLow" << PageRangeLow << "PageRangeHigh" << PageRangeHigh << "pages" << pages; - - bool urf = false; - bool ps = false; - bool pdf = false; + qDebug() << "to pdf" << HwResX << HwResY; if(targetFormat == Mimer::URF) { - urf = true; + format = Format::URF; } else if(targetFormat == Mimer::PWG) { - //ok + format = Format::PWG; } else if(targetFormat == Mimer::Postscript) { - ps = true; + format = Format::Postscript; } else if (targetFormat == Mimer::PDF) { - pdf = true; + format = Format::PDF; } else { throw ConvertFailedException(tr("Unsupported target format")); } - if(urf && (HwResX != HwResY)) - { // URF only supports symmetric resolutions - qDebug() << "Unsupported URF resolution" << PaperSize; - throw ConvertFailedException(tr("Unsupported resolution (dpi)")); - } - - QTemporaryFile tempfile; - tempfile.open(); - tempfile.close(); - - if(ps) + if(Colors == 0) { - pdftoPs(PaperSize, TwoSided, PageRangeLow, PageRangeHigh, filename, &tempfile); - } - else if(pdf) - { - adjustPageRange(PaperSize, PageRangeLow, PageRangeHigh, filename, &tempfile); - } - else - { - pdfToRaster(targetFormat, Colors, Quality, PaperSize, - HwResX, HwResY, TwoSided, Tumble, - PageRangeLow, PageRangeHigh, pages, BackHFlip, BackVFlip, - filename, &tempfile, true); - + Colors = 3; } + CurlRequester cid(_printer->httpUrl()); + cid.setFinishedCallback(_printer, &IppPrinter::printRequestFinished); + + cid.write(header.data(), header.length()); + + write_fun WriteFun([&cid](unsigned char const* buf, unsigned int len) -> bool + { + qDebug() << "wf called " << len; + cid.write((const char*)buf, len); + qDebug() << "wf returns " << len; + return true; + }); + + if(!PaperSizes.contains(PaperSize)) + { + qDebug() << "Unsupported paper size" << PaperSize; + throw ConvertFailedException(tr("Unsupported paper size")); + } + QSizeF size = PaperSizes[PaperSize]; + float Width = size.width(); + float Height = size.height(); + + int res = pdf_to_printable(filename.toStdString(), WriteFun, Colors, Quality, PaperSize.toStdString(), Width, Height, HwResX, HwResY, + format, TwoSided, Tumble, BackHFlip, BackVFlip, PageRangeLow, PageRangeHigh); + + if(res != 0) + { + throw ConvertFailedException("Conversion failed"); + } qDebug() << "Finished"; - - justUpload(tempfile.fileName(), header); - qDebug() << "posted"; - } catch(const ConvertFailedException& e) { diff --git a/src/convertworker.h b/src/convertworker.h index 664485f..6b4ba86 100644 --- a/src/convertworker.h +++ b/src/convertworker.h @@ -2,7 +2,7 @@ #define CONVERTWORKER_H #include #include -#include "curliodevice.h" +#include "curlrequester.h" class IppPrinter; diff --git a/src/curliodevice.cpp b/src/curliodevice.cpp deleted file mode 100644 index be0bebd..0000000 --- a/src/curliodevice.cpp +++ /dev/null @@ -1,124 +0,0 @@ -#include "curliodevice.h" -#include -#include - -Q_DECLARE_METATYPE(CURLcode) - - -static size_t trampoline(char* dest, size_t size, size_t nmemb, void* userp) -{ - qDebug() << "boingiddy!"; - CurlIODevice* cid = (CurlIODevice*)userp; - return cid->requestWrite(dest, size*nmemb); -} - -CurlIODevice::CurlIODevice(QUrl addr) : _addr(addr), _canWrite(1), _canRead(), _reading(false), _done(false), _dest(nullptr), _size(0), _offset(0) -{ - qRegisterMetaType(); - -// if(openMode() != NotOpen && mode != WriteOnly) -// return false; - - CURL* curl = curl_easy_init(); -// if(!curl) -// return false; - - curl_easy_setopt(curl, CURLOPT_URL, _addr.toString().toStdString().c_str()); - curl_easy_setopt(curl, CURLOPT_POST, 1L); - curl_easy_setopt(curl, CURLOPT_READFUNCTION, trampoline); - curl_easy_setopt(curl, CURLOPT_READDATA, this); - curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 0L); - - //TODO: free this list - struct curl_slist *opts = NULL; - - opts = curl_slist_append(opts, "Transfer-Encoding: chunked"); - opts = curl_slist_append(opts, "Content-Type: application/ipp"); - opts = curl_slist_append(opts, "User-Agent: SeaPrint " SEAPRINT_VERSION); - opts = curl_slist_append(opts, "Accept-Encoding: identity"); - - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, opts); - - _performer = new CurlWorker(curl); - connect(_performer, &CurlWorker::done, this, &CurlIODevice::done); - connect(_performer, &CurlWorker::finished, _performer, &CurlWorker::deleteLater); - _performer->start(); - - qDebug() << "worker started"; - -} - -CurlIODevice::~CurlIODevice() -{ - qDebug() << "destroying"; - - _canWrite.acquire(); - _done = true; - _canRead.release(); - _performer->wait(); - - if(_dest != nullptr) - { - delete[] _dest; - } - qDebug() << "done destroying"; - -} - -void CurlIODevice::write(const char *data, size_t size) -{ - qDebug() << "write " << size; - _canWrite.acquire(); - - if(_dest != nullptr) - { - delete[] _dest; - } - _dest = new char[size]; - memcpy(_dest, data, size); - _size = size; - _offset = 0; - - _canRead.release(); - -} - -size_t CurlIODevice::requestWrite(char* dest, size_t size) -{ - qDebug() << "requestWrite " << size; - if(!_reading) - { - _canRead.acquire(); - if(_done) // Can only have been set by write() - only relevant to check if strating to write - { - return 0; - } - _reading = true; - } - - size_t remaining = _size - _offset; - - qDebug() << "requestWrite canwrite"; - - size_t actualSize = std::min(size, remaining); - memcpy(dest, (_dest+_offset), actualSize); - _offset += actualSize; - - remaining = _size - _offset; - if(remaining == 0) - { - _reading = false; - _canWrite.release(); - } - - qDebug() << "requestWrite returns " << _size; - return actualSize; -} - -void CurlIODevice::done(CURLcode) -{ - -} diff --git a/src/curlrequester.cpp b/src/curlrequester.cpp new file mode 100644 index 0000000..6e38b83 --- /dev/null +++ b/src/curlrequester.cpp @@ -0,0 +1,71 @@ +#include "curlrequester.h" +#include + +CurlRequester::CurlRequester(QUrl addr) : _addr(addr), _canWrite(1), _canRead(), _reading(false), _done(false), _dest(nullptr), _size(0), _offset(0), _performer(addr, this) +{ + + connect(&_performer, &CurlWorker::done, this, &CurlRequester::done); + _performer.start(); +} + +CurlRequester::~CurlRequester() +{ + _canWrite.acquire(); + _done = true; + _canRead.release(); + _performer.wait(); + + if(_dest != nullptr) + { + delete _dest; + } +} + +void CurlRequester::write(const char *data, size_t size) +{ + qDebug() << "write " << size; + _canWrite.acquire(); + + if(_dest != nullptr) + { + delete _dest; + } + _dest = new char[size]; + memcpy(_dest, data, size); + _size = size; + _offset = 0; + _canRead.release(); +} + +size_t CurlRequester::requestWrite(char* dest, size_t size) +{ + if(!_reading) + { + _canRead.acquire(); + if(_done) // Can only have been set by write() - only relevant to check if strating to write + { + return 0; + } + _reading = true; + } + + size_t remaining = _size - _offset; + + size_t actualSize = std::min(size, remaining); + + memcpy(dest, (_dest+_offset), actualSize); + _offset += actualSize; + + remaining = _size - _offset; + if(remaining == 0) + { + _reading = false; + _canWrite.release(); + } + return actualSize; +} + +void CurlRequester::done(CURLcode) +{ + +} diff --git a/src/curliodevice.h b/src/curlrequester.h similarity index 71% rename from src/curliodevice.h rename to src/curlrequester.h index bd98586..302d404 100644 --- a/src/curliodevice.h +++ b/src/curlrequester.h @@ -1,5 +1,5 @@ -#ifndef CURLIODEVICE_H -#define CURLIODEVICE_H +#ifndef CURLREQUESTER_H +#define CURLREQUESTER_H #include #include @@ -9,17 +9,17 @@ #include #include "curlworker.h" -class CurlIODevice : public QObject +class CurlRequester : public QObject { Q_OBJECT public: - CurlIODevice(QUrl addr); - ~CurlIODevice(); + CurlRequester(QUrl addr); + ~CurlRequester(); template bool setFinishedCallback(const Class* receiverObject, Callback cb) { - connect(_performer, &CurlWorker::done, receiverObject, cb); + connect(&_performer, &CurlWorker::done, receiverObject, cb); return true; } @@ -33,7 +33,6 @@ private: QUrl _addr; bool _open; - CurlWorker* _performer; QSemaphore _canWrite; QSemaphore _canRead; @@ -44,6 +43,7 @@ private: size_t _size; size_t _offset; + CurlWorker _performer; }; -#endif // CURLIODEVICE_H +#endif // CURLREQUESTER_H diff --git a/src/curlworker.cpp b/src/curlworker.cpp index bb81006..7c89806 100644 --- a/src/curlworker.cpp +++ b/src/curlworker.cpp @@ -1,22 +1,57 @@ #include "curlworker.h" +#include "curlrequester.h" +#include -CurlWorker::CurlWorker(CURL* curl) +Q_DECLARE_METATYPE(CURLcode) + +static size_t trampoline(char* dest, size_t size, size_t nmemb, void* userp) { - _curl = curl; + CurlRequester* cid = (CurlRequester*)userp; + return cid->requestWrite(dest, size*nmemb); } +CurlWorker::CurlWorker(QUrl addr, void* parent) +{ + qRegisterMetaType(); + + _curl = curl_easy_init(); +// if(!curl) +// return false; + + curl_easy_setopt(_curl, CURLOPT_URL, addr.toString().toStdString().c_str()); + curl_easy_setopt(_curl, CURLOPT_POST, 1L); + curl_easy_setopt(_curl, CURLOPT_READFUNCTION, trampoline); + curl_easy_setopt(_curl, CURLOPT_READDATA, parent); + curl_easy_setopt(_curl, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(_curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(_curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(_curl, CURLOPT_SSL_VERIFYSTATUS, 0L); + + _opts = NULL; + + _opts = curl_slist_append(_opts, "Transfer-Encoding: chunked"); + _opts = curl_slist_append(_opts, "Content-Type: application/ipp"); + _opts = curl_slist_append(_opts, "User-Agent: SeaPrint " SEAPRINT_VERSION); + _opts = curl_slist_append(_opts, "Accept-Encoding: identity"); + + curl_easy_setopt(_curl, CURLOPT_HTTPHEADER, _opts); + +} + +CurlWorker::~CurlWorker() +{ + curl_slist_free_all(_opts); + curl_easy_cleanup(_curl); +} void CurlWorker::run(){ QByteArray buf; curl_easy_setopt(_curl, CURLOPT_WRITEDATA, &buf); curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, write_callback); - qDebug() << "performer running"; CURLcode res = curl_easy_perform(_curl); if(res != CURLE_OK) qDebug() << "curl_easy_perform() failed: " << curl_easy_strerror(res); - curl_easy_cleanup(_curl); - curl_global_cleanup(); - qDebug() << "performer done " << buf.length(); + emit done(res, buf); } diff --git a/src/curlworker.h b/src/curlworker.h index 1f19f26..c22cc52 100644 --- a/src/curlworker.h +++ b/src/curlworker.h @@ -2,6 +2,7 @@ #define CURLWORKER_H #include +#include #include #include @@ -9,12 +10,13 @@ class CurlWorker : public QThread { Q_OBJECT public: - CurlWorker(CURL* curl); + CurlWorker(QUrl addr, void* parent); + ~CurlWorker(); + void run() override; static size_t write_callback(char *ptr, size_t size, size_t nmemb, void* userdata) { - qDebug() << "writing resp" << size*nmemb; size_t bytes_to_write = size*nmemb; ((QByteArray*)userdata)->append(ptr, bytes_to_write); return bytes_to_write; @@ -41,6 +43,7 @@ private: CurlWorker(); CURL* _curl = nullptr; + struct curl_slist* _opts; }; diff --git a/src/harbour-seaprint.cpp b/src/harbour-seaprint.cpp index b740170..a9fad9a 100644 --- a/src/harbour-seaprint.cpp +++ b/src/harbour-seaprint.cpp @@ -9,9 +9,6 @@ #include #include -#define PPM2PWG_MAIN ppm2pwg_main -#include - template static QObject* singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine) { @@ -25,12 +22,6 @@ static QObject* singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngi int main(int argc, char *argv[]) { - if(argc >= 1 && QString("ppm2pwg") == argv[1]) - { - return ppm2pwg_main(argc-1, &(argv[1])); - } - - QGuiApplication* app = SailfishApp::application(argc, argv); app->setOrganizationName(QStringLiteral("net.attah")); @@ -53,5 +44,4 @@ int main(int argc, char *argv[]) view->setSource(SailfishApp::pathToMainQml()); view->show(); return app->exec(); - } diff --git a/src/ippprinter.h b/src/ippprinter.h index e4513b6..dee3f3c 100644 --- a/src/ippprinter.h +++ b/src/ippprinter.h @@ -5,7 +5,7 @@ #include #include "ippmsg.h" #include "convertworker.h" -#include "curliodevice.h" +#include "curlrequester.h" #include class IppPrinter : public QObject