mirror of
https://invent.kde.org/graphics/okular
synced 2024-10-02 14:14:10 +00:00
Implement several new print scaling options
This patch introduces the choice between three scaling options for printing: * Fit to printable area * Fit to full page * No scaling The new options only work with the QPrinter backend. Therefore they are only enabled if 'force rasterization' is selected. Differential Revision: https://phabricator.kde.org/D7962
This commit is contained in:
parent
677fc76760
commit
2e97d58750
|
@ -26,6 +26,7 @@
|
|||
#include <qstack.h>
|
||||
#include <qtemporaryfile.h>
|
||||
#include <qtextstream.h>
|
||||
#include <QComboBox>
|
||||
#include <QPrinter>
|
||||
#include <QPainter>
|
||||
#include <QTimer>
|
||||
|
@ -76,8 +77,26 @@ static const int defaultPageHeight = 842;
|
|||
class PDFOptionsPage : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public slots:
|
||||
void enableOrDisableScaleMode()
|
||||
{
|
||||
m_scaleMode->setEnabled ( m_forceRaster->isChecked() );
|
||||
|
||||
if ( m_forceRaster->isChecked() ) {
|
||||
m_scaleMode->setToolTip( i18n( "Scaling mode for the printed pages" ) );
|
||||
} else {
|
||||
m_scaleMode->setToolTip( i18n( "Select rasterization to enable this!" ) );
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
enum ScaleMode {
|
||||
FitToPrintableArea,
|
||||
FitToPage,
|
||||
None
|
||||
};
|
||||
Q_ENUM(ScaleMode)
|
||||
|
||||
PDFOptionsPage()
|
||||
{
|
||||
setWindowTitle( i18n( "PDF Options" ) );
|
||||
|
@ -90,8 +109,26 @@ class PDFOptionsPage : public QWidget
|
|||
m_forceRaster->setToolTip(i18n("Rasterize into an image before printing"));
|
||||
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);
|
||||
|
||||
QWidget* formWidget = new QWidget(this);
|
||||
QFormLayout* printBackendLayout = new QFormLayout(formWidget);
|
||||
|
||||
m_scaleMode = new QComboBox;
|
||||
m_scaleMode->insertItem(FitToPrintableArea, i18n("Fit to printable area"), FitToPrintableArea);
|
||||
m_scaleMode->insertItem(FitToPage, i18n("Fit to full page"), FitToPage);
|
||||
m_scaleMode->insertItem(None, i18n("None; print original size"), None);
|
||||
m_scaleMode->setToolTip(i18n("Select rasterization to enable this!"));
|
||||
printBackendLayout->addRow(i18n("Scale mode:"), m_scaleMode);
|
||||
|
||||
layout->addWidget(formWidget);
|
||||
|
||||
layout->addStretch(1);
|
||||
|
||||
// Enable scaleMode only if the file is to be rasterized before printing
|
||||
m_scaleMode->setEnabled( false );
|
||||
|
||||
connect( m_forceRaster, &QCheckBox::stateChanged, this, &PDFOptionsPage::enableOrDisableScaleMode );
|
||||
|
||||
#if defined(Q_OS_WIN) && !defined HAVE_POPPLER_0_60
|
||||
m_printAnnots->setVisible( false );
|
||||
#endif
|
||||
|
@ -118,9 +155,15 @@ class PDFOptionsPage : public QWidget
|
|||
m_forceRaster->setChecked( forceRaster );
|
||||
}
|
||||
|
||||
ScaleMode scaleMode() const
|
||||
{
|
||||
return m_scaleMode->currentData().value<ScaleMode>();
|
||||
}
|
||||
|
||||
private:
|
||||
QCheckBox *m_printAnnots;
|
||||
QCheckBox *m_forceRaster;
|
||||
QComboBox *m_scaleMode;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1291,11 +1334,13 @@ bool PDFGenerator::print( QPrinter& printer )
|
|||
{
|
||||
bool printAnnots = true;
|
||||
bool forceRasterize = false;
|
||||
PDFOptionsPage::ScaleMode scaleMode = PDFOptionsPage::FitToPrintableArea;
|
||||
|
||||
if ( pdfOptionsPage )
|
||||
{
|
||||
printAnnots = pdfOptionsPage->printAnnots();
|
||||
forceRasterize = pdfOptionsPage->printForceRaster();
|
||||
scaleMode = pdfOptionsPage->scaleMode();
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
@ -1317,6 +1362,11 @@ bool PDFGenerator::print( QPrinter& printer )
|
|||
if ( forceRasterize && printAnnots)
|
||||
{
|
||||
#endif
|
||||
|
||||
// If requested, scale to full page instead of the printable area
|
||||
if ( scaleMode == PDFOptionsPage::FitToPage )
|
||||
printer.setFullPage( true );
|
||||
|
||||
QPainter painter;
|
||||
painter.begin(&printer);
|
||||
|
||||
|
@ -1333,13 +1383,30 @@ bool PDFGenerator::print( QPrinter& printer )
|
|||
Poppler::Page *pp = pdfdoc->page( page );
|
||||
if (pp)
|
||||
{
|
||||
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'
|
||||
// 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();
|
||||
|
||||
if ( scaleMode != PDFOptionsPage::None )
|
||||
{
|
||||
// Get the two scaling factors needed to fit the page onto paper horizontally or vertically
|
||||
auto horizontalScaling = painterWindow.width() / pageSize.width();
|
||||
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);
|
||||
}
|
||||
|
||||
#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( painter.window(), img, QRectF(0, 0, img.width(), img.height()) );
|
||||
painter.drawImage( QRectF( QPointF( 0, 0 ), scaling * pp->pageSizeF() ), img );
|
||||
delete pp;
|
||||
}
|
||||
userMutex()->unlock();
|
||||
|
|
Loading…
Reference in a new issue