Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CUPS does not appear to respect the 'cupsManualCopies' PPD parameter when printing AirPrint-supplied jobs with multiple copies #613

Closed
speachy opened this issue Dec 31, 2024 · 17 comments

Comments

@speachy
Copy link

speachy commented Dec 31, 2024

This is with CUPS 2.4.11 and cups-filters 2.0.1, from MacOS 10.14 (I think?) client, and the latest gutenprint snapshot.

Using the Apple preview application, if you tell it to print two copies of a single image, by the time the job passed to the rastertogutenprint filter has two pages, yet the 'copies' argument on the filter command line is still 2. The PPD specifies 'cupsManualCopies: false' which means the "hardware" (ie not CUPS or its filter chain) is responsible for generating copies.

I can't be sure the problem isn't with the Apple preview application or MacOS's AirPrint client implementation, but I do not consider that likely.

Attached are:

  • Comprehensive 'LogLevel debug' logs covering the entire job from submission to completion
  • PPD
  • IPP get-attrs

Here's an excerpt of the logs, showing the arguments passed to the filters:

[Job 216] 3 filters for job:
[Job 216] - (application/pdf to application/vnd.universal-input, cost 0)
[Job 216] universal (application/vnd.universal-input to application/vnd.cups-raster, cost 0)
[Job 216] rastertogutenprint.5.3 (application/vnd.cups-raster to printer/U826, cost 100)
[Job 216] job-sheets=none,none
[Job 216] argv[0]="U826"
[Job 216] argv[1]="216"
[Job 216] argv[2]="USERNAMEHIDDEN"
[Job 216] argv[3]="20090117 IMG_7901.JPG"
[Job 216] argv[4]="2"
[Job 216] argv[5]="<cut out see below>"
[Job 216] argv[6]="/var/spool/cups/d00216-001"
[Job 216] envp[0]="CUPS_CACHEDIR=/var/cache/cups"
[Job 216] envp[1]="CUPS_DATADIR=/usr/share/cups"
[Job 216] envp[2]="CUPS_DOCROOT=/usr/share/cups/www"
[Job 216] envp[3]="CUPS_REQUESTROOT=/var/spool/cups"
[Job 216] envp[4]="CUPS_SERVERBIN=/usr/lib/cups"
[Job 216] envp[5]="CUPS_SERVERROOT=/etc/cups"
[Job 216] envp[6]="CUPS_STATEDIR=/run/cups"
[Job 216] envp[7]="HOME=/var/spool/cups/tmp"
[Job 216] envp[8]="PATH=/usr/lib/cups/filter:/usr/bin:/usr/sbin:/bin:/usr/bin"
[Job 216] envp[9]="[email protected]"
[Job 216] envp[10]="SOFTWARE=CUPS/2.4.11"
[Job 216] envp[11]="TMPDIR=/var/spool/cups/tmp"
[Job 216] envp[12]="USER=root"
[Job 216] envp[13]="CUPS_MAX_MESSAGE=2047"
[Job 216] envp[14]="CUPS_SERVER=/run/cups/cups.sock"
[Job 216] envp[15]="CUPS_ENCRYPTION=IfRequested"
[Job 216] envp[16]="IPP_PORT=631"
[Job 216] envp[17]="CHARSET=u (application/pdftf-8"
[Job 216] envp[18]="LANG=en_US.UTF-8"
[Job 216] envp[19]="PPD=/etc/cups/ppd/U826.ppd"
[Job 216] envp[20]="CONTENT_TYPE=application/pdf"
[Job 216] envp[21]="DEVICE_URI=gutenprint53+usb://joyspace-u826/4FC3B1084248015"
[Job 216] envp[22]="PRINTER_INFO=Joyspace U826"
[Job 216] envp[23]="PRINTER_LOCATION=Office"
[Job 216] envp[24]="PRINTER=U826"
[Job 216] envp[25]="PRINTER_STATE_REASONS=none"
[Job 216] envp[26]="CUPS_FILETYPE=document"
[Job 216] envp[27]="FINAL_CONTENT_TYPE=application/vnd.cups-raster"
[Job 216] envp[28]="AUTH_I****"
[Job 216] Started filter /usr/lib/cups/filter/universal (PID 2482)
[Job 216] Started filter /usr/lib/cups/filter/rastertogutenprint.5.3 (PID 2483)
[Job 216] Started backend /usr/lib/cups/backend/gutenprint53+usb (PID 2484)

[Job 216] ppdFilterUniversal: \"*cupsFilter(2): ...\" lines in the PPD file:
[Job 216] ppdFilterUniversal:    application/vnd.cups-raw application/octet-stream 0 -
[Job 216] ppdFilterUniversal:    application/vnd.cups-command 33 commandtodyesub
[Job 216] ppdFilterUniversal: PPD uses \"*cupsFilter: ...\" lines, so we always convert to format given by FINAL_CONTENT_TYPE
[Job 216] ppdFilterUniversal: Converting from application/pdf to application/vnd.cups-raster
[Job 216] cfFilterUniversal: Converting from application/pdf to application/vnd.cups-raster
[Job 216] cfFilterUniversal: Final output format for job: application/vnd.cups-raster
[Job 216] cfFilterUniversal: Adding pdftopdf to chain
[Job 216] cfFilterUniversal: Adding ghostscript to chain
[Job 216] cfFilterChain: Running filter: pdftopdf

[Job 216] Gutenprint: 5.3.4 Starting
[Job 216] Gutenprint: command line: U826 \'216\' \'USERNAMEHIDDEN\' \'20090117 IMG_7901.JPG\' \'2\' <args>
[Job 216] Gutenprint: using PPD file /etc/cups/ppd/U826.ppd

[Job 216] Gutenprint: CUPS option count is 66 (4332 bytes)
[Job 216] Gutenprint:  CUPS option 0 AP_ColorMatchingMode = AP_ApplicationColorMatching
[Job 216] Gutenprint:  CUPS option 1 AP_D_InputSlot =
[Job 216] Gutenprint:  CUPS option 2 collate = true
[Job 216] Gutenprint:  CUPS option 3 ColorModel = RGB
[Job 216] Gutenprint:  CUPS option 4 com.apple.print.DialogDismissedBy = Print
[Job 216] Gutenprint:  CUPS option 5 com.apple.print.DocumentTicket.PMSpoolFormat = application/pdf
[Job 216] Gutenprint:  CUPS option 6 com.apple.print.JobInfo.PMApplicationName = Preview
[Job 216] Gutenprint:  CUPS option 7 com.apple.print.JobInfo.PMJobName = 20090117 IMG_7901.JPG
[Job 216] Gutenprint:  CUPS option 8 com.apple.print.JobInfo.PMJobOwner = System Administrator
[Job 216] Gutenprint:  CUPS option 9 com.apple.print.PageToPaperMappingAllowScalingUp..b. = true
[Job 216] Gutenprint:  CUPS option 10 com.apple.print.PageToPaperMappingMediaName = 104.99x156.13mm
[Job 216] Gutenprint:  CUPS option 11 com.apple.print.PageToPaperMappingType..n. = 1
[Job 216] Gutenprint:  CUPS option 12 com.apple.print.PDEsUsed =  com.apple.print.pde.MediaQualityPDEKind, com.apple.print.pde.NSPrintAccessoryViewPDE,
[Job 216] Gutenprint:  CUPS option 13 com.apple.print.PMPresetUsed = 4x6 prints
[Job 216] Gutenprint:  CUPS option 14 com.apple.print.preset.Orientation..n. = 1
[Job 216] Gutenprint:  CUPS option 15 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.PageFormat.PMAdjustedPageRect..a.0..n. = 0
[Job 216] Gutenprint:  CUPS option 16 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.PageFormat.PMAdjustedPageRect..a.1..n. = 0
[Job 216] Gutenprint:  CUPS option 17 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.PageFormat.PMAdjustedPageRect..a.2..n. = 442.57321166992188
[Job 216] Gutenprint:  CUPS option 18 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.PageFormat.PMAdjustedPageRect..a.3..n. = 297.60940551757812
[Job 216] Gutenprint:  CUPS option 19 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.PageFormat.PMAdjustedPaperRect..a.0..n. = 0
[Job 216] Gutenprint:  CUPS option 20 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.PageFormat.PMAdjustedPaperRect..a.1..n. = 0
[Job 216] Gutenprint:  CUPS option 21 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.PageFormat.PMAdjustedPaperRect..a.2..n. = 442.57321166992188
[Job 216] Gutenprint:  CUPS option 22 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.PageFormat.PMAdjustedPaperRect..a.3..n. = 297.60940551757812
[Job 216] Gutenprint:  CUPS option 23 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.PaperInfo.PMCustomPaper..b. = false
[Job 216] Gutenprint:  CUPS option 24 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.PaperInfo.PMPaperName = 104.99x156.13mm
[Job 216] Gutenprint:  CUPS option 25 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.PaperInfo.PMUnadjustedPageRect..a.0..n. = 0
[Job 216] Gutenprint:  CUPS option 26 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.PaperInfo.PMUnadjustedPageRect..a.1..n. = 0
[Job 216] Gutenprint:  CUPS option 27 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.PaperInfo.PMUnadjustedPageRect..a.2..n. = 442.57321166992188
[Job 216] Gutenprint:  CUPS option 28 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.PaperInfo.PMUnadjustedPageRect..a.3..n. = 297.60940551757812
[Job 216] Gutenprint:  CUPS option 29 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.PaperInfo.PMUnadjustedPaperRect..a.0..n. = 0
[Job 216] Gutenprint:  CUPS option 30 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.PaperInfo.PMUnadjustedPaperRect..a.1..n. = 0
[Job 216] Gutenprint:  CUPS option 31 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.PaperInfo.PMUnadjustedPaperRect..a.2..n. = 442.57321166992188
[Job 216] Gutenprint:  CUPS option 32 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.PaperInfo.PMUnadjustedPaperRect..a.3..n. = 297.60940551757812
[Job 216] Gutenprint:  CUPS option 33 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.PaperInfo.ppd.PMPaperName = 104.99x156.13mm
[Job 216] Gutenprint:  CUPS option 34 com.apple.print.preset.PaperInfo..d.paperInfo..d.com.apple.print.ticket.type = com.apple.print.PaperInfoTicket
[Job 216] Gutenprint:  CUPS option 35 com.apple.print.preset.PaperInfo..d.paperInfo..d.PMPPDPaperCodeName = 104.99x156.13mm
[Job 216] Gutenprint:  CUPS option 36 com.apple.print.preset.PaperInfo..d.paperInfo..d.PMPPDTranslationStringPaperName = 104.99x156.13mm
[Job 216] Gutenprint:  CUPS option 37 com.apple.print.preset.PaperInfo..d.paperInfo..d.PMTiogaPaperName = 104.99x156.13mm
[Job 216] Gutenprint:  CUPS option 38 com.apple.print.PrinterInfo.PMColorDeviceID..n. = 7385
[Job 216] Gutenprint:  CUPS option 39 com.apple.print.PrintSettings.PMColorSpaceModel..n. = 2
[Job 216] Gutenprint:  CUPS option 40 com.apple.print.PrintSettings.PMCopies..n. = 2
[Job 216] Gutenprint:  CUPS option 41 com.apple.print.PrintSettings.PMCopyCollate..b. = true
[Job 216] Gutenprint:  CUPS option 42 com.apple.print.PrintSettings.PMDestinationType..n. = 1
[Job 216] Gutenprint:  CUPS option 43 com.apple.print.PrintSettings.PMDuplexing..n. = 1
[Job 216] Gutenprint:  CUPS option 44 com.apple.print.PrintSettings.PMFirstPage..n. = 1
[Job 216] Gutenprint:  CUPS option 45 com.apple.print.PrintSettings.PMLastPage..n. = 2147483647
[Job 216] Gutenprint:  CUPS option 46 com.apple.print.PrintSettings.PMPageRange..a.0..n. = 1
[Job 216] Gutenprint:  CUPS option 47 com.apple.print.PrintSettings.PMPageRange..a.1..n. = 2147483647
[Job 216] Gutenprint:  CUPS option 48 com.apple.print.PrintSettings.PMTotalBeginPages..n. = 1
[Job 216] Gutenprint:  CUPS option 49 com.apple.print.PrintSettings.PMTotalSidesImaged..n. = 2
[Job 216] Gutenprint:  CUPS option 50 com.apple.print.totalPages..n. = 1
[Job 216] Gutenprint:  CUPS option 51 date-time-at-creation =
[Job 216] Gutenprint:  CUPS option 52 date-time-at-processing =
[Job 216] Gutenprint:  CUPS option 53 DestinationPrinterID = Joyspace_U826
[Job 216] Gutenprint:  CUPS option 54 document-name-supplied = 20090117 IMG_7901.JPG
[Job 216] Gutenprint:  CUPS option 55 Duplex = None
[Job 216] Gutenprint:  CUPS option 56 job-originating-host-name = 192.168.10.193
[Job 216] Gutenprint:  CUPS option 57 job-uuid = urn:uuid:d5e6f44e-834b-3b82-58ee-9711f35624c7
[Job 216] Gutenprint:  CUPS option 58 media = 104.99x156.13mm
[Job 216] Gutenprint:  CUPS option 59 PageSize = 104.99x156.13mm
[Job 216] Gutenprint:  CUPS option 60 PaperInfoIsSuggested..b. = true
[Job 216] Gutenprint:  CUPS option 61 PDFIsProtected..b. = false
[Job 216] Gutenprint:  CUPS option 62 pserrorhandler-requested = standard
[Job 216] Gutenprint:  CUPS option 63 sides = one-sided
[Job 216] Gutenprint:  CUPS option 64 time-at-creation = 1735673751
[Job 216] Gutenprint:  CUPS option 65 time-at-processing = 1735673753

[Job 216] cfFilterGhostscript: Processing page 1...

[Job 216] cfFilterGhostscript: Processing page 2...

It shows that MacOS is requesting two copies of one page, but it looks like the universal filter's pdftopdf step is apparently doubling this up to two pages, passing that to ghostscript, before eventually sending that to rastertogutenprint (which takes the 'copies' argument from the command line and tells the printer to generate two copies)

I haven't figured out how to enable more verbose debugging of the pdftopdf or ghostscript filters yet, if I can I'll update this with more info.

attrs.txt
cups.log.txt
U826.ppd.txt

@michaelrsweet
Copy link
Member

Not sure what is going on here, but the CUPS server is getting a PDF file from the Mac so it should just be pdftopdf adding the copies? Moving to the cups-filters project to debug... (not a CUPS problem...)

@michaelrsweet michaelrsweet transferred this issue from OpenPrinting/cups Jan 1, 2025
@ValdikSS
Copy link

ValdikSS commented Jan 1, 2025

@speachy could you please test the following

  1. Print with collate=off
  2. Setup your printer destination as file:///tmp/testprint, print into file, and check whether 2 page resulting document is 4 times larger than 1 page (with collate=on).

I have a report of a similar issue, but I can't reproduce it on macOS 13 and 10.15.

With collate=on, if PPD does not have Collate option (hardware collate), the filter will duplicate the pages. #3265

@ValdikSS
Copy link

ValdikSS commented Jan 1, 2025

OpenPrinting/libcupsfilters#53 may be relevant

@speachy
Copy link
Author

speachy commented Jan 1, 2025

The MacOS print dialog (or at least the photo preview application) doesn't give the option of collating or not. It appears that it automatically requests collation if you request more than one copy, even if you are printing only one page.

For these dye-sublimation photo printers, multi-page jobs are exceedingly rare, but most models support producing multiple copies of a single image and this feature is widely used in practice due to the performance/throughput benefits.

I guess a least-PITA workaround in the short term is to claim support for hardware collation on the models that support hardware copies.

That doesn't change the underlying problem that we shoudn't be manually making copies without also telling the later parts of the filter chain that only one copy is requested.

@ValdikSS
Copy link

ValdikSS commented Jan 1, 2025

The MacOS print dialog (or at least the photo preview application) doesn't give the option of collating or not

It does, open "paper handling" tab in the printing dialog. It is present in "preview" app when printing jpeg, at least in macOS 13.

I guess a least-PITA workaround in the short term is to claim support for hardware collation on the models that support hardware copies.

Unfortunately, I'm unable to reproduce this issue on macOS 13 and 10.15. The user who has reported this issue to me (I'm not a part of cups/cups-filters project, but i'm selling print servers) is using brlaser driver (which accepts cups-raster only, manualcopies=false, no collation in ppd), poppler instead of ghostscript is configured in cups.

The user reports the issue on macOS 14 and 10.15, when printing pdfs and webpages from safari. I'm waiting for more info from the user, but if you have any additional details and peculiarities on how to reproduce this issue, please post.

FYI, the print server is running Debian 12: cups 2.4.2-3 (+debian patches), cups-filters 1.28.17-3 (+debian patches).

@speachy
Copy link
Author

speachy commented Jan 1, 2025

It does, open "paper handling" tab in the printing dialog. It is present in "preview" app when printing jpeg, at least in macOS 13.

Ah, the "tab" that's not actually a tab. Not exactly the most discoverable interface..

Turning off collation resulted in the desired outcome.

Interestingly, editing the PPD to specify '*Collate: False' (or True) seems to have no effect; if collation is requested by the application, the filter chain appears to produces its own copies no matter what. (I need to double-check this though, I don't think I added it properly)

Unfortunately, I'm unable to reproduce this issue on macOS 13 and 10.15. The user who has reported this issue to me (I'm not a part of cups/cups-filters project, but i'm selling print servers) is using brlaser driver (which accepts cups-raster only, manualcopies=false, no collation in ppd), poppler instead of ghostscript is configured in cups.

The Mac in question is currently running Big Sur (11.7) and printing from the built-in photo preview application. After running out of paper with the Joyspace U826 I originally reported this against, I switched to a Kodak 605 which exhibits the same problem -- It is trivially recreateable with any Gutenprint-supported dyesub model that can produce its own copies.

@speachy
Copy link
Author

speachy commented Jan 4, 2025

cups-filters does the expected thing with a construct like this added to the PPD:

*OpenUI *Collate/Collate: Boolean
*OrderDependency: 50 AnySetup *Collate
*DefaultCollate: True
*Collate False/Off: ""
*Collate True/On: ""
*CloseUI: *Collate

I've altered Gutenprint's PPD generator to add something similar for all models that report "cupsManualCopies: False", but this is still just a workaround.

@ValdikSS
Copy link

ValdikSS commented Jan 5, 2025

Unfortunately I still not able to reproduce it on my Debian 12 system with the output to a file://, even with Kodak 605. I'm printing a .jpg file from Preview application with copies=2 and collate=on, get two pages (as expected) to gutenprint, and despite the command line has copies=2 in the argv (as stated by you), gutenprint parses the raster header, and gets NumCopies=1 right.

The output document presumably has 2 pages with copies=1 in the header, as checked with hexdump:

# hexdump -n 8 -C /tmp/testprnt 
00000000  01 40 0a 00 01 00 **01** 34                           |[email protected]|

What's strange is that in your log, NumCopies is also 1, but your log also has Printing started (2 copies) / Parsed page 2 (2 copies), while my does not contain this string.

Skimming through Gutenprint code, I can see that Parsed page string is generated by the gutenprint backend code, not by rastertoX:

$ grep -r Parsed
src/cups/backend_common.c:      INFO("Parsed page %d (%d copies)\n", read_page, ncopies);
if (argv[base + 3])
    ncopies = atoi(argv[base + 3]);

So apparently it is not reproducible with file://, but only with gutenprint53+usb?

CUPS documentations says the following:

The argv[4] argument specifies the number of copies to produce of the input file. In general, you should only generate copies if the filename argument is supplied. The only exception to this are filters that produce device-independent PostScript output, since the PostScript filter pstops is responsible for generating copies of PostScript files.

Could this be the bug in gutenprint53+usb then, which should parse NumCopies instead of argv[4]?

@ValdikSS
Copy link

ValdikSS commented Jan 5, 2025

Guess I found the mistake, grep by Use larger of our copy counts string in gutenprint backends.

/* Use larger of our copy counts */
if (job->common.copies < copies)
    job->common.copies = copies;
$ grep -r 'copy counts'
backend_shinkos6245.c:  /* Use larger of our copy counts */
backend_kodak6800.c:    /* Use larger of our copy counts */
backend_shinkos1245.c:  /* Use larger of our copy counts */
backend_kodak605.c:     /* Use larger of our copy counts */

@speachy
Copy link
Author

speachy commented Jan 5, 2025

Guess I found the mistake, grep by Use larger of our copy counts string in gutenprint backends.

No, that's not the mistake. or at least not THE mistake.

[Job 216] Gutenprint: ================ Printing page 2      ================
[Job 216] PAGE: 2 1

(Line 1351-2 of rastertogutenprint.c)

Backing up a step; from the logs above, you can see that both Gutenprint and Ghostscript are handed two pages, the PPD option NumCopies is set to 2, and '2' is the copy count handed to all filters (including the backend) on the command line. HOWEVER, the 'NumCopies' argument cups_page_header_t/cups_page_header2_t on each individual page handed to gutenprint is set to 1.

The salient question -- Should the NumCopies in the page header always take precedence over the PPD NumCopies setting (and/or the filter cmdline argument?) Either way, how exactly is the backend supposed to know, given that it doesn't have access to the page header, just the cmdline (and PPD) which specify two copies?

Going back to the the backend's "use larger of" logic -- that was put there for backwards compatibility reasons at the time that gutenprint gained the ability to parse NumCopies itself. Additionally, the backend actually implements manual copy creation (on printers that normally can do it completely in hardware) in some circumstances.

@ValdikSS
Copy link

ValdikSS commented Jan 5, 2025

Yes, I understand, I can see this irregularity myself.

splix, brlaser, some other filters all use the value from cups_page_header2_t, and don't use argv[4] at all anywhere.
Since CUPS "Filter and Backend Programming" documentation mentions that argv[4] should not be used unless the filter produces postscript output, I guess that applies to backends as well.
Don't know about Copies from PPD, but I don't see NumCopies=2 anywhere in the log.

@michaelrsweet ^^^

@michaelrsweet
Copy link
Member

@speachy @ValdikSS A filter or backend is only responsible for producing copies when they are given a file to print. If they are reading data from stdin, they should assume that the number of copies (on the command-line) has been applied. For a backend the only time you normally see it producing copies is when doing so-called "raw" printing of printer-ready data.

You can't depend on the NumCopies field in the raster page header because it represents the number of uncollated copies the printer should produce, and then only if the PPD file contains the "cupsManualCopies: false" keyword/value (a value of "true" means the printer can't make its own copies so the RIP filter needs to generate them at all times...) A separate PPD keyword (cupsMaxCopies) tells the RIP filter the maximum number of copies the printer supports...

@ValdikSS
Copy link

ValdikSS commented Jan 5, 2025

You can't depend on the NumCopies field in the raster page header

But that's all the filters I checked do, and it works as intended for both cupsManualCopies=true and false, collated and uncollated printouts. Do you have an example how it should be done then? Could you describe which logic gutenprint with its filter+backend architecture should use?

Or did you mean argv[4], not raster header data?

@michaelrsweet
Copy link
Member

@ValdikSS As a raster driver (filter), you look at NumCopies and generate copies if NumCopies > 1. This should always work as expected with the usual cups-filters and when you (as the driver developer) provide the correct values in the PPD file.

I say "you can't depend on NumCopies" to know whether a job is producing multiple copies. All it tells you is, as a driver filter, whether you need to produce an (uncollated) copy of this page - nothing more, nothing less.

The Gutenprint backend should only be producing copies of files supplied on the command-line ("raw" printing) and otherwise not producing copies at all. It is up to the Gutenprint raster filter to do any (uncollated) copy generation.

@speachy
Copy link
Author

speachy commented Jan 5, 2025

If I'm understanding this correctly, the NumCopies PPD option applies to the job as a whole, but the NumCopies value in the cupsraster page header is only for the specific page in a given job?

Consequently, a rastertoPRINTER filter should only pay attention to the NumCopies PPD option if it supports job Collation?

Meanwhile, with respect to the backend, it's been long enough that dropping the backwards compatibility workarounds for page copy generation is warranted. But it seems that no matter which way I go I'm going to cause regressions for some folks. I'll have the backend ignore argv[4] if no filename is supplied, and work through the fallout..)

@michaelrsweet
Copy link
Member

@speachy NumCopies only exists as a CUPS raster page header field and corresponding PostScript device dictionary value. CUPS uses the name "copies", which corresponds to the IPP attribute of the same name which applies to the entire job and is passed in argv[4] to filters and the backend.

The per-page header field NumCopies specifies the number of uncollated copies for that page.

Consequently, a rastertoPRINTER filter should only pay attention to the NumCopies PPD option if it supports job Collation?

No, rastertoPRINTER filters should only pay attention to the NumCopies field in the cups_page_header_t structure (CUPS raster page header), and then ONLY if the printer actually supports making its own copies. Most of the printers supported by Gutenprint do not support copy generation and depend on the computer to send multiple pages when copies are needed. If the PPD file correctly reflects the printer's ability to do copies, then you will only ever see the number 1 in that field anyways... Trust that the upstream filters will be generating the copies for you as needed, and you just print whatever comes your way...

@speachy
Copy link
Author

speachy commented Jan 7, 2025

Okay, I've rejiggered things so that rastertogutenprint only uses the NumCopies from cups_page_header_t, and will pass that information in-band to the printer (if supported/appropriate), and the backend will now only care about argv4[] if a file is passed on the filter command line.

...I still have yet to run this stuff through any sort of regression/smoke tests. I guess we can consider this resolved.

@speachy speachy closed this as completed Jan 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants