mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-05-11 15:28:49 +02:00
Inverting colors feature
This commit is contained in:
parent
0bc64494fd
commit
e4effbc29a
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user