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 @@ -74,6 +74,20 @@ class PDFOptionsPage : public QWidget { Q_OBJECT +public slots: + void showOrHideScaleMode() + { + bool isVisible = (printBackend() == QPrinterBackend || m_forceRaster->isChecked()); + m_scaleMode->setVisible ( isVisible ); + m_scaleTo->setVisible ( isVisible ); + if ( isVisible ) { + m_printBackendLayout->labelForField(m_scaleMode)->show(); + m_printBackendLayout->labelForField(m_scaleTo)->show(); + } else { + m_printBackendLayout->labelForField(m_scaleMode)->hide(); + m_printBackendLayout->labelForField(m_scaleTo)->hide(); + } + } public: @@ -83,6 +97,19 @@ }; Q_ENUM(PrintBackend) + enum ScaleMode { + FitToPage, + ShrinkToPage, + None + }; + Q_ENUM(ScaleMode) + + enum ScaleTo { + PrintableArea, + FullPage + }; + Q_ENUM(ScaleTo) + PDFOptionsPage() { setWindowTitle( i18n( "PDF Options" ) ); @@ -117,12 +144,35 @@ 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_printBackendLayout = new QFormLayout(formWidget); + m_printBackendLayout->addRow(i18n("Print backend:"), m_printBackend); + + m_scaleMode = new QComboBox; + m_scaleMode->insertItem(FitToPage, i18n("Fit to page")); + m_scaleMode->insertItem(ShrinkToPage, i18n("Shrink to page")); + m_scaleMode->insertItem(None, i18n("None")); + m_printBackendLayout->addRow(i18n("Scale mode"), m_scaleMode); + + m_scaleTo = new QComboBox; + m_scaleTo->insertItem(PrintableArea, i18n("Printable area")); + m_scaleTo->insertItem(FullPage, i18n("Full page")); + m_printBackendLayout->addRow(i18n("Scale to"), m_scaleTo); + layout->addWidget(formWidget); layout->addStretch(1); + // Show scaleMode and scaleTo only if experimental QPrinter backend is selected + // or if the file is to be rasterized before printing + m_scaleMode->hide(); + m_scaleTo->hide(); + m_printBackendLayout->labelForField(m_scaleMode)->hide(); + m_printBackendLayout->labelForField(m_scaleTo)->hide(); + + connect(m_printBackend, QOverload::of(&QComboBox::currentIndexChanged), + this, &PDFOptionsPage::showOrHideScaleMode); + connect(m_forceRaster, &QCheckBox::stateChanged, this, &PDFOptionsPage::showOrHideScaleMode); + #if defined(Q_OS_WIN) && !defined HAVE_POPPLER_0_60 m_printAnnots->setVisible( false ); #endif @@ -155,11 +205,26 @@ return m_printBackend->currentData().value(); } + ScaleMode scaleMode() const + { + return m_scaleMode->currentData().value(); + } + + ScaleTo scaleTo() const + { + return m_scaleTo->currentData().value(); + } + private: QCheckBox *m_printAnnots; QCheckBox *m_forceRaster; QComboBox *m_printBackend; + QComboBox *m_scaleMode; + QComboBox *m_scaleTo; + + // Needs to be a member so we can hide certain elements dynamically + QFormLayout *m_printBackendLayout; }; @@ -1323,12 +1388,16 @@ bool printAnnots = true; bool forceRasterize = false; PDFOptionsPage::PrintBackend printBackend = PDFOptionsPage::CUPSBackend; + PDFOptionsPage::ScaleMode scaleMode = PDFOptionsPage::FitToPage; + PDFOptionsPage::ScaleTo scaleTo = PDFOptionsPage::PrintableArea; if ( pdfOptionsPage ) { printAnnots = pdfOptionsPage->printAnnots(); forceRasterize = pdfOptionsPage->printForceRaster(); printBackend = pdfOptionsPage->printBackend(); + scaleMode = pdfOptionsPage->scaleMode(); + scaleTo = pdfOptionsPage->scaleTo(); } if ( printBackend == PDFOptionsPage::QPrinterBackend ) @@ -1338,8 +1407,9 @@ pdfdoc->setRenderHint( Poppler::Document::HideAnnotations, !printAnnots ); #endif - // Scale to the entire page, not only the printable area - printer.setFullPage( true ); + // If requested, scale to full page instead of the printable area + if ( scaleTo == PDFOptionsPage::FullPage ) + printer.setFullPage( true ); QPainter painter; painter.begin(&printer); @@ -1357,6 +1427,25 @@ Poppler::Page *pp = pdfdoc->page( page ); if (pp) { + double scaling = 1.0; // Default: no scaling at all + + if ( scaleMode != PDFOptionsPage::None ) + { + // Get the two scaling needed to fit the page onto paper horizontally or vertically + QSizeF pageSize = pp->pageSizeF(); + auto horizontalScaling = printer.pageRect(QPrinter::Point).width() / pageSize.width(); + auto verticalScaling = printer.pageRect(QPrinter::Point).height() / pageSize.height(); + + // We use the smaller of the two for both directions, to keep the aspect ratio + scaling = std::min(horizontalScaling,verticalScaling); + } + + // If shrink-to-page mode we disregard the scaling if it is an enlargement. + if ( scaleMode == PDFOptionsPage::ShrinkToPage ) + { + scaling = std::min(1.0, scaling); + } + if ( forceRasterize ) { #ifdef Q_OS_WIN @@ -1372,7 +1461,7 @@ auto actualRenderBackend = pdfdoc->renderBackend(); pdfdoc->setRenderBackend( Poppler::Document::ArthurBackend ); - pp->renderToPainter( &painter, printer.logicalDpiX(), printer.logicalDpiY() ); + pp->renderToPainter( &painter, scaling*printer.logicalDpiX(), scaling*printer.logicalDpiY() ); pdfdoc->setRenderBackend( actualRenderBackend ); }