]>
git.ipfire.org Git - thirdparty/cups.git/blob - filter/pstops.c
74eee05547a47eafc1578f9fbdfcc938a3203904
2 * "$Id: pstops.c,v 1.92 2002/12/17 16:17:27 mike Exp $"
4 * PostScript filter for the Common UNIX Printing System (CUPS).
6 * Copyright 1993-2002 by Easy Software Products.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
24 * This file is subject to the Apple OS-Developed Software exception.
28 * main() - Main entry...
29 * check_range() - Check to see if the current page is selected for
30 * copy_bytes() - Copy bytes from the input file to stdout...
31 * do_prolog() - Send the necessary document prolog commands...
32 * do_setup() - Send the necessary document setup commands...
33 * end_nup() - End processing for N-up printing...
34 * psgets() - Get a line from a file.
35 * start_nup() - Start processing for N-up printing...
39 * Include necessary headers...
49 #define MAX_PAGES 10000
51 #define BORDER_NONE 0 /* No border or hairline border */
52 #define BORDER_THICK 1 /* Think border */
53 #define BORDER_SINGLE 2 /* Single-line hairline border */
54 #define BORDER_SINGLE2 3 /* Single-line thick border */
55 #define BORDER_DOUBLE 4 /* Double-line hairline border */
56 #define BORDER_DOUBLE2 5 /* Double-line thick border */
58 #define LAYOUT_LRBT 0 /* Left to right, bottom to top */
59 #define LAYOUT_LRTB 1 /* Left to right, top to bottom */
60 #define LAYOUT_RLBT 2 /* Right to left, bottom to top */
61 #define LAYOUT_RLTB 3 /* Right to left, top to bottom */
62 #define LAYOUT_BTLR 4 /* Bottom to top, left to right */
63 #define LAYOUT_TBLR 5 /* Top to bottom, left to right */
64 #define LAYOUT_BTRL 6 /* Bottom to top, right to left */
65 #define LAYOUT_TBRL 7 /* Top to bottom, right to left */
67 #define LAYOUT_NEGATEY 1
68 #define LAYOUT_NEGATEX 2
69 #define LAYOUT_VERTICAL 4
76 int NumPages
= 0; /* Number of pages in file */
77 long Pages
[MAX_PAGES
]; /* Offsets to each page */
78 char PageLabels
[MAX_PAGES
][64];
80 const char *PageRanges
= NULL
; /* Range of pages selected */
81 const char *PageSet
= NULL
; /* All, Even, Odd pages */
82 int Order
= 0, /* 0 = normal, 1 = reverse pages */
83 Flip
= 0, /* Flip/mirror pages */
84 NUp
= 1, /* Number of pages on each sheet (1, 2, 4) */
85 Collate
= 0, /* Collate copies? */
86 Copies
= 1, /* Number of copies */
87 UseESPsp
= 0, /* Use ESPshowpage? */
88 Border
= BORDER_NONE
, /* Border around pages */
89 Layout
= LAYOUT_LRTB
, /* Layout of N-up pages */
90 NormalLandscape
= 0; /* Normal rotation for landscape? */
97 static int check_range(int page
);
98 static void copy_bytes(FILE *fp
, size_t length
);
99 static void do_prolog(ppd_file_t
*ppd
);
100 static void do_setup(ppd_file_t
*ppd
, int copies
, int collate
,
101 int slowcollate
, float g
, float b
);
102 static void end_nup(int number
);
103 #define is_first_page(p) (NUp == 1 || (((p)+1) % NUp) == 1)
104 #define is_last_page(p) (NUp > 1 && (((p)+1) % NUp) == 0)
105 #define is_not_last_page(p) (NUp > 1 && ((p) % NUp) != 0)
106 static char *psgets(char *buf
, size_t len
, FILE *fp
);
107 static void start_nup(int number
, int show_border
);
111 * 'main()' - Main entry...
114 int /* O - Exit status */
115 main(int argc
, /* I - Number of command-line arguments */
116 char *argv
[]) /* I - Command-line arguments */
118 FILE *fp
; /* Print file */
119 ppd_file_t
*ppd
; /* PPD file */
120 int num_options
; /* Number of print options */
121 cups_option_t
*options
; /* Print options */
122 const char *val
; /* Option value */
123 char tempfile
[255]; /* Temporary file name */
124 FILE *temp
; /* Temporary file */
125 int tempfd
; /* Temporary file descriptor */
126 int number
; /* Page number */
127 int slowcollate
; /* 1 if we need to collate manually */
128 int sloworder
; /* 1 if we need to order manually */
129 int slowduplex
; /* 1 if we need an even number of pages */
130 char line
[8192]; /* Line buffer */
131 float g
; /* Gamma correction value */
132 float b
; /* Brightness factor */
133 int level
; /* Nesting level for embedded files */
134 int nbytes
, /* Number of bytes read */
135 tbytes
; /* Total bytes to read for binary data */
136 int page
; /* Current page sequence number */
137 int real_page
; /* "Real" page number in document */
138 int page_count
; /* Page count for NUp */
139 int basepage
; /* Base page number */
140 int subpage
; /* Sub-page number */
141 int copy
; /* Current copy */
142 int saweof
; /* Did we see a %%EOF tag? */
143 int sent_espsp
, /* Did we send the ESPshowpage commands? */
144 sent_prolog
, /* Did we send the prolog commands? */
145 sent_setup
; /* Did we send the setup commands? */
149 * Make sure status messages are not buffered...
152 setbuf(stderr
, NULL
);
155 * Check command-line...
158 if (argc
< 6 || argc
> 7)
160 fputs("ERROR: pstops job-id user title copies options [file]\n", stderr
);
165 * If we have 7 arguments, print the file named on the command-line.
166 * Otherwise, send stdin instead...
174 * Try to open the print file...
177 if ((fp
= fopen(argv
[6], "rb")) == NULL
)
179 fprintf(stderr
, "ERROR: unable to open print file \"%s\" - %s\n",
180 argv
[6], strerror(errno
));
186 * Process command-line options and write the prolog...
192 Copies
= atoi(argv
[4]);
195 num_options
= cupsParseOptions(argv
[5], 0, &options
);
197 ppd
= SetCommonOptions(num_options
, options
, 1);
199 if (ppd
&& ppd
->landscape
> 0)
202 if ((val
= cupsGetOption("page-ranges", num_options
, options
)) != NULL
)
205 if ((val
= cupsGetOption("page-set", num_options
, options
)) != NULL
)
208 if ((val
= cupsGetOption("multiple-document-handling", num_options
, options
)) != NULL
)
211 * This IPP attribute is unnecessarily complicated...
213 * single-document, separate-documents-collated-copies, and
214 * single-document-new-sheet all require collated copies.
216 * separate-documents-uncollated-copies allows for uncollated copies.
219 Collate
= strcasecmp(val
, "separate-documents-uncollated-copies") != 0;
222 if ((val
= cupsGetOption("Collate", num_options
, options
)) != NULL
&&
223 strcasecmp(val
, "True") == 0)
226 if ((val
= cupsGetOption("OutputOrder", num_options
, options
)) != NULL
&&
227 strcasecmp(val
, "Reverse") == 0)
230 if ((val
= cupsGetOption("number-up", num_options
, options
)) != NULL
)
233 if ((val
= cupsGetOption("page-border", num_options
, options
)) != NULL
)
235 if (strcasecmp(val
, "none") == 0)
236 Border
= BORDER_NONE
;
237 else if (strcasecmp(val
, "single") == 0)
238 Border
= BORDER_SINGLE
;
239 else if (strcasecmp(val
, "single-thick") == 0)
240 Border
= BORDER_SINGLE2
;
241 else if (strcasecmp(val
, "double") == 0)
242 Border
= BORDER_DOUBLE
;
243 else if (strcasecmp(val
, "double-thick") == 0)
244 Border
= BORDER_DOUBLE2
;
247 if ((val
= cupsGetOption("number-up-layout", num_options
, options
)) != NULL
)
249 if (strcasecmp(val
, "lrtb") == 0)
250 Layout
= LAYOUT_LRTB
;
251 else if (strcasecmp(val
, "lrbt") == 0)
252 Layout
= LAYOUT_LRBT
;
253 else if (strcasecmp(val
, "rltb") == 0)
254 Layout
= LAYOUT_RLTB
;
255 else if (strcasecmp(val
, "rlbt") == 0)
256 Layout
= LAYOUT_RLBT
;
257 else if (strcasecmp(val
, "tblr") == 0)
258 Layout
= LAYOUT_TBLR
;
259 else if (strcasecmp(val
, "tbrl") == 0)
260 Layout
= LAYOUT_TBRL
;
261 else if (strcasecmp(val
, "btlr") == 0)
262 Layout
= LAYOUT_BTLR
;
263 else if (strcasecmp(val
, "btrl") == 0)
264 Layout
= LAYOUT_BTRL
;
267 if ((val
= cupsGetOption("gamma", num_options
, options
)) != NULL
)
268 g
= atoi(val
) * 0.001f
;
270 if ((val
= cupsGetOption("brightness", num_options
, options
)) != NULL
)
271 b
= atoi(val
) * 0.01f
;
273 if ((val
= cupsGetOption("mirror", num_options
, options
)) != NULL
&&
274 strcasecmp(val
, "True") == 0)
278 * See if we have to filter the fast or slow way...
281 if (ppd
&& ppd
->manual_copies
&& Duplex
&& Copies
> 1)
284 * Force collated copies when printing a duplexed document to
285 * a non-PS printer that doesn't do hardware copy generation.
286 * Otherwise the copies will end up on the front/back side of
287 * each page. Also, set the "slowduplex" option to make sure
288 * that we output an even number of pages...
297 if (ppdFindOption(ppd
, "Collate") == NULL
&& Collate
&& Copies
> 1)
302 if (ppdFindOption(ppd
, "OutputOrder") == NULL
&& Order
)
308 * If we need to filter slowly, then create a temporary file for page data...
310 * If the temp file can't be created, then we'll ignore the collating/output
314 if (sloworder
|| slowcollate
)
316 tempfd
= cupsTempFd(tempfile
, sizeof(tempfile
));
319 perror("ERROR: Unable to open temp file");
323 temp
= fdopen(tempfd
, "wb+");
326 slowcollate
= sloworder
= 0;
332 * Write any "exit server" options that have been selected...
335 ppdEmit(ppd
, stdout
, PPD_ORDER_EXIT
);
338 * Write any JCL commands that are needed to print PostScript code...
341 ppdEmitJCL(ppd
, stdout
, atoi(argv
[1]), argv
[2], argv
[3]);
344 * Read the first line to see if we have DSC comments...
347 if (psgets(line
, sizeof(line
), fp
) == NULL
)
349 fputs("ERROR: Empty print file!\n", stderr
);
355 * Start sending the document with any commands needed...
365 if (Copies
!= 1 && (!Collate
|| !slowcollate
))
368 * Tell the document processor the copy and duplex options
369 * that are required...
372 printf("%%%%Requirements: numcopies(%d)%s%s\n", Copies
,
373 Collate
? " collate" : "",
374 Duplex
? " duplex" : "");
377 * Apple uses RBI comments for various non-PPD options...
380 printf("%%RBINumCopies: %d\n", Copies
);
385 * Tell the document processor the duplex option that is required...
389 puts("%%Requirements: duplex\n");
392 * Apple uses RBI comments for various non-PPD options...
395 puts("%RBINumCopies: 1");
399 * Figure out if we should use ESPshowpage or not...
402 val
= cupsGetOption("page-label", num_options
, options
);
404 if (val
!= NULL
|| getenv("CLASSIFICATION") != NULL
|| NUp
> 1 ||
405 Border
|| strstr(line
, "EPS") != NULL
)
408 * Yes, use ESPshowpage...
414 if (strncmp(line
, "%!PS-Adobe-", 11) == 0 && strstr(line
, "EPSF") == NULL
)
417 * OK, we have DSC comments and this isn't an EPS file; read until we
418 * find a %%Page comment...
421 puts("%%Pages: (atend)");
425 while (psgets(line
, sizeof(line
), fp
) != NULL
)
427 if (strncmp(line
, "%%", 2) == 0)
428 fprintf(stderr
, "DEBUG: %d %s", level
, line
);
429 else if (line
[0] != '%' && line
[0] && !sent_espsp
&& UseESPsp
)
432 * Send ESPshowpage stuff...
437 puts("userdict/ESPshowpage/showpage load put\n"
438 "userdict/showpage{}put");
441 if (strncmp(line
, "%%BeginDocument:", 16) == 0 ||
442 strncmp(line
, "%%BeginDocument ", 16) == 0) /* Adobe Acrobat BUG */
447 else if (strncmp(line
, "%%EndDocument", 13) == 0 && level
> 0)
452 else if (strncmp(line
, "%cupsRotation:", 14) == 0 && level
== 0)
455 * Reset orientation of document?
458 int orient
= (atoi(line
+ 14) / 90) & 3;
460 if (orient
!= Orientation
)
462 Orientation
= (4 - Orientation
+ orient
) & 3;
464 Orientation
= orient
;
467 else if (strncmp(line
, "%%BeginProlog", 13) == 0 && level
== 0)
470 * Write the existing comment line, and then follow with patches
471 * and prolog commands...
482 else if (strncmp(line
, "%%BeginSetup", 12) == 0 && level
== 0)
485 * Write the existing comment line, and then follow with document
494 do_setup(ppd
, Copies
, Collate
, slowcollate
, g
, b
);
497 else if (strncmp(line
, "%%Page:", 7) == 0 && level
== 0)
499 else if (strncmp(line
, "%%BeginBinary:", 14) == 0 ||
500 (strncmp(line
, "%%BeginData:", 12) == 0 &&
501 strstr(line
, "ASCII") == NULL
&& strstr(line
, "Hex") == NULL
))
504 * Copy binary data...
507 tbytes
= atoi(strchr(line
, ':') + 1);
512 if (tbytes
> sizeof(line
))
513 nbytes
= fread(line
, 1, sizeof(line
), fp
);
515 nbytes
= fread(line
, 1, tbytes
, fp
);
519 perror("ERROR: Early end-of-file while reading binary data");
523 fwrite(line
, 1, nbytes
, stdout
);
527 else if (strncmp(line
, "%%Pages:", 8) != 0)
532 * Make sure we have the prolog and setup commands written...
537 puts("%%BeginProlog");
547 puts("%%BeginSetup");
550 do_setup(ppd
, Copies
, Collate
, slowcollate
, g
, b
);
555 if (!sent_espsp
&& UseESPsp
)
558 * Send ESPshowpage stuff...
563 puts("userdict/ESPshowpage/showpage load put\n"
564 "userdict/showpage{}put");
568 * Write the page and label prologs...
571 if (NUp
== 2 || NUp
== 6)
574 * For 2- and 6-up output, rotate the labels to match the orientation
579 WriteLabelProlog(val
, PageBottom
, PageWidth
- PageLength
+ PageTop
,
582 WriteLabelProlog(val
, PageLeft
, PageRight
, PageLength
);
585 WriteLabelProlog(val
, PageBottom
, PageTop
, PageWidth
);
588 * Then read all of the pages, filtering as needed...
591 for (page
= 1, real_page
= 1;;)
593 if (strncmp(line
, "%%", 2) == 0)
594 fprintf(stderr
, "DEBUG: %d %s", level
, line
);
596 if (strncmp(line
, "%%BeginDocument:", 16) == 0 ||
597 strncmp(line
, "%%BeginDocument ", 16) == 0) /* Adobe Acrobat BUG */
599 else if (strncmp(line
, "%%EndDocument", 13) == 0 && level
> 0)
601 else if (strcmp(line
, "\004") == 0)
603 else if (strncmp(line
, "%%EOF", 5) == 0 && level
== 0)
605 fputs("DEBUG: Saw EOF!\n", stderr
);
609 else if (strncmp(line
, "%%Page:", 7) == 0 && level
== 0)
611 if (!check_range(real_page
))
613 while (psgets(line
, sizeof(line
), fp
) != NULL
)
614 if (strncmp(line
, "%%BeginDocument:", 16) == 0 ||
615 strncmp(line
, "%%BeginDocument ", 16) == 0) /* Adobe Acrobat BUG */
617 else if (strcmp(line
, "%%EndDocument") == 0 && level
> 0)
619 else if (strncmp(line
, "%%Page:", 7) == 0 && level
== 0)
628 if (!sloworder
&& NumPages
> 0)
629 end_nup(NumPages
- 1);
631 if (slowcollate
|| sloworder
)
632 Pages
[NumPages
] = ftell(temp
);
636 if (is_first_page(NumPages
))
638 if (ppd
== NULL
|| ppd
->num_filters
== 0)
639 fprintf(stderr
, "PAGE: %d %d\n", page
, Copies
);
641 printf("%%%%Page: %d %d\n", page
, page
);
643 ppdEmit(ppd
, stdout
, PPD_ORDER_PAGE
);
646 start_nup(NumPages
, 1);
652 else if (strncmp(line
, "%%BeginBinary:", 14) == 0 ||
653 (strncmp(line
, "%%BeginData:", 12) == 0 &&
654 strstr(line
, "ASCII") == NULL
&& strstr(line
, "Hex") == NULL
))
657 * Copy binary data...
660 tbytes
= atoi(strchr(line
, ':') + 1);
664 if (slowcollate
|| sloworder
)
669 if (tbytes
> sizeof(line
))
670 nbytes
= fread(line
, 1, sizeof(line
), fp
);
672 nbytes
= fread(line
, 1, tbytes
, fp
);
676 perror("ERROR: Early end-of-file while reading binary data");
681 fwrite(line
, 1, nbytes
, stdout
);
683 if (slowcollate
|| sloworder
)
684 fwrite(line
, 1, nbytes
, temp
);
689 else if (strncmp(line
, "%%Trailer", 9) == 0 && level
== 0)
691 fputs("DEBUG: Saw Trailer!\n", stderr
);
699 if (slowcollate
|| sloworder
)
703 if (psgets(line
, sizeof(line
), fp
) == NULL
)
709 end_nup(NumPages
- 1);
711 if (is_not_last_page(NumPages
))
713 start_nup(NUp
- 1, 0);
717 if (slowduplex
&& !(page
& 1))
720 * Make sure we have an even number of pages...
723 if (ppd
== NULL
|| ppd
->num_filters
== 0)
724 fprintf(stderr
, "PAGE: %d %d\n", page
, Copies
);
726 printf("%%%%Page: %d %d\n", page
, page
);
728 ppdEmit(ppd
, stdout
, PPD_ORDER_PAGE
);
730 start_nup(NUp
- 1, 0);
736 if (slowcollate
|| sloworder
)
738 Pages
[NumPages
] = ftell(temp
);
746 for (number
= 0; number
< NumPages
; number
++)
748 if (is_first_page(number
))
750 if (ppd
== NULL
|| ppd
->num_filters
== 0)
751 fprintf(stderr
, "PAGE: %d 1\n", page
);
753 printf("%%%%Page: %d %d\n", page
, page
);
755 ppdEmit(ppd
, stdout
, PPD_ORDER_PAGE
);
758 start_nup(number
, 1);
759 copy_bytes(temp
, Pages
[number
+ 1] - Pages
[number
]);
763 if (is_not_last_page(NumPages
))
765 start_nup(NUp
- 1, 0);
769 if (slowduplex
&& !(page
& 1))
772 * Make sure we have an even number of pages...
775 if (ppd
== NULL
|| ppd
->num_filters
== 0)
776 fprintf(stderr
, "PAGE: %d 1\n", page
);
778 printf("%%%%Page: %d %d\n", page
, page
);
780 ppdEmit(ppd
, stdout
, PPD_ORDER_PAGE
);
782 start_nup(NUp
- 1, 0);
792 page_count
= (NumPages
+ NUp
- 1) / NUp
;
797 if (slowduplex
&& (page_count
& 1))
799 basepage
= page_count
- 1;
802 basepage
= page_count
- 1 - slowduplex
;
804 for (; basepage
>= 0; basepage
-= 1 + slowduplex
)
806 if (ppd
== NULL
|| ppd
->num_filters
== 0)
807 fprintf(stderr
, "PAGE: %d %d\n", page
,
808 slowcollate
? 1 : Copies
);
810 printf("%%%%Page: %d %d\n", page
, page
);
813 ppdEmit(ppd
, stdout
, PPD_ORDER_PAGE
);
815 for (subpage
= 0, number
= basepage
* NUp
;
816 subpage
< NUp
&& number
< NumPages
;
817 subpage
++, number
++)
819 start_nup(number
, 1);
820 fseek(temp
, Pages
[number
], SEEK_SET
);
821 copy_bytes(temp
, Pages
[number
+ 1] - Pages
[number
]);
825 if (is_not_last_page(number
))
827 start_nup(NUp
- 1, 0);
833 if (number
< NumPages
)
835 if (ppd
== NULL
|| ppd
->num_filters
== 0)
836 fprintf(stderr
, "PAGE: %d %d\n", page
,
837 slowcollate
? 1 : Copies
);
839 printf("%%%%Page: %d %d\n", page
, page
);
842 ppdEmit(ppd
, stdout
, PPD_ORDER_PAGE
);
844 for (subpage
= 0, number
= (basepage
+ 1) * NUp
;
845 subpage
< NUp
&& number
< NumPages
;
846 subpage
++, number
++)
848 start_nup(number
, 1);
849 fseek(temp
, Pages
[number
], SEEK_SET
);
850 copy_bytes(temp
, Pages
[number
+ 1] - Pages
[number
]);
854 if (is_not_last_page(number
))
856 start_nup(NUp
- 1, 0);
863 * Make sure we have an even number of pages...
866 if (ppd
== NULL
|| ppd
->num_filters
== 0)
867 fprintf(stderr
, "PAGE: %d %d\n", page
, slowcollate
? 1 : Copies
);
869 printf("%%%%Page: %d %d\n", page
, page
);
871 ppdEmit(ppd
, stdout
, PPD_ORDER_PAGE
);
873 start_nup(NUp
- 1, 0);
877 basepage
= page_count
- 1;
884 while (copy
< Copies
&& slowcollate
);
889 * Copy the trailer, if any...
893 printf("%%%%Pages: %d\n", page
- 1);
896 puts("userdict/showpage/ESPshowpage load put\n");
898 while (psgets(line
, sizeof(line
), fp
) != NULL
)
900 if (strcmp(line
, "\004") != 0 &&
901 strncmp(line
, "%%Pages:", 8) != 0)
904 if (strncmp(line
, "%%EOF", 5) == 0)
906 fputs("DEBUG: Saw EOF!\n", stderr
);
915 * No DSC comments - write any page commands and then the rest of the file...
918 if (slowcollate
&& Copies
> 1)
919 printf("%%%%Pages: %d\n", Copies
);
924 puts("userdict/ESPshowpage/showpage load put\n"
925 "userdict/showpage{}put");
927 puts("%%BeginProlog");
931 puts("%%BeginSetup");
932 do_setup(ppd
, Copies
, Collate
, slowcollate
, g
, b
);
935 if (ppd
== NULL
|| ppd
->num_filters
== 0)
936 fprintf(stderr
, "PAGE: 1 %d\n", slowcollate
? 1 : Copies
);
938 ppdEmit(ppd
, stdout
, PPD_ORDER_PAGE
);
942 while ((nbytes
= fread(line
, 1, sizeof(line
), fp
)) > 0)
944 fwrite(line
, 1, nbytes
, stdout
);
947 fwrite(line
, 1, nbytes
, temp
);
957 if (ppd
== NULL
|| ppd
->num_filters
== 0)
958 fputs("PAGE: 1 1\n", stderr
);
960 ppdEmit(ppd
, stdout
, PPD_ORDER_PAGE
);
972 * Send %%EOF if needed...
979 * End the job with the appropriate JCL command or CTRL-D otherwise.
985 fputs(ppd
->jcl_end
, stdout
);
986 else if (ppd
->num_filters
== 0)
991 * Close files and remove the temporary file if needed...
994 if (slowcollate
|| sloworder
)
1010 * 'check_range()' - Check to see if the current page is selected for
1014 static int /* O - 1 if selected, 0 otherwise */
1015 check_range(int page
) /* I - Page number */
1017 const char *range
; /* Pointer into range string */
1018 int lower
, upper
; /* Lower and upper page numbers */
1021 if (PageSet
!= NULL
)
1024 * See if we only print even or odd pages...
1027 if (strcasecmp(PageSet
, "even") == 0 && ((page
- 1) % (NUp
<< 1)) < NUp
)
1029 if (strcasecmp(PageSet
, "odd") == 0 && ((page
- 1) % (NUp
<< 1)) >= NUp
)
1033 if (PageRanges
== NULL
)
1034 return (1); /* No range, print all pages... */
1036 for (range
= PageRanges
; *range
!= '\0';)
1042 upper
= strtol(range
, (char **)&range
, 10);
1046 lower
= strtol(range
, (char **)&range
, 10);
1051 if (!isdigit(*range
))
1054 upper
= strtol(range
, (char **)&range
, 10);
1060 if (page
>= lower
&& page
<= upper
)
1074 * 'copy_bytes()' - Copy bytes from the input file to stdout...
1078 copy_bytes(FILE *fp
, /* I - File to read from */
1079 size_t length
) /* I - Length of page data */
1081 char buffer
[8192]; /* Data buffer */
1082 size_t nbytes
, /* Number of bytes read */
1083 nleft
; /* Number of bytes left/remaining */
1088 while (nleft
> 0 || length
== 0)
1090 if (nleft
> sizeof(buffer
) || length
== 0)
1091 nbytes
= sizeof(buffer
);
1095 if ((nbytes
= fread(buffer
, 1, nbytes
, fp
)) < 1)
1100 fwrite(buffer
, 1, nbytes
, stdout
);
1106 * 'do_prolog()' - Send the necessary document prolog commands...
1110 do_prolog(ppd_file_t
*ppd
) /* I - PPD file */
1113 * Send the document prolog commands...
1116 if (ppd
!= NULL
&& ppd
->patches
!= NULL
)
1118 puts("%%BeginFeature: *JobPatchFile 1");
1120 puts("%%EndFeature");
1123 ppdEmit(ppd
, stdout
, PPD_ORDER_PROLOG
);
1128 * 'do_setup()' - Send the necessary document setup commands...
1132 do_setup(ppd_file_t
*ppd
, /* I - PPD file */
1133 int copies
, /* I - Number of copies */
1134 int collate
, /* I - Collate output? */
1135 int slowcollate
, /* I - Slow collate */
1136 float g
, /* I - Gamma value */
1137 float b
) /* I - Brightness value */
1140 * Send all the printer-specific setup commands...
1143 ppdEmit(ppd
, stdout
, PPD_ORDER_DOCUMENT
);
1144 ppdEmit(ppd
, stdout
, PPD_ORDER_ANY
);
1147 * Set the number of copies for the job...
1150 if (copies
!= 1 && (!collate
|| !slowcollate
))
1152 printf("%%RBIBeginNonPPDFeature: *NumCopies %d\n", copies
);
1153 printf("%d/languagelevel where{pop languagelevel 2 ge}{false}ifelse{1 dict begin"
1154 "/NumCopies exch def currentdict end "
1155 "setpagedevice}{userdict/#copies 3 -1 roll put}ifelse\n", copies
);
1156 printf("%%RBIEndNonPPDFeature\n");
1160 * Changes to the transfer function must be made AFTER any
1161 * setpagedevice code...
1164 if (g
!= 1.0 || b
!= 1.0)
1165 printf("{ neg 1 add dup 0 lt { pop 1 } { %.3f exp neg 1 add } "
1166 "ifelse %.3f mul } bind settransfer\n", g
, b
);
1169 * Make sure we have rectclip and rectstroke procedures of some sort...
1177 * 'end_nup()' - End processing for N-up printing...
1181 end_nup(int number
) /* I - Page number */
1185 if (Flip
|| Orientation
|| NUp
> 1)
1186 puts("userdict /ESPsave get restore");
1193 WriteLabels(Orientation
);
1194 puts("ESPshowpage");
1200 if (is_last_page(number
) && UseESPsp
)
1202 if (Orientation
& 1)
1205 * Rotate the labels back to portrait...
1208 WriteLabels(Orientation
- 1);
1210 else if (Orientation
== 0)
1213 * Rotate the labels to landscape...
1216 WriteLabels(NormalLandscape
? 1 : 3);
1221 * Rotate the labels to landscape...
1224 WriteLabels(NormalLandscape
? 3 : 1);
1227 puts("ESPshowpage");
1232 if (is_last_page(number
) && UseESPsp
)
1234 WriteLabels(Orientation
);
1235 puts("ESPshowpage");
1245 * 'psgets()' - Get a line from a file.
1249 * This function differs from the gets() function in that it
1250 * handles any combination of CR, LF, or CR LF to end input
1254 static char * /* O - String or NULL if EOF */
1255 psgets(char *buf
, /* I - Buffer to read into */
1256 size_t len
, /* I - Length of buffer */
1257 FILE *fp
) /* I - File to read from */
1259 char *bufptr
; /* Pointer into buffer */
1260 int ch
; /* Character from file */
1267 while ((bufptr
- buf
) < len
)
1269 if ((ch
= getc(fp
)) == EOF
)
1275 * Got a CR; see if there is a LF as well...
1279 if (ch
!= EOF
&& ch
!= 0x0a)
1280 ungetc(ch
, fp
); /* Nope, save it for later... */
1285 else if (ch
== 0x0a)
1292 * Add a trailing newline if it is there...
1299 * Nul-terminate the string and return it (or NULL for EOF).
1304 if (ch
== EOF
&& bufptr
== buf
)
1312 * 'start_nup()' - Start processing for N-up printing...
1316 start_nup(int number
, /* I - Page number */
1317 int show_border
) /* I - Show the page border? */
1319 int pos
; /* Position on page */
1320 int x
, y
; /* Relative position of subpage */
1321 float w
, l
, /* Width and length of subpage */
1322 tx
, ty
; /* Translation values for subpage */
1323 float pw
, pl
; /* Printable width and length of full page */
1326 if (Flip
|| Orientation
|| NUp
> 1)
1327 puts("userdict/ESPsave save put");
1330 printf("%.1f 0.0 translate -1 1 scale\n", PageWidth
);
1333 pw
= PageRight
- PageLeft
;
1334 pl
= PageTop
- PageBottom
;
1336 fprintf(stderr
, "DEBUG: pw = %.1f, pl = %.1f\n", pw
, pl
);
1337 fprintf(stderr
, "DEBUG: PageLeft = %.1f, PageRight = %.1f\n", PageLeft
, PageRight
);
1338 fprintf(stderr
, "DEBUG: PageTop = %.1f, PageBottom = %.1f\n", PageTop
, PageBottom
);
1339 fprintf(stderr
, "DEBUG: PageWidth = %.1f, PageLength = %.1f\n", PageWidth
, PageLength
);
1341 switch (Orientation
)
1343 case 1 : /* Landscape */
1344 printf("%.1f 0.0 translate 90 rotate\n", PageLength
);
1346 case 2 : /* Reverse Portrait */
1347 printf("%.1f %.1f translate 180 rotate\n", PageWidth
, PageLength
);
1349 case 3 : /* Reverse Landscape */
1350 printf("0.0 %.1f translate -90 rotate\n", PageWidth
);
1354 if (Duplex
&& NUp
> 1 && ((number
/ NUp
) & 1))
1355 printf("%.1f %.1f translate\n", PageWidth
- PageRight
, PageBottom
);
1357 printf("%.1f %.1f translate\n", PageLeft
, PageBottom
);
1367 if (Orientation
& 1)
1371 if (Layout
& LAYOUT_NEGATEY
)
1375 l
= w
* PageLength
/ PageWidth
;
1380 w
= l
* PageWidth
/ PageLength
;
1383 tx
= 0.5 * (pw
* 0.5 - l
);
1384 ty
= 0.5 * (pl
- w
);
1386 if (NormalLandscape
)
1387 printf("0.0 %.1f translate -90 rotate\n", pl
);
1389 printf("%.1f 0.0 translate 90 rotate\n", pw
);
1391 printf("%.1f %.1f translate %.3f %.3f scale\n",
1392 ty
, tx
+ l
* x
, w
/ PageWidth
, l
/ PageLength
);
1398 if (Layout
& LAYOUT_NEGATEX
)
1402 w
= l
* PageWidth
/ PageLength
;
1407 l
= w
* PageLength
/ PageWidth
;
1410 tx
= 0.5 * (pl
* 0.5 - w
);
1411 ty
= 0.5 * (pw
- l
);
1413 if (NormalLandscape
)
1414 printf("%.1f 0.0 translate 90 rotate\n", pw
);
1416 printf("0.0 %.1f translate -90 rotate\n", pl
);
1418 printf("%.1f %.1f translate %.3f %.3f scale\n",
1419 tx
+ w
* x
, ty
, w
/ PageWidth
, l
/ PageLength
);
1424 if (Layout
& LAYOUT_VERTICAL
)
1435 if (Layout
& LAYOUT_NEGATEX
)
1438 if (Layout
& LAYOUT_NEGATEY
)
1442 l
= w
* PageLength
/ PageWidth
;
1447 w
= l
* PageWidth
/ PageLength
;
1450 tx
= 0.5 * (pw
* 0.5 - w
);
1451 ty
= 0.5 * (pl
* 0.5 - l
);
1453 printf("%.1f %.1f translate %.3f %.3f scale\n", tx
+ x
* w
, ty
+ y
* l
,
1454 w
/ PageWidth
, l
/ PageLength
);
1458 if (Orientation
& 1)
1460 if (Layout
& LAYOUT_VERTICAL
)
1465 if (Layout
& LAYOUT_NEGATEX
)
1468 if (Layout
& LAYOUT_NEGATEY
)
1476 if (Layout
& LAYOUT_NEGATEX
)
1479 if (Layout
& LAYOUT_NEGATEY
)
1484 l
= w
* PageLength
/ PageWidth
;
1486 if (l
> (pw
* 0.333))
1489 w
= l
* PageWidth
/ PageLength
;
1492 tx
= 0.5 * (pl
- 2 * w
);
1493 ty
= 0.5 * (pw
- 3 * l
);
1495 if (NormalLandscape
)
1496 printf("0.0 %.1f translate -90 rotate\n", pl
);
1498 printf("%.1f 0.0 translate 90 rotate\n", pw
);
1500 printf("%.1f %.1f translate %.3f %.3f scale\n",
1501 tx
+ x
* w
, ty
+ y
* l
, w
/ PageWidth
, l
/ PageLength
);
1505 if (Layout
& LAYOUT_VERTICAL
)
1510 if (Layout
& LAYOUT_NEGATEX
)
1513 if (Layout
& LAYOUT_NEGATEY
)
1521 if (Layout
& LAYOUT_NEGATEX
)
1524 if (Layout
& LAYOUT_NEGATEY
)
1529 w
= l
* PageWidth
/ PageLength
;
1531 if (w
> (pl
* 0.333))
1534 l
= w
* PageLength
/ PageWidth
;
1537 tx
= 0.5 * (pl
- 3 * w
);
1538 ty
= 0.5 * (pw
- 2 * l
);
1540 if (NormalLandscape
)
1541 printf("%.1f 0.0 translate 90 rotate\n", pw
);
1543 printf("0.0 %.1f translate -90 rotate\n", pl
);
1545 printf("%.1f %.1f translate %.3f %.3f scale\n",
1546 tx
+ w
* x
, ty
+ l
* y
, w
/ PageWidth
, l
/ PageLength
);
1551 if (Layout
& LAYOUT_VERTICAL
)
1562 if (Layout
& LAYOUT_NEGATEX
)
1565 if (Layout
& LAYOUT_NEGATEY
)
1569 l
= w
* PageLength
/ PageWidth
;
1571 if (l
> (pl
* 0.333))
1574 w
= l
* PageWidth
/ PageLength
;
1577 tx
= 0.5 * (pw
* 0.333 - w
);
1578 ty
= 0.5 * (pl
* 0.333 - l
);
1580 printf("%.1f %.1f translate %.3f %.3f scale\n", tx
+ x
* w
, ty
+ y
* l
,
1581 w
/ PageWidth
, l
/ PageLength
);
1585 if (Layout
& LAYOUT_VERTICAL
)
1596 if (Layout
& LAYOUT_NEGATEX
)
1599 if (Layout
& LAYOUT_NEGATEY
)
1603 l
= w
* PageLength
/ PageWidth
;
1605 if (l
> (pl
* 0.25))
1608 w
= l
* PageWidth
/ PageLength
;
1611 tx
= 0.5 * (pw
* 0.25 - w
);
1612 ty
= 0.5 * (pl
* 0.25 - l
);
1614 printf("%.1f %.1f translate %.3f %.3f scale\n", tx
+ x
* w
, ty
+ y
* l
,
1615 w
/ PageWidth
, l
/ PageLength
);
1620 * Draw borders as necessary...
1623 if (Border
&& show_border
)
1625 int rects
; /* Number of border rectangles */
1626 float fscale
, /* Scaling value for points */
1627 margin
; /* Current margin for borders */
1630 rects
= (Border
& BORDER_DOUBLE
) ? 2 : 1;
1631 fscale
= PageWidth
/ w
;
1632 margin
= 2.25 * fscale
;
1635 * Set the line width and color...
1639 printf("%.3f setlinewidth 0 setgray newpath\n",
1640 (Border
& BORDER_THICK
) ? 0.5 * fscale
: 0.24 * fscale
);
1643 * Draw border boxes...
1646 for (; rects
> 0; rects
--, margin
+= 2 * fscale
)
1648 printf("%.1f %.1f %.1f %.1f ESPrs\n",
1651 PageWidth
- 2 * margin
,
1652 PageLength
- 2 * margin
);
1654 printf("%.1f %.1f %.1f %.1f ESPrs\n",
1656 PageBottom
+ margin
,
1657 PageRight
- PageLeft
- 2 * margin
,
1658 PageTop
- PageBottom
- 2 * margin
);
1661 * Restore pen settings...
1670 * Clip the page that follows to the bounding box of the page...
1673 printf("0 0 %.1f %.1f ESPrc\n", PageWidth
, PageLength
);
1679 * End of "$Id: pstops.c,v 1.92 2002/12/17 16:17:27 mike Exp $".