Fixing AirPrint bottom clipping on CUPS with Gutenprint

When printing via AirPrint to a CUPS server using a Gutenprint driver (tested with a Canon PIXMA MG2450), the bottom of most pages gets cut off. The CUPS test page, PDFs, web pages - everything loses content - mostly at the bottom for me. Direct printing via lp works better.

The cause

iOS seems to hardcode print-scaling=auto-fit in every print job it sends. The pdftopdf filter in CUPS interprets auto-fit as: "if the source page size matches the target page size, do not scale — just center and crop." Since both source and target are A4, no scaling happens, and any content in the non-printable margin zone is simply cropped off.

This is different from print-scaling=fit, which scales content to fit within the imageable area (the page minus margins). With printers that have large bottom margins (the MG2450 has a 16.7mm hardware limit per Canon's spec), the cropped zone is substantial.

Server-side settings like fitplot or print-scaling-default don't help because the client-specified print-scaling job attribute takes priority over server defaults.

Testing

I made an A4 pdf file for testing with much less ink use than most test pdfs, you can get it at margin.pdf.

My fix

1. Fix the PPD imageable area

On this printer the Gutenprint PPD reported incorrect imageable area limits — the bottom margin was set to about 5.3mm when Canon's spec says 16.7mm. I edited /etc/cups/ppd/Canon_MG2450.ppd and changed the bottom margin value in both *HWMargins and *ImageableArea A4 from 15.000 to 48.189 (17mm in PostScript points). Check your printer's spec and adjust accordingly.

2. Replace the pdftopdf filter

Rename the original filter and replace it with a wrapper that rewrites auto-fit to fit:

sudo mv /usr/lib/cups/filter/pdftopdf /usr/lib/cups/filter/pdftopdf.real

Create /usr/lib/cups/filter/pdftopdf with the following contents:

#!/bin/bash
# Override print-scaling=auto-fit from AirPrint clients.
# auto-fit compares page sizes and crops; fit scales to the imageable area.
OPTS="$(echo "$5" | sed 's/print-scaling=auto-fit/print-scaling=fit/g; s/print-scaling=auto\b/print-scaling=fit/g')"
exec /usr/lib/cups/filter/pdftopdf.real "$1" "$2" "$3" "$4" "$OPTS" "$6"

Make it executable and restart CUPS:

sudo chmod 755 /usr/lib/cups/filter/pdftopdf
sudo systemctl restart cups

Notes