]>
git.ipfire.org Git - thirdparty/cups.git/blob - filter/pstops.c
2 * "$Id: pstops.c 5092 2006-02-09 00:54:31Z mike $"
4 * PostScript filter for the Common UNIX Printing System (CUPS).
6 * Copyright 1993-2006 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 USA
20 * Voice: (301) 373-9600
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 * add_page() - Add a page to the Pages array...
30 * check_range() - Check to see if the current page is selected for
31 * copy_bytes() - Copy bytes from the input file to stdout...
32 * do_prolog() - Send the necessary document prolog commands...
33 * do_setup() - Send the necessary document setup commands...
34 * end_nup() - End processing for N-up printing...
35 * include_feature() - Include a printer option/feature command.
36 * psgets() - Get a line from a file.
37 * start_nup() - Start processing for N-up printing...
41 * Include necessary headers...
46 #include <cups/file.h>
47 #include <cups/array.h>
54 #define BORDER_NONE 0 /* No border or hairline border */
55 #define BORDER_THICK 1 /* Think border */
56 #define BORDER_SINGLE 2 /* Single-line hairline border */
57 #define BORDER_SINGLE2 3 /* Single-line thick border */
58 #define BORDER_DOUBLE 4 /* Double-line hairline border */
59 #define BORDER_DOUBLE2 5 /* Double-line thick border */
61 #define LAYOUT_LRBT 0 /* Left to right, bottom to top */
62 #define LAYOUT_LRTB 1 /* Left to right, top to bottom */
63 #define LAYOUT_RLBT 2 /* Right to left, bottom to top */
64 #define LAYOUT_RLTB 3 /* Right to left, top to bottom */
65 #define LAYOUT_BTLR 4 /* Bottom to top, left to right */
66 #define LAYOUT_TBLR 5 /* Top to bottom, left to right */
67 #define LAYOUT_BTRL 6 /* Bottom to top, right to left */
68 #define LAYOUT_TBRL 7 /* Top to bottom, right to left */
70 #define LAYOUT_NEGATEY 1 /* The bits for the layout */
71 #define LAYOUT_NEGATEX 2 /* definitions above... */
72 #define LAYOUT_VERTICAL 4
74 #define PROT_STANDARD 0 /* Adobe standard protocol */
75 #define PROT_BCP 1 /* Adobe BCP protocol */
76 #define PROT_TBCP 2 /* Adobe TBCP protocol */
83 typedef struct /**** Page information ****/
85 char *label
; /* Page label */
86 off_t offset
; /* Offset to start of page */
87 ssize_t length
; /* Number of bytes for page */
88 int lbrt
[4]; /* PageBoundingBox */
89 const char *input_slot
, /* Input slot option or NULL */
90 *manual_feed
; /* Manual feed option or NULL */
98 int NumPages
= 0; /* Number of pages in file */
99 cups_array_t
*Pages
; /* Info on each page */
100 const char *PageRanges
= NULL
; /* Range of pages selected */
101 const char *PageSet
= NULL
; /* All, Even, Odd pages */
102 int Order
= 0, /* 0 = normal, 1 = reverse pages */
103 Flip
= 0, /* Flip/mirror pages */
104 FitPlot
= 0, /* Fit pages to media */
105 NUp
= 1, /* Number of pages on each sheet (1, 2, 4) */
106 Collate
= 0, /* Collate copies? */
107 Copies
= 1, /* Number of copies */
108 UseESPsp
= 0, /* Use ESPshowpage? */
109 Border
= BORDER_NONE
, /* Border around pages */
110 Layout
= LAYOUT_LRTB
, /* Layout of N-up pages */
111 NormalLandscape
= 0; /* Normal rotation for landscape? */
118 static page_info_t
*add_page(const char *label
, off_t offset
,
120 static int check_range(int page
);
121 static void copy_bytes(cups_file_t
*fp
, off_t offset
,
123 static void do_prolog(ppd_file_t
*ppd
);
124 static void do_setup(ppd_file_t
*ppd
, int copies
, int collate
,
125 int slowcollate
, float g
, float b
);
126 static void end_nup(int number
);
127 static void include_feature(ppd_file_t
*ppd
, const char *line
,
129 #define is_first_page(p) (NUp == 1 || (((p)+1) % NUp) == 1)
130 #define is_last_page(p) (NUp > 1 && (((p)+1) % NUp) == 0)
131 #define is_not_last_page(p) (NUp > 1 && ((p) % NUp) != 0)
132 static char *psgets(char *buf
, size_t *bytes
, FILE *fp
);
133 static void start_nup(int number
, int show_border
, const int *lbrt
);
137 * 'main()' - Main entry...
140 int /* O - Exit status */
141 main(int argc
, /* I - Number of command-line args */
142 char *argv
[]) /* I - Command-line arguments */
144 FILE *fp
; /* Print file */
145 ppd_file_t
*ppd
; /* PPD file */
146 ppd_attr_t
*attr
; /* Attribute in PPD file */
147 ppd_option_t
*option
; /* Option */
148 ppd_choice_t
*choice
; /* Marked option choice */
149 int num_options
; /* Number of print options */
150 cups_option_t
*options
; /* Print options */
151 const char *val
; /* Option value */
152 char tempfile
[255]; /* Temporary file name */
153 cups_file_t
*temp
; /* Temporary file */
154 int number
; /* Page number */
155 int slowcollate
; /* 1 if we need to collate manually */
156 int sloworder
; /* 1 if we need to order manually */
157 int slowduplex
; /* 1 if we need an even page count */
158 char line
[8192]; /* Line buffer */
159 int lbrt
[4], /* BoundingBox */
160 pagelbrt
[4]; /* PageBoundingBox */
161 size_t len
; /* Length of line buffer */
162 float g
; /* Gamma correction value */
163 float b
; /* Brightness factor */
164 int level
; /* Nesting level for embedded files */
165 int nbytes
, /* Number of bytes read */
166 tbytes
; /* Bytes to read for binary data */
167 int page
; /* Current page sequence number */
168 int real_page
; /* "Real" page number in document */
169 int page_count
; /* Page count for NUp */
170 int basepage
; /* Base page number */
171 int subpage
; /* Sub-page number */
172 int copy
; /* Current copy */
173 int saweof
; /* Did we see a %%EOF tag? */
174 int sent_espsp
, /* Did we send ESPshowpage commands? */
175 sent_prolog
, /* Did we send the prolog commands? */
176 sent_setup
, /* Did we send the setup commands? */
177 emit_jcl
; /* Emit JCL? */
178 float min_order
; /* Minimum output order for selection */
179 char label
[256]; /* Page label */
180 page_info_t
*pageinfo
; /* Page information */
181 const char *ap_input_slot
, /* First page InputSlot option */
182 *ap_manual_feed
, /* First page ManualFeed option */
183 *input_slot
, /* Original InputSlot option */
184 *manual_feed
; /* Original ManualFeed option */
187 * Make sure status messages are not buffered...
190 setbuf(stderr
, NULL
);
193 * Check command-line...
196 if (argc
< 6 || argc
> 7)
198 fputs("ERROR: pstops job-id user title copies options [file]\n", stderr
);
203 * If we have 7 arguments, print the file named on the command-line.
204 * Otherwise, send stdin instead...
212 * Try to open the print file...
215 if ((fp
= fopen(argv
[6], "rb")) == NULL
)
217 fprintf(stderr
, "ERROR: unable to open print file \"%s\" - %s\n",
218 argv
[6], strerror(errno
));
224 * Process command-line options and write the prolog...
230 Copies
= atoi(argv
[4]);
233 num_options
= cupsParseOptions(argv
[5], 0, &options
);
235 ppd
= SetCommonOptions(num_options
, options
, 1);
237 if (ppd
&& ppd
->landscape
> 0)
240 if ((val
= cupsGetOption("page-ranges", num_options
, options
)) != NULL
)
243 if ((val
= cupsGetOption("page-set", num_options
, options
)) != NULL
)
246 if ((val
= cupsGetOption("multiple-document-handling", num_options
, options
)) != NULL
)
249 * This IPP attribute is unnecessarily complicated...
251 * single-document, separate-documents-collated-copies, and
252 * single-document-new-sheet all require collated copies.
254 * separate-documents-uncollated-copies allows for uncollated copies.
257 Collate
= strcasecmp(val
, "separate-documents-uncollated-copies") != 0;
260 if ((val
= cupsGetOption("Collate", num_options
, options
)) != NULL
&&
261 (!strcasecmp(val
, "true") ||!strcasecmp(val
, "on") ||
262 !strcasecmp(val
, "yes")))
265 if ((val
= cupsGetOption("OutputOrder", num_options
, options
)) != NULL
)
267 if (!strcasecmp(val
, "Reverse"))
273 * Figure out the right default output order from the PPD file...
276 if ((choice
= ppdFindMarkedChoice(ppd
, "OutputBin")) != NULL
&&
277 (attr
= ppdFindAttr(ppd
, "PageStackOrder", choice
->choice
)) != NULL
&&
279 Order
= !strcasecmp(attr
->value
, "Reverse");
280 else if ((attr
= ppdFindAttr(ppd
, "DefaultOutputOrder", NULL
)) != NULL
&&
282 Order
= !strcasecmp(attr
->value
, "Reverse");
285 if ((val
= cupsGetOption("number-up", num_options
, options
)) != NULL
)
288 if ((val
= cupsGetOption("page-border", num_options
, options
)) != NULL
)
290 if (!strcasecmp(val
, "none"))
291 Border
= BORDER_NONE
;
292 else if (!strcasecmp(val
, "single"))
293 Border
= BORDER_SINGLE
;
294 else if (!strcasecmp(val
, "single-thick"))
295 Border
= BORDER_SINGLE2
;
296 else if (!strcasecmp(val
, "double"))
297 Border
= BORDER_DOUBLE
;
298 else if (!strcasecmp(val
, "double-thick"))
299 Border
= BORDER_DOUBLE2
;
302 if ((val
= cupsGetOption("number-up-layout", num_options
, options
)) != NULL
)
304 if (!strcasecmp(val
, "lrtb"))
305 Layout
= LAYOUT_LRTB
;
306 else if (!strcasecmp(val
, "lrbt"))
307 Layout
= LAYOUT_LRBT
;
308 else if (!strcasecmp(val
, "rltb"))
309 Layout
= LAYOUT_RLTB
;
310 else if (!strcasecmp(val
, "rlbt"))
311 Layout
= LAYOUT_RLBT
;
312 else if (!strcasecmp(val
, "tblr"))
313 Layout
= LAYOUT_TBLR
;
314 else if (!strcasecmp(val
, "tbrl"))
315 Layout
= LAYOUT_TBRL
;
316 else if (!strcasecmp(val
, "btlr"))
317 Layout
= LAYOUT_BTLR
;
318 else if (!strcasecmp(val
, "btrl"))
319 Layout
= LAYOUT_BTRL
;
322 if ((val
= cupsGetOption("gamma", num_options
, options
)) != NULL
)
325 * Get gamma value from 1 to 10000...
328 g
= atoi(val
) * 0.001f
;
336 if ((val
= cupsGetOption("brightness", num_options
, options
)) != NULL
)
339 * Get brightness value from 10 to 1000.
342 b
= atoi(val
) * 0.01f
;
350 if ((val
= cupsGetOption("mirror", num_options
, options
)) != NULL
&&
351 (!strcasecmp(val
, "true") || !strcasecmp(val
, "on") ||
352 !strcasecmp(val
, "yes")))
355 if ((val
= cupsGetOption("fitplot", num_options
, options
)) != NULL
&&
356 (!strcasecmp(val
, "true") || !strcasecmp(val
, "on") ||
357 !strcasecmp(val
, "yes")))
360 if ((val
= cupsGetOption("emit-jcl", num_options
, options
)) != NULL
&&
361 (!strcasecmp(val
, "false") || !strcasecmp(val
, "off") ||
362 !strcasecmp(val
, "no") || !strcmp(val
, "0")))
368 * Handle input slot/manual feed selections...
371 if ((choice
= ppdFindMarkedChoice(ppd
, "InputSlot")) != NULL
)
372 input_slot
= choice
->choice
;
376 if ((choice
= ppdFindMarkedChoice(ppd
, "ManualFeed")) != NULL
)
377 manual_feed
= choice
->choice
;
381 ap_input_slot
= cupsGetOption("AP_FIRSTPAGE_InputSlot", num_options
,
383 ap_manual_feed
= cupsGetOption("AP_FIRSTPAGE_ManualFeed", num_options
,
387 if (ppd
&& (ap_input_slot
|| ap_manual_feed
))
390 * The first page/sheet will be using different options than
391 * the rest, so figure out the minimum order dependency for
392 * each of the options...
395 if ((option
= ppdFindOption(ppd
, "PageRegion")) != NULL
&&
396 option
->order
< min_order
)
397 min_order
= option
->order
;
399 if ((option
= ppdFindOption(ppd
, "InputSlot")) != NULL
&&
400 option
->order
< min_order
)
401 min_order
= option
->order
;
403 if ((option
= ppdFindOption(ppd
, "ManualFeed")) != NULL
&&
404 option
->order
< min_order
)
405 min_order
= option
->order
;
408 if (ppd
&& ppd
->manual_copies
&& Duplex
&& Copies
> 1)
411 * Force collated copies when printing a duplexed document to
412 * a non-PS printer that doesn't do hardware copy generation.
413 * Otherwise the copies will end up on the front/back side of
421 * See if we have to filter the fast or slow way...
424 if (Collate
&& Copies
> 1)
427 * See if we need to manually collate the pages...
432 if ((choice
= ppdFindMarkedChoice(ppd
, "Collate")) != NULL
&&
433 !strcasecmp(choice
->choice
, "True"))
436 * Hardware collate option is selected, see if the option is
437 * conflicting - if not, collate in hardware. Otherwise,
438 * turn the hardware collate option off...
441 if ((option
= ppdFindOption(ppd
, "Option")) != NULL
&&
445 ppdMarkOption(ppd
, "Collate", "False");
451 if (ppdFindOption(ppd
, "OutputOrder") == NULL
&& Order
)
456 if ((slowcollate
|| sloworder
) && Duplex
)
462 * If we need to filter slowly, then create a temporary file for page data...
464 * If the temp file can't be created, then we'll ignore the collating/output
468 if (sloworder
|| slowcollate
)
470 if ((temp
= cupsTempFile2(tempfile
, sizeof(tempfile
))) == NULL
)
471 slowcollate
= sloworder
= 0;
477 * Write any "exit server" options that have been selected...
480 ppdEmit(ppd
, stdout
, PPD_ORDER_EXIT
);
483 * Write any JCL commands that are needed to print PostScript code...
487 ppdEmitJCL(ppd
, stdout
, atoi(argv
[1]), argv
[2], argv
[3]);
490 * Read the first line to see if we have DSC comments...
494 if (psgets(line
, &len
, fp
) == NULL
)
496 fputs("ERROR: Empty print file!\n", stderr
);
502 * Handle leading PJL fun...
505 while (!strncmp(line
, "\033%-12345X", 9) || !strncmp(line
, "@PJL ", 5))
508 * Yup, we have leading PJL fun, so skip it until we hit the line
509 * with "ENTER LANGUAGE"...
512 fputs("DEBUG: Skipping PJL header...\n", stderr
);
514 while (strstr(line
, "ENTER LANGUAGE") == NULL
)
517 if (psgets(line
, &len
, fp
) == NULL
)
522 if (psgets(line
, &len
, fp
) == NULL
)
527 * Start sending the document with any commands needed...
530 fwrite(line
, 1, len
, stdout
);
537 if (Copies
!= 1 && (!Collate
|| !slowcollate
))
540 * Tell the document processor the copy and duplex options
541 * that are required...
544 printf("%%%%Requirements: numcopies(%d)%s%s\n", Copies
,
545 Collate
? " collate" : "",
546 Duplex
? " duplex" : "");
549 * Apple uses RBI comments for various non-PPD options...
552 printf("%%RBINumCopies: %d\n", Copies
);
557 * Tell the document processor the duplex option that is required...
561 puts("%%Requirements: duplex");
564 * Apple uses RBI comments for various non-PPD options...
567 puts("%RBINumCopies: 1");
571 * Figure out if we should use ESPshowpage or not...
574 val
= cupsGetOption("page-label", num_options
, options
);
576 if (val
!= NULL
|| getenv("CLASSIFICATION") != NULL
|| NUp
> 1 ||
577 Border
|| strstr(line
, "EPS") != NULL
)
580 * Yes, use ESPshowpage...
586 fprintf(stderr
, "DEBUG: slowcollate=%d, slowduplex=%d, sloworder=%d\n",
587 slowcollate
, slowduplex
, sloworder
);
589 if (!strncmp(line
, "%!PS-Adobe-", 11) && !strstr(line
, "EPSF"))
592 * OK, we have DSC comments and this isn't an EPS file; read until we
593 * find a %%Page comment...
596 puts("%%Pages: (atend)");
597 printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n", PageLeft
, PageBottom
,
603 lbrt
[2] = (int)PageWidth
;
604 lbrt
[3] = (int)PageLength
;
609 if (psgets(line
, &len
, fp
) == NULL
)
612 if (!strncmp(line
, "%%", 2))
613 fprintf(stderr
, "DEBUG: %d %s", level
, line
);
614 else if (line
[0] != '%' && line
[0] && !sent_espsp
&& UseESPsp
)
617 * Send ESPshowpage stuff...
622 puts("userdict/ESPshowpage/showpage load put\n"
623 "userdict/showpage{}put");
626 if (!strncmp(line
, "%%BeginDocument:", 16) ||
627 !strncmp(line
, "%%BeginDocument ", 16) || /* Adobe Acrobat BUG */
628 !strncmp(line
, "%ADO_BeginApplication", 21))
633 else if ((!strncmp(line
, "%%EndDocument", 13) ||
634 !strncmp(line
, "%ADO_EndApplication", 19)) && level
> 0)
639 else if (!strncmp(line
, "%cupsRotation:", 14) && level
== 0)
642 * Reset orientation of document?
645 int orient
= (atoi(line
+ 14) / 90) & 3;
647 if (orient
!= Orientation
)
649 Orientation
= (4 - Orientation
+ orient
) & 3;
651 Orientation
= orient
;
654 else if (!strncmp(line
, "%%BeginProlog", 13) && level
== 0)
657 * Write the existing comment line, and then follow with patches
658 * and prolog commands...
669 else if (!strncmp(line
, "%%BeginSetup", 12) && level
== 0)
672 * Write the existing comment line, and then follow with document
687 do_setup(ppd
, Copies
, Collate
, slowcollate
, g
, b
);
690 else if (!strncmp(line
, "%%BoundingBox:", 14) && level
== 0)
692 if (sscanf(line
+ 14, "%d%d%d%d", pagelbrt
+ 0, pagelbrt
+ 1,
693 pagelbrt
+ 2, pagelbrt
+ 3) == 4)
694 memcpy(lbrt
, pagelbrt
, sizeof(lbrt
));
696 else if (!strncmp(line
, "%%Page:", 7) && level
== 0)
698 else if (!strncmp(line
, "%%IncludeFeature:", 17) && level
== 0 &&
699 NUp
== 1 && !FitPlot
)
700 include_feature(ppd
, line
, NULL
);
701 else if (!strncmp(line
, "%%BeginBinary:", 14) ||
702 (!strncmp(line
, "%%BeginData:", 12) &&
703 !strstr(line
, "ASCII") && !strstr(line
, "Hex")))
706 * Copy binary data...
709 tbytes
= atoi(strchr(line
, ':') + 1);
714 if (tbytes
> sizeof(line
))
715 nbytes
= fread(line
, 1, sizeof(line
), fp
);
717 nbytes
= fread(line
, 1, tbytes
, fp
);
721 perror("ERROR: Early end-of-file while reading binary data");
725 fwrite(line
, 1, nbytes
, stdout
);
729 else if (strncmp(line
, "%%Pages:", 8) != 0)
730 fwrite(line
, 1, len
, stdout
);
734 * Make sure we have the prolog and setup commands written...
739 puts("%%BeginProlog");
749 puts("%%BeginSetup");
752 do_setup(ppd
, Copies
, Collate
, slowcollate
, g
, b
);
757 if (!sent_espsp
&& UseESPsp
)
760 * Send ESPshowpage stuff...
765 puts("userdict/ESPshowpage/showpage load put\n"
766 "userdict/showpage{}put");
770 * Write the page and label prologs...
773 if (NUp
== 2 || NUp
== 6)
776 * For 2- and 6-up output, rotate the labels to match the orientation
781 WriteLabelProlog(val
, PageBottom
, PageWidth
- PageLength
+ PageTop
,
784 WriteLabelProlog(val
, PageLeft
, PageRight
, PageLength
);
787 WriteLabelProlog(val
, PageBottom
, PageTop
, PageWidth
);
790 * Then read all of the pages, filtering as needed...
793 for (page
= 1, real_page
= 1, pageinfo
= NULL
;;)
795 if (!strncmp(line
, "%%", 2))
796 fprintf(stderr
, "DEBUG: %d %s", level
, line
);
798 if (!strncmp(line
, "%%BeginDocument:", 16) ||
799 !strncmp(line
, "%%BeginDocument ", 16) || /* Adobe Acrobat BUG */
800 !strncmp(line
, "%ADO_BeginApplication", 21))
807 if (slowcollate
|| sloworder
)
808 cupsFilePuts(temp
, line
);
810 else if ((!strncmp(line
, "%%EndDocument", 13) ||
811 !strncmp(line
, "%ADO_EndApplication", 19)) && level
> 0)
818 if (slowcollate
|| sloworder
)
819 cupsFilePuts(temp
, line
);
821 else if (!strcmp(line
, "\004") && len
== 1)
823 else if (!strncmp(line
, "%%EOF", 5) && level
== 0)
825 fputs("DEBUG: Saw EOF!\n", stderr
);
829 else if (!strncmp(line
, "%%Page:", 7) && level
== 0)
831 if (!check_range(real_page
))
836 if (psgets(line
, &len
, fp
) == NULL
)
839 if (!strncmp(line
, "%%", 2))
840 fprintf(stderr
, "DEBUG: %d %s", level
, line
);
842 if (!strncmp(line
, "%%BeginDocument:", 16) ||
843 !strncmp(line
, "%%BeginDocument ", 16) || /* Adobe Acrobat BUG */
844 !strncmp(line
, "%ADO_BeginApplication", 21))
846 else if ((!strncmp(line
, "%%EndDocument", 13) ||
847 !strncmp(line
, "%ADO_EndApplication", 19)) && level
> 0)
849 else if (!strncmp(line
, "%%Page:", 7) && level
== 0)
854 else if (!strncmp(line
, "%%BeginBinary:", 14) ||
855 (!strncmp(line
, "%%BeginData:", 12) &&
856 !strstr(line
, "ASCII") && !strstr(line
, "Hex")))
859 * Skip binary data...
862 tbytes
= atoi(strchr(line
, ':') + 1);
866 if (tbytes
> sizeof(line
))
867 nbytes
= fread(line
, 1, sizeof(line
), fp
);
869 nbytes
= fread(line
, 1, tbytes
, fp
);
873 perror("ERROR: Early end-of-file while reading binary data");
885 if (!sloworder
&& NumPages
> 0)
886 end_nup(NumPages
- 1);
888 if (sscanf(line
, "%%%%Page:%255s%*d", label
) != 1)
889 sprintf(label
, "%d", page
);
891 if (slowcollate
|| sloworder
)
893 pageinfo
= add_page(label
, cupsFileTell(temp
), lbrt
);
895 if (ap_input_slot
|| ap_manual_feed
)
899 pageinfo
->input_slot
= ap_input_slot
;
900 pageinfo
->manual_feed
= ap_manual_feed
;
902 else if (page
== (1 + Duplex
))
904 pageinfo
->input_slot
= input_slot
;
905 pageinfo
->manual_feed
= manual_feed
;
914 if (is_first_page(NumPages
))
916 if (ppd
== NULL
|| ppd
->num_filters
== 0)
917 fprintf(stderr
, "PAGE: %d %d\n", page
, slowcollate
? 1 : Copies
);
920 printf("%%%%Page: %d %d\n", page
, page
);
922 printf("%%%%Page: %s %d\n", label
, page
);
924 if (ap_input_slot
|| ap_manual_feed
)
929 ppdMarkOption(ppd
, "InputSlot", ap_input_slot
);
931 ppdMarkOption(ppd
, "ManualFeed", ap_manual_feed
);
933 else if (page
== (1 + Duplex
))
936 ppdMarkOption(ppd
, "InputSlot", input_slot
);
938 ppdMarkOption(ppd
, "ManualFeed", manual_feed
);
941 ppdEmitAfterOrder(ppd
, stdout
, PPD_ORDER_DOCUMENT
, 1, min_order
);
942 ppdEmitAfterOrder(ppd
, stdout
, PPD_ORDER_ANY
, 1, min_order
);
946 ppdEmit(ppd
, stdout
, PPD_ORDER_PAGE
);
949 start_nup(NumPages
, 1, lbrt
);
955 else if (!strncmp(line
, "%%PageBoundingBox:", 18) && level
== 0 &&
958 if (sscanf(line
+ 18, "%d%d%d%d", pagelbrt
+ 0, pagelbrt
+ 1,
959 pagelbrt
+ 2, pagelbrt
+ 3) == 4)
960 memcpy(pageinfo
->lbrt
, pagelbrt
, sizeof(pageinfo
->lbrt
));
962 else if (!strncmp(line
, "%%BeginBinary:", 14) ||
963 (!strncmp(line
, "%%BeginData:", 12) &&
964 !strstr(line
, "ASCII") && !strstr(line
, "Hex")))
967 * Copy binary data...
970 tbytes
= atoi(strchr(line
, ':') + 1);
974 if (slowcollate
|| sloworder
)
975 cupsFilePuts(temp
, line
);
979 if (tbytes
> sizeof(line
))
980 nbytes
= fread(line
, 1, sizeof(line
), fp
);
982 nbytes
= fread(line
, 1, tbytes
, fp
);
986 perror("ERROR: Early end-of-file while reading binary data");
991 fwrite(line
, 1, nbytes
, stdout
);
993 if (slowcollate
|| sloworder
)
994 cupsFileWrite(temp
, line
, nbytes
);
999 else if (!strncmp(line
, "%%IncludeFeature:", 17) && level
== 0 &&
1000 NUp
== 1 && !FitPlot
)
1003 * Embed printer commands as needed...
1006 if (level
== 0 && NUp
== 1)
1008 include_feature(ppd
, line
, NULL
);
1010 if (slowcollate
|| sloworder
)
1011 include_feature(ppd
, line
, temp
);
1014 else if (!strncmp(line
, "%%BeginFeature:", 15) && (NUp
> 1 || FitPlot
))
1017 * Strip page options for N-up > 1 or "fitplot"...
1023 if (psgets(line
, &len
, fp
) == NULL
)
1026 while (strncmp(line
, "%%EndFeature", 12));
1028 else if (!strncmp(line
, "%%Trailer", 9) && level
== 0)
1030 fputs("DEBUG: Saw Trailer!\n", stderr
);
1036 fwrite(line
, 1, len
, stdout
);
1038 if (slowcollate
|| sloworder
)
1039 cupsFileWrite(temp
, line
, len
);
1043 * Get next line from file...
1047 pageinfo
->length
= cupsFileTell(temp
) - pageinfo
->offset
;
1050 if (psgets(line
, &len
, fp
) == NULL
)
1056 end_nup(NumPages
- 1);
1058 if (is_not_last_page(NumPages
))
1060 start_nup(NUp
- 1, 0, lbrt
);
1064 if (slowduplex
&& !(page
& 1))
1067 * Make sure we have an even number of pages...
1070 if (ppd
== NULL
|| ppd
->num_filters
== 0)
1071 fprintf(stderr
, "PAGE: %d %d\n", page
, slowcollate
? 1 : Copies
);
1073 printf("%%%%Page: %d %d\n", page
, page
);
1075 ppdEmit(ppd
, stdout
, PPD_ORDER_PAGE
);
1077 start_nup(NUp
- 1, 0, lbrt
);
1083 if (slowcollate
|| sloworder
)
1089 for (number
= 0, pageinfo
= (page_info_t
*)cupsArrayFirst(Pages
);
1090 number
< NumPages
&& pageinfo
;
1091 number
++, pageinfo
= (page_info_t
*)cupsArrayNext(Pages
))
1093 if (is_first_page(number
))
1095 if (ppd
== NULL
|| ppd
->num_filters
== 0)
1096 fprintf(stderr
, "PAGE: %d 1\n", page
);
1099 printf("%%%%Page: %s %d\n", pageinfo
->label
, page
);
1101 printf("%%%%Page: %d %d\n", page
, page
);
1103 if (pageinfo
->input_slot
|| pageinfo
->manual_feed
)
1105 if (pageinfo
->input_slot
)
1106 ppdMarkOption(ppd
, "InputSlot", pageinfo
->input_slot
);
1107 if (pageinfo
->manual_feed
)
1108 ppdMarkOption(ppd
, "ManualFeed", pageinfo
->manual_feed
);
1110 ppdEmitAfterOrder(ppd
, stdout
, PPD_ORDER_DOCUMENT
, 1, min_order
);
1111 ppdEmitAfterOrder(ppd
, stdout
, PPD_ORDER_ANY
, 1, min_order
);
1115 ppdEmit(ppd
, stdout
, PPD_ORDER_PAGE
);
1118 start_nup(number
, 1, pageinfo
->lbrt
);
1119 copy_bytes(temp
, pageinfo
->offset
, pageinfo
->length
);
1123 if (is_not_last_page(NumPages
))
1125 start_nup(NUp
- 1, 0, lbrt
);
1129 if (slowduplex
&& !(page
& 1))
1132 * Make sure we have an even number of pages...
1135 if (ppd
== NULL
|| ppd
->num_filters
== 0)
1136 fprintf(stderr
, "PAGE: %d 1\n", page
);
1138 printf("%%%%Page: %d %d\n", page
, page
);
1140 ppdEmit(ppd
, stdout
, PPD_ORDER_PAGE
);
1142 start_nup(NUp
- 1, 0, lbrt
);
1152 page_count
= (NumPages
+ NUp
- 1) / NUp
;
1155 fprintf(stderr
, "DEBUG: page_count=%d\n", page_count
);
1159 if (slowduplex
&& (page_count
& 1))
1160 basepage
= page_count
;
1162 basepage
= page_count
- 1;
1164 for (; basepage
>= 0; basepage
--)
1166 if (ppd
== NULL
|| ppd
->num_filters
== 0)
1167 fprintf(stderr
, "PAGE: %d %d\n", page
,
1168 slowcollate
? 1 : Copies
);
1170 pageinfo
= (page_info_t
*)cupsArrayIndex(Pages
, basepage
);
1173 printf("%%%%Page: %s %d\n", pageinfo
->label
, page
);
1175 printf("%%%%Page: %d %d\n", page
, page
);
1177 if (pageinfo
->input_slot
|| pageinfo
->manual_feed
)
1179 if (pageinfo
->input_slot
)
1180 ppdMarkOption(ppd
, "InputSlot", pageinfo
->input_slot
);
1181 if (pageinfo
->manual_feed
)
1182 ppdMarkOption(ppd
, "ManualFeed", pageinfo
->manual_feed
);
1184 ppdEmitAfterOrder(ppd
, stdout
, PPD_ORDER_DOCUMENT
, 1, min_order
);
1185 ppdEmitAfterOrder(ppd
, stdout
, PPD_ORDER_ANY
, 1, min_order
);
1190 ppdEmit(ppd
, stdout
, PPD_ORDER_PAGE
);
1192 if (basepage
>= page_count
)
1194 start_nup(NUp
- 1, 0, pageinfo
->lbrt
);
1200 for (subpage
= 0, number
= basepage
* NUp
;
1201 subpage
< NUp
&& number
< NumPages
;
1202 subpage
++, number
++)
1204 pageinfo
= (page_info_t
*)cupsArrayIndex(Pages
, number
);
1206 start_nup(number
, 1, pageinfo
->lbrt
);
1207 copy_bytes(temp
, pageinfo
->offset
, pageinfo
->length
);
1211 if (is_not_last_page(number
))
1213 start_nup(NUp
- 1, 0, lbrt
);
1221 while (copy
< Copies
&& slowcollate
);
1226 * Copy the trailer, if any...
1230 printf("%%%%Pages: %d\n", page
- 1);
1233 puts("userdict/showpage/ESPshowpage load put\n");
1238 if (psgets(line
, &len
, fp
) == NULL
)
1241 if (!(!strcmp(line
, "\004") && len
== 1) &&
1242 strncmp(line
, "%%Pages:", 8) != 0)
1243 fwrite(line
, 1, len
, stdout
);
1245 if (!strncmp(line
, "%%EOF", 5))
1247 fputs("DEBUG: Saw EOF!\n", stderr
);
1256 * No DSC comments - write any page commands and then the rest of the file...
1259 if (slowcollate
&& Copies
> 1)
1260 printf("%%%%Pages: %d\n", Copies
);
1265 puts("userdict/ESPshowpage/showpage load put\n"
1266 "userdict/showpage{}put");
1268 puts("%%BeginProlog");
1269 WriteLabelProlog(val
, PageBottom
, PageTop
, PageWidth
);
1271 puts("%%EndProlog");
1273 puts("%%BeginSetup");
1274 do_setup(ppd
, Copies
, Collate
, slowcollate
, g
, b
);
1277 if (ppd
== NULL
|| ppd
->num_filters
== 0)
1278 fprintf(stderr
, "PAGE: 1 %d\n", slowcollate
? 1 : Copies
);
1280 ppdEmit(ppd
, stdout
, PPD_ORDER_PAGE
);
1284 while ((nbytes
= fread(line
, 1, sizeof(line
), fp
)) > 0)
1286 fwrite(line
, 1, nbytes
, stdout
);
1289 cupsFileWrite(temp
, line
, nbytes
);
1294 WriteLabels(Orientation
);
1295 puts("ESPshowpage");
1302 if (ppd
== NULL
|| ppd
->num_filters
== 0)
1303 fputs("PAGE: 1 1\n", stderr
);
1305 ppdEmit(ppd
, stdout
, PPD_ORDER_PAGE
);
1306 copy_bytes(temp
, 0, 0);
1311 WriteLabels(Orientation
);
1312 puts("ESPshowpage");
1319 * Send %%EOF if needed...
1326 * End the job with the appropriate JCL command or CTRL-D otherwise.
1331 if (ppd
&& ppd
->jcl_end
)
1332 ppdEmitJCLEnd(ppd
, stdout
);
1338 * Close files and remove the temporary file if needed...
1341 if (slowcollate
|| sloworder
)
1343 cupsFileClose(temp
);
1357 * 'check_range()' - Check to see if the current page is selected for
1361 static int /* O - 1 if selected, 0 otherwise */
1362 check_range(int page
) /* I - Page number */
1364 const char *range
; /* Pointer into range string */
1365 int lower
, upper
; /* Lower and upper page numbers */
1368 if (PageSet
!= NULL
)
1371 * See if we only print even or odd pages...
1374 if (!strcasecmp(PageSet
, "even") && ((page
- 1) % (NUp
<< 1)) < NUp
)
1376 if (!strcasecmp(PageSet
, "odd") && ((page
- 1) % (NUp
<< 1)) >= NUp
)
1380 if (PageRanges
== NULL
)
1381 return (1); /* No range, print all pages... */
1383 for (range
= PageRanges
; *range
!= '\0';)
1389 upper
= strtol(range
, (char **)&range
, 10);
1393 lower
= strtol(range
, (char **)&range
, 10);
1398 if (!isdigit(*range
& 255))
1401 upper
= strtol(range
, (char **)&range
, 10);
1407 if (page
>= lower
&& page
<= upper
)
1421 * 'add_page()' - Add a page to the Pages array...
1424 static page_info_t
* /* O - New page info object */
1425 add_page(const char *label
, /* I - Page label */
1426 off_t offset
, /* I - Offset in file */
1427 const int *lbrt
) /* I - BoundingBox for page */
1429 page_info_t
*pageinfo
; /* New page info object */
1433 Pages
= cupsArrayNew(NULL
, NULL
);
1437 fprintf(stderr
, "EMERG: Unable to allocate memory for pages array: %s\n",
1442 if ((pageinfo
= calloc(1, sizeof(page_info_t
))) == NULL
)
1444 fprintf(stderr
, "EMERG: Unable to allocate memory for page info: %s\n",
1449 pageinfo
->label
= strdup(label
);
1450 pageinfo
->offset
= offset
;
1452 memcpy(pageinfo
->lbrt
, lbrt
, sizeof(pageinfo
->lbrt
));
1454 cupsArrayAdd(Pages
, pageinfo
);
1461 * 'copy_bytes()' - Copy bytes from the input file to stdout...
1465 copy_bytes(cups_file_t
*fp
, /* I - File to read from */
1466 off_t offset
, /* I - Offset to page data */
1467 size_t length
) /* I - Length of page data */
1469 char buffer
[8192]; /* Data buffer */
1470 ssize_t nbytes
; /* Number of bytes read */
1471 size_t nleft
; /* Number of bytes left/remaining */
1476 cupsFileSeek(fp
, offset
);
1478 while (nleft
> 0 || length
== 0)
1480 if (nleft
> sizeof(buffer
) || length
== 0)
1481 nbytes
= sizeof(buffer
);
1485 if ((nbytes
= cupsFileRead(fp
, buffer
, nbytes
)) < 1)
1490 fwrite(buffer
, 1, nbytes
, stdout
);
1496 * 'do_prolog()' - Send the necessary document prolog commands...
1500 do_prolog(ppd_file_t
*ppd
) /* I - PPD file */
1503 * Send the document prolog commands...
1506 if (ppd
&& ppd
->patches
)
1508 puts("%%BeginFeature: *JobPatchFile 1");
1510 puts("%%EndFeature");
1513 ppdEmit(ppd
, stdout
, PPD_ORDER_PROLOG
);
1518 * 'do_setup()' - Send the necessary document setup commands...
1522 do_setup(ppd_file_t
*ppd
, /* I - PPD file */
1523 int copies
, /* I - Number of copies */
1524 int collate
, /* I - Collate output? */
1525 int slowcollate
, /* I - Slow collate */
1526 float g
, /* I - Gamma value */
1527 float b
) /* I - Brightness value */
1530 * Send all the printer-specific setup commands...
1533 ppdEmit(ppd
, stdout
, PPD_ORDER_DOCUMENT
);
1534 ppdEmit(ppd
, stdout
, PPD_ORDER_ANY
);
1537 * Set the number of copies for the job...
1540 if (copies
!= 1 && (!collate
|| !slowcollate
))
1542 printf("%%RBIBeginNonPPDFeature: *NumCopies %d\n", copies
);
1543 printf("%d/languagelevel where{pop languagelevel 2 ge}{false}ifelse{1 dict begin"
1544 "/NumCopies exch def currentdict end "
1545 "setpagedevice}{userdict/#copies 3 -1 roll put}ifelse\n", copies
);
1546 printf("%%RBIEndNonPPDFeature\n");
1550 * If we are doing N-up printing, disable setpagedevice...
1554 puts("userdict/setpagedevice{pop}bind put");
1557 * Changes to the transfer function must be made AFTER any
1558 * setpagedevice code...
1561 if (g
!= 1.0 || b
!= 1.0)
1562 printf("{ neg 1 add dup 0 lt { pop 1 } { %.3f exp neg 1 add } "
1563 "ifelse %.3f mul } bind settransfer\n", g
, b
);
1566 * Make sure we have rectclip and rectstroke procedures of some sort...
1574 * 'end_nup()' - End processing for N-up printing...
1578 end_nup(int number
) /* I - Page number */
1582 if (Flip
|| Orientation
|| NUp
> 1)
1583 puts("userdict /ESPsave get restore");
1590 WriteLabels(Orientation
);
1591 puts("ESPshowpage");
1597 if (is_last_page(number
) && UseESPsp
)
1599 if (Orientation
& 1)
1602 * Rotate the labels back to portrait...
1605 WriteLabels(Orientation
- 1);
1607 else if (Orientation
== 0)
1610 * Rotate the labels to landscape...
1613 WriteLabels(NormalLandscape
? 1 : 3);
1618 * Rotate the labels to landscape...
1621 WriteLabels(NormalLandscape
? 3 : 1);
1624 puts("ESPshowpage");
1629 if (is_last_page(number
) && UseESPsp
)
1631 WriteLabels(Orientation
);
1632 puts("ESPshowpage");
1642 * 'include_feature()' - Include a printer option/feature command.
1646 include_feature(ppd_file_t
*ppd
, /* I - PPD file */
1647 const char *line
, /* I - DSC line */
1648 cups_file_t
*out
) /* I - Output file */
1650 char name
[255], /* Option name */
1651 value
[255]; /* Option value */
1652 ppd_option_t
*option
; /* Option in file */
1653 ppd_choice_t
*choice
; /* Choice */
1657 * Get the "%%IncludeFeature: *Keyword OptionKeyword" values...
1660 if (sscanf(line
+ 17, "%254s%254s", name
, value
) != 2)
1662 fprintf(stderr
, "ERROR: Bad line: \"%s\"!\n", line
);
1667 * Find the option and choice...
1670 if ((option
= ppdFindOption(ppd
, name
+ 1)) == NULL
)
1672 fprintf(stderr
, "WARNING: Unknown option \"%s\"!\n", name
+ 1);
1676 if (option
->section
== PPD_ORDER_EXIT
||
1677 option
->section
== PPD_ORDER_JCL
)
1679 fprintf(stderr
, "WARNING: Option \"%s\" cannot be included via "
1680 "IncludeFeature!\n", name
+ 1);
1684 if ((choice
= ppdFindChoice(option
, value
)) == NULL
)
1686 fprintf(stderr
, "WARNING: Unknown choice \"%s\" for option \"%s\"!\n",
1692 * Emit the option...
1697 cupsFilePuts(out
, "[{\n");
1698 cupsFilePrintf(out
, "%%%%BeginFeature: %s %s\n", name
, value
);
1699 if (choice
->code
&& choice
->code
[0])
1701 if (choice
->code
[strlen(choice
->code
) - 1] != '\n')
1702 cupsFilePrintf(out
, "%s\n", choice
->code
);
1704 cupsFilePuts(out
, choice
->code
);
1706 cupsFilePuts(out
, "%%EndFeature\n");
1707 cupsFilePuts(out
, "} stopped cleartomark\n");
1712 printf("%%%%BeginFeature: %s %s\n", name
, value
);
1713 if (choice
->code
&& choice
->code
[0])
1715 if (choice
->code
[strlen(choice
->code
) - 1] != '\n')
1716 printf("%s\n", choice
->code
);
1718 fputs(choice
->code
, stdout
);
1720 puts("%%EndFeature");
1721 puts("} stopped cleartomark");
1727 * 'psgets()' - Get a line from a file.
1731 * This function differs from the gets() function in that it
1732 * handles any combination of CR, LF, or CR LF to end input
1736 static char * /* O - String or NULL if EOF */
1737 psgets(char *buf
, /* I - Buffer to read into */
1738 size_t *bytes
, /* IO - Length of buffer */
1739 FILE *fp
) /* I - File to read from */
1741 char *bufptr
; /* Pointer into buffer */
1742 int ch
; /* Character from file */
1743 size_t len
; /* Max length of string */
1750 while ((bufptr
- buf
) < len
)
1752 if ((ch
= getc(fp
)) == EOF
)
1758 * Got a CR; see if there is a LF as well...
1763 if (ch
!= EOF
&& ch
!= '\n')
1765 ungetc(ch
, fp
); /* Nope, save it for later... */
1772 else if (ch
== '\n')
1779 * Add a trailing newline if it is there...
1782 if (ch
== '\n' || ch
== '\r')
1784 if ((bufptr
- buf
) < len
)
1791 * Nul-terminate the string and return it (or NULL for EOF).
1795 *bytes
= bufptr
- buf
;
1797 if (ch
== EOF
&& bufptr
== buf
)
1805 * 'start_nup()' - Start processing for N-up printing...
1809 start_nup(int number
, /* I - Page number */
1810 int show_border
, /* I - Show the page border? */
1811 const int *lbrt
) /* I - Page BoundingBox */
1813 int pos
; /* Position on page */
1814 int x
, y
; /* Relative position of subpage */
1815 float w
, l
, /* Width and length of subpage */
1816 tx
, ty
; /* Translation values for subpage */
1817 float pw
, pl
; /* Printable width and length of full page */
1820 if (Flip
|| Orientation
|| NUp
> 1)
1821 puts("userdict/ESPsave save put");
1824 printf("%.1f 0.0 translate -1 1 scale\n", PageWidth
);
1827 pw
= lbrt
[2] - lbrt
[0];
1828 pl
= lbrt
[3] - lbrt
[1];
1830 fprintf(stderr
, "DEBUG: pw = %.1f, pl = %.1f\n", pw
, pl
);
1831 fprintf(stderr
, "DEBUG: PageLeft = %.1f, PageRight = %.1f\n", PageLeft
, PageRight
);
1832 fprintf(stderr
, "DEBUG: PageTop = %.1f, PageBottom = %.1f\n", PageTop
, PageBottom
);
1833 fprintf(stderr
, "DEBUG: PageWidth = %.1f, PageLength = %.1f\n", PageWidth
, PageLength
);
1835 switch (Orientation
)
1837 case 1 : /* Landscape */
1838 printf("%.1f 0.0 translate 90 rotate\n", PageLength
);
1840 case 2 : /* Reverse Portrait */
1841 printf("%.1f %.1f translate 180 rotate\n", PageWidth
, PageLength
);
1843 case 3 : /* Reverse Landscape */
1844 printf("0.0 %.1f translate -90 rotate\n", PageWidth
);
1848 if (Duplex
&& NUp
> 1 && ((number
/ NUp
) & 1))
1849 printf("%.1f %.1f translate\n", PageWidth
- PageRight
, PageBottom
);
1850 else if (NUp
> 1 || FitPlot
)
1851 printf("%.1f %.1f translate\n", PageLeft
, PageBottom
);
1858 w
= PageRight
- PageLeft
;
1861 if (l
> (PageTop
- PageBottom
))
1863 l
= PageTop
- PageBottom
;
1867 tx
= 0.5 * (PageRight
- PageLeft
- w
);
1868 ty
= 0.5 * (PageTop
- PageBottom
- l
);
1870 printf("%.1f %.1f translate %.3f %.3f scale\n", tx
, ty
, w
/ pw
,
1881 if (Orientation
& 1)
1885 if (Layout
& LAYOUT_NEGATEY
)
1889 l
= w
* PageLength
/ PageWidth
;
1894 w
= l
* PageWidth
/ PageLength
;
1897 tx
= 0.5 * (pw
* 0.5 - l
);
1898 ty
= 0.5 * (pl
- w
);
1900 if (NormalLandscape
)
1901 printf("0.0 %.1f translate -90 rotate\n", pl
);
1903 printf("%.1f 0.0 translate 90 rotate\n", pw
);
1905 printf("%.1f %.1f translate %.3f %.3f scale\n",
1906 ty
, tx
+ l
* x
, w
/ PageWidth
, l
/ PageLength
);
1912 if (Layout
& LAYOUT_NEGATEX
)
1916 w
= l
* PageWidth
/ PageLength
;
1921 l
= w
* PageLength
/ PageWidth
;
1924 tx
= 0.5 * (pl
* 0.5 - w
);
1925 ty
= 0.5 * (pw
- l
);
1927 if (NormalLandscape
)
1928 printf("%.1f 0.0 translate 90 rotate\n", pw
);
1930 printf("0.0 %.1f translate -90 rotate\n", pl
);
1932 printf("%.1f %.1f translate %.3f %.3f scale\n",
1933 tx
+ w
* x
, ty
, w
/ PageWidth
, l
/ PageLength
);
1938 if (Layout
& LAYOUT_VERTICAL
)
1949 if (Layout
& LAYOUT_NEGATEX
)
1952 if (Layout
& LAYOUT_NEGATEY
)
1956 l
= w
* PageLength
/ PageWidth
;
1961 w
= l
* PageWidth
/ PageLength
;
1964 tx
= 0.5 * (pw
* 0.5 - w
);
1965 ty
= 0.5 * (pl
* 0.5 - l
);
1967 printf("%.1f %.1f translate %.3f %.3f scale\n", tx
+ x
* w
, ty
+ y
* l
,
1968 w
/ PageWidth
, l
/ PageLength
);
1972 if (Orientation
& 1)
1974 if (Layout
& LAYOUT_VERTICAL
)
1979 if (Layout
& LAYOUT_NEGATEX
)
1982 if (Layout
& LAYOUT_NEGATEY
)
1990 if (Layout
& LAYOUT_NEGATEX
)
1993 if (Layout
& LAYOUT_NEGATEY
)
1998 l
= w
* PageLength
/ PageWidth
;
2000 if (l
> (pw
* 0.333))
2003 w
= l
* PageWidth
/ PageLength
;
2006 tx
= 0.5 * (pl
- 2 * w
);
2007 ty
= 0.5 * (pw
- 3 * l
);
2009 if (NormalLandscape
)
2010 printf("0.0 %.1f translate -90 rotate\n", pl
);
2012 printf("%.1f 0.0 translate 90 rotate\n", pw
);
2014 printf("%.1f %.1f translate %.3f %.3f scale\n",
2015 tx
+ x
* w
, ty
+ y
* l
, w
/ PageWidth
, l
/ PageLength
);
2019 if (Layout
& LAYOUT_VERTICAL
)
2024 if (Layout
& LAYOUT_NEGATEX
)
2027 if (Layout
& LAYOUT_NEGATEY
)
2035 if (Layout
& LAYOUT_NEGATEX
)
2038 if (Layout
& LAYOUT_NEGATEY
)
2043 w
= l
* PageWidth
/ PageLength
;
2045 if (w
> (pl
* 0.333))
2048 l
= w
* PageLength
/ PageWidth
;
2051 tx
= 0.5 * (pl
- 3 * w
);
2052 ty
= 0.5 * (pw
- 2 * l
);
2054 if (NormalLandscape
)
2055 printf("%.1f 0.0 translate 90 rotate\n", pw
);
2057 printf("0.0 %.1f translate -90 rotate\n", pl
);
2059 printf("%.1f %.1f translate %.3f %.3f scale\n",
2060 tx
+ w
* x
, ty
+ l
* y
, w
/ PageWidth
, l
/ PageLength
);
2065 if (Layout
& LAYOUT_VERTICAL
)
2076 if (Layout
& LAYOUT_NEGATEX
)
2079 if (Layout
& LAYOUT_NEGATEY
)
2083 l
= w
* PageLength
/ PageWidth
;
2085 if (l
> (pl
* 0.333))
2088 w
= l
* PageWidth
/ PageLength
;
2091 tx
= 0.5 * (pw
* 0.333 - w
);
2092 ty
= 0.5 * (pl
* 0.333 - l
);
2094 printf("%.1f %.1f translate %.3f %.3f scale\n", tx
+ x
* w
, ty
+ y
* l
,
2095 w
/ PageWidth
, l
/ PageLength
);
2099 if (Layout
& LAYOUT_VERTICAL
)
2110 if (Layout
& LAYOUT_NEGATEX
)
2113 if (Layout
& LAYOUT_NEGATEY
)
2117 l
= w
* PageLength
/ PageWidth
;
2119 if (l
> (pl
* 0.25))
2122 w
= l
* PageWidth
/ PageLength
;
2125 tx
= 0.5 * (pw
* 0.25 - w
);
2126 ty
= 0.5 * (pl
* 0.25 - l
);
2128 printf("%.1f %.1f translate %.3f %.3f scale\n", tx
+ x
* w
, ty
+ y
* l
,
2129 w
/ PageWidth
, l
/ PageLength
);
2134 * Draw borders as necessary...
2137 if (Border
&& show_border
)
2139 int rects
; /* Number of border rectangles */
2140 float fscale
, /* Scaling value for points */
2141 margin
; /* Current margin for borders */
2144 rects
= (Border
& BORDER_DOUBLE
) ? 2 : 1;
2145 fscale
= PageWidth
/ w
;
2146 margin
= 2.25 * fscale
;
2149 * Set the line width and color...
2153 printf("%.3f setlinewidth 0 setgray newpath\n",
2154 (Border
& BORDER_THICK
) ? 0.5 * fscale
: 0.24 * fscale
);
2157 * Draw border boxes...
2160 for (; rects
> 0; rects
--, margin
+= 2 * fscale
)
2162 printf("%.1f %.1f %.1f %.1f ESPrs\n",
2165 PageWidth
- 2 * margin
,
2166 PageLength
- 2 * margin
);
2168 printf("%.1f %.1f %.1f %.1f ESPrs\n",
2170 PageBottom
+ margin
,
2171 PageRight
- PageLeft
- 2 * margin
,
2172 PageTop
- PageBottom
- 2 * margin
);
2175 * Restore pen settings...
2184 * Clip the page that follows to the bounding box of the page...
2187 printf("%d %d translate\n", -lbrt
[0], -lbrt
[1]);
2188 printf("0 0 %.1f %.1f ESPrc\n", w
, l
);
2194 * End of "$Id: pstops.c 5092 2006-02-09 00:54:31Z mike $".