diff --git a/src/core/config/common.pri b/src/core/config/common.pri index 7a9656fca8fee06a5a1c7eb256e05a45d50f8551..b5bb23684f1db0e150fb53aa2f0dbeba099824e5 100644 --- a/src/core/config/common.pri +++ b/src/core/config/common.pri @@ -2,8 +2,6 @@ # Trigger Qt-specific build conditions. GYP_CONFIG += use_qt=1 -# Enable printing. We enable preview because we use preview logic even if we don't support preview. -GYP_CONFIG += enable_basic_printing=1 enable_print_preview=1 # We do not want to ship more external binary blobs, so let v8 embed its startup data. GYP_CONFIG += v8_use_external_startup_data=0 # WebSpeech requires Google API keys and adds dependencies on speex and flac. diff --git a/src/core/config/desktop_linux.pri b/src/core/config/desktop_linux.pri index e28d7eb7c0d06d1c75a11e28202e399c1b17b756..23044619b5d5cfbb6977636f2c893670f094d3e2 100644 --- a/src/core/config/desktop_linux.pri +++ b/src/core/config/desktop_linux.pri @@ -5,6 +5,8 @@ include(linux.pri) GYP_CONFIG += \ desktop_linux=1 \ enable_widevine=1 \ + enable_basic_printing=1 \ + enable_print_preview=1 \ enable_pdf=1 clang { diff --git a/src/core/config/mac_osx.pri b/src/core/config/mac_osx.pri index be037cbde5b334746524f8bff7277e5a4a0cf081..4111236eda510ba44f129e70ab7b816e558d0413 100644 --- a/src/core/config/mac_osx.pri +++ b/src/core/config/mac_osx.pri @@ -26,6 +26,8 @@ GYP_CONFIG += \ make_clang_dir=\"$${QMAKE_CLANG_DIR}\" \ clang_use_chrome_plugins=0 \ enable_widevine=1 \ + enable_basic_printing=1 \ + enable_print_preview=1 \ enable_pdf=1 # Force touch API is used in 49-based Chromium, which is included starting with 10.10.3 SDK, so we diff --git a/src/core/config/windows.pri b/src/core/config/windows.pri index 5b9551b5a40d5ef6ff9cac8bdfa8e953e2d4781e..7f87e885d1db744da094dbbe4ed1aaa860e09487 100644 --- a/src/core/config/windows.pri +++ b/src/core/config/windows.pri @@ -7,6 +7,8 @@ GYP_CONFIG += \ remoting=0 \ use_ash=0 \ enable_widevine=1 \ + enable_basic_printing=1 \ + enable_print_preview=1 \ enable_pdf=1 # Libvpx build needs additional search path on Windows. diff --git a/src/core/core_common.pri b/src/core/core_common.pri index 721e8c71a820deb7aec6034c1cecc524c9ac634b..9c29aea718dffe4158a2625d3db091b8e303a461 100644 --- a/src/core/core_common.pri +++ b/src/core/core_common.pri @@ -10,4 +10,3 @@ CHROMIUM_SRC_DIR = $$QTWEBENGINE_ROOT/$$getChromiumSrcDir() INCLUDEPATH += $$CHROMIUM_SRC_DIR qtHaveModule(positioning):QT += positioning -qtHaveModule(printsupport):QT += printsupport diff --git a/src/core/core_gyp_generator.pro b/src/core/core_gyp_generator.pro index 81dea855a5656224275b3d94ecec9bdc43662d1c..a09683ba6f6cca85d6b243ca4edde6dcfb53a385 100644 --- a/src/core/core_gyp_generator.pro +++ b/src/core/core_gyp_generator.pro @@ -75,6 +75,7 @@ SOURCES = \ native_web_keyboard_event_qt.cpp \ network_delegate_qt.cpp \ ozone_platform_eglfs.cpp \ + pdfium_document_wrapper_qt.cpp \ permission_manager_qt.cpp \ process_main.cpp \ proxy_config_service_qt.cpp \ @@ -155,6 +156,7 @@ HEADERS = \ media_capture_devices_dispatcher.h \ network_delegate_qt.h \ ozone_platform_eglfs.h \ + pdfium_document_wrapper_qt.h \ permission_manager_qt.h \ process_main.h \ proxy_config_service_qt.h \ @@ -211,8 +213,3 @@ qtHaveModule(positioning) { HEADERS += location_provider_qt.h DEFINES += QT_USE_POSITIONING=1 } - -qtHaveModule(printsupport) { - SOURCES += pdfium_printing_wrapper_qt.cpp - HEADERS += pdfium_printing_wrapper_qt.h -} diff --git a/src/core/pdfium_printing_wrapper_qt.cpp b/src/core/pdfium_document_wrapper_qt.cpp similarity index 53% rename from src/core/pdfium_printing_wrapper_qt.cpp rename to src/core/pdfium_document_wrapper_qt.cpp index fceb381af24ddda06f785f36f43ba2bf31b7be4b..7c43c77db5ec9e0abb48916ef672e410a0b00a91 100644 --- a/src/core/pdfium_printing_wrapper_qt.cpp +++ b/src/core/pdfium_document_wrapper_qt.cpp @@ -36,23 +36,22 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - -#include "pdfium_printing_wrapper_qt.h" +#if defined (ENABLE_PDF) +#include "pdfium_document_wrapper_qt.h" #include <QtCore/qhash.h> #include <QtGui/qimage.h> #include <QtGui/qpainter.h> -#include <QtPrintSupport/qprinter.h> #include "third_party/pdfium/public/fpdf_doc.h" #include "third_party/pdfium/public/fpdfview.h" namespace QtWebEngineCore { -int PdfiumPrintingWrapperQt::m_libraryUsers = 0; +int PdfiumDocumentWrapperQt::m_libraryUsers = 0; -class PDFiumPageWrapper { +class QWEBENGINE_EXPORT PdfiumPageWrapperQt { public: - PDFiumPageWrapper(void *data, int pageIndex, int targetWidth, int targetHeight) + PdfiumPageWrapperQt(void *data, int pageIndex, int targetWidth, int targetHeight) : m_pageData(FPDF_LoadPage(data, pageIndex)) , m_width(FPDF_GetPageWidth(m_pageData)) , m_height(FPDF_GetPageHeight(m_pageData)) @@ -61,7 +60,7 @@ public: { } - PDFiumPageWrapper() + PdfiumPageWrapperQt() : m_pageData(nullptr) , m_width(-1) , m_height(-1) @@ -70,7 +69,7 @@ public: { } - virtual ~PDFiumPageWrapper() + virtual ~PdfiumPageWrapperQt() { FPDF_ClosePage(m_pageData); } @@ -125,111 +124,49 @@ private: }; -PdfiumPrintingWrapperQt::PdfiumPrintingWrapperQt(const void *pdfData, size_t size, const char *password) +PdfiumDocumentWrapperQt::PdfiumDocumentWrapperQt(const void *pdfData, size_t size, const QSize& imageSize, const char *password) + : m_imageSize(imageSize * 2.0) { - Q_ASSERT(pdfData); - Q_ASSERT(size); - if (m_libraryUsers++ == 0) - FPDF_InitLibrary(); + Q_ASSERT(pdfData); + Q_ASSERT(size); + if (m_libraryUsers++ == 0) + FPDF_InitLibrary(); - m_documentHandle = FPDF_LoadMemDocument(pdfData, static_cast<int>(size), password); - m_pageCount = FPDF_GetPageCount(m_documentHandle); + m_documentHandle = FPDF_LoadMemDocument(pdfData, static_cast<int>(size), password); + m_pageCount = FPDF_GetPageCount(m_documentHandle); } -bool PdfiumPrintingWrapperQt::printOnPrinter(QPrinter &printer) +QImage PdfiumDocumentWrapperQt::pageAsQImage(size_t index) { if (!m_documentHandle || !m_pageCount) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) - qWarning("Failure to print on printer %ls: invalid document.\n", qUtf16Printable(printer.printerName())); -#endif - return false; - } - - int toPage = printer.toPage(); - int fromPage = printer.fromPage(); - bool ascendingOrder = true; - - if (fromPage == 0 && toPage == 0) { - fromPage = 1; - toPage = m_pageCount; + qWarning("Failure to generate QImage from invalid or empty PDF document."); + return QImage(); } - fromPage = qMax(1, fromPage); - toPage = qMin(m_pageCount, toPage); - if (printer.pageOrder() == QPrinter::LastPageFirst) { - qSwap(fromPage, toPage); - ascendingOrder = false; + if (static_cast<int>(index) >= m_pageCount) { + qWarning("Failure to generate QImage from PDF data: index out of bounds."); + return QImage(); } - int documentCopies = printer.copyCount(); - int pageCopies = 1; - if (printer.collateCopies()) { - pageCopies = documentCopies; - documentCopies = 1; + PdfiumPageWrapperQt *pageWrapper = nullptr; + if (!m_cachedPages.contains(index)) { + pageWrapper = new PdfiumPageWrapperQt(m_documentHandle, index, + m_imageSize.width(), m_imageSize.height()); + m_cachedPages.insert(index, pageWrapper); + } else { + pageWrapper = m_cachedPages.value(index); } - QRect printerPageRect = printer.pageRect(); - int doubledPrinterWidth = 2 * printerPageRect.width(); - int doubledPrinterHeight = 2 * printerPageRect.height(); - - QPainter painter; - if (!painter.begin(&printer)) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) - qWarning("Failure to print on printer %ls: Could not open printer for painting.\n", qUtf16Printable(printer.printerName())); -#endif - return false; - } - - QHash<int, PDFiumPageWrapper*> cachedPages; - for (int printedDocuments = 0; printedDocuments < documentCopies; printedDocuments++) { - int currentPageIndex = fromPage; - while (true) { - for (int printedPages = 0; printedPages < pageCopies; printedPages++) { - if (printer.printerState() == QPrinter::Aborted - || printer.printerState() == QPrinter::Error) - return false; - - PDFiumPageWrapper *currentPageWrapper; - if (!cachedPages.contains(currentPageIndex - 1)) { - currentPageWrapper - = new PDFiumPageWrapper(m_documentHandle, currentPageIndex - 1 - , doubledPrinterWidth, doubledPrinterHeight); - cachedPages.insert(currentPageIndex - 1, currentPageWrapper); - } else { - currentPageWrapper = cachedPages.value(currentPageIndex - 1); - } - - QImage currentImage = currentPageWrapper->image(); - painter.drawImage(printerPageRect, currentImage, currentImage.rect()); - if (printedPages < pageCopies - 1) - printer.newPage(); - } - - if (currentPageIndex == toPage) - break; - - if (ascendingOrder) - currentPageIndex++; - else - currentPageIndex--; - - printer.newPage(); - } - if (printedDocuments < documentCopies - 1) - printer.newPage(); - } - painter.end(); - - qDeleteAll(cachedPages); - - return true; + return pageWrapper->image(); } -PdfiumPrintingWrapperQt::~PdfiumPrintingWrapperQt() +PdfiumDocumentWrapperQt::~PdfiumDocumentWrapperQt() { + qDeleteAll(m_cachedPages); FPDF_CloseDocument(m_documentHandle); if (--m_libraryUsers == 0) FPDF_DestroyLibrary(); } } +#endif // defined (ENABLE_PDF) diff --git a/src/core/pdfium_printing_wrapper_qt.h b/src/core/pdfium_document_wrapper_qt.h similarity index 78% rename from src/core/pdfium_printing_wrapper_qt.h rename to src/core/pdfium_document_wrapper_qt.h index 3aaf2b461a0b0394ee0b697e2a8535859cf4e06e..42ac94a28bbedf84367d72a83033f078badf8593 100644 --- a/src/core/pdfium_printing_wrapper_qt.h +++ b/src/core/pdfium_document_wrapper_qt.h @@ -37,30 +37,35 @@ ** ****************************************************************************/ -#ifndef PDFIUM_PRINTING_WRAPPER_QT_H -#define PDFIUM_PRINTING_WRAPPER_QT_H +#ifndef PDFIUM_DOCUMENT_WRAPPER_QT_H +#define PDFIUM_DOCUMENT_WRAPPER_QT_H -#include <QtCore/qglobal.h> +#if defined(ENABLE_PDF) +#include "qtwebenginecoreglobal.h" -QT_BEGIN_NAMESPACE -class QPrinter; -QT_END_NAMESPACE +#include <QtCore/qglobal.h> +#include <QtCore/qhash.h> +#include <QtGui/qimage.h> namespace QtWebEngineCore { +class PdfiumPageWrapperQt; -class PdfiumPrintingWrapperQt +class QWEBENGINE_EXPORT PdfiumDocumentWrapperQt { public: - PdfiumPrintingWrapperQt(const void *pdfData, size_t size, const char *password = nullptr); - virtual ~PdfiumPrintingWrapperQt(); - bool printOnPrinter(QPrinter &printer); + PdfiumDocumentWrapperQt(const void *pdfData, size_t size, const QSize &imageSize, const char *password = nullptr); + virtual ~PdfiumDocumentWrapperQt(); + QImage pageAsQImage(size_t index); int pageCount() const { return m_pageCount; } private: static int m_libraryUsers; - void *m_documentHandle; int m_pageCount; + void *m_documentHandle; + QSize m_imageSize; + QHash<int, PdfiumPageWrapperQt*> m_cachedPages; }; } // namespace QtWebEngineCore -#endif // PDFIUM_PRINTING_WRAPPER_QT_H +#endif // defined (ENABLE_PDF) +#endif // PDFIUM_DOCUMENT_WRAPPER_QT_H diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index fadbd6d2eecb7ac66c5ff3c7de49790d1605a190..cafaad93de1cf29f207cbc4529aeb6dc2478301c 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -50,7 +50,7 @@ #include "browser_context_qt.h" #include "download_manager_delegate_qt.h" #include "media_capture_devices_dispatcher.h" -#include "pdfium_printing_wrapper_qt.h" +#include "pdfium_document_wrapper_qt.h" #include "print_view_manager_qt.h" #include "qwebenginecallback_p.h" #include "renderer_host/web_channel_ipc_transport_host.h" @@ -92,9 +92,6 @@ #include <QtGui/qaccessible.h> #include <QtGui/qdrag.h> #include <QtGui/qpixmap.h> -#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) -#include <QtPrintSupport/qprinter.h> -#endif // QT_NO_PRINTER #include <QtWebChannel/QWebChannel> namespace QtWebEngineCore { @@ -188,21 +185,9 @@ static void callbackOnEvaluateJS(WebContentsAdapterClient *adapterClient, quint6 static void callbackOnPrintingFinished(WebContentsAdapterClient *adapterClient, int requestId, const std::vector<char>& result) { - if (requestId) { + if (requestId) adapterClient->didPrintPage(requestId, QByteArray(result.data(), result.size())); - } -} - -#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) -static void callbackOnPrintingOnPrinterFinished(WebContentsAdapterClient *adapterClient, int requestId, QPrinter *printer, const std::vector<char> &result) -{ - if (requestId) { - PdfiumPrintingWrapperQt printWrapper(result.data(), result.size()); - bool printerResult = printWrapper.printOnPrinter(*printer); - adapterClient->didPrintPageOnPrinter(requestId, printerResult); - } } -#endif // QT_NO_PRINTER static content::WebContents *createBlankWebContents(WebContentsAdapterClient *adapterClient, content::BrowserContext *browserContext) { @@ -978,14 +963,14 @@ void WebContentsAdapter::printToPDF(const QPageLayout &pageLayout, const QString #endif // if defined(ENABLE_BASIC_PRINTING) } -quint64 WebContentsAdapter::printToPDFCallbackResult(const QPageLayout &pageLayout) +quint64 WebContentsAdapter::printToPDFCallbackResult(const QPageLayout &pageLayout, const bool colorMode) { #if defined(ENABLE_BASIC_PRINTING) Q_D(WebContentsAdapter); PrintViewManagerQt::PrintToPDFCallback callback = base::Bind(&callbackOnPrintingFinished , d->adapterClient , d->nextRequestId); - PrintViewManagerQt::FromWebContents(webContents())->PrintToPDFWithCallback(pageLayout, true + PrintViewManagerQt::FromWebContents(webContents())->PrintToPDFWithCallback(pageLayout, colorMode , callback); return d->nextRequestId++; #else @@ -993,23 +978,6 @@ quint64 WebContentsAdapter::printToPDFCallbackResult(const QPageLayout &pageLayo #endif // if defined(ENABLE_BASIC_PRINTING) } -#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) -quint64 WebContentsAdapter::printOnPrinterCallbackResult(QPrinter *printer) -{ -#if defined(ENABLE_BASIC_PRINTING) - Q_D(WebContentsAdapter); - PrintViewManagerQt::PrintToPDFCallback callback - = base::Bind(&callbackOnPrintingOnPrinterFinished, d->adapterClient - , d->nextRequestId, printer); - PrintViewManagerQt::FromWebContents(webContents())->PrintToPDFWithCallback( - printer->pageLayout(), printer->colorMode() == QPrinter::Color, callback); - return d->nextRequestId++; -#else - return 0; -#endif // if defined(ENABLE_BASIC_PRINTING) -} -#endif // QT_NO_PRINTER - QPointF WebContentsAdapter::lastScrollOffset() const { Q_D(const WebContentsAdapter); diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index 7a109770ed5e5fbfb7bcd21140b791ba9f6117cf..3befe6d278c78c8688de4a82ab2570126b700ec9 100644 --- a/src/core/web_contents_adapter.h +++ b/src/core/web_contents_adapter.h @@ -58,9 +58,6 @@ class QAccessibleInterface; class QDragEnterEvent; class QDragMoveEvent; class QPageLayout; -#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) -class QPrinter; -#endif // QT_NO_PRINTER class QString; class QWebChannel; QT_END_NAMESPACE @@ -175,11 +172,7 @@ public: void leaveDrag(); void initUpdateDragCursorMessagePollingTimer(); void printToPDF(const QPageLayout&, const QString&); - quint64 printToPDFCallbackResult(const QPageLayout &); - -#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) - quint64 printOnPrinterCallbackResult(QPrinter *printer); -#endif + quint64 printToPDFCallbackResult(const QPageLayout &, const bool colorMode = true); // meant to be used within WebEngineCore only content::WebContents *webContents() const; diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index 85a3794099f95172598a4880f20d798d3550367c..4e15df7531698c5c9830c6cff997b9c0ac37ec50 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -347,9 +347,6 @@ public: virtual void didFetchDocumentInnerText(quint64 requestId, const QString& result) = 0; virtual void didFindText(quint64 requestId, int matchCount) = 0; virtual void didPrintPage(quint64 requestId, const QByteArray &result) = 0; -#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) - virtual void didPrintPageOnPrinter(quint64 requestId, bool result) = 0; -#endif virtual void passOnFocus(bool reverse) = 0; // returns the last QObject (QWidget/QQuickItem) based object in the accessibility // hierarchy before going into the BrowserAccessibility tree diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index 6ca9954cf6c5a5df5ded4aac62469bb91708ed8c..3830a3ea24ac14c18218620bac55228836c1a2a5 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -1302,16 +1302,19 @@ bool QQuickWebEngineView::recentlyAudible() const void QQuickWebEngineView::printToPdf(const QString& filePath, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation) { +#if defined(ENABLE_PDF) Q_D(const QQuickWebEngineView); QPageSize layoutSize(static_cast<QPageSize::PageSizeId>(pageSizeId)); QPageLayout::Orientation layoutOrientation = static_cast<QPageLayout::Orientation>(orientation); QPageLayout pageLayout(layoutSize, layoutOrientation, QMarginsF(0.0, 0.0, 0.0, 0.0)); d->adapter->printToPDF(pageLayout, filePath); +#endif } void QQuickWebEngineView::printToPdf(const QJSValue &callback, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation) { +#if defined (ENABLE_PDF) Q_D(QQuickWebEngineView); QPageSize layoutSize(static_cast<QPageSize::PageSizeId>(pageSizeId)); QPageLayout::Orientation layoutOrientation = static_cast<QPageLayout::Orientation>(orientation); @@ -1322,6 +1325,13 @@ void QQuickWebEngineView::printToPdf(const QJSValue &callback, PrintedPageSizeId quint64 requestId = d->adapter->printToPDFCallbackResult(pageLayout); d->m_callbacks.insert(requestId, callback); +#else + // Call back with null result. + QJSValueList args; + args.append(QJSValue(QByteArray().data())); + QJSValue callbackCopy = callback; + callbackCopy.call(args); +#endif } void QQuickWebEngineView::replaceMisspelledWord(const QString &replacement) diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index b111e92cd59b4225efdb7a42d8041b0c1fa80ede..d692140ef167debb875576441f31330c33929848 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -123,9 +123,6 @@ public: virtual void didFetchDocumentInnerText(quint64, const QString&) Q_DECL_OVERRIDE { } virtual void didFindText(quint64, int) Q_DECL_OVERRIDE; virtual void didPrintPage(quint64 requestId, const QByteArray &result) Q_DECL_OVERRIDE; -#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) - virtual void didPrintPageOnPrinter(quint64, bool) Q_DECL_OVERRIDE { } -#endif virtual void passOnFocus(bool reverse) Q_DECL_OVERRIDE; virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) Q_DECL_OVERRIDE; virtual void authenticationRequired(QSharedPointer<QtWebEngineCore::AuthenticationDialogController>) Q_DECL_OVERRIDE; diff --git a/src/webengine/webengine.pro b/src/webengine/webengine.pro index 99b9c4e6f5ed09bb5bb1061345a8cc69c8beba90..2bbf8281094e57b60adff0d832bb2fde015d394e 100644 --- a/src/webengine/webengine.pro +++ b/src/webengine/webengine.pro @@ -65,6 +65,10 @@ contains(WEBENGINE_CONFIG, use_spellchecker) { DEFINES += ENABLE_SPELLCHECK } +contains(WEBENGINE_CONFIG, enable_pdf) { + DEFINES += ENABLE_PDF +} + !build_pass { chromium_attributions.commands = \ cd $$shell_quote($$shell_path($$PWD/../3rdparty)) && \ diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index 0188cfef89b2eefb5d3a74b59cf2027a62ca5b82..0b15731cf4f60ba89856569d596a213089583729 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -47,6 +47,7 @@ #include "favicon_manager.h" #include "file_picker_controller.h" #include "javascript_dialog_controller.h" +#include "pdfium_document_wrapper_qt.h" #include "qwebenginefullscreenrequest.h" #include "qwebenginehistory.h" #include "qwebenginehistory_p.h" @@ -79,6 +80,9 @@ #include <QMenu> #include <QMessageBox> #include <QMimeData> +#ifndef QT_NO_PRINTER +#include <QPrinter> +#endif #include <QStandardPaths> #include <QStyle> #include <QTimer> @@ -92,6 +96,83 @@ using namespace QtWebEngineCore; static const int MaxTooltipLength = 1024; +#ifndef QT_NO_PRINTER +#if defined(ENABLE_PDF) +static bool printPdfDataOnPrinter(const QByteArray& data, QPrinter& printer) +{ + QRect printerPageRect = printer.pageRect(); + PdfiumDocumentWrapperQt pdfiumWrapper(data.constData(), data.size(), printerPageRect.size()); + + int toPage = printer.toPage(); + int fromPage = printer.fromPage(); + bool ascendingOrder = true; + + if (fromPage == 0 && toPage == 0) { + fromPage = 1; + toPage = pdfiumWrapper.pageCount(); + } + fromPage = qMax(1, fromPage); + toPage = qMin(pdfiumWrapper.pageCount(), toPage); + + if (printer.pageOrder() == QPrinter::LastPageFirst) { + qSwap(fromPage, toPage); + ascendingOrder = false; + } + + int documentCopies = printer.copyCount(); + int pageCopies = 1; + if (printer.collateCopies()) { + pageCopies = documentCopies; + documentCopies = 1; + } + + QPainter painter; + if (!painter.begin(&printer)) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) + qWarning("Failure to print on printer %ls: Could not open printer for painting.", qUtf16Printable(printer.printerName())); +#else + qWarning("Failure to print on printer %s: Could not open printer for painting.", qPrintable(printer.printerName())); +#endif + return false; + } + + for (int printedDocuments = 0; printedDocuments < documentCopies; printedDocuments++) { + int currentPageIndex = fromPage; + while (true) { + for (int printedPages = 0; printedPages < pageCopies; printedPages++) { + if (printer.printerState() == QPrinter::Aborted + || printer.printerState() == QPrinter::Error) + return false; + + QImage currentImage = pdfiumWrapper.pageAsQImage(currentPageIndex - 1); + if (currentImage.isNull()) + return false; + + painter.drawImage(printerPageRect, currentImage, currentImage.rect()); + if (printedPages < pageCopies - 1) + printer.newPage(); + } + + if (currentPageIndex == toPage) + break; + + if (ascendingOrder) + currentPageIndex++; + else + currentPageIndex--; + + printer.newPage(); + } + if (printedDocuments < documentCopies - 1) + printer.newPage(); + } + painter.end(); + + return true; +} +#endif // defined(ENABLE_PDF) +#endif // QT_NO_PRINTER + static QWebEnginePage::WebWindowType toWindowType(WebContentsAdapterClient::WindowOpenDisposition disposition) { switch (disposition) { @@ -142,6 +223,9 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile) , fullscreenMode(false) , webChannel(nullptr) , webChannelWorldId(QWebEngineScript::MainWorld) +#ifndef QT_NO_PRINTER + , currentPrinter(nullptr) +#endif { memset(actions, 0, sizeof(actions)); } @@ -389,15 +473,27 @@ void QWebEnginePagePrivate::didFindText(quint64 requestId, int matchCount) void QWebEnginePagePrivate::didPrintPage(quint64 requestId, const QByteArray &result) { - m_callbacks.invoke(requestId, result); -} - +#if defined(ENABLE_PDF) #ifndef QT_NO_PRINTER -void QWebEnginePagePrivate::didPrintPageOnPrinter(quint64 requestId, bool result) -{ + // If no currentPrinter is set that means that were printing to PDF only. + if (!currentPrinter) { + m_callbacks.invoke(requestId, result); + return; + } + + bool printerResult = printPdfDataOnPrinter(result, *currentPrinter); + + m_callbacks.invoke(requestId, printerResult); + currentPrinter = nullptr; +#else // If print support is disabled, only PDF printing is available. m_callbacks.invoke(requestId, result); +#endif // ifndef QT_NO_PRINTER +#else // defined(ENABLE_PDF) + // we should never enter this branch, but just for safe-keeping... + Q_UNUSED(result); + m_callbacks.invoke(requestId, QByteArray()); +#endif // defined(ENABLE_PDF) } -#endif void QWebEnginePagePrivate::passOnFocus(bool reverse) { @@ -1844,8 +1940,20 @@ QSizeF QWebEnginePage::contentsSize() const */ void QWebEnginePage::printToPdf(const QString &filePath, const QPageLayout &pageLayout) { +#if defined(ENABLE_PDF) Q_D(const QWebEnginePage); +#ifndef QT_NO_PRINTER + if (d->currentPrinter) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) + qWarning("Cannot print to PDF while at the same time printing on printer %ls", qUtf16Printable(d->currentPrinter->printerName())); +#else + qWarning("Cannot print to PDF while at the same time printing on printer %s", qPrintable(d->currentPrinter->printerName())); +#endif + return; + } +#endif d->adapter->printToPDF(pageLayout, filePath); +#endif // if defined(ENABLE_PDF) } @@ -1863,8 +1971,23 @@ void QWebEnginePage::printToPdf(const QString &filePath, const QPageLayout &page void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &resultCallback, const QPageLayout &pageLayout) { Q_D(QWebEnginePage); +#if defined(ENABLE_PDF) +#ifndef QT_NO_PRINTER + if (d->currentPrinter) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) + qWarning("Cannot print to PDF while at the same time printing on printer %ls", qUtf16Printable(d->currentPrinter->printerName())); +#else + qWarning("Cannot print to PDF while at the same time printing on printer %s", qPrintable(d->currentPrinter->printerName())); +#endif + d->m_callbacks.invokeEmpty(resultCallback); + return; + } +#endif // ifndef QT_NO_PRINTER quint64 requestId = d->adapter->printToPDFCallbackResult(pageLayout); d->m_callbacks.registerCallback(requestId, resultCallback); +#else // if defined(ENABLE_PDF) + d->m_callbacks.invokeEmpty(resultCallback); +#endif // if defined(ENABLE_PDF) } #ifndef QT_NO_PRINTER @@ -1884,8 +2007,22 @@ void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &res void QWebEnginePage::print(QPrinter *printer, const QWebEngineCallback<bool> &resultCallback) { Q_D(QWebEnginePage); - quint64 requestId = d->adapter->printOnPrinterCallbackResult(printer); +#if defined(ENABLE_PDF) + if (d->currentPrinter) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) + qWarning("Cannot print page on printer %ls: Already printing on %ls.", qUtf16Printable(printer->printerName()), qUtf16Printable(d->currentPrinter->printerName())); +#else + qWarning("Cannot print page on printer %s: Already printing on %s.", qPrintable(printer->printerName()), qPrintable(d->currentPrinter->printerName())); +#endif + d->m_callbacks.invokeDirectly(resultCallback, false); + return; + } + d->currentPrinter = printer; + quint64 requestId = d->adapter->printToPDFCallbackResult(printer->pageLayout(), printer->colorMode() == QPrinter::Color); d->m_callbacks.registerCallback(requestId, resultCallback); +#else // if defined(ENABLE_PDF) + d->m_callbacks.invokeDirectly(resultCallback, false); +#endif // if defined(ENABLE_PDF) } #endif // QT_NO_PRINTER diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h index 8d78429d88feddc8344c78daee0c533c4568920d..0ad077a0e1c2f5497e19ada3eb6b2a9295c3d88d 100644 --- a/src/webenginewidgets/api/qwebenginepage_p.h +++ b/src/webenginewidgets/api/qwebenginepage_p.h @@ -119,9 +119,6 @@ public: virtual void didFetchDocumentInnerText(quint64 requestId, const QString& result) Q_DECL_OVERRIDE; virtual void didFindText(quint64 requestId, int matchCount) Q_DECL_OVERRIDE; virtual void didPrintPage(quint64 requestId, const QByteArray &result) Q_DECL_OVERRIDE; -#ifndef QT_NO_PRINTER - virtual void didPrintPageOnPrinter(quint64 requestId, bool result) Q_DECL_OVERRIDE; -#endif virtual void passOnFocus(bool reverse) Q_DECL_OVERRIDE; virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) Q_DECL_OVERRIDE; virtual void authenticationRequired(QSharedPointer<QtWebEngineCore::AuthenticationDialogController>) Q_DECL_OVERRIDE; @@ -181,6 +178,9 @@ public: mutable QtWebEngineCore::CallbackDirectory m_callbacks; mutable QAction *actions[QWebEnginePage::WebActionCount]; +#ifndef QT_NO_PRINTER + QPrinter *currentPrinter; +#endif // QT_NO_PRINTER }; QT_END_NAMESPACE diff --git a/src/webenginewidgets/webenginewidgets.pro b/src/webenginewidgets/webenginewidgets.pro index 64e4754228a3095e66ac0bbc1a37f56438810292..b60de6e1e2af2d08a8d9cf8fd4d212a69200688a 100644 --- a/src/webenginewidgets/webenginewidgets.pro +++ b/src/webenginewidgets/webenginewidgets.pro @@ -52,4 +52,11 @@ contains(WEBENGINE_CONFIG, use_spellchecker) { DEFINES += ENABLE_SPELLCHECK } +contains(WEBENGINE_CONFIG, enable_pdf) { + DEFINES += ENABLE_PDF +} + +qtHaveModule(printsupport) { + QT += printsupport +} load(qt_module) diff --git a/tests/auto/widgets/qwebenginepage/qwebenginepage.pro b/tests/auto/widgets/qwebenginepage/qwebenginepage.pro index 70786e70f9c8b49d8b3d96a457df627f2b3cc04f..df733c473984014b00a48763e40550e5553e9134 100644 --- a/tests/auto/widgets/qwebenginepage/qwebenginepage.pro +++ b/tests/auto/widgets/qwebenginepage/qwebenginepage.pro @@ -1,2 +1,4 @@ include(../tests.pri) QT *= core-private gui-private + +contains(WEBENGINE_CONFIG, enable_pdf): DEFINES+=QWEBENGINEPAGE_PDFPRINTINGENABLED diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index 0b6354cc21b22e9128ab2ba027eef6ffb2a5815b..1377c9a52dcd3f4e4b45f4365dceee0afc430921 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -4895,6 +4895,9 @@ void tst_QWebEnginePage::setZoomFactor() void tst_QWebEnginePage::printToPdf() { +#if !defined(QWEBENGINEPAGE_PDFPRINTINGENABLED) + QSKIP("QWEBENGINEPAGE_PDFPRINTINGENABLED"); +#else QTemporaryDir tempDir(QDir::tempPath() + "/tst_qwebengineview-XXXXXX"); QVERIFY(tempDir.isValid()); QWebEnginePage page; @@ -4922,6 +4925,7 @@ void tst_QWebEnginePage::printToPdf() CallbackSpy<QByteArray> failedInvalidLayoutSpy; page.printToPdf(failedInvalidLayoutSpy.ref(), QPageLayout()); QCOMPARE(failedInvalidLayoutSpy.waitForResult().length(), 0); +#endif } void tst_QWebEnginePage::mouseButtonTranslation() diff --git a/tools/qmake/mkspecs/features/configure.prf b/tools/qmake/mkspecs/features/configure.prf index c6f07e39dfce01241fbc6f046ca7635089e3345e..bb4c56cae7d0bdbae4f44880d5303f36c64fe7da 100644 --- a/tools/qmake/mkspecs/features/configure.prf +++ b/tools/qmake/mkspecs/features/configure.prf @@ -78,6 +78,9 @@ defineTest(runConfigure) { else: log("System NSS not found, BoringSSL will be used.$${EOL}") } } + !cross_compile { + WEBENGINE_CONFIG += enable_pdf + } isQtMinimum(5, 8) { include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri) QT_FOR_CONFIG += webengine-private