]> git.ipfire.org Git - thirdparty/cups.git/blob - filter/pstops.c
Merge changes from 1.1.x into 1.2 devel.
[thirdparty/cups.git] / filter / pstops.c
1 /*
2 * "$Id: pstops.c,v 1.54.2.2 2001/12/26 16:52:39 mike Exp $"
3 *
4 * PostScript filter for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1993-2001 by Easy Software Products.
7 *
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
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
19 *
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * Contents:
25 *
26 * main() - Main entry...
27 * check_range() - Check to see if the current page is selected for
28 * copy_bytes() - Copy bytes from the input file to stdout...
29 * end_nup() - End processing for N-up printing...
30 * psgets() - Get a line from a file.
31 * start_nup() - Start processing for N-up printing...
32 */
33
34 /*
35 * Include necessary headers...
36 */
37
38 #include "common.h"
39
40
41 /*
42 * Constants...
43 */
44
45 #define MAX_PAGES 10000
46
47
48 /*
49 * Globals...
50 */
51
52 int NumPages = 0; /* Number of pages in file */
53 long Pages[MAX_PAGES]; /* Offsets to each page */
54 char PageLabels[MAX_PAGES][64];
55 /* Page labels */
56 const char *PageRanges = NULL; /* Range of pages selected */
57 const char *PageSet = NULL; /* All, Even, Odd pages */
58 int Order = 0, /* 0 = normal, 1 = reverse pages */
59 Flip = 0, /* Flip/mirror pages */
60 NUp = 1, /* Number of pages on each sheet (1, 2, 4) */
61 Collate = 0, /* Collate copies? */
62 Copies = 1, /* Number of copies */
63 UseESPsp = 0; /* Use ESPshowpage? */
64
65
66 /*
67 * Local functions...
68 */
69
70 static int check_range(int page);
71 static void copy_bytes(FILE *fp, size_t length);
72 static void end_nup(int number);
73 static char *psgets(char *buf, size_t len, FILE *fp);
74 static void start_nup(int number);
75
76
77 /*
78 * 'main()' - Main entry...
79 */
80
81 int /* O - Exit status */
82 main(int argc, /* I - Number of command-line arguments */
83 char *argv[]) /* I - Command-line arguments */
84 {
85 FILE *fp; /* Print file */
86 ppd_file_t *ppd; /* PPD file */
87 int num_options; /* Number of print options */
88 cups_option_t *options; /* Print options */
89 const char *val; /* Option value */
90 char tempfile[255]; /* Temporary file name */
91 FILE *temp; /* Temporary file */
92 int tempfd; /* Temporary file descriptor */
93 int number; /* Page number */
94 int slowcollate; /* 1 if we need to collate manually */
95 int sloworder; /* 1 if we need to order manually */
96 char line[8192]; /* Line buffer */
97 float g; /* Gamma correction value */
98 float b; /* Brightness factor */
99 int level; /* Nesting level for embedded files */
100 int nbytes, /* Number of bytes read */
101 tbytes; /* Total bytes to read for binary data */
102 int page; /* Current page sequence number */
103 int real_page; /* "Real" page number in document */
104 int page_count; /* Page count for NUp */
105 int subpage; /* Sub-page number */
106 int copy; /* Current copy */
107 int saweof; /* Did we see a %%EOF tag? */
108
109
110 /*
111 * Make sure status messages are not buffered...
112 */
113
114 setbuf(stderr, NULL);
115
116 /*
117 * Check command-line...
118 */
119
120 if (argc < 6 || argc > 7)
121 {
122 fputs("ERROR: pstops job-id user title copies options [file]\n", stderr);
123 return (1);
124 }
125
126 /*
127 * If we have 7 arguments, print the file named on the command-line.
128 * Otherwise, send stdin instead...
129 */
130
131 if (argc == 6)
132 fp = stdin;
133 else
134 {
135 /*
136 * Try to open the print file...
137 */
138
139 if ((fp = fopen(argv[6], "rb")) == NULL)
140 {
141 perror("ERROR: unable to open print file - ");
142 return (1);
143 }
144 }
145
146 /*
147 * Process command-line options and write the prolog...
148 */
149
150 g = 1.0;
151 b = 1.0;
152
153 Copies = atoi(argv[4]);
154
155 options = NULL;
156 num_options = cupsParseOptions(argv[5], 0, &options);
157
158 ppd = SetCommonOptions(num_options, options, 1);
159
160 if ((val = cupsGetOption("page-ranges", num_options, options)) != NULL)
161 PageRanges = val;
162
163 if ((val = cupsGetOption("page-set", num_options, options)) != NULL)
164 PageSet = val;
165
166 if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL)
167 {
168 /*
169 * This IPP attribute is unnecessarily complicated...
170 *
171 * single-document, separate-documents-collated-copies, and
172 * single-document-new-sheet all require collated copies.
173 *
174 * separate-documents-uncollated-copies allows for uncollated copies.
175 */
176
177 Collate = strcasecmp(val, "separate-documents-uncollated-copies") != 0;
178 }
179
180 if ((val = cupsGetOption("Collate", num_options, options)) != NULL &&
181 strcasecmp(val, "True") == 0)
182 Collate = 1;
183
184 if ((val = cupsGetOption("OutputOrder", num_options, options)) != NULL &&
185 strcasecmp(val, "Reverse") == 0)
186 Order = 1;
187
188 if ((val = cupsGetOption("number-up", num_options, options)) != NULL)
189 NUp = atoi(val);
190
191 if ((val = cupsGetOption("gamma", num_options, options)) != NULL)
192 g = atoi(val) * 0.001f;
193
194 if ((val = cupsGetOption("brightness", num_options, options)) != NULL)
195 b = atoi(val) * 0.01f;
196
197 /*
198 * See if we have to filter the fast or slow way...
199 */
200
201 if (ppdFindOption(ppd, "Collate") == NULL && Collate && Copies > 1)
202 slowcollate = 1;
203 else
204 slowcollate = 0;
205
206 if (ppdFindOption(ppd, "OutputOrder") == NULL && Order)
207 sloworder = 1;
208 else
209 sloworder = 0;
210
211 /*
212 * If we need to filter slowly, then create a temporary file for page data...
213 *
214 * If the temp file can't be created, then we'll ignore the collating/output
215 * order options...
216 */
217
218 if (sloworder || slowcollate)
219 {
220 tempfd = cupsTempFd(tempfile, sizeof(tempfile));
221 temp = fdopen(tempfd, "wb+");
222
223 if (temp == NULL)
224 slowcollate = sloworder = 0;
225 }
226 else
227 temp = NULL;
228
229 /*
230 * Write any "exit server" options that have been selected...
231 */
232
233 ppdEmit(ppd, stdout, PPD_ORDER_EXIT);
234
235 /*
236 * Write any JCL commands that are needed to print PostScript code...
237 */
238
239 ppdEmitJCL(ppd, stdout, atoi(argv[1]), argv[2], argv[3]);
240
241 /*
242 * Read the first line to see if we have DSC comments...
243 */
244
245 if (psgets(line, sizeof(line), fp) == NULL)
246 {
247 fputs("ERROR: Empty print file!\n", stderr);
248 ppdClose(ppd);
249 return (1);
250 }
251
252 /*
253 * See if this is an EPS file...
254 */
255
256 UseESPsp = strstr(line, "EPS") != NULL;
257
258 /*
259 * Start sending the document with any commands needed...
260 */
261
262 puts(line);
263
264 saweof = 0;
265
266 if (ppd != NULL && ppd->patches != NULL)
267 puts(ppd->patches);
268
269 ppdEmit(ppd, stdout, PPD_ORDER_DOCUMENT);
270 ppdEmit(ppd, stdout, PPD_ORDER_ANY);
271 ppdEmit(ppd, stdout, PPD_ORDER_PROLOG);
272
273 if (g != 1.0 || b != 1.0)
274 printf("{ neg 1 add dup 0 lt { pop 1 } { %.3f exp neg 1 add } "
275 "ifelse %.3f mul } bind settransfer\n", g, b);
276
277 /*
278 * Figure out if we should use ESPshowpage or not...
279 */
280
281 val = cupsGetOption("page-label", num_options, options);
282
283 if (val != NULL || getenv("CLASSIFICATION") != NULL || NUp > 1)
284 {
285 /*
286 * Yes, use ESPshowpage...
287 */
288
289 UseESPsp = 1;
290 }
291
292 WriteLabelProlog(val);
293
294 if (UseESPsp)
295 puts("userdict begin\n"
296 "/ESPshowpage /showpage load def\n"
297 "/showpage { } def\n"
298 "end");
299
300 if (Copies > 1 && (!Collate || !slowcollate))
301 {
302 if (Collate)
303 printf("%%%%Requirements: numcopies(%d) collate\n", Copies);
304 else
305 printf("%%%%Requirements: numcopies(%d)\n", Copies);
306
307 if (LanguageLevel == 1)
308 printf("/#copies %d def\n", Copies);
309 else
310 printf("<</NumCopies %d>>setpagedevice\n", Copies);
311 }
312
313 if (strncmp(line, "%!PS-Adobe-", 11) == 0 && atof(line + 11) >= 3.0)
314 {
315 /*
316 * OK, we have DSC comments; read until we find a %%Page comment...
317 */
318
319 level = 0;
320
321 while (psgets(line, sizeof(line), fp) != NULL)
322 if (strncmp(line, "%%BeginDocument:", 16) == 0 ||
323 strncmp(line, "%%BeginDocument ", 16) == 0) /* Adobe Acrobat BUG */
324 level ++;
325 else if (strncmp(line, "%%EndDocument", 13) == 0 && level > 0)
326 level --;
327 else if (strncmp(line, "%%Page:", 7) == 0 && level == 0)
328 break;
329 else if (strncmp(line, "%%BeginBinary:", 14) == 0 ||
330 (strncmp(line, "%%BeginData:", 12) == 0 &&
331 strstr(line, "Binary") != NULL))
332 {
333 /*
334 * Copy binary data...
335 */
336
337 tbytes = atoi(strchr(line, ':') + 1);
338 while (tbytes > 0)
339 {
340 if (tbytes > sizeof(line))
341 nbytes = fread(line, 1, sizeof(line), fp);
342 else
343 nbytes = fread(line, 1, tbytes, fp);
344
345 fwrite(line, 1, nbytes, stdout);
346 tbytes -= nbytes;
347 }
348 }
349 else
350 fputs(line, stdout);
351
352 /*
353 * Then read all of the pages, filtering as needed...
354 */
355
356 for (page = 1, real_page = 1;;)
357 {
358 if (strncmp(line, "%%BeginDocument:", 16) == 0 ||
359 strncmp(line, "%%BeginDocument ", 16) == 0) /* Adobe Acrobat BUG */
360 level ++;
361 else if (strncmp(line, "%%EndDocument", 13) == 0 && level > 0)
362 level --;
363 else if (strcmp(line, "\004") == 0)
364 continue;
365 else if (strncmp(line, "%%EOF", 5) == 0 && level == 0)
366 {
367 fputs("DEBUG: Saw EOF!\n", stderr);
368 saweof = 1;
369 break;
370 }
371 else if (strncmp(line, "%%Page:", 7) == 0 && level == 0)
372 {
373 if (!check_range(real_page))
374 {
375 while (psgets(line, sizeof(line), fp) != NULL)
376 if (strncmp(line, "%%BeginDocument:", 16) == 0 ||
377 strncmp(line, "%%BeginDocument ", 16) == 0) /* Adobe Acrobat BUG */
378 level ++;
379 else if (strcmp(line, "%%EndDocument") == 0 && level > 0)
380 level --;
381 else if (strncmp(line, "%%Page:", 7) == 0 && level == 0)
382 {
383 real_page ++;
384 break;
385 }
386
387 continue;
388 }
389
390 if (!sloworder && NumPages > 0)
391 end_nup(NumPages - 1);
392
393 if (slowcollate || sloworder)
394 Pages[NumPages] = ftell(temp);
395
396 if (!sloworder)
397 {
398 if ((NumPages & (NUp - 1)) == 0)
399 {
400 if (ppd == NULL || ppd->num_filters == 0)
401 fprintf(stderr, "PAGE: %d %d\n", page, Copies);
402
403 printf("%%%%Page: %d %d\n", page, page);
404 page ++;
405 ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
406 }
407
408 start_nup(NumPages);
409 }
410
411 NumPages ++;
412 real_page ++;
413 }
414 else if (strncmp(line, "%%BeginBinary:", 14) == 0 ||
415 (strncmp(line, "%%BeginData:", 12) == 0 &&
416 strstr(line, "Binary") != NULL))
417 {
418 /*
419 * Copy binary data...
420 */
421
422 tbytes = atoi(strchr(line, ':') + 1);
423 while (tbytes > 0)
424 {
425 if (tbytes > sizeof(line))
426 nbytes = fread(line, 1, sizeof(line), fp);
427 else
428 nbytes = fread(line, 1, tbytes, fp);
429
430 if (!sloworder)
431 fwrite(line, 1, nbytes, stdout);
432
433 if (slowcollate || sloworder)
434 fwrite(line, 1, nbytes, stdout);
435
436 tbytes -= nbytes;
437 }
438 }
439 else if (strncmp(line, "%%Trailer", 9) == 0 && level == 0)
440 {
441 fputs("DEBUG: Saw Trailer!\n", stderr);
442 break;
443 }
444 else
445 {
446 if (!sloworder)
447 fputs(line, stdout);
448
449 if (slowcollate || sloworder)
450 fputs(line, temp);
451 }
452
453 if (psgets(line, sizeof(line), fp) == NULL)
454 break;
455 }
456
457 if (!sloworder)
458 {
459 end_nup(NumPages - 1);
460
461 if (NumPages & (NUp - 1))
462 {
463 start_nup(NUp - 1);
464 end_nup(NUp - 1);
465 }
466 }
467
468 if (slowcollate || sloworder)
469 {
470 Pages[NumPages] = ftell(temp);
471 page = 1;
472
473 if (!sloworder)
474 {
475 while (Copies > 0)
476 {
477 rewind(temp);
478
479 for (number = 0; number < NumPages; number ++)
480 {
481 if ((number & (NUp - 1)) == 0)
482 {
483 if (ppd == NULL || ppd->num_filters == 0)
484 fprintf(stderr, "PAGE: %d 1\n", page);
485
486 printf("%%%%Page: %d %d\n", page, page);
487 page ++;
488 ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
489 }
490
491 start_nup(number);
492 copy_bytes(temp, Pages[number + 1] - Pages[number]);
493 end_nup(number);
494 }
495
496 if (NumPages & (NUp - 1))
497 {
498 start_nup(NUp - 1);
499 end_nup(NUp - 1);
500 }
501
502 Copies --;
503 }
504 }
505 else
506 {
507 page_count = (NumPages + NUp - 1) / NUp;
508 copy = 0;
509
510 do
511 {
512 for (page = page_count - 1; page >= 0; page --)
513 {
514 if (ppd == NULL || ppd->num_filters == 0)
515 fprintf(stderr, "PAGE: %d %d\n", page + 1,
516 slowcollate ? 1 : Copies);
517
518 if (slowcollate)
519 printf("%%%%Page: %d %d\n", page + 1,
520 page_count - page + copy * page_count);
521 else
522 printf("%%%%Page: %d %d\n", page + 1, page_count - page);
523
524 ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
525
526 for (subpage = 0, number = page * NUp;
527 subpage < NUp && number < NumPages;
528 subpage ++, number ++)
529 {
530 start_nup(number);
531 fseek(temp, Pages[number], SEEK_SET);
532 copy_bytes(temp, Pages[number + 1] - Pages[number]);
533 end_nup(number);
534 }
535
536 if (number & (NUp - 1))
537 {
538 start_nup(NUp - 1);
539 end_nup(NUp - 1);
540 }
541 }
542
543 copy ++;
544 }
545 while (copy < Copies && slowcollate);
546 }
547 }
548
549 /*
550 * Copy the trailer, if any...
551 */
552
553 while (psgets(line, sizeof(line), fp) != NULL)
554 {
555 if (strcmp(line, "\004") != 0)
556 fputs(line, stdout);
557
558 if (strncmp(line, "%%EOF", 5) == 0)
559 {
560 fputs("DEBUG: Saw EOF!\n", stderr);
561 saweof = 1;
562 break;
563 }
564 }
565 }
566 else
567 {
568 /*
569 * No DSC comments - write any page commands and then the rest of the file...
570 */
571
572 if (ppd == NULL || ppd->num_filters == 0)
573 fprintf(stderr, "PAGE: 1 %d\n", slowcollate ? 1 : Copies);
574
575 ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
576
577 while (psgets(line, sizeof(line), fp) != NULL)
578 {
579 fputs(line, stdout);
580
581 if (slowcollate)
582 fputs(line, temp);
583 }
584
585 if (UseESPsp)
586 puts("ESPshowpage");
587
588 if (slowcollate)
589 {
590 while (Copies > 1)
591 {
592 if (ppd == NULL || ppd->num_filters == 0)
593 fputs("PAGE: 1 1\n", stderr);
594
595 ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
596 rewind(temp);
597 copy_bytes(temp, 0);
598 Copies --;
599
600 if (UseESPsp)
601 puts("ESPshowpage");
602 }
603 }
604 }
605
606 /*
607 * Send %%EOF if needed...
608 */
609
610 if (!saweof)
611 puts("%%EOF");
612
613 /*
614 * End the job with the appropriate JCL command or CTRL-D otherwise.
615 */
616
617 if (ppd != NULL && ppd->jcl_end)
618 fputs(ppd->jcl_end, stdout);
619 else if (ppd != NULL && ppd->num_filters == 0)
620 putchar(0x04);
621
622 /*
623 * Close files and remove the temporary file if needed...
624 */
625
626 if (slowcollate || sloworder)
627 {
628 fclose(temp);
629 unlink(tempfile);
630 }
631
632 ppdClose(ppd);
633
634 if (fp != stdin)
635 fclose(fp);
636
637 return (0);
638 }
639
640
641 /*
642 * 'check_range()' - Check to see if the current page is selected for
643 * printing.
644 */
645
646 static int /* O - 1 if selected, 0 otherwise */
647 check_range(int page) /* I - Page number */
648 {
649 const char *range; /* Pointer into range string */
650 int lower, upper; /* Lower and upper page numbers */
651
652
653 if (PageSet != NULL)
654 {
655 /*
656 * See if we only print even or odd pages...
657 */
658
659 if (strcasecmp(PageSet, "even") == 0 && (page & 1))
660 return (0);
661 if (strcasecmp(PageSet, "odd") == 0 && !(page & 1))
662 return (0);
663 }
664
665 if (PageRanges == NULL)
666 return (1); /* No range, print all pages... */
667
668 for (range = PageRanges; *range != '\0';)
669 {
670 if (*range == '-')
671 {
672 lower = 1;
673 range ++;
674 upper = strtol(range, (char **)&range, 10);
675 }
676 else
677 {
678 lower = strtol(range, (char **)&range, 10);
679
680 if (*range == '-')
681 {
682 range ++;
683 if (!isdigit(*range))
684 upper = 65535;
685 else
686 upper = strtol(range, (char **)&range, 10);
687 }
688 else
689 upper = lower;
690 }
691
692 if (page >= lower && page <= upper)
693 return (1);
694
695 if (*range == ',')
696 range ++;
697 else
698 break;
699 }
700
701 return (0);
702 }
703
704
705 /*
706 * 'copy_bytes()' - Copy bytes from the input file to stdout...
707 */
708
709 static void
710 copy_bytes(FILE *fp, /* I - File to read from */
711 size_t length) /* I - Length of page data */
712 {
713 char buffer[8192]; /* Data buffer */
714 size_t nbytes, /* Number of bytes read */
715 nleft; /* Number of bytes left/remaining */
716
717
718 nleft = length;
719
720 while (nleft > 0 || length == 0)
721 {
722 if (nleft > sizeof(buffer))
723 nbytes = sizeof(buffer);
724 else
725 nbytes = nleft;
726
727 if ((nbytes = fread(buffer, 1, nbytes, fp)) < 1)
728 return;
729
730 nleft -= nbytes;
731
732 fwrite(buffer, 1, nbytes, stdout);
733 }
734 }
735
736
737 /*
738 * 'end_nup()' - End processing for N-up printing...
739 */
740
741 static void
742 end_nup(int number) /* I - Page number */
743 {
744 if (Flip || Orientation || NUp > 1)
745 puts("ESPsave restore");
746
747 switch (NUp)
748 {
749 case 1 :
750 if (UseESPsp)
751 {
752 WriteLabels();
753 puts("ESPshowpage");
754 }
755 break;
756
757 case 2 :
758 if ((number & 1) == 1 && UseESPsp)
759 {
760 WriteLabels();
761 puts("ESPshowpage");
762 }
763 break;
764
765 case 4 :
766 if ((number & 3) == 3 && UseESPsp)
767 {
768 WriteLabels();
769 puts("ESPshowpage");
770 }
771 break;
772 }
773 }
774
775
776 /*
777 * 'psgets()' - Get a line from a file.
778 *
779 * Note:
780 *
781 * This function differs from the gets() function in that it
782 * handles any combination of CR, LF, or CR LF to end input
783 * lines.
784 */
785
786 static char * /* O - String or NULL if EOF */
787 psgets(char *buf, /* I - Buffer to read into */
788 size_t len, /* I - Length of buffer */
789 FILE *fp) /* I - File to read from */
790 {
791 char *bufptr; /* Pointer into buffer */
792 int ch; /* Character from file */
793
794
795 len --;
796 bufptr = buf;
797 ch = EOF;
798
799 while ((bufptr - buf) < len)
800 {
801 if ((ch = getc(fp)) == EOF)
802 break;
803
804 if (ch == 0x0d)
805 {
806 /*
807 * Got a CR; see if there is a LF as well...
808 */
809
810 ch = getc(fp);
811 if (ch != EOF && ch != 0x0a)
812 ungetc(ch, fp); /* Nope, save it for later... */
813
814 ch = 0x0a;
815 break;
816 }
817 else if (ch == 0x0a)
818 break;
819 else
820 *bufptr++ = ch;
821 }
822
823 /*
824 * Add a trailing newline if it is there...
825 */
826
827 if (ch == '\n')
828 *bufptr++ = '\n';
829
830 /*
831 * Nul-terminate the string and return it (or NULL for EOF).
832 */
833
834 *bufptr = '\0';
835
836 if (ch == EOF && bufptr == buf)
837 return (NULL);
838 else
839 return (buf);
840 }
841
842
843 /*
844 * 'start_nup()' - Start processing for N-up printing...
845 */
846
847 static void
848 start_nup(int number) /* I - Page number */
849 {
850 int x, y; /* Relative position of subpage */
851 float w, l, /* Width and length of subpage */
852 tx, ty; /* Translation values for subpage */
853 float pw, pl; /* Printable width and length of full page */
854
855
856 if (Flip || Orientation || NUp > 1)
857 puts("/ESPsave save def");
858
859 if (Flip)
860 printf("%.1f 0.0 translate -1 1 scale\n", PageWidth);
861
862 pw = PageRight - PageLeft;
863 pl = PageTop - PageBottom;
864
865 fprintf(stderr, "DEBUG: pw = %.1f, pl = %.1f\n", pw, pl);
866 fprintf(stderr, "DEBUG: PageLeft = %.1f, PageRight = %.1f\n", PageLeft, PageRight);
867 fprintf(stderr, "DEBUG: PageTop = %.1f, PageBottom = %.1f\n", PageTop, PageBottom);
868 fprintf(stderr, "DEBUG: PageWidth = %.1f, PageLength = %.1f\n", PageWidth, PageLength);
869
870 switch (Orientation)
871 {
872 case 1 : /* Landscape */
873 printf("%.1f 0.0 translate 90 rotate\n", PageLength);
874 break;
875 case 2 : /* Reverse Portrait */
876 printf("%.1f %.1f translate 180 rotate\n", PageWidth, PageLength);
877 break;
878 case 3 : /* Reverse Landscape */
879 printf("0.0 %.1f translate -90 rotate\n", PageWidth);
880 break;
881 }
882
883 switch (NUp)
884 {
885 case 2 :
886 x = number & 1;
887
888 if (Orientation & 1)
889 {
890 x = 1 - x;
891 w = pl;
892 l = w * PageLength / PageWidth;
893
894 if (l > (pw * 0.5))
895 {
896 l = pw * 0.5;
897 w = l * PageWidth / PageLength;
898 }
899
900 tx = pw * 0.5 - l;
901 ty = (pl - w) * 0.5;
902 }
903 else
904 {
905 l = pw;
906 w = l * PageWidth / PageLength;
907
908 if (w > (pl * 0.5))
909 {
910 w = pl * 0.5;
911 l = w * PageLength / PageWidth;
912 }
913
914 tx = pl * 0.5 - w;
915 ty = (pw - l) * 0.5;
916 }
917
918 if (Duplex && (number & 2))
919 printf("%.1f %.1f translate\n", PageWidth - PageRight, PageBottom);
920 else
921 printf("%.1f %.1f translate\n", PageLeft, PageBottom);
922
923 if (Orientation & 1)
924 {
925 printf("0.0 %.1f translate -90 rotate\n", pl);
926 printf("%.1f %.1f translate %.3f %.3f scale\n",
927 ty, tx + l * x, w / PageWidth, l / PageLength);
928 }
929 else
930 {
931 printf("%.1f 0.0 translate 90 rotate\n", pw);
932 printf("%.1f %.1f translate %.3f %.3f scale\n",
933 tx + w * x, ty, w / PageWidth, l / PageLength);
934 }
935
936 printf("newpath\n"
937 "0.0 0.0 moveto\n"
938 "%.1f 0.0 lineto\n"
939 "%.1f %.1f lineto\n"
940 "0.0 %.1f lineto\n"
941 "closepath clip newpath\n",
942 PageWidth, PageWidth, PageLength, PageLength);
943 break;
944
945 case 4 :
946 x = number & 1;
947 y = 1 - ((number & 2) != 0);
948
949 w = pw * 0.5;
950 l = w * PageLength / PageWidth;
951
952 if (l > (pl * 0.5))
953 {
954 l = pl * 0.5;
955 w = l * PageWidth / PageLength;
956 }
957
958 if (Duplex && (number & 4))
959 printf("%.1f %.1f translate\n", PageWidth - PageRight, PageBottom);
960 else
961 printf("%.1f %.1f translate\n", PageLeft, PageBottom);
962
963 printf("%.1f %.1f translate %.3f %.3f scale\n", x * w, y * l,
964 w / PageWidth, l / PageLength);
965 printf("newpath\n"
966 "0.0 0.0 moveto\n"
967 "%.1f 0.0 lineto\n"
968 "%.1f %.1f lineto\n"
969 "0.0 %.1f lineto\n"
970 "closepath clip newpath\n",
971 PageWidth, PageWidth, PageLength, PageLength);
972 break;
973 }
974 }
975
976
977 /*
978 * End of "$Id: pstops.c,v 1.54.2.2 2001/12/26 16:52:39 mike Exp $".
979 */