From c96c3adda8b637ea884b13505d4d8e16a3c2783f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lipinsk=C3=BD?= <6032558+Mr-Tao@users.noreply.github.com> Date: Tue, 18 Aug 2026 21:09:50 +0200 Subject: [PATCH] Add 8-up printing support --- berkeley/lpr.c | 2 +- doc/help/man-lp.html | 4 +- doc/help/man-lpr.html | 4 +- doc/help/options.html | 3 +- filter/pstops.c | 99 +++++++++++++++++++++++++++++++++- man/lp.1 | 4 +- man/lpr.1 | 4 +- scheduler/ipp.c | 1 + scheduler/printers.c | 1 + systemv/lp.c | 2 +- test/4.2-cups-printer-ops.test | 1 + test/5.6-lpr.sh | 4 +- 12 files changed, 114 insertions(+), 15 deletions(-) diff --git a/berkeley/lpr.c b/berkeley/lpr.c index 287e5e2f4f..1bdf6c6144 100644 --- a/berkeley/lpr.c +++ b/berkeley/lpr.c @@ -438,7 +438,7 @@ usage(void) _cupsLangPuts(stdout, _("-o option[=value] Specify a printer-specific option")); _cupsLangPuts(stdout, _("-o job-sheets=standard Print a banner page with the job")); _cupsLangPuts(stdout, _("-o media=size Specify the media size to use")); - _cupsLangPuts(stdout, _("-o number-up=N Specify that input pages should be printed N-up (1, 2, 4, 6, 9, and 16 are supported)")); + _cupsLangPuts(stdout, _("-o number-up=N Specify that input pages should be printed N-up (1, 2, 4, 6, 8, 9, and 16 are supported)")); _cupsLangPuts(stdout, _("-o orientation-requested=N\n" " Specify portrait (3) or landscape (4) orientation")); _cupsLangPuts(stdout, _("-o print-quality=N Specify the print quality - draft (3), normal (4), or best (5)")); diff --git a/doc/help/man-lp.html b/doc/help/man-lp.html index 7b3e448390..db6fcc9965 100644 --- a/doc/help/man-lp.html +++ b/doc/help/man-lp.html @@ -173,8 +173,8 @@

Common Job Options

-o media=size
Sets the page size to size. Most printers support at least the size names "a4", "letter", and "legal".

-

-o number-up={2|4|6|9|16}
-Prints 2, 4, 6, 9, or 16 document (input) pages on each output page. +

-o number-up={2|4|6|8|9|16}
+Prints 2, 4, 6, 8, 9, or 16 document (input) pages on each output page.

-o orientation-requested=4
Prints the job in landscape (rotated 90 degrees counter-clockwise). diff --git a/doc/help/man-lpr.html b/doc/help/man-lpr.html index c5f5b3548a..f79da9369d 100644 --- a/doc/help/man-lpr.html +++ b/doc/help/man-lpr.html @@ -128,8 +128,8 @@

Common Job Options

-o media=size
Sets the page size to size. Most printers support at least the size names "a4", "letter", and "legal".

-

-o number-up={2|4|6|9|16}
-Prints 2, 4, 6, 9, or 16 document (input) pages on each output page. +

-o number-up={2|4|6|8|9|16}
+Prints 2, 4, 6, 8, 9, or 16 document (input) pages on each output page.

-o orientation-requested=4
Prints the job in landscape (rotated 90 degrees counter-clockwise). diff --git a/doc/help/options.html b/doc/help/options.html index 9d612fcc97..dc4efb6070 100644 --- a/doc/help/options.html +++ b/doc/help/options.html @@ -456,13 +456,14 @@

N-Up Printing

The -o number-up=value option selects N-Up printing. N-Up printing places multiple document pages on a -single printed page. CUPS supports 1, 2, 4, 6, 9, and 16-Up +single printed page. CUPS supports 1, 2, 4, 6, 8, 9, and 16-Up formats; the default format is 1-Up:

 lp -o number-up=1 filename
 lp -o number-up=2 filename
 lp -o number-up=4 filename
+lpr -o number-up=8 filename
 lpr -o number-up=16 filename
 
diff --git a/filter/pstops.c b/filter/pstops.c index 987ecc9c80..fe5d44b922 100644 --- a/filter/pstops.c +++ b/filter/pstops.c @@ -1973,10 +1973,10 @@ do_setup(pstops_doc_t *doc, /* I - Document information */ * Write the page and label prologs... */ - if (doc->number_up == 2 || doc->number_up == 6) + if (doc->number_up == 2 || doc->number_up == 6 || doc->number_up == 8) { /* - * For 2- and 6-up output, rotate the labels to match the orientation + * For 2-, 6-, and 8-up output, rotate the labels to match the orientation * of the pages... */ @@ -2079,6 +2079,7 @@ end_nup(pstops_doc_t *doc, /* I - Document information */ case 2 : case 6 : + case 8 : if (is_last_page(number) && doc->use_ESPshowpage) { if (Orientation & 1) @@ -2431,6 +2432,7 @@ set_pstops_options( case 2 : case 4 : case 6 : + case 8 : case 9 : case 16 : doc->number_up = intval; @@ -3007,6 +3009,99 @@ start_nup(pstops_doc_t *doc, /* I - Document information */ } break; + case 8 : + if (Orientation & 1) + { + if (doc->number_up_layout & PSTOPS_LAYOUT_VERTICAL) + { + x = pos / 4; + y = pos & 3; + + if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEX) + x = 1 - x; + + if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEY) + y = 3 - y; + } + else + { + x = pos & 1; + y = pos / 2; + + if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEX) + x = 1 - x; + + if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEY) + y = 3 - y; + } + + w = pagel * 0.5; + l = w * bboxl / bboxw; + + if (l > (pagew * 0.25)) + { + l = pagew * 0.25; + w = l * bboxw / bboxl; + } + + tx = 0.5 * (pagel - 2 * w); + ty = 0.5 * (pagew - 4 * l); + + if (doc->normal_landscape) + doc_printf(doc, "0 %.1f translate -90 rotate\n", pagel); + else + doc_printf(doc, "%.1f 0 translate 90 rotate\n", pagew); + + doc_printf(doc, "%.1f %.1f translate %.3f %.3f scale\n", + tx + x * w, ty + y * l, l / bboxl, w / bboxw); + } + else + { + if (doc->number_up_layout & PSTOPS_LAYOUT_VERTICAL) + { + x = pos / 2; + y = pos & 1; + + if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEX) + x = 3 - x; + + if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEY) + y = 1 - y; + } + else + { + x = pos & 3; + y = pos / 4; + + if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEX) + x = 3 - x; + + if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEY) + y = 1 - y; + } + + l = pagew * 0.5; + w = l * bboxw / bboxl; + + if (w > (pagel * 0.25)) + { + w = pagel * 0.25; + l = w * bboxl / bboxw; + } + + tx = 0.5 * (pagel - 4 * w); + ty = 0.5 * (pagew - 2 * l); + + if (doc->normal_landscape) + doc_printf(doc, "%.1f 0 translate 90 rotate\n", pagew); + else + doc_printf(doc, "0 %.1f translate -90 rotate\n", pagel); + + doc_printf(doc, "%.1f %.1f translate %.3f %.3f scale\n", + tx + w * x, ty + l * y, w / bboxw, l / bboxl); + } + break; + case 9 : if (doc->number_up_layout & PSTOPS_LAYOUT_VERTICAL) { diff --git a/man/lp.1 b/man/lp.1 index 26d7421ffa..7133606e2d 100644 --- a/man/lp.1 +++ b/man/lp.1 @@ -168,8 +168,8 @@ The "name" can be "classified", "confidential", "secret", "standard", "topsecret \fB\-o media=\fIsize\fR Sets the page size to \fIsize\fR. Most printers support at least the size names "a4", "letter", and "legal". .TP 5 -\fB\-o number\-up=\fR{\fI2|4|6|9|16\fR} -Prints 2, 4, 6, 9, or 16 document (input) pages on each output page. +\fB\-o number\-up=\fR{\fI2|4|6|8|9|16\fR} +Prints 2, 4, 6, 8, 9, or 16 document (input) pages on each output page. .TP 5 \fB\-o orientation\-requested=4\fR Prints the job in landscape (rotated 90 degrees counter-clockwise). diff --git a/man/lpr.1 b/man/lpr.1 index febd920bed..8c4560612b 100644 --- a/man/lpr.1 +++ b/man/lpr.1 @@ -123,8 +123,8 @@ The "name" can be "classified", "confidential", "secret", "standard", "topsecret \fB\-o media=\fIsize\fR Sets the page size to \fIsize\fR. Most printers support at least the size names "a4", "letter", and "legal". .TP 5 -\fB\-o number\-up=\fR{\fI2|4|6|9|16\fR} -Prints 2, 4, 6, 9, or 16 document (input) pages on each output page. +\fB\-o number\-up=\fR{\fI2|4|6|8|9|16\fR} +Prints 2, 4, 6, 8, 9, or 16 document (input) pages on each output page. .TP 5 \fB\-o orientation\-requested=4\fR Prints the job in landscape (rotated 90 degrees counter-clockwise). diff --git a/scheduler/ipp.c b/scheduler/ipp.c index bf0072c80d..e23af75e2a 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -1349,6 +1349,7 @@ add_job(cupsd_client_t *con, /* I - Client connection */ attr->values[0].integer != 2 && attr->values[0].integer != 4 && attr->values[0].integer != 6 && + attr->values[0].integer != 8 && attr->values[0].integer != 9 && attr->values[0].integer != 16) { diff --git a/scheduler/printers.c b/scheduler/printers.c index ec50183815..18a3822a33 100644 --- a/scheduler/printers.c +++ b/scheduler/printers.c @@ -180,6 +180,7 @@ cupsdCreateCommonData(void) 2, 4, 6, + 8, 9, 16 }; diff --git a/systemv/lp.c b/systemv/lp.c index f277f3c8d4..15dea8b1c8 100644 --- a/systemv/lp.c +++ b/systemv/lp.c @@ -766,7 +766,7 @@ usage(void) _cupsLangPuts(stdout, _("-o option[=value] Specify a printer-specific option")); _cupsLangPuts(stdout, _("-o job-sheets=standard Print a banner page with the job")); _cupsLangPuts(stdout, _("-o media=size Specify the media size to use")); - _cupsLangPuts(stdout, _("-o number-up=N Specify that input pages should be printed N-up (1, 2, 4, 6, 9, and 16 are supported)")); + _cupsLangPuts(stdout, _("-o number-up=N Specify that input pages should be printed N-up (1, 2, 4, 6, 8, 9, and 16 are supported)")); _cupsLangPuts(stdout, _("-o orientation-requested=N\n" " Specify portrait (3) or landscape (4) orientation")); _cupsLangPuts(stdout, _("-o print-quality=N Specify the print quality - draft (3), normal (4), or best (5)")); diff --git a/test/4.2-cups-printer-ops.test b/test/4.2-cups-printer-ops.test index 0abaccaf22..b1b702932e 100644 --- a/test/4.2-cups-printer-ops.test +++ b/test/4.2-cups-printer-ops.test @@ -326,4 +326,5 @@ # What attributes do we expect? EXPECT media-col-default + EXPECT number-up-supported WITH-VALUE 8 } diff --git a/test/5.6-lpr.sh b/test/5.6-lpr.sh index a02971b3c8..f0495c596a 100644 --- a/test/5.6-lpr.sh +++ b/test/5.6-lpr.sh @@ -36,8 +36,8 @@ echo "" echo "LPR Options Test" echo "" -echo " lpr -P Test1 -o number-up=4 -o job-sheets=standard,none testfile.pdf" -$runcups $VALGRIND ../berkeley/lpr -P Test1 -o number-up=4 -o job-sheets=standard,none ../examples/testfile.pdf 2>&1 +echo " lpr -P Test1 -o number-up=8 -o job-sheets=standard,none testfile.pdf" +$runcups $VALGRIND ../berkeley/lpr -P Test1 -o number-up=8 -o job-sheets=standard,none ../examples/testfile.pdf 2>&1 if test $? != 0; then echo " FAILED" exit 1