Possibly related:
The problem
I am trying to print a landscape A4 PDF page that I created in LibreOffice writer. (But other landscape PDFs, e.g. from TeXLive, behave equally bad.)
The information about the PDF obtained from the Poppler’s pdfinfo utility is:
Creator: Writer
Producer: LibreOffice 25.8.1.1 (X86_64) / LibreOffice Community
CreationDate: Sat Oct 11 22:13:00 2025 CEST
Custom Metadata: no
Metadata Stream: yes
Tagged: yes
UserProperties: no
Suspects: no
Form: none
JavaScript: no
Pages: 1
Encrypted: no
Page size: 841.89 x 595.304 pts (A4)
Page rot: 0
File size: 6910 bytes
Optimized: no
PDF version: 1.7
If I keep the default print options—“Fit to printable area” scaling mode and “landscape” autodetected orientation—, the result looks like this:
+---------+
| |
| |
|xxxxxx |
|xxxxxx |
|xxxxxx |
|xxxxxx |
|xxxxxx |
+---------+
The orientation is correct, but the page is shrunk to a corner.
When I switch to “portrait”, the result looks like this:
+---------+
| |
| |
|xxxxxxxxx|
|xxxxxxxxx|
|xxxxxxxxx|
| |
| |
+---------+
Here the orientation is wrong, as is the scale.
Is this a bug? (I suppose it is.) Should I report it? Can I do anything to help with fixing it?
It may also be a defect in my printer (or driver). But when I print the same page from qpdfview using their defaults, the result is correct.
What I found so far
I know close to nothing about the internals of KDE applications, of Poppler or of CUPS. But as this issue bothers me quite a lot (and already for a rather long time), I tried to look into the code anyway.
Okular uses Poppler to work with PDFs. When printing a PDF, under certain circumstances it uses the Poppler class Poppler::PSConverter to convert the PDF to a PostScript file. (My case falls among those circumstances.) This PS document is in turn printed using the CUPS program lpr launched via KProcess::execute. When converting PDF to PS, the paper dimension has to be specified to Poppler. This is done in Okular’s function PDFGenerator::print:
psConverter->setPaperWidth(width);
psConverter->setPaperHeight(height);
These dimensions correspond to the selected paper size and orientation in the print dialog. A PostScript file produced in this way, with the default print setup, carries the geometry in its header:
%%DocumentMedia: 297x209mm 842 595 0 () ()
%%BoundingBox: 0 0 842 595
%%Pages: 1
%%EndComments
%%BeginDefaults
%%PageMedia: 297x209mm
%%EndDefaults
...
%%Page: 1 1
%%PageBoundingBox: 0 0 842 595
%%PageOrientation: Portrait
So, the paper is a landscape A4 (width > height) and the PS document preserves the orientation of the PDF file being printed. The page orientation is given as “portrait”, presumably meaning that no additional rotating of the content is required. That seems to agree with the original PDF. When printing the PostScript file using CUPS, a command line like this is internally used by Okular:
lpr -P HP_LaserJet_100_colorMFP_M175nw \
-#1 \
-J page.pdf \
-o media=A4 \
-o portrait \
-o sides=one-sided \
-o outputorder=normal \
-o Collate=True \
-o page-left=12 \
-o page-top=12 \
-o page-right=12 \
-o page-bottom=12 \
-o fit-to-page \
-o number-up=1 \
-o number-up-layout=lrtb \
-o job-billing \
-o job-priority=50 \
-o job-sheets=none,none \
-r \
/tmp/okular_RTmZzi.ps
It specifies that the page should be scaled (“fit-to-page”) to fit onto a portrait A4 paper. But, according to the PostScript header, the document is a landscape A4. What does CUPS do? My interpretation is that it scales the document by a factor of 1/sqrt(2) to squeeze a landscape A4 onto a portrait A4. Then, because the PostScript specifies a landscape mode, it rotates the document +90 degrees. So, the outcome is eventually correctly oriented but incorrectly scaled, as shown above and repeated here:
+---------+
| |
| |
|xxxxxx |
|xxxxxx |
|xxxxxx |
|xxxxxx |
|xxxxxx |
+---------+
In the second attempt I set the orientation to “portrait” in the Okular’s print dialog. The exported PostScript file now has the following metadata:
%%DocumentMedia: A4 595 842 0 () ()
%%BoundingBox: 0 0 595 842
%%Pages: 1
%%EndComments
%%BeginDefaults
%%PageMedia: A4
%%EndDefaults
...
%%Page: 1 1
%%PageBoundingBox: 0 0 595 842
%%PageOrientation: Landscape
That is a standard upright A4, consistent with the Okular’s print dialog. The page is specified as landscape, presumably indicating that the content should be rotated before placing on a physical medium. This also sounds consistent with the original landscape PDF. The CUPS command invoked by Okular is now
lpr -P HP_LaserJet_100_colorMFP_M175nw \
-#1 \
-J page.pdf \
-o media=A4 \
-o landscape \
-o sides=one-sided \
-o outputorder=normal \
-o Collate=True \
-o page-left=12 \
-o page-top=12 \
-o page-right=12 \
-o page-bottom=12 \
-o fit-to-page \
-o number-up=1 \
-o number-up-layout=lrtb \
-o job-billing \
-o job-priority=50 \
-o job-sheets=none,none \
-r \
/tmp/okular_NGJkWC.ps
This “-o landscape” breaks the result again, rotating the correctly prepared upright A4 PostScript page by +90 degrees and scaling it to fit:
+---------+
| |
| |
|xxxxxxxxx|
|xxxxxxxxx|
|xxxxxxxxx|
| |
| |
+---------+
There seem to be several ways how to work around the problem:
-
When I uncheck “Print annotations”, the PDF is passed directly to CUPS, bypassing the PostScript conversion step, and the document is printed correctly. In that case Okular prints using the following command:
lpr -P HP_LaserJet_100_colorMFP_M175nw \ -#1 \ -J page.pdf \ -o media=A4 \ -o portrait \ -o sides=one-sided \ -o outputorder=normal \ -o Collate=True \ -o page-left=12 \ -o page-top=12 \ -o page-right=12 \ -o page-bottom=12 \ -o fit-to-page \ -o number-up=1 \ -o number-up-layout=lrtb \ -o job-billing \ -o job-priority=50 \ -o job-sheets=none,none \ /home/jacob/Dokumenty/prog/bugs/okular-printing/page.pdfThis works best, but only if I really do not want the annotations. Otherwise it is not useful.
-
Selecting “Fit to full page” (forcing rasterization) in the scaling options also leads to the correct output. In that case Okular renders the page using
QPainterdirectly, again bypassing PostScript conversion, and has the geometry fully under control. However, the rasterization seems to be slow for complicated documents and one would like to avoid it if possible. -
Removing
-o portrait,-o landscapeand-o fit-to-pageoptions altogether, as they duplicate information already present in the PostScript file.index 8c96e7da2..f8db94f76 100644 --- a/core/fileprinter.cpp +++ b/core/fileprinter.cpp @@ -326,10 +332,6 @@ QStringList FilePrinter::cupsOptions(QPrinter &printer, QPageLayout::Orientation optionList << optionMedia(printer); } - if (!optionOrientation(printer, documentOrientation).isEmpty()) { - optionList << optionOrientation(printer, documentOrientation); - } - if (!optionDoubleSidedPrinting(printer).isEmpty()) { optionList << optionDoubleSidedPrinting(printer); } @@ -541,9 +543,6 @@ QStringList FilePrinter::optionPageMargins(QPrinter &printer, ScaleMode scaleMod QStringList marginOptions; marginOptions << (QStringLiteral("-o")) << QStringLiteral("page-left=%1").arg(l) << QStringLiteral("-o") << QStringLiteral("page-top=%1").arg(t) << QStringLiteral("-o") << QStringLiteral("page-right=%1").arg(r) << QStringLiteral("-o") << QStringLiteral("page-bottom=%1").arg(b); - if (scaleMode == ScaleMode::FitToPrintArea) { - marginOptions << QStringLiteral("-o") << QStringLiteral("fit-to-page"); - } return marginOptions; }This is rather drastic and will break many other use cases. But it works and it illustrates that the issue is likely arising in a clash between the Poppler and CUPS options. Maybe the options should be used differently when printing the intermediate PostScript file.
My hardware:
- HP LaserJet 100 Color MFP M175NW
My software:
- openSUSE Tumbleweed 20251007
- Okular 25.11.70 (self-compiled from GitLab)
- Poppler 25.09.1
- CUPS 2.4.14