From e4effbc29a95f3e55bc43da162c25c47747ab6cb Mon Sep 17 00:00:00 2001 From: Jakub Melka Date: Tue, 28 Jan 2020 19:17:45 +0100 Subject: [PATCH] Inverting colors feature --- .../sources/pdfdrawspacecontroller.cpp | 4 ++ PdfForQtLib/sources/pdfpainter.cpp | 47 +++++++++++++++++++ PdfForQtLib/sources/pdfpainter.h | 17 ++++--- PdfForQtLib/sources/pdfpattern.cpp | 10 ++++ PdfForQtLib/sources/pdfpattern.h | 3 ++ PdfForQtLib/sources/pdfrenderer.cpp | 8 +++- PdfForQtLib/sources/pdfrenderer.h | 3 +- PdfForQtLib/sources/pdfutils.h | 16 +++++++ PdfForQtViewer/pdfviewermainwindow.cpp | 4 +- PdfForQtViewer/pdfviewermainwindow.ui | 10 ++++ 10 files changed, 112 insertions(+), 10 deletions(-) diff --git a/PdfForQtLib/sources/pdfdrawspacecontroller.cpp b/PdfForQtLib/sources/pdfdrawspacecontroller.cpp index 7526171..17c1bee 100644 --- a/PdfForQtLib/sources/pdfdrawspacecontroller.cpp +++ b/PdfForQtLib/sources/pdfdrawspacecontroller.cpp @@ -600,6 +600,10 @@ void PDFDrawWidgetProxy::draw(QPainter* painter, QRect rect) // Use current paper color (it can be a bit different from white) QColor paperColor = getCMSManager()->getCurrentCMS()->getPaperColor(); + if (m_features.testFlag(PDFRenderer::InvertColors)) + { + paperColor = invertColor(paperColor); + } // Iterate trough pages and display them on the painter device for (const LayoutItem& item : m_layout.items) diff --git a/PdfForQtLib/sources/pdfpainter.cpp b/PdfForQtLib/sources/pdfpainter.cpp index 67b06b7..f151b51 100644 --- a/PdfForQtLib/sources/pdfpainter.cpp +++ b/PdfForQtLib/sources/pdfpainter.cpp @@ -17,6 +17,7 @@ #include "pdfpainter.h" #include "pdfpattern.h" +#include "pdfcms.h" #include @@ -389,6 +390,20 @@ void PDFPainter::setCompositionMode(QPainter::CompositionMode mode) m_painter->setCompositionMode(mode); } +PDFPrecompiledPageGenerator::PDFPrecompiledPageGenerator(PDFPrecompiledPage* precompiledPage, + PDFRenderer::Features features, + const PDFPage* page, + const PDFDocument* document, + const PDFFontCache* fontCache, + const PDFCMS* cms, + const PDFOptionalContentActivity* optionalContentActivity, + const PDFMeshQualitySettings& meshQualitySettings) : + BaseClass(features, page, document, fontCache, cms, optionalContentActivity, QMatrix(), meshQualitySettings), + m_precompiledPage(precompiledPage) +{ + m_precompiledPage->setPaperColor(cms->getPaperColor()); +} + void PDFPrecompiledPageGenerator::performPathPainting(const QPainterPath& path, bool stroke, bool fill, bool text, Qt::FillRule fillRule) { Q_ASSERT(stroke || fill); @@ -632,6 +647,38 @@ void PDFPrecompiledPage::optimize() m_compositionModes.shrink_to_fit(); } +void PDFPrecompiledPage::invertColors() +{ + // Jakub Melka: we must invert colors in following areas: + // - painter paths + // - images + // - meshes + + for (PathPaintData& pathData : m_paths) + { + if (pathData.pen.style() != Qt::NoPen) + { + pathData.pen.setColor(invertColor(pathData.pen.color())); + } + if (pathData.brush.style() == Qt::SolidPattern) + { + pathData.brush.setColor(invertColor(pathData.brush.color())); + } + } + + for (ImageData& imageData : m_images) + { + imageData.image.invertPixels(QImage::InvertRgb); + } + + for (MeshPaintData& meshPaintData : m_meshes) + { + meshPaintData.mesh.invertColors(); + } + + m_paperColor = invertColor(m_paperColor); +} + void PDFPrecompiledPage::finalize(qint64 compilingTimeNS, QList errors) { m_compilingTimeNS = compilingTimeNS; diff --git a/PdfForQtLib/sources/pdfpainter.h b/PdfForQtLib/sources/pdfpainter.h index d007de4..f70c316 100644 --- a/PdfForQtLib/sources/pdfpainter.h +++ b/PdfForQtLib/sources/pdfpainter.h @@ -199,6 +199,9 @@ public: /// Optimizes page memory allocation to contain less space void optimize(); + /// Inverts all colors + void invertColors(); + /// Finalizes precompiled page /// \param compilingTimeNS Compiling time in nanoseconds /// \param errors List of rendering errors @@ -216,6 +219,10 @@ public: /// Returns memory consumption estimate qint64 getMemoryConsumptionEstimate() const { return m_memoryConsumptionEstimate; } + /// Returns paper color + QColor getPaperColor() const { return m_paperColor; } + void setPaperColor(QColor paperColor) { m_paperColor = paperColor; } + private: struct PathPaintData { @@ -275,6 +282,7 @@ private: qint64 m_compilingTimeNS = 0; qint64 m_memoryConsumptionEstimate = 0; + QColor m_paperColor = QColor(Qt::white); std::vector m_instructions; std::vector m_paths; std::vector m_clips; @@ -287,7 +295,7 @@ private: /// Processor, which processes PDF's page commands and writes them to the precompiled page. /// Precompiled page then can be used to execute these commands on QPainter. -class PDFPrecompiledPageGenerator : public PDFPainterBase +class PDFFORQTLIBSHARED_EXPORT PDFPrecompiledPageGenerator : public PDFPainterBase { using BaseClass = PDFPainterBase; @@ -299,12 +307,7 @@ public: const PDFFontCache* fontCache, const PDFCMS* cms, const PDFOptionalContentActivity* optionalContentActivity, - const PDFMeshQualitySettings& meshQualitySettings) : - BaseClass(features, page, document, fontCache, cms, optionalContentActivity, QMatrix(), meshQualitySettings), - m_precompiledPage(precompiledPage) - { - - } + const PDFMeshQualitySettings& meshQualitySettings); protected: virtual void performPathPainting(const QPainterPath& path, bool stroke, bool fill, bool text, Qt::FillRule fillRule) override; diff --git a/PdfForQtLib/sources/pdfpattern.cpp b/PdfForQtLib/sources/pdfpattern.cpp index 59e1a79..c03df65 100644 --- a/PdfForQtLib/sources/pdfpattern.cpp +++ b/PdfForQtLib/sources/pdfpattern.cpp @@ -1106,6 +1106,16 @@ qint64 PDFMesh::getMemoryConsumptionEstimate() const return memoryConsumption; } +void PDFMesh::invertColors() +{ + for (Triangle& triangle : m_triangles) + { + triangle.color = 0x00FFFFFF - triangle.color; + } + + m_backgroundColor = invertColor(m_backgroundColor); +} + void PDFMeshQualitySettings::initResolution() { Q_ASSERT(deviceSpaceMeshingArea.isValid()); diff --git a/PdfForQtLib/sources/pdfpattern.h b/PdfForQtLib/sources/pdfpattern.h index ffee0fa..a718811 100644 --- a/PdfForQtLib/sources/pdfpattern.h +++ b/PdfForQtLib/sources/pdfpattern.h @@ -143,6 +143,9 @@ public: /// Returns estimate of number of bytes, which this mesh occupies in memory qint64 getMemoryConsumptionEstimate() const; + /// Invert colors + void invertColors(); + private: std::vector m_vertices; std::vector m_triangles; diff --git a/PdfForQtLib/sources/pdfrenderer.cpp b/PdfForQtLib/sources/pdfrenderer.cpp index 38e7a0e..880021b 100644 --- a/PdfForQtLib/sources/pdfrenderer.cpp +++ b/PdfForQtLib/sources/pdfrenderer.cpp @@ -144,6 +144,12 @@ void PDFRenderer::compile(PDFPrecompiledPage* precompiledPage, size_t pageIndex) PDFPrecompiledPageGenerator generator(precompiledPage, m_features, page, m_document, m_fontCache, m_cms, m_optionalContentActivity, m_meshQualitySettings); QList errors = generator.processContents(); + + if (m_features.testFlag(InvertColors)) + { + precompiledPage->invertColors(); + } + precompiledPage->optimize(); precompiledPage->finalize(timer.nsecsElapsed(), qMove(errors)); timer.invalidate(); @@ -214,7 +220,7 @@ QImage PDFRasterizer::render(const PDFPage* page, const PDFPrecompiledPage* comp { QOpenGLPaintDevice device(size); QPainter painter(&device); - painter.fillRect(QRect(QPoint(0, 0), size), Qt::white); + painter.fillRect(QRect(QPoint(0, 0), size), compiledPage->getPaperColor()); compiledPage->draw(&painter, page->getCropBox(), matrix, features); } diff --git a/PdfForQtLib/sources/pdfrenderer.h b/PdfForQtLib/sources/pdfrenderer.h index 296b2f5..556d045 100644 --- a/PdfForQtLib/sources/pdfrenderer.h +++ b/PdfForQtLib/sources/pdfrenderer.h @@ -50,7 +50,8 @@ public: ClipToCropBox = 0x0010, ///< Clip page content to crop box (items outside crop box will not be visible) DisplayTimes = 0x0020, ///< Display page compile/draw time DebugTextBlocks = 0x0040, ///< Debug text block layout algorithm - DebugTextLines = 0x0080 ///< Debug text line layout algorithm + DebugTextLines = 0x0080, ///< Debug text line layout algorithm + InvertColors = 0x0100, ///< Invert colors }; Q_DECLARE_FLAGS(Features, Feature) diff --git a/PdfForQtLib/sources/pdfutils.h b/PdfForQtLib/sources/pdfutils.h index d0de67a..35a6b98 100644 --- a/PdfForQtLib/sources/pdfutils.h +++ b/PdfForQtLib/sources/pdfutils.h @@ -22,6 +22,7 @@ #include "pdfglobal.h" #include +#include #include #include @@ -429,6 +430,21 @@ constexpr bool isRectangleHorizontallyOverlapped(const QRectF& r1, const QRectF& return isIntervalOverlap(r1.left(), r1.right(), r2.left(), r2.right()); } +inline QColor invertColor(QColor color) +{ + qreal r = 0.0; + qreal g = 0.0; + qreal b = 0.0; + qreal a = 0.0; + + color.getRgbF(&r, &g, &b, &a); + + r = 1.0 - r; + g = 1.0 - g; + b = 1.0 - b; + return QColor::fromRgbF(r, g, b, a); +} + } // namespace pdf #endif // PDFUTILS_H diff --git a/PdfForQtViewer/pdfviewermainwindow.cpp b/PdfForQtViewer/pdfviewermainwindow.cpp index faf1aa2..4383c5e 100644 --- a/PdfForQtViewer/pdfviewermainwindow.cpp +++ b/PdfForQtViewer/pdfviewermainwindow.cpp @@ -212,6 +212,7 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) : ui->actionRenderOptionTextAntialiasing->setData(pdf::PDFRenderer::TextAntialiasing); ui->actionRenderOptionSmoothPictures->setData(pdf::PDFRenderer::SmoothImages); ui->actionRenderOptionIgnoreOptionalContentSettings->setData(pdf::PDFRenderer::IgnoreOptionalContent); + ui->actionInvertColors->setData(pdf::PDFRenderer::InvertColors); ui->actionShow_Text_Blocks->setData(pdf::PDFRenderer::DebugTextBlocks); ui->actionShow_Text_Lines->setData(pdf::PDFRenderer::DebugTextLines); @@ -970,7 +971,8 @@ std::vector PDFViewerMainWindow::getRenderingOptionActions() const ui->actionRenderOptionSmoothPictures, ui->actionRenderOptionIgnoreOptionalContentSettings, ui->actionShow_Text_Blocks, - ui->actionShow_Text_Lines }; + ui->actionShow_Text_Lines, + ui->actionInvertColors }; } QList PDFViewerMainWindow::getActions() const diff --git a/PdfForQtViewer/pdfviewermainwindow.ui b/PdfForQtViewer/pdfviewermainwindow.ui index c1a5034..64eee00 100644 --- a/PdfForQtViewer/pdfviewermainwindow.ui +++ b/PdfForQtViewer/pdfviewermainwindow.ui @@ -74,6 +74,8 @@ + + @@ -409,6 +411,14 @@ Copy text + + + true + + + Invert Colors + +