diff --git a/generators/poppler/generator_pdf.cpp b/generators/poppler/generator_pdf.cpp
--- a/generators/poppler/generator_pdf.cpp
+++ b/generators/poppler/generator_pdf.cpp
@@ -82,16 +82,24 @@
public slots:
void enableOrDisableScaleMode()
{
- m_scaleMode->setEnabled ( m_forceRaster->isChecked() );
+ bool enableScaleModes = m_forceRaster->isChecked() || printBackend() == PDFOptionsPage::QPrinterBackend;
- if ( m_forceRaster->isChecked() ) {
+ m_scaleMode->setEnabled ( enableScaleModes );
+
+ if ( enableScaleModes ) {
m_scaleMode->setToolTip( i18n( "Scaling mode for the printed pages" ) );
} else {
- m_scaleMode->setToolTip( i18n( "Select rasterization to enable this!" ) );
+ m_scaleMode->setToolTip( i18n( "Select rasterization or QPrinter printing to enable this!" ) );
}
}
public:
+ enum PrintBackend {
+ CUPSBackend,
+ QPrinterBackend
+ };
+ Q_ENUM(PrintBackend)
+
enum ScaleMode {
FitToPrintableArea,
FitToPage,
@@ -112,8 +120,29 @@
m_forceRaster->setWhatsThis(i18n("Forces the rasterization of each page into an image before printing it. This usually gives somewhat worse results, but is useful when printing documents that appear to print incorrectly."));
layout->addWidget(m_forceRaster);
+ m_printBackend = new QComboBox;
+ // Windows can only print with the QPrinter backend, because the CUPS backend
+ // is UNIX-specific.
+#if !defined(Q_OS_WIN)
+ m_printBackend->insertItem(CUPSBackend, i18n("CUPS"), CUPSBackend);
+ m_printBackend->setItemData(CUPSBackend, xi18n("Print using the CUPS printing system.This will convert your PDF file to PostScript first,and then send the PostScript file to the printer."), Qt::ToolTipRole);
+ m_printBackend->setItemData(CUPSBackend, xi18n("Print using the CUPS printing system.This will convert your PDF file to PostScript first,and then send the PostScript file to the printer."), Qt::WhatsThisRole);
+#endif
+
+ // Print using the platform-independent Qt infrastructure. By necessity,
+ // this uses a backend of the Poppler PDF library that is called 'Arthur'.
+ // This Arthur backend is still somewhat immature, and you may see misrenderings
+ // of your PDF document. In fact, the backend is so bad before poppler 0.60
+ // that we'd rather not expose the QPrinter option at all for older poppler versions.
+ // On Windows we have no choice, because there the CUPS backend will not work.
+ // On the positive side, QPrinter printing allows more printing options.
+#if defined(Q_OS_WIN) || HAVE_POPPLER_0_60
+ m_printBackend->insertItem(QPrinterBackend, i18n("QPrinter (experimental)"), QPrinterBackend);
+ m_printBackend->setItemData(QPrinterBackend, i18n("Print with Qt (experimental, you may see rendering artifacts)"), Qt::ToolTipRole);
+#endif
QWidget* formWidget = new QWidget(this);
QFormLayout* printBackendLayout = new QFormLayout(formWidget);
+ printBackendLayout->addRow(i18n("Print backend:"), m_printBackend);
m_scaleMode = new QComboBox;
m_scaleMode->insertItem(FitToPrintableArea, i18n("Fit to printable area"), FitToPrintableArea);
@@ -129,6 +158,7 @@
// Enable scaleMode only if the file is to be rasterized before printing
m_scaleMode->setEnabled( false );
+ connect( m_printBackend, QOverload::of( &QComboBox::currentIndexChanged ), this, &PDFOptionsPage::enableOrDisableScaleMode );
connect( m_forceRaster, &QCheckBox::stateChanged, this, &PDFOptionsPage::enableOrDisableScaleMode );
#if defined(Q_OS_WIN) && !defined HAVE_POPPLER_0_60
@@ -157,6 +187,11 @@
m_forceRaster->setChecked( forceRaster );
}
+ PrintBackend printBackend() const
+ {
+ return m_printBackend->currentData().value();
+ }
+
ScaleMode scaleMode() const
{
return m_scaleMode->currentData().value();
@@ -165,6 +200,7 @@
private:
QCheckBox *m_printAnnots;
QCheckBox *m_forceRaster;
+ QComboBox *m_printBackend;
QComboBox *m_scaleMode;
};
@@ -1336,33 +1372,21 @@
{
bool printAnnots = true;
bool forceRasterize = false;
+ PDFOptionsPage::PrintBackend printBackend = PDFOptionsPage::CUPSBackend;
PDFOptionsPage::ScaleMode scaleMode = PDFOptionsPage::FitToPrintableArea;
if ( pdfOptionsPage )
{
printAnnots = pdfOptionsPage->printAnnots();
forceRasterize = pdfOptionsPage->printForceRaster();
+ printBackend = pdfOptionsPage->printBackend();
scaleMode = pdfOptionsPage->scaleMode();
}
-#ifdef Q_OS_WIN
- // Windows can only print by rasterization, because that is
- // currently the only way Okular implements printing without using UNIX-specific
- // tools like 'lpr'.
- forceRasterize = true;
-#ifndef HAVE_POPPLER_0_60
- // The Document::HideAnnotations flags was introduced in poppler 0.60
- printAnnots = true;
-#endif
-#endif
-
-#ifdef HAVE_POPPLER_0_60
- if ( forceRasterize )
+ if ( forceRasterize || printBackend == PDFOptionsPage::QPrinterBackend )
{
+#ifdef HAVE_POPPLER_0_60
pdfdoc->setRenderHint(Poppler::Document::HideAnnotations, !printAnnots);
-#else
- if ( forceRasterize && printAnnots)
- {
#endif
// If requested, scale to full page instead of the printable area
@@ -1388,9 +1412,12 @@
QSizeF pageSize = pp->pageSizeF(); // Unit is 'points' (i.e., 1/72th of an inch)
QRect painterWindow = painter.window(); // Unit is 'QPrinter::DevicePixel'
- // Default: no scaling at all, but we need to go from DevicePixel units to 'points'
+ // We need to convert from DevicePixel units to 'points'
// Warning: We compute the horizontal scaling, and later assume that the vertical scaling will be the same.
- double scaling = printer.paperRect(QPrinter::DevicePixel).width() / printer.paperRect(QPrinter::Point).width();
+ double unitsConversion = printer.paperRect(QPrinter::DevicePixel).width() / printer.paperRect(QPrinter::Point).width();
+
+ // Default: no scaling at all
+ double scaling = 1.0;
if ( scaleMode != PDFOptionsPage::None )
{
@@ -1399,16 +1426,34 @@
auto verticalScaling = painterWindow.height() / pageSize.height();
// We use the smaller of the two for both directions, to keep the aspect ratio
- scaling = std::min(horizontalScaling, verticalScaling);
+ scaling = std::min(horizontalScaling, verticalScaling) / unitsConversion;
}
+ if ( forceRasterize )
+ {
#ifdef Q_OS_WIN
QImage img = pp->renderToImage( printer.physicalDpiX(), printer.physicalDpiY() );
#else
// UNIX: Same resolution as the postscript rasterizer; see discussion at https://git.reviewboard.kde.org/r/130218/
QImage img = pp->renderToImage( 300, 300 );
#endif
- painter.drawImage( QRectF( QPointF( 0, 0 ), scaling * pp->pageSizeF() ), img );
+ painter.drawImage( QRectF( QPointF( 0, 0 ), unitsConversion * scaling * pp->pageSizeF() ), img );
+ } else
+ {
+ QRect viewport;
+ viewport.setWidth(scaling * painter.window().width());
+ viewport.setHeight(scaling * painter.window().height());
+ painter.setViewport(viewport);
+
+ // temporarily switch to poppler's Arthur backend.
+ // It is the only one that implements renderToPainter.
+ auto actualRenderBackend = pdfdoc->renderBackend();
+ pdfdoc->setRenderBackend( Poppler::Document::ArthurBackend );
+
+ pp->renderToPainter( &painter, printer.logicalDpiX(), printer.logicalDpiY() );
+
+ pdfdoc->setRenderBackend( actualRenderBackend );
+ }
}
userMutex()->unlock();
}