mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Output preview widget (first part)
This commit is contained in:
@ -989,12 +989,13 @@ void PDFTransparencyRenderer::beginPaint(QSize pixelSize)
|
|||||||
Q_ASSERT(m_deviceColorSpace);
|
Q_ASSERT(m_deviceColorSpace);
|
||||||
Q_ASSERT(m_processColorSpace);
|
Q_ASSERT(m_processColorSpace);
|
||||||
|
|
||||||
|
m_originalProcessBitmap = PDFFloatBitmapWithColorSpace();
|
||||||
m_transparencyGroupDataStack.clear();
|
m_transparencyGroupDataStack.clear();
|
||||||
m_painterStateStack.push(PDFTransparencyPainterState());
|
m_painterStateStack.push(PDFTransparencyPainterState());
|
||||||
|
|
||||||
// Initialize initial opaque soft mask
|
// Initialize initial opaque soft mask
|
||||||
PDFFloatBitmap initialSoftMaskBitmap(pixelSize.width(), pixelSize.height(), PDFPixelFormat::createOpacityMask());
|
PDFFloatBitmap initialSoftMaskBitmap;
|
||||||
initialSoftMaskBitmap.makeOpaque();
|
createOpaqueSoftMask(initialSoftMaskBitmap, pixelSize.width(), pixelSize.height());
|
||||||
m_painterStateStack.top().softMask = PDFTransparencySoftMask(true, qMove(initialSoftMaskBitmap));
|
m_painterStateStack.top().softMask = PDFTransparencySoftMask(true, qMove(initialSoftMaskBitmap));
|
||||||
|
|
||||||
PDFPixelFormat pixelFormat = PDFPixelFormat::createFormat(uint8_t(m_deviceColorSpace->getColorComponentCount()),
|
PDFPixelFormat pixelFormat = PDFPixelFormat::createFormat(uint8_t(m_deviceColorSpace->getColorComponentCount()),
|
||||||
@ -1033,6 +1034,7 @@ void PDFTransparencyRenderer::beginPaint(QSize pixelSize)
|
|||||||
m_settings.activeColorMask != PDFPixelFormat::getAllColorsMask());
|
m_settings.activeColorMask != PDFPixelFormat::getAllColorsMask());
|
||||||
m_transparencyGroupDataStack.back().activeColorMask = m_settings.activeColorMask;
|
m_transparencyGroupDataStack.back().activeColorMask = m_settings.activeColorMask;
|
||||||
m_transparencyGroupDataStack.back().transformSpotsToDevice = m_settings.flags.testFlag(PDFTransparencyRendererSettings::SeparationSimulation);
|
m_transparencyGroupDataStack.back().transformSpotsToDevice = m_settings.flags.testFlag(PDFTransparencyRendererSettings::SeparationSimulation);
|
||||||
|
m_transparencyGroupDataStack.back().saveOriginalImage = m_settings.flags.testFlag(PDFTransparencyRendererSettings::SaveOriginalProcessImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
const PDFFloatBitmap& PDFTransparencyRenderer::endPaint()
|
const PDFFloatBitmap& PDFTransparencyRenderer::endPaint()
|
||||||
@ -2524,6 +2526,11 @@ void PDFTransparencyRenderer::performEndTransparencyGroup(ProcessOrder order, co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sourceData.saveOriginalImage)
|
||||||
|
{
|
||||||
|
m_originalProcessBitmap = sourceData.immediateBackdrop;
|
||||||
|
}
|
||||||
|
|
||||||
// Collapse spot colors
|
// Collapse spot colors
|
||||||
if (sourceData.transformSpotsToDevice)
|
if (sourceData.transformSpotsToDevice)
|
||||||
{
|
{
|
||||||
|
@ -136,7 +136,7 @@ private:
|
|||||||
|
|
||||||
/// Represents float bitmap with arbitrary color channel count. Bitmap can also
|
/// Represents float bitmap with arbitrary color channel count. Bitmap can also
|
||||||
/// have auxiliary channels, such as shape and opacity channels.
|
/// have auxiliary channels, such as shape and opacity channels.
|
||||||
class PDFFloatBitmap
|
class Pdf4QtLIBSHARED_EXPORT PDFFloatBitmap
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PDFFloatBitmap();
|
explicit PDFFloatBitmap();
|
||||||
@ -311,7 +311,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Float bitmap with color space
|
/// Float bitmap with color space
|
||||||
class PDFFloatBitmapWithColorSpace : public PDFFloatBitmap
|
class Pdf4QtLIBSHARED_EXPORT PDFFloatBitmapWithColorSpace : public PDFFloatBitmap
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PDFFloatBitmapWithColorSpace();
|
explicit PDFFloatBitmapWithColorSpace();
|
||||||
@ -602,6 +602,11 @@ struct PDFTransparencyRendererSettings
|
|||||||
|
|
||||||
/// Display tiling patterns (if this flag is false, tiling patterns aren't processed)
|
/// Display tiling patterns (if this flag is false, tiling patterns aren't processed)
|
||||||
DisplayTilingPatterns = 0x0200,
|
DisplayTilingPatterns = 0x0200,
|
||||||
|
|
||||||
|
/// Saves process image before it is transformed into device space
|
||||||
|
/// and before separation simulation is applied. Active color mask
|
||||||
|
/// is still applied to this image.
|
||||||
|
SaveOriginalProcessImage = 0x0400,
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_FLAGS(Flags, Flag)
|
Q_DECLARE_FLAGS(Flags, Flag)
|
||||||
@ -671,6 +676,11 @@ public:
|
|||||||
/// \param color Color
|
/// \param color Color
|
||||||
void clearColor(const PDFColor& color);
|
void clearColor(const PDFColor& color);
|
||||||
|
|
||||||
|
/// Returns original process bitmap, before it is transformed into device space,
|
||||||
|
/// and before separation simulation is being processed. Active color mask is still
|
||||||
|
/// applied to this image.
|
||||||
|
PDFFloatBitmapWithColorSpace getOriginalProcessBitmap() const { return m_originalProcessBitmap; }
|
||||||
|
|
||||||
virtual bool isContentKindSuppressed(ContentKind kind) const override;
|
virtual bool isContentKindSuppressed(ContentKind kind) const override;
|
||||||
virtual void performPathPainting(const QPainterPath& path, bool stroke, bool fill, bool text, Qt::FillRule fillRule) override;
|
virtual void performPathPainting(const QPainterPath& path, bool stroke, bool fill, bool text, Qt::FillRule fillRule) override;
|
||||||
virtual bool performPathPaintingUsingShading(const QPainterPath& path, bool stroke, bool fill, const PDFShadingPattern* shadingPattern) override;
|
virtual bool performPathPaintingUsingShading(const QPainterPath& path, bool stroke, bool fill, const PDFShadingPattern* shadingPattern) override;
|
||||||
@ -742,6 +752,7 @@ private:
|
|||||||
bool filterColorsUsingMask = false;
|
bool filterColorsUsingMask = false;
|
||||||
uint32_t activeColorMask = PDFPixelFormat::getAllColorsMask();
|
uint32_t activeColorMask = PDFPixelFormat::getAllColorsMask();
|
||||||
bool transformSpotsToDevice = false;
|
bool transformSpotsToDevice = false;
|
||||||
|
bool saveOriginalImage = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PDFTransparencyPainterState
|
struct PDFTransparencyPainterState
|
||||||
@ -901,6 +912,7 @@ private:
|
|||||||
PDFCachedItem<PDFMappedColor> m_mappedFillColor;
|
PDFCachedItem<PDFMappedColor> m_mappedFillColor;
|
||||||
PDFTransparencyRendererSettings m_settings;
|
PDFTransparencyRendererSettings m_settings;
|
||||||
PDFDrawBuffer m_drawBuffer;
|
PDFDrawBuffer m_drawBuffer;
|
||||||
|
PDFFloatBitmapWithColorSpace m_originalProcessBitmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
@ -28,7 +28,7 @@ int qt_default_dpi_y() { return 96; }
|
|||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
|
|
||||||
int PDFWidgetUtils::getPixelSize(QPaintDevice* device, pdf::PDFReal sizeMM)
|
int PDFWidgetUtils::getPixelSize(const QPaintDevice* device, pdf::PDFReal sizeMM)
|
||||||
{
|
{
|
||||||
const int width = device->width();
|
const int width = device->width();
|
||||||
const int height = device->height();
|
const int height = device->height();
|
||||||
@ -43,21 +43,21 @@ int PDFWidgetUtils::getPixelSize(QPaintDevice* device, pdf::PDFReal sizeMM)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int PDFWidgetUtils::scaleDPI_x(QPaintDevice* device, int unscaledSize)
|
int PDFWidgetUtils::scaleDPI_x(const QPaintDevice* device, int unscaledSize)
|
||||||
{
|
{
|
||||||
const double logicalDPI_x = device->logicalDpiX();
|
const double logicalDPI_x = device->logicalDpiX();
|
||||||
const double defaultDPI_x = qt_default_dpi_x();
|
const double defaultDPI_x = qt_default_dpi_x();
|
||||||
return (logicalDPI_x / defaultDPI_x) * unscaledSize;
|
return (logicalDPI_x / defaultDPI_x) * unscaledSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PDFWidgetUtils::scaleDPI_y(QPaintDevice* device, int unscaledSize)
|
int PDFWidgetUtils::scaleDPI_y(const QPaintDevice* device, int unscaledSize)
|
||||||
{
|
{
|
||||||
const double logicalDPI_y = device->logicalDpiY();
|
const double logicalDPI_y = device->logicalDpiY();
|
||||||
const double defaultDPI_y = qt_default_dpi_y();
|
const double defaultDPI_y = qt_default_dpi_y();
|
||||||
return (logicalDPI_y / defaultDPI_y) * unscaledSize;
|
return (logicalDPI_y / defaultDPI_y) * unscaledSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFReal PDFWidgetUtils::scaleDPI_x(QPaintDevice* device, PDFReal unscaledSize)
|
PDFReal PDFWidgetUtils::scaleDPI_x(const QPaintDevice* device, PDFReal unscaledSize)
|
||||||
{
|
{
|
||||||
const double logicalDPI_x = device->logicalDpiX();
|
const double logicalDPI_x = device->logicalDpiX();
|
||||||
const double defaultDPI_x = qt_default_dpi_x();
|
const double defaultDPI_x = qt_default_dpi_x();
|
||||||
@ -77,7 +77,7 @@ void PDFWidgetUtils::scaleWidget(QWidget* widget, QSize unscaledSize)
|
|||||||
widget->resize(width, height);
|
widget->resize(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize PDFWidgetUtils::scaleDPI(QPaintDevice* widget, QSize unscaledSize)
|
QSize PDFWidgetUtils::scaleDPI(const QPaintDevice* widget, QSize unscaledSize)
|
||||||
{
|
{
|
||||||
const double logicalDPI_x = widget->logicalDpiX();
|
const double logicalDPI_x = widget->logicalDpiX();
|
||||||
const double logicalDPI_y = widget->logicalDpiY();
|
const double logicalDPI_y = widget->logicalDpiY();
|
||||||
|
@ -31,19 +31,19 @@ public:
|
|||||||
PDFWidgetUtils() = delete;
|
PDFWidgetUtils() = delete;
|
||||||
|
|
||||||
/// Converts size in MM to pixel size
|
/// Converts size in MM to pixel size
|
||||||
static int getPixelSize(QPaintDevice* device, pdf::PDFReal sizeMM);
|
static int getPixelSize(const QPaintDevice* device, pdf::PDFReal sizeMM);
|
||||||
|
|
||||||
/// Scale horizontal DPI value
|
/// Scale horizontal DPI value
|
||||||
/// \param device Paint device to obtain logical DPI for scaling
|
/// \param device Paint device to obtain logical DPI for scaling
|
||||||
static int scaleDPI_x(QPaintDevice* device, int unscaledSize);
|
static int scaleDPI_x(const QPaintDevice* device, int unscaledSize);
|
||||||
|
|
||||||
/// Scale vertical DPI value
|
/// Scale vertical DPI value
|
||||||
/// \param device Paint device to obtain logical DPI for scaling
|
/// \param device Paint device to obtain logical DPI for scaling
|
||||||
static int scaleDPI_y(QPaintDevice* device, int unscaledSize);
|
static int scaleDPI_y(const QPaintDevice* device, int unscaledSize);
|
||||||
|
|
||||||
/// Scale horizontal DPI value
|
/// Scale horizontal DPI value
|
||||||
/// \param device Paint device to obtain logical DPI for scaling
|
/// \param device Paint device to obtain logical DPI for scaling
|
||||||
static PDFReal scaleDPI_x(QPaintDevice* device, PDFReal unscaledSize);
|
static PDFReal scaleDPI_x(const QPaintDevice* device, PDFReal unscaledSize);
|
||||||
|
|
||||||
/// Scales widget based on DPI
|
/// Scales widget based on DPI
|
||||||
/// \param widget Widget to be scaled
|
/// \param widget Widget to be scaled
|
||||||
@ -53,7 +53,7 @@ public:
|
|||||||
/// Scales size based on DPI
|
/// Scales size based on DPI
|
||||||
/// \param device Paint device to obtain logical DPI for scaling
|
/// \param device Paint device to obtain logical DPI for scaling
|
||||||
/// \param unscaledSize Unscaled size
|
/// \param unscaledSize Unscaled size
|
||||||
static QSize scaleDPI(QPaintDevice* widget, QSize unscaledSize);
|
static QSize scaleDPI(const QPaintDevice* widget, QSize unscaledSize);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
@ -34,11 +34,13 @@ CONFIG += c++11
|
|||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
outputpreviewdialog.cpp \
|
outputpreviewdialog.cpp \
|
||||||
outputpreviewplugin.cpp
|
outputpreviewplugin.cpp \
|
||||||
|
outputpreviewwidget.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
outputpreviewdialog.h \
|
outputpreviewdialog.h \
|
||||||
outputpreviewplugin.h
|
outputpreviewplugin.h \
|
||||||
|
outputpreviewwidget.h
|
||||||
|
|
||||||
CONFIG += force_debug_info
|
CONFIG += force_debug_info
|
||||||
|
|
||||||
|
@ -44,12 +44,14 @@ OutputPreviewDialog::OutputPreviewDialog(const pdf::PDFDocument* document, pdf::
|
|||||||
ui->pageIndexScrollBar->setValue(1);
|
ui->pageIndexScrollBar->setValue(1);
|
||||||
ui->pageIndexScrollBar->setMaximum(int(document->getCatalog()->getPageCount()));
|
ui->pageIndexScrollBar->setMaximum(int(document->getCatalog()->getPageCount()));
|
||||||
|
|
||||||
ui->displayModeComboBox->addItem(tr("Separations"), Separations);
|
ui->displayModeComboBox->addItem(tr("Separations"), OutputPreviewWidget::Separations);
|
||||||
ui->displayModeComboBox->addItem(tr("Color Warnings | Ink Coverage"), ColorWarningInkCoverage);
|
ui->displayModeComboBox->addItem(tr("Color Warnings | Ink Coverage"), OutputPreviewWidget::ColorWarningInkCoverage);
|
||||||
ui->displayModeComboBox->addItem(tr("Color Warnings | Rich Black"), ColorWarningRichBlack);
|
ui->displayModeComboBox->addItem(tr("Color Warnings | Rich Black"), OutputPreviewWidget::ColorWarningRichBlack);
|
||||||
ui->displayModeComboBox->addItem(tr("Ink Coverage"), InkCoverage);
|
ui->displayModeComboBox->addItem(tr("Ink Coverage"), OutputPreviewWidget::InkCoverage);
|
||||||
ui->displayModeComboBox->setCurrentIndex(0);
|
ui->displayModeComboBox->setCurrentIndex(0);
|
||||||
|
|
||||||
|
ui->imageWidget->setInkMapper(&m_inkMapper);
|
||||||
|
|
||||||
m_inkMapper.createSpotColors(ui->simulateSeparationsCheckBox->isChecked());
|
m_inkMapper.createSpotColors(ui->simulateSeparationsCheckBox->isChecked());
|
||||||
connect(ui->simulateSeparationsCheckBox, &QCheckBox::clicked, this, &OutputPreviewDialog::onSimulateSeparationsChecked);
|
connect(ui->simulateSeparationsCheckBox, &QCheckBox::clicked, this, &OutputPreviewDialog::onSimulateSeparationsChecked);
|
||||||
connect(ui->simulatePaperColorCheckBox, &QCheckBox::clicked, this, &OutputPreviewDialog::onSimulatePaperColorChecked);
|
connect(ui->simulatePaperColorCheckBox, &QCheckBox::clicked, this, &OutputPreviewDialog::onSimulatePaperColorChecked);
|
||||||
@ -208,7 +210,7 @@ void OutputPreviewDialog::updatePageImage()
|
|||||||
const pdf::PDFPage* page = m_document->getCatalog()->getPage(ui->pageIndexScrollBar->value() - 1);
|
const pdf::PDFPage* page = m_document->getCatalog()->getPage(ui->pageIndexScrollBar->value() - 1);
|
||||||
if (!page)
|
if (!page)
|
||||||
{
|
{
|
||||||
ui->imageLabel->setPixmap(QPixmap());
|
ui->imageWidget->clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,9 +257,10 @@ void OutputPreviewDialog::updatePageImage()
|
|||||||
flags.setFlag(pdf::PDFTransparencyRendererSettings::DisplayVectorGraphics, ui->displayVectorGraphicsCheckBox->isChecked());
|
flags.setFlag(pdf::PDFTransparencyRendererSettings::DisplayVectorGraphics, ui->displayVectorGraphicsCheckBox->isChecked());
|
||||||
flags.setFlag(pdf::PDFTransparencyRendererSettings::DisplayShadings, ui->displayShadingCheckBox->isChecked());
|
flags.setFlag(pdf::PDFTransparencyRendererSettings::DisplayShadings, ui->displayShadingCheckBox->isChecked());
|
||||||
flags.setFlag(pdf::PDFTransparencyRendererSettings::DisplayTilingPatterns, ui->displayTilingPatternsCheckBox->isChecked());
|
flags.setFlag(pdf::PDFTransparencyRendererSettings::DisplayTilingPatterns, ui->displayTilingPatternsCheckBox->isChecked());
|
||||||
|
flags.setFlag(pdf::PDFTransparencyRendererSettings::SaveOriginalProcessImage, true);
|
||||||
|
|
||||||
m_inkMapperForRendering = m_inkMapper;
|
m_inkMapperForRendering = m_inkMapper;
|
||||||
QSize renderSize = ui->imageLabel->size();
|
QSize renderSize = ui->imageWidget->getPageImageSizeHint();
|
||||||
auto renderImage = [this, page, renderSize, paperColor, activeColorMask, flags]() -> RenderedImage
|
auto renderImage = [this, page, renderSize, paperColor, activeColorMask, flags]() -> RenderedImage
|
||||||
{
|
{
|
||||||
return renderPage(page, renderSize, paperColor, activeColorMask, flags);
|
return renderPage(page, renderSize, paperColor, activeColorMask, flags);
|
||||||
@ -312,6 +315,8 @@ OutputPreviewDialog::RenderedImage OutputPreviewDialog::renderPage(const pdf::PD
|
|||||||
QImage image = renderer.toImage(false, true, paperColor);
|
QImage image = renderer.toImage(false, true, paperColor);
|
||||||
|
|
||||||
result.image = qMove(image);
|
result.image = qMove(image);
|
||||||
|
result.originalProcessImage = renderer.getOriginalProcessBitmap();
|
||||||
|
result.pageSize = page->getRotatedMediaBoxMM().size();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,7 +331,7 @@ void OutputPreviewDialog::onPageImageRendered()
|
|||||||
m_futureWatcher->deleteLater();
|
m_futureWatcher->deleteLater();
|
||||||
m_futureWatcher = nullptr;
|
m_futureWatcher = nullptr;
|
||||||
|
|
||||||
ui->imageLabel->setPixmap(QPixmap::fromImage(result.image));
|
ui->imageWidget->setPageImage(qMove(result.image), qMove(result.originalProcessImage), result.pageSize);
|
||||||
|
|
||||||
if (m_needUpdateImage)
|
if (m_needUpdateImage)
|
||||||
{
|
{
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "pdfdocument.h"
|
#include "pdfdocument.h"
|
||||||
#include "pdfdrawwidget.h"
|
#include "pdfdrawwidget.h"
|
||||||
#include "pdftransparencyrenderer.h"
|
#include "pdftransparencyrenderer.h"
|
||||||
|
#include "outputpreviewwidget.h"
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QFuture>
|
#include <QFuture>
|
||||||
@ -50,15 +51,6 @@ public:
|
|||||||
virtual void reject() override;
|
virtual void reject() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum DisplayMode
|
|
||||||
{
|
|
||||||
Separations,
|
|
||||||
ColorWarningInkCoverage,
|
|
||||||
ColorWarningRichBlack,
|
|
||||||
InkCoverage
|
|
||||||
};
|
|
||||||
|
|
||||||
void updateInks();
|
void updateInks();
|
||||||
void updatePaperColorWidgets();
|
void updatePaperColorWidgets();
|
||||||
|
|
||||||
@ -70,6 +62,8 @@ private:
|
|||||||
struct RenderedImage
|
struct RenderedImage
|
||||||
{
|
{
|
||||||
QImage image;
|
QImage image;
|
||||||
|
pdf::PDFFloatBitmapWithColorSpace originalProcessImage;
|
||||||
|
QSizeF pageSize;
|
||||||
QList<pdf::PDFRenderError> errors;
|
QList<pdf::PDFRenderError> errors;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,11 +41,7 @@
|
|||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="imageLabel">
|
<widget class="pdfplugin::OutputPreviewWidget" name="imageWidget" native="true"/>
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QScrollBar" name="pageIndexScrollBar">
|
<widget class="QScrollBar" name="pageIndexScrollBar">
|
||||||
@ -320,6 +316,14 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>pdfplugin::OutputPreviewWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>outputpreviewwidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
|
312
Pdf4QtViewerPlugins/OutputPreviewPlugin/outputpreviewwidget.cpp
Normal file
312
Pdf4QtViewerPlugins/OutputPreviewPlugin/outputpreviewwidget.cpp
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
// Copyright (C) 2021 Jakub Melka
|
||||||
|
//
|
||||||
|
// This file is part of Pdf4Qt.
|
||||||
|
//
|
||||||
|
// Pdf4Qt is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Pdf4Qt is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with Pdf4Qt. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include "outputpreviewwidget.h"
|
||||||
|
|
||||||
|
#include "pdfwidgetutils.h"
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QFontMetrics>
|
||||||
|
|
||||||
|
namespace pdfplugin
|
||||||
|
{
|
||||||
|
|
||||||
|
OutputPreviewWidget::OutputPreviewWidget(QWidget* parent) :
|
||||||
|
BaseClass(parent),
|
||||||
|
m_inkMapper(nullptr),
|
||||||
|
m_displayMode(Separations)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize OutputPreviewWidget::sizeHint() const
|
||||||
|
{
|
||||||
|
return pdf::PDFWidgetUtils::scaleDPI(this, QSize(400, 300));
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize OutputPreviewWidget::minimumSizeHint() const
|
||||||
|
{
|
||||||
|
return pdf::PDFWidgetUtils::scaleDPI(this, QSize(200, 200));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OutputPreviewWidget::clear()
|
||||||
|
{
|
||||||
|
m_pageImage = QImage();
|
||||||
|
m_originalProcessBitmap = pdf::PDFFloatBitmapWithColorSpace();
|
||||||
|
m_pageSizeMM = QSizeF();
|
||||||
|
m_infoBoxItems.clear();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OutputPreviewWidget::setPageImage(QImage image, pdf::PDFFloatBitmapWithColorSpace originalProcessBitmap, QSizeF pageSizeMM)
|
||||||
|
{
|
||||||
|
m_pageImage = qMove(image);
|
||||||
|
m_originalProcessBitmap = qMove(originalProcessBitmap);
|
||||||
|
m_pageSizeMM = pageSizeMM;
|
||||||
|
buildInfoBoxItems();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OutputPreviewWidget::paintEvent(QPaintEvent* event)
|
||||||
|
{
|
||||||
|
QPainter painter(this);
|
||||||
|
|
||||||
|
Q_UNUSED(event);
|
||||||
|
|
||||||
|
QRect rect = this->rect();
|
||||||
|
painter.fillRect(rect, Qt::gray);
|
||||||
|
|
||||||
|
QRect contentRect = getContentRect();
|
||||||
|
QRect pageImageRect = getPageImageRect(contentRect);
|
||||||
|
|
||||||
|
if (pageImageRect.isValid() && !m_pageImage.isNull())
|
||||||
|
{
|
||||||
|
painter.save();
|
||||||
|
painter.setClipRect(pageImageRect, Qt::IntersectClip);
|
||||||
|
painter.translate(0, (pageImageRect.height() - m_pageImage.height()) / 2);
|
||||||
|
painter.drawImage(pageImageRect.topLeft(), m_pageImage);
|
||||||
|
painter.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_infoBoxItems.empty())
|
||||||
|
{
|
||||||
|
painter.save();
|
||||||
|
|
||||||
|
int infoBoxWidth = getInfoBoxWidth();
|
||||||
|
int itemHorizontalMargin = getInfoBoxContentHorizontalMargin();
|
||||||
|
|
||||||
|
QRect infoBoxRect = contentRect;
|
||||||
|
infoBoxRect.setLeft(infoBoxRect.right() - infoBoxWidth);
|
||||||
|
|
||||||
|
painter.setPen(Qt::black);
|
||||||
|
painter.setBrush(QBrush(Qt::white));
|
||||||
|
painter.drawRect(infoBoxRect);
|
||||||
|
painter.setClipRect(infoBoxRect, Qt::IntersectClip);
|
||||||
|
painter.setBrush(Qt::NoBrush);
|
||||||
|
|
||||||
|
QFontMetrics fontMetrics(painter.font(), painter.device());
|
||||||
|
QRect rowRect = infoBoxRect;
|
||||||
|
rowRect.setHeight(fontMetrics.lineSpacing());
|
||||||
|
|
||||||
|
for (const auto& infoBoxItem : m_infoBoxItems)
|
||||||
|
{
|
||||||
|
switch (infoBoxItem.style)
|
||||||
|
{
|
||||||
|
case pdfplugin::OutputPreviewWidget::Header:
|
||||||
|
{
|
||||||
|
painter.save();
|
||||||
|
|
||||||
|
QFont font = painter.font();
|
||||||
|
font.setBold(true);
|
||||||
|
painter.setFont(font);
|
||||||
|
|
||||||
|
painter.drawText(rowRect, Qt::AlignCenter | Qt::TextSingleLine, infoBoxItem.caption);
|
||||||
|
|
||||||
|
painter.restore();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case pdfplugin::OutputPreviewWidget::Separator:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case pdfplugin::OutputPreviewWidget::ColoredItem:
|
||||||
|
{
|
||||||
|
QRect cellRect = rowRect.marginsRemoved(QMargins(itemHorizontalMargin, 0, itemHorizontalMargin, 0));
|
||||||
|
|
||||||
|
if (infoBoxItem.color.isValid())
|
||||||
|
{
|
||||||
|
QRect ellipseRect = cellRect;
|
||||||
|
ellipseRect.setWidth(ellipseRect.height());
|
||||||
|
cellRect.setLeft(ellipseRect.right() + 1);
|
||||||
|
|
||||||
|
painter.save();
|
||||||
|
painter.setPen(Qt::NoPen);
|
||||||
|
painter.setBrush(QBrush(infoBoxItem.color));
|
||||||
|
painter.drawEllipse(ellipseRect);
|
||||||
|
painter.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
painter.drawText(cellRect, Qt::AlignVCenter | Qt::AlignLeft | Qt::TextSingleLine, infoBoxItem.caption);
|
||||||
|
painter.drawText(cellRect, Qt::AlignVCenter | Qt::AlignRight | Qt::TextSingleLine, infoBoxItem.value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
Q_ASSERT(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rowRect.translate(0, rowRect.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
painter.restore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QMargins OutputPreviewWidget::getDrawMargins() const
|
||||||
|
{
|
||||||
|
const int horizontalMargin = pdf::PDFWidgetUtils::scaleDPI_x(this, 5);
|
||||||
|
const int verticalMargin = pdf::PDFWidgetUtils::scaleDPI_y(this, 5);
|
||||||
|
|
||||||
|
return QMargins(horizontalMargin, verticalMargin, horizontalMargin, verticalMargin);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect OutputPreviewWidget::getContentRect() const
|
||||||
|
{
|
||||||
|
QRect rect = this->rect();
|
||||||
|
QRect contentRect = rect.marginsRemoved(getDrawMargins());
|
||||||
|
return contentRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect OutputPreviewWidget::getPageImageRect(QRect contentRect) const
|
||||||
|
{
|
||||||
|
int infoBoxWidth = getInfoBoxWidth();
|
||||||
|
|
||||||
|
if (infoBoxWidth > 0)
|
||||||
|
{
|
||||||
|
infoBoxWidth += pdf::PDFWidgetUtils::scaleDPI_x(this, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
contentRect.setRight(contentRect.right() - infoBoxWidth);
|
||||||
|
return contentRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
int OutputPreviewWidget::getInfoBoxWidth() const
|
||||||
|
{
|
||||||
|
if (m_infoBoxItems.empty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pdf::PDFWidgetUtils::scaleDPI_x(this, 150);
|
||||||
|
}
|
||||||
|
|
||||||
|
int OutputPreviewWidget::getInfoBoxContentHorizontalMargin() const
|
||||||
|
{
|
||||||
|
return pdf::PDFWidgetUtils::scaleDPI_x(this, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OutputPreviewWidget::buildInfoBoxItems()
|
||||||
|
{
|
||||||
|
m_infoBoxItems.clear();
|
||||||
|
|
||||||
|
switch (m_displayMode)
|
||||||
|
{
|
||||||
|
case pdfplugin::OutputPreviewWidget::Separations:
|
||||||
|
case pdfplugin::OutputPreviewWidget::ColorWarningInkCoverage:
|
||||||
|
case pdfplugin::OutputPreviewWidget::ColorWarningRichBlack:
|
||||||
|
{
|
||||||
|
if (m_originalProcessBitmap.getWidth() > 0 && m_originalProcessBitmap.getHeight() > 0)
|
||||||
|
{
|
||||||
|
const pdf::PDFPixelFormat pixelFormat = m_originalProcessBitmap.getPixelFormat();
|
||||||
|
std::vector<pdf::PDFInkMapper::ColorInfo> separations = m_inkMapper->getSeparations(pixelFormat.getProcessColorChannelCount(), true);
|
||||||
|
|
||||||
|
// Count process/spot inks
|
||||||
|
|
||||||
|
int processInks = 0;
|
||||||
|
int spotInks = 0;
|
||||||
|
|
||||||
|
for (const auto& colorInfo : separations)
|
||||||
|
{
|
||||||
|
if (!colorInfo.isSpot)
|
||||||
|
{
|
||||||
|
++processInks;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++spotInks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processInks > 0)
|
||||||
|
{
|
||||||
|
addInfoBoxSeparator();
|
||||||
|
addInfoBoxHeader(tr("Process Inks"));
|
||||||
|
|
||||||
|
for (const auto& colorInfo : separations)
|
||||||
|
{
|
||||||
|
if (colorInfo.isSpot)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
addInfoBoxColoredItem(Qt::green, colorInfo.textName, QString("100 %"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spotInks > 0)
|
||||||
|
{
|
||||||
|
addInfoBoxSeparator();
|
||||||
|
addInfoBoxHeader(tr("Spot Inks"));
|
||||||
|
|
||||||
|
for (const auto& colorInfo : separations)
|
||||||
|
{
|
||||||
|
if (!colorInfo.isSpot)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
addInfoBoxColoredItem(Qt::blue, colorInfo.textName, QString("100 %"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case pdfplugin::OutputPreviewWidget::InkCoverage:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Q_ASSERT(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OutputPreviewWidget::addInfoBoxHeader(QString caption)
|
||||||
|
{
|
||||||
|
m_infoBoxItems.push_back(InfoBoxItem(Header, QColor(), caption, QString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OutputPreviewWidget::addInfoBoxSeparator()
|
||||||
|
{
|
||||||
|
if (!m_infoBoxItems.empty())
|
||||||
|
{
|
||||||
|
m_infoBoxItems.push_back(InfoBoxItem(Separator, QColor(), QString(), QString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OutputPreviewWidget::addInfoBoxColoredItem(QColor color, QString caption, QString value)
|
||||||
|
{
|
||||||
|
m_infoBoxItems.push_back(InfoBoxItem(ColoredItem, color, caption, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
const pdf::PDFInkMapper* OutputPreviewWidget::getInkMapper() const
|
||||||
|
{
|
||||||
|
return m_inkMapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OutputPreviewWidget::setInkMapper(const pdf::PDFInkMapper* inkMapper)
|
||||||
|
{
|
||||||
|
m_inkMapper = inkMapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize OutputPreviewWidget::getPageImageSizeHint() const
|
||||||
|
{
|
||||||
|
return getPageImageRect(getContentRect()).size();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // pdfplugin
|
112
Pdf4QtViewerPlugins/OutputPreviewPlugin/outputpreviewwidget.h
Normal file
112
Pdf4QtViewerPlugins/OutputPreviewPlugin/outputpreviewwidget.h
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
// Copyright (C) 2021 Jakub Melka
|
||||||
|
//
|
||||||
|
// This file is part of Pdf4Qt.
|
||||||
|
//
|
||||||
|
// Pdf4Qt is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Pdf4Qt is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with Pdf4Qt. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#ifndef OUTPUTPREVIEWWIDGET_H
|
||||||
|
#define OUTPUTPREVIEWWIDGET_H
|
||||||
|
|
||||||
|
#include "pdftransparencyrenderer.h"
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
namespace pdfplugin
|
||||||
|
{
|
||||||
|
|
||||||
|
class OutputPreviewWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
using BaseClass = QWidget;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit OutputPreviewWidget(QWidget* parent);
|
||||||
|
|
||||||
|
enum DisplayMode
|
||||||
|
{
|
||||||
|
Separations,
|
||||||
|
ColorWarningInkCoverage,
|
||||||
|
ColorWarningRichBlack,
|
||||||
|
InkCoverage
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual QSize sizeHint() const override;
|
||||||
|
virtual QSize minimumSizeHint() const override;
|
||||||
|
|
||||||
|
/// Clears all widget contents
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/// Set active image
|
||||||
|
void setPageImage(QImage image, pdf::PDFFloatBitmapWithColorSpace originalProcessBitmap, QSizeF pageSizeMM);
|
||||||
|
|
||||||
|
const pdf::PDFInkMapper* getInkMapper() const;
|
||||||
|
void setInkMapper(const pdf::PDFInkMapper* inkMapper);
|
||||||
|
|
||||||
|
/// Returns page image size hint (ideal size of page image)
|
||||||
|
QSize getPageImageSizeHint() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void paintEvent(QPaintEvent* event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QMargins getDrawMargins() const;
|
||||||
|
QRect getContentRect() const;
|
||||||
|
QRect getPageImageRect(QRect contentRect) const;
|
||||||
|
|
||||||
|
int getInfoBoxWidth() const;
|
||||||
|
int getInfoBoxContentHorizontalMargin() const;
|
||||||
|
void buildInfoBoxItems();
|
||||||
|
|
||||||
|
void addInfoBoxHeader(QString caption);
|
||||||
|
void addInfoBoxSeparator();
|
||||||
|
void addInfoBoxColoredItem(QColor color, QString caption, QString value);
|
||||||
|
|
||||||
|
enum InfoBoxStyle
|
||||||
|
{
|
||||||
|
Header,
|
||||||
|
Separator,
|
||||||
|
ColoredItem
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InfoBoxItem
|
||||||
|
{
|
||||||
|
InfoBoxItem(InfoBoxStyle style, QColor color, QString caption, QString value) :
|
||||||
|
style(style),
|
||||||
|
color(color),
|
||||||
|
caption(caption),
|
||||||
|
value(value)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
InfoBoxStyle style = InfoBoxStyle::Separator;
|
||||||
|
QColor color;
|
||||||
|
QString caption;
|
||||||
|
QString value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const pdf::PDFInkMapper* m_inkMapper;
|
||||||
|
DisplayMode m_displayMode;
|
||||||
|
std::vector<InfoBoxItem> m_infoBoxItems;
|
||||||
|
|
||||||
|
QImage m_pageImage;
|
||||||
|
pdf::PDFFloatBitmapWithColorSpace m_originalProcessBitmap;
|
||||||
|
QSizeF m_pageSizeMM;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // pdfplugin
|
||||||
|
|
||||||
|
#endif // OUTPUTPREVIEWWIDGET_H
|
Reference in New Issue
Block a user