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

driverless: Incorrectly passing IPP 'media' value directly as 'PageSize' argument #1125

Open
speachy opened this issue Dec 23, 2024 · 3 comments

Comments

@speachy
Copy link
Contributor

speachy commented Dec 23, 2024

I do nearly all of my printing using native CUPS queues. That works perfectly. However some members of my household wish to use (eg) Mac systems to print using AirPrint. That malfunctions quite spectacularly.

The PPD specifies page sizes using nominal names like 'w360h504' for a 5x7" print. However the actual paper dimensions are slightly larger (~371x514pt). The 'drivereless' printer translates this to IPP print sizes like "custom_131.06x181.19mm_131.06x181.19mm_borderless" and exports that to clients. So far so good.

Unfortunately, when the client selects this size and submits a print job, the driverless filter passes the IPP size through instead of finding the matching size in the PPD -- Eg the PageSize option gets set to "131.06x181.19mm.Borderless" instead of the "w360h504' specified in the PPD. As the submitted PageSize is not one of the legal options enumerated in the PPD, the filter fails to find a match yielding incorrect output, if not an outright error due to a media type mismatch.

This is 100% reproducible on the fully up-to-date Fedora 41 system that acts as my current printer server. The major components in play:

cups-2.4.11-8
cups-filters-2.0.1-1
gutenprint 5.3.5-pre1

This is a representative eample of the options that CUPS is passing to the filter chain:

noCollate ColorModel=RGB job-uuid=urn:uuid:36242691-74a8-3363-41de-d1256a095156 media=custom_131.06x181.19mm_131.06x181.19mm_borderless MediaType=Standard number-up=1 OutputBin=FaceDown
PageSize=131.06x181.19mm.Borderless print-quality=4 job-originating-host-name=XXX date-time-at-creation= date-time-at-processing= time-at-creation=1734972775 time-at-processing=1734972775 cupsPrintQuality=Normal

rastertogutenprint's parsing makes this more legible:

]: [Job 64] Gutenprint:  CUPS option 13 time-at-processing = 1734972775
]: [Job 64] Gutenprint:  CUPS option 12 time-at-creation = 1734972775
]: [Job 64] Gutenprint:  CUPS option 11 PageSize = 131.06x181.19mm.Borderless
]: [Job 64] Gutenprint:  CUPS option 10 OutputBin = FaceDown
]: [Job 64] Gutenprint:  CUPS option 9 number-up = 1
]: [Job 64] Gutenprint:  CUPS option 8 MediaType = Standard
]: [Job 64] Gutenprint:  CUPS option 7 media = custom_131.06x181.19mm_131.06x181.19mm_borderless
]: [Job 64] Gutenprint:  CUPS option 6 job-uuid = urn:uuid:36242691-74a8-3363-41de-d1256a095156
]: [Job 64] Gutenprint:  CUPS option 5 job-originating-host-name = XXX
]: [Job 64] Gutenprint:  CUPS option 4 date-time-at-processing =
]: [Job 64] Gutenprint:  CUPS option 3 date-time-at-creation =
]: [Job 64] Gutenprint:  CUPS option 2 cupsPrintQuality = Normal
]: [Job 64] Gutenprint:  CUPS option 1 ColorModel = RGB
]: [Job 64] Gutenprint:  CUPS option 0 Collate = false

option 7 shows the IPP media atrtibute, and option 11 shows how this was translated into the 'PageSize' PPD option. Below is the actual options lifted from the PPD:

*PageSize w360h504/5x7: "<</PageSize[371.520 513.600]/ImagingBBox null>>setpagedevice"
*PageRegion w360h504/5x7:       "<</PageSize[371.520 513.600]/ImagingBBox null>>setpagedevice"
*ImageableArea w360h504/5x7:    "0.000 0.000 371.520 513.600"
*PaperDimension w360h504/5x7:   "371.520 513.600"

131.06x181.19mm converts back to 371.509 x 513.609 points, clearly some rounding errors in play. But I don't know if that's responsible for this failure or not.

I realize that Gutenprint playing a bit loose with PageSizes (eg w360h504 actually being 372x514) but I'd still expect a valid (ie present in the PPD) PageSize passed into the rastertogutenprint filter.

EDIT: Given that the IPP sizes reported are clearly derived from the specifics of the PageSize/ImageableArea definittion rather than the wXXXhYYY identifier, it stands to reason that a reverse lookup would work the same way.

@tillkamppeter
Copy link
Member

Can you tell us how you exactly have set up the queue and also attach the PPD file in use?

Could you also run the follwing command (from a Linux client):

ipptool -tv ipp://HOSTNAME_OR_IP:631/printers/QUEUE get-printer-attributes.test > attrs.txt

Replace HOSTNAME_OR_IP by the appropriate of your server and QUEUE by the name of your print queue on your server. Please attach the file attrs.txt to this issue.

The client (macOS in your case) discovers the print server with your printer via DNS-SD and sends a get-printer-attributes IPP request. The response contains the list of paper sizes, with generated IPP names and with size dimensions (in units of 1/100 of a mm). This response is solely produced by CUPS based on the PPD file. Code of cups-filters or libcupsfilters is not involved here.

When sending a job, CUPS is generating the option list to supply to the filter chain. CUPS could try to match the media size with the PageSize entries of the PPD here.

Now you tell that a "driverless filter" does something wrong here. What do you mean with driverless filter?

For me it seems that what is needed is that rastertogutenprint needs to adjust the size to the one of the PPD file here so that the printer gets the correct amount of pixels.

So for me I do not see a bug in cups-filters, both CUPS and rastertogutenprint could snap the size requested by the job to the next PPD size (the gstoraster CUPS filter does that, too).

CUPS will not be able to send w360h504 in its IPP response as this is not an IPP standard name.

Moving to CUPS ...

@tillkamppeter tillkamppeter transferred this issue from OpenPrinting/cups-filters Dec 23, 2024
@speachy
Copy link
Contributor Author

speachy commented Dec 24, 2024

Apologies for incorrectly blaming 'driverless' but everything works correctly when using traditional CUPS queues (eg printing via LP/LPR on the command line).

As for what you asked for, see attached PPD and IPP attribute dump.

attrs.txt
P520L.ppd.txt

The specific queue was set up through the CUPS web UI, and it will happily generates a successful test print. This failure happens with both MacOS's photo preview app and Firefox on Linux (Fedora 41) on two different printers.

This "pass the filter a PageSize identifier not present in the PPD" behavior not only breaks Gutenprint but numerous manufacturer PPD-based drivers -- Every PPD-based driver I've encountered matches against their identifier list solely using strcmp(). If a more elaborate parsing/matching strategy is needed, shouldn't CUPS do this itself as part of the cupsMarkOptions() call?

(I might add that Gutenprint can and does handle truly "custom" page sizes when requested via the PageSizeCustom PPD option. But that's not being passed in here)

  num_options = cupsParseOptions(argv[5], 0, &options);
  ppdMarkDefaults(ppd);
  cupsMarkOptions(ppd, num_options, options);
  ppd_size_t size = ppdPageSize(ppd, NULL);

@speachy
Copy link
Contributor Author

speachy commented Dec 30, 2024

It looks like CUPS is generating (eg) "custom_131.06x181.19mm_131.06x181.19mm_borderless" in the IPP attributes based on the entry in the PPD, but it is not passing that "custom" definition to the derived PageSize -- ie it's passing "131.06x181.19mm.Borderless" instead of "Custom.131.06x181.19mm.Borderless"

Because there is no 'Custom.' prefix in the PageSize, cupsMarkOptions(), ppd_mark_option(), and ppdPageSize() only attempts to perform a simple string match lookup, which fails to find a match, so we end up falling back to the default option marked in the PPD.

So, there appear to be two separate problems in play here with PPD-based printer queues:

  1. CUPS is not respecting its own conventions by failing to properly map "custom" IPP media sizes to a "Custom" PPD PageSize.
  2. CUPS is not attempting to reverse-lookup/map a "custom" IPP media size to the list of PageSizes specified in the PPD.

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

2 participants