Skip to content

pdftopdf (cfFilterPDFToPDF) no longer generates soft copies with *cupsManualCopies: True — regression in libcupsfilters 2.2.x #226

Description

@Leechadoro

pdftopdf (cfFilterPDFToPDF) no longer generates soft copies with *cupsManualCopies: True — regression in libcupsfilters 2.2.x

Summary

After upgrading libcupsfilters 2.1.1 → 2.2.1, printing with copies > 1 to a raster-driver
queue produces exactly one copy. The queue uses a classic CUPS raster driver
(*cupsFilter: "application/vnd.cups-raster 0 rastertosnailtspl-xprinter") whose PPD has
*cupsManualCopies: True, so the copies must be produced in software by
pdftopdf / cfFilterPDFToPDF().

pdftopdf runs and exits with status 0, but the page count is not multiplied: Ghostscript is
subsequently invoked without any copy count (no /NumCopies), and only a single copy reaches
the printer.

Nothing else changed on the system: the same queue, same PPD and same vendor filter worked
correctly with libcupsfilters 2.1.1. Downgrading libcupsfilters back to 2.1.1 is the only change
needed to restore correct behaviour.

libcupsfilters 2.2.0 rewrote cfFilterPDFToPDF() from C++/QPDF to C/PDFio, which appears to be
where the regression was introduced:
https://openprinting.github.io/libcupsfilters-2.2.0

Environment

Item Value
Distribution CachyOS (Arch Linux based), x86_64
cups 2:2.4.19-1
cups-filters 2.0.1-2.1
libppd 2.1.1-2.1
libcupsfilters 2.2.1-2.1 (broken) / 2.1.1-4.4 (works)
Printer Xprinter XP-420B (203 dpi thermal label printer, USB)
Driver xprinter-cups 3.13.55-2 (vendor CUPS raster filter rastertosnailtspl-xprinter)
Ghostscript in filter chain via cfFilterGhostscript

Relevant PPD lines:

*cupsManualCopies: True
*cupsFilter: "application/vnd.cups-raster 0 rastertosnailtspl-xprinter"

Exact upgrade timestamp from /var/log/pacman.log:

[2026-08-31T10:48:08+0300] [ALPM] upgraded libcupsfilters (2.1.1-4.4 -> 2.2.1-2.1)

The breakage was noticed the same day.

Steps to reproduce

  1. Set up a CUPS queue with a classic raster driver whose PPD contains
    *cupsManualCopies: True and a single *cupsFilter: "application/vnd.cups-raster 0 <vendor filter>".

  2. Submit a job with more than one copy, e.g.:

    lp -d Xprinter_XP-420B -n 3 /usr/share/cups/data/testprint.ps
    
  3. Observe the output.

Expected behaviour

Three copies are printed. Because the printer cannot generate copies in hardware and
*cupsManualCopies: True is set, cfFilterPDFToPDF() should replicate the pages so that the
downstream raster chain rasterises three copies.

Actual behaviour

Exactly one copy is printed, regardless of the requested copy count. Reproducible both from
lp -n N and from GUI print dialogs, so it is not an application-side issue.

Debug log (cupsctl --debug-logging)

D [01/Sep/2026:00:08:54 +0300] [Job 414] rastertosnailtspl-xprinter (application/vnd.cups-raster to printer/Xprinter_XP-420B, cost 0)
I [01/Sep/2026:00:08:54 +0300] [Job 414] Started filter /usr/lib/cups/filter/rastertosnailtspl-xprinter (PID 65037)
D [01/Sep/2026:00:08:54 +0300] [Job 414] ppdFilterLoadPPD: Last filter determined by the PPD: rastertosnailtspl-xprinter; Final data MIME type: application/vnd.cups-raster => PDF filter will not log pages in page_log.
D [01/Sep/2026:00:08:54 +0300] [Job 414] ppdFilterUniversal:    application/vnd.cups-raster 0 rastertosnailtspl-xprinter
D [01/Sep/2026:00:08:54 +0300] [Job 414] cfFilterUniversal: Adding pdftopdf to chain
D [01/Sep/2026:00:08:54 +0300] [Job 414] cfFilterChain: Running filter: pdftopdf
D [01/Sep/2026:00:08:54 +0300] [Job 414] Set job-printer-state-message to "cfFilterChain: Running filter: pdftopdf", current level=INFO
D [01/Sep/2026:00:08:54 +0300] [Job 414] cfFilterChain: pdftopdf (PID 65043) started.
D [01/Sep/2026:00:08:54 +0300] [Job 414] Set job-printer-state-message to "cfFilterChain: pdftopdf (PID 65043) started.", current level=INFO
D [01/Sep/2026:00:08:54 +0300] [Job 414] cfFilterChain: pdftopdf completed with status 0.
D [01/Sep/2026:00:08:54 +0300] [Job 414] cfFilterGhostscript: Ghostscript command line: gs -dQUIET -dSAFER -dNOPAUSE -dBATCH -dNOINTERPOLATE -dNOMEDIAATTRS -dUsePDFX3Profile -sstdout=%stderr -sOutputFile=%stdout -sDEVICE=cups -r203x203 -dDEVICEWIDTHPOINTS=288 -dDEVICEHEIGHTPOINTS=432 -dcupsBitsPerColor=8 -dcupsColorOrder=0 -dcupsColorSpace=3 -dcupsRowCount=8 -scupsRenderingIntent=auto -scupsPageSizeName=4x6.Borderless -dcupsManualCopies -I/usr/share/cups/fonts -c '<< /.HWMargins[0.000000 0.000000 0.000000 0.000000] /Margins[0 0]>>setpagedevice' -f -_
D [01/Sep/2026:00:08:55 +0300] [Job 414] cfFilterChain: pdftopdf (PID 65043) exited with no errors.
D [01/Sep/2026:00:08:55 +0300] [Job 414] Set job-printer-state-message to "cfFilterChain: pdftopdf (PID 65043) exited with no errors.", current level=INFO
D [01/Sep/2026:00:08:55 +0300] [Job 414] PID 65037 (/usr/lib/cups/filter/rastertosnailtspl-xprinter) exited with no errors.

Two things stand out:

  • pdftopdf is added to the chain and exits cleanly, but the document handed to Ghostscript
    evidently still contains a single copy.
  • The Ghostscript command line carries -dcupsManualCopies but no copy count, so no copies can
    be produced downstream either — the copies are silently lost between the job attributes and the
    rasteriser.

Workaround

Confirmed: downgrading libcupsfilters to 2.1.1 restores correct multi-copy printing with the
same PPD, same queue and same vendor filter, with no other changes to the system. Re-installing
2.2.1 brings the single-copy behaviour back.

pacman -U /var/cache/pacman/pkg/libcupsfilters-2.1.1-4.4-x86_64.pkg.tar.zst
systemctl restart cups

Additional notes

This configuration — a classic (non-driverless) CUPS raster driver relying on
*cupsManualCopies: True for software copy generation — may not be covered by the new
cupsfilters/test-filter-cases.txt CI cases added in 2.2.0. A regression test asserting that
cfFilterPDFToPDF() multiplies the page count when num-copies > 1 and
cupsManualCopies is true would catch this.

Happy to provide additional debug logs, the full PPD, or to test patches.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions