Inverting colors feature

This commit is contained in:
Jakub Melka 2020-01-28 19:17:45 +01:00
parent 0bc64494fd
commit e4effbc29a
10 changed files with 112 additions and 10 deletions

View File

@ -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)

View File

@ -17,6 +17,7 @@
#include "pdfpainter.h"
#include "pdfpattern.h"
#include "pdfcms.h"
#include <QPainter>
@ -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<PDFRenderError> errors)
{
m_compilingTimeNS = compilingTimeNS;

View File

@ -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<Instruction> m_instructions;
std::vector<PathPaintData> m_paths;
std::vector<ClipData> 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;

View File

@ -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());

View File

@ -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<QPointF> m_vertices;
std::vector<Triangle> m_triangles;

View File

@ -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<PDFRenderError> 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);
}

View File

@ -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)

View File

@ -22,6 +22,7 @@
#include "pdfglobal.h"
#include <QRectF>
#include <QColor>
#include <QByteArray>
#include <QDataStream>
@ -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

View File

@ -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<QAction*> PDFViewerMainWindow::getRenderingOptionActions() const
ui->actionRenderOptionSmoothPictures,
ui->actionRenderOptionIgnoreOptionalContentSettings,
ui->actionShow_Text_Blocks,
ui->actionShow_Text_Lines };
ui->actionShow_Text_Lines,
ui->actionInvertColors };
}
QList<QAction*> PDFViewerMainWindow::getActions() const

View File

@ -74,6 +74,8 @@
<addaction name="actionFitPage"/>
<addaction name="actionFitWidth"/>
<addaction name="actionFitHeight"/>
<addaction name="separator"/>
<addaction name="actionInvertColors"/>
</widget>
<widget class="QMenu" name="menuTools">
<property name="title">
@ -409,6 +411,14 @@
<string>Copy text</string>
</property>
</action>
<action name="actionInvertColors">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Invert Colors</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>