]> git.ipfire.org Git - thirdparty/cups.git/blob - filter/imagetops.c
Merge changes from CUPS 1.5b1-r9798.
[thirdparty/cups.git] / filter / imagetops.c
1 /*
2 * "$Id: imagetops.c 6649 2007-07-11 21:46:42Z mike $"
3 *
4 * Image file to PostScript filter for CUPS.
5 *
6 * Copyright 2007-2011 by Apple Inc.
7 * Copyright 1993-2007 by Easy Software Products.
8 *
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
14 *
15 * This file is subject to the Apple OS-Developed Software exception.
16 *
17 * Contents:
18 *
19 * main() - Main entry...
20 * ps_hex() - Print binary data as a series of hexadecimal numbers.
21 * ps_ascii85() - Print binary data as a series of base-85 numbers.
22 */
23
24 /*
25 * Include necessary headers...
26 */
27
28 #include "common.h"
29 #include "image.h"
30 #include <math.h>
31 #include <cups/language-private.h>
32 #include <signal.h>
33
34
35 /*
36 * Globals...
37 */
38
39 int Flip = 0, /* Flip/mirror pages */
40 XPosition = 0, /* Horizontal position on page */
41 YPosition = 0, /* Vertical position on page */
42 Collate = 0, /* Collate copies? */
43 Copies = 1; /* Number of copies */
44
45
46 /*
47 * Local functions...
48 */
49
50 static void ps_hex(cups_ib_t *, int, int);
51 static void ps_ascii85(cups_ib_t *, int, int);
52
53
54 /*
55 * 'main()' - Main entry...
56 */
57
58 int /* O - Exit status */
59 main(int argc, /* I - Number of command-line arguments */
60 char *argv[]) /* I - Command-line arguments */
61 {
62 cups_image_t *img; /* Image to print */
63 float xprint, /* Printable area */
64 yprint,
65 xinches, /* Total size in inches */
66 yinches;
67 float xsize, /* Total size in points */
68 ysize,
69 xsize2,
70 ysize2;
71 float aspect; /* Aspect ratio */
72 int xpages, /* # x pages */
73 ypages, /* # y pages */
74 xpage, /* Current x page */
75 ypage, /* Current y page */
76 page; /* Current page number */
77 int xc0, yc0, /* Corners of the page in image coords */
78 xc1, yc1;
79 cups_ib_t *row; /* Current row */
80 int y; /* Current Y coordinate in image */
81 int colorspace; /* Output colorspace */
82 int out_offset, /* Offset into output buffer */
83 out_length; /* Length of output buffer */
84 ppd_file_t *ppd; /* PPD file */
85 ppd_choice_t *choice; /* PPD option choice */
86 int num_options; /* Number of print options */
87 cups_option_t *options; /* Print options */
88 const char *val; /* Option value */
89 int slowcollate; /* Collate copies the slow way */
90 float g; /* Gamma correction value */
91 float b; /* Brightness factor */
92 float zoom; /* Zoom facter */
93 int xppi, yppi; /* Pixels-per-inch */
94 int hue, sat; /* Hue and saturation adjustment */
95 int realcopies, /* Real copies being printed */
96 emit_jcl; /* Emit JCL? */
97 float left, top; /* Left and top of image */
98 char filename[1024]; /* Name of file to print */
99 time_t curtime; /* Current time */
100 struct tm *curtm; /* Current date */
101 char curdate[255]; /* Current date string */
102
103
104 /*
105 * Make sure status messages are not buffered...
106 */
107
108 setbuf(stderr, NULL);
109
110 /*
111 * Ignore broken pipe signals...
112 */
113
114 signal(SIGPIPE, SIG_IGN);
115
116 /*
117 * Check command-line...
118 */
119
120 if (argc < 6 || argc > 7)
121 {
122 _cupsLangPrintf(stderr,
123 _("Usage: %s job-id user title copies options file"),
124 argv[0]);
125 return (1);
126 }
127
128 /*
129 * Copy stdin as needed...
130 */
131
132 if (argc == 6)
133 {
134 int fd; /* File to write to */
135 char buffer[8192]; /* Buffer to read into */
136 int bytes; /* # of bytes to read */
137
138
139 if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
140 {
141 _cupsLangPrintError("ERROR", _("Unable to copy print file"));
142 return (1);
143 }
144
145 fprintf(stderr, "DEBUG: imagetops - copying to temp print file \"%s\".\n",
146 filename);
147
148 while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
149 write(fd, buffer, bytes);
150
151 close(fd);
152 }
153 else
154 strlcpy(filename, argv[6], sizeof(filename));
155
156 /*
157 * Process command-line options and write the prolog...
158 */
159
160 zoom = 0.0;
161 xppi = 0;
162 yppi = 0;
163 hue = 0;
164 sat = 100;
165 g = 1.0;
166 b = 1.0;
167
168 Copies = atoi(argv[4]);
169
170 options = NULL;
171 num_options = cupsParseOptions(argv[5], 0, &options);
172
173 ppd = SetCommonOptions(num_options, options, 0);
174
175 if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL)
176 {
177 /*
178 * This IPP attribute is unnecessarily complicated...
179 *
180 * single-document, separate-documents-collated-copies, and
181 * single-document-new-sheet all require collated copies.
182 *
183 * separate-documents-uncollated-copies allows for uncollated copies.
184 */
185
186 Collate = _cups_strcasecmp(val, "separate-documents-uncollated-copies") != 0;
187 }
188
189 if ((val = cupsGetOption("Collate", num_options, options)) != NULL &&
190 _cups_strcasecmp(val, "True") == 0)
191 Collate = 1;
192
193 if ((val = cupsGetOption("gamma", num_options, options)) != NULL)
194 {
195 /*
196 * Get gamma value from 1 to 10000...
197 */
198
199 g = atoi(val) * 0.001f;
200
201 if (g < 0.001f)
202 g = 0.001f;
203 else if (g > 10.0f)
204 g = 10.0f;
205 }
206
207 if ((val = cupsGetOption("brightness", num_options, options)) != NULL)
208 {
209 /*
210 * Get brightness value from 10 to 1000.
211 */
212
213 b = atoi(val) * 0.01f;
214
215 if (b < 0.1f)
216 b = 0.1f;
217 else if (b > 10.0f)
218 b = 10.0f;
219 }
220
221 if ((val = cupsGetOption("scaling", num_options, options)) != NULL)
222 zoom = atoi(val) * 0.01;
223 else if ((val = cupsGetOption("fitplot", num_options, options)) != NULL &&
224 !_cups_strcasecmp(val, "true"))
225 zoom = 1.0;
226 else if ((val = cupsGetOption("fit-to-page", num_options, options)) != NULL &&
227 !_cups_strcasecmp(val, "true"))
228 zoom = 1.0;
229
230 if ((val = cupsGetOption("ppi", num_options, options)) != NULL)
231 if (sscanf(val, "%dx%d", &xppi, &yppi) < 2)
232 yppi = xppi;
233
234 if ((val = cupsGetOption("position", num_options, options)) != NULL)
235 {
236 if (_cups_strcasecmp(val, "center") == 0)
237 {
238 XPosition = 0;
239 YPosition = 0;
240 }
241 else if (_cups_strcasecmp(val, "top") == 0)
242 {
243 XPosition = 0;
244 YPosition = 1;
245 }
246 else if (_cups_strcasecmp(val, "left") == 0)
247 {
248 XPosition = -1;
249 YPosition = 0;
250 }
251 else if (_cups_strcasecmp(val, "right") == 0)
252 {
253 XPosition = 1;
254 YPosition = 0;
255 }
256 else if (_cups_strcasecmp(val, "top-left") == 0)
257 {
258 XPosition = -1;
259 YPosition = 1;
260 }
261 else if (_cups_strcasecmp(val, "top-right") == 0)
262 {
263 XPosition = 1;
264 YPosition = 1;
265 }
266 else if (_cups_strcasecmp(val, "bottom") == 0)
267 {
268 XPosition = 0;
269 YPosition = -1;
270 }
271 else if (_cups_strcasecmp(val, "bottom-left") == 0)
272 {
273 XPosition = -1;
274 YPosition = -1;
275 }
276 else if (_cups_strcasecmp(val, "bottom-right") == 0)
277 {
278 XPosition = 1;
279 YPosition = -1;
280 }
281 }
282
283 if ((val = cupsGetOption("saturation", num_options, options)) != NULL)
284 sat = atoi(val);
285
286 if ((val = cupsGetOption("hue", num_options, options)) != NULL)
287 hue = atoi(val);
288
289 if ((choice = ppdFindMarkedChoice(ppd, "MirrorPrint")) != NULL)
290 {
291 val = choice->choice;
292 choice->marked = 0;
293 }
294 else
295 val = cupsGetOption("mirror", num_options, options);
296
297 if (val && (!_cups_strcasecmp(val, "true") || !_cups_strcasecmp(val, "on") ||
298 !_cups_strcasecmp(val, "yes")))
299 Flip = 1;
300
301 if ((val = cupsGetOption("emit-jcl", num_options, options)) != NULL &&
302 (!_cups_strcasecmp(val, "false") || !_cups_strcasecmp(val, "off") ||
303 !_cups_strcasecmp(val, "no") || !strcmp(val, "0")))
304 emit_jcl = 0;
305 else
306 emit_jcl = 1;
307
308 /*
309 * Open the input image to print...
310 */
311
312 colorspace = ColorDevice ? CUPS_IMAGE_RGB_CMYK : CUPS_IMAGE_WHITE;
313
314 img = cupsImageOpen(filename, colorspace, CUPS_IMAGE_WHITE, sat, hue, NULL);
315
316 if (argc == 6)
317 unlink(filename);
318
319 if (img == NULL)
320 {
321 _cupsLangPrintFilter(stderr, "ERROR",
322 _("The print file could not be opened."));
323 ppdClose(ppd);
324 return (1);
325 }
326
327 colorspace = cupsImageGetColorSpace(img);
328
329 /*
330 * Scale as necessary...
331 */
332
333 if (zoom == 0.0 && xppi == 0)
334 {
335 xppi = cupsImageGetXPPI(img);
336 yppi = cupsImageGetYPPI(img);
337 }
338
339 if (yppi == 0)
340 yppi = xppi;
341
342 fprintf(stderr, "DEBUG: Before scaling: xppi=%d, yppi=%d, zoom=%.2f\n",
343 xppi, yppi, zoom);
344
345 if (xppi > 0)
346 {
347 /*
348 * Scale the image as neccesary to match the desired pixels-per-inch.
349 */
350
351 if (Orientation & 1)
352 {
353 xprint = (PageTop - PageBottom) / 72.0;
354 yprint = (PageRight - PageLeft) / 72.0;
355 }
356 else
357 {
358 xprint = (PageRight - PageLeft) / 72.0;
359 yprint = (PageTop - PageBottom) / 72.0;
360 }
361
362 fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
363 xprint, yprint);
364
365 xinches = (float)cupsImageGetWidth(img) / (float)xppi;
366 yinches = (float)cupsImageGetHeight(img) / (float)yppi;
367
368 fprintf(stderr, "DEBUG: Image size is %.1f x %.1f inches...\n",
369 xinches, yinches);
370
371 if ((val = cupsGetOption("natural-scaling", num_options, options)) != NULL)
372 {
373 xinches = xinches * atoi(val) / 100;
374 yinches = yinches * atoi(val) / 100;
375 }
376
377 if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
378 cupsGetOption("landscape", num_options, options) == NULL)
379 {
380 /*
381 * Rotate the image if it will fit landscape but not portrait...
382 */
383
384 fputs("DEBUG: Auto orientation...\n", stderr);
385
386 if ((xinches > xprint || yinches > yprint) &&
387 xinches <= yprint && yinches <= xprint)
388 {
389 /*
390 * Rotate the image as needed...
391 */
392
393 fputs("DEBUG: Using landscape orientation...\n", stderr);
394
395 Orientation = (Orientation + 1) & 3;
396 xsize = yprint;
397 yprint = xprint;
398 xprint = xsize;
399 }
400 }
401 }
402 else
403 {
404 /*
405 * Scale percentage of page size...
406 */
407
408 xprint = (PageRight - PageLeft) / 72.0;
409 yprint = (PageTop - PageBottom) / 72.0;
410 aspect = (float)cupsImageGetYPPI(img) / (float)cupsImageGetXPPI(img);
411
412 fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
413 xprint, yprint);
414
415 fprintf(stderr, "DEBUG: cupsImageGetXPPI(img) = %d, cupsImageGetYPPI(img) = %d, aspect = %f\n",
416 cupsImageGetXPPI(img), cupsImageGetYPPI(img), aspect);
417
418 xsize = xprint * zoom;
419 ysize = xsize * cupsImageGetHeight(img) / cupsImageGetWidth(img) / aspect;
420
421 if (ysize > (yprint * zoom))
422 {
423 ysize = yprint * zoom;
424 xsize = ysize * cupsImageGetWidth(img) * aspect / cupsImageGetHeight(img);
425 }
426
427 xsize2 = yprint * zoom;
428 ysize2 = xsize2 * cupsImageGetHeight(img) / cupsImageGetWidth(img) / aspect;
429
430 if (ysize2 > (xprint * zoom))
431 {
432 ysize2 = xprint * zoom;
433 xsize2 = ysize2 * cupsImageGetWidth(img) * aspect / cupsImageGetHeight(img);
434 }
435
436 fprintf(stderr, "DEBUG: Portrait size is %.2f x %.2f inches\n", xsize, ysize);
437 fprintf(stderr, "DEBUG: Landscape size is %.2f x %.2f inches\n", xsize2, ysize2);
438
439 if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
440 cupsGetOption("landscape", num_options, options) == NULL)
441 {
442 /*
443 * Choose the rotation with the largest area, but prefer
444 * portrait if they are equal...
445 */
446
447 fputs("DEBUG: Auto orientation...\n", stderr);
448
449 if ((xsize * ysize) < (xsize2 * xsize2))
450 {
451 /*
452 * Do landscape orientation...
453 */
454
455 fputs("DEBUG: Using landscape orientation...\n", stderr);
456
457 Orientation = 1;
458 xinches = xsize2;
459 yinches = ysize2;
460 xprint = (PageTop - PageBottom) / 72.0;
461 yprint = (PageRight - PageLeft) / 72.0;
462 }
463 else
464 {
465 /*
466 * Do portrait orientation...
467 */
468
469 fputs("DEBUG: Using portrait orientation...\n", stderr);
470
471 Orientation = 0;
472 xinches = xsize;
473 yinches = ysize;
474 }
475 }
476 else if (Orientation & 1)
477 {
478 fputs("DEBUG: Using landscape orientation...\n", stderr);
479
480 xinches = xsize2;
481 yinches = ysize2;
482 xprint = (PageTop - PageBottom) / 72.0;
483 yprint = (PageRight - PageLeft) / 72.0;
484 }
485 else
486 {
487 fputs("DEBUG: Using portrait orientation...\n", stderr);
488
489 xinches = xsize;
490 yinches = ysize;
491 xprint = (PageRight - PageLeft) / 72.0;
492 yprint = (PageTop - PageBottom) / 72.0;
493 }
494 }
495
496 /*
497 * Compute the number of pages to print and the size of the image on each
498 * page...
499 */
500
501 xpages = ceil(xinches / xprint);
502 ypages = ceil(yinches / yprint);
503
504 xprint = xinches / xpages;
505 yprint = yinches / ypages;
506
507 fprintf(stderr, "DEBUG: xpages = %dx%.2fin, ypages = %dx%.2fin\n",
508 xpages, xprint, ypages, yprint);
509
510 /*
511 * Update the page size for custom sizes...
512 */
513
514 if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) != NULL &&
515 _cups_strcasecmp(choice->choice, "Custom") == 0)
516 {
517 float width, /* New width in points */
518 length; /* New length in points */
519 char s[255]; /* New custom page size... */
520
521
522 /*
523 * Use the correct width and length for the current orientation...
524 */
525
526 if (Orientation & 1)
527 {
528 width = yprint * 72.0;
529 length = xprint * 72.0;
530 }
531 else
532 {
533 width = xprint * 72.0;
534 length = yprint * 72.0;
535 }
536
537 /*
538 * Add margins to page size...
539 */
540
541 width += ppd->custom_margins[0] + ppd->custom_margins[2];
542 length += ppd->custom_margins[1] + ppd->custom_margins[3];
543
544 /*
545 * Enforce minimums...
546 */
547
548 if (width < ppd->custom_min[0])
549 width = ppd->custom_min[0];
550
551 if (length < ppd->custom_min[1])
552 length = ppd->custom_min[1];
553
554 fprintf(stderr, "DEBUG: Updated custom page size to %.2f x %.2f inches...\n",
555 width / 72.0, length / 72.0);
556
557 /*
558 * Set the new custom size...
559 */
560
561 sprintf(s, "Custom.%.0fx%.0f", width, length);
562 ppdMarkOption(ppd, "PageSize", s);
563
564 /*
565 * Update page variables...
566 */
567
568 PageWidth = width;
569 PageLength = length;
570 PageLeft = ppd->custom_margins[0];
571 PageRight = width - ppd->custom_margins[2];
572 PageBottom = ppd->custom_margins[1];
573 PageTop = length - ppd->custom_margins[3];
574 }
575
576 /*
577 * See if we need to collate, and if so how we need to do it...
578 */
579
580 if (xpages == 1 && ypages == 1)
581 Collate = 0;
582
583 slowcollate = Collate && ppdFindOption(ppd, "Collate") == NULL;
584
585 if (Copies > 1 && !slowcollate)
586 {
587 realcopies = Copies;
588 Copies = 1;
589 }
590 else
591 realcopies = 1;
592
593 /*
594 * Write any "exit server" options that have been selected...
595 */
596
597 ppdEmit(ppd, stdout, PPD_ORDER_EXIT);
598
599 /*
600 * Write any JCL commands that are needed to print PostScript code...
601 */
602
603 if (emit_jcl)
604 ppdEmitJCL(ppd, stdout, atoi(argv[1]), argv[2], argv[3]);
605
606 /*
607 * Start sending the document with any commands needed...
608 */
609
610 curtime = time(NULL);
611 curtm = localtime(&curtime);
612
613 puts("%!PS-Adobe-3.0");
614 printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n", PageLeft, PageBottom,
615 PageRight, PageTop);
616 printf("%%%%LanguageLevel: %d\n", LanguageLevel);
617 printf("%%%%Pages: %d\n", xpages * ypages * Copies);
618 puts("%%DocumentData: Clean7Bit");
619 puts("%%DocumentNeededResources: font Helvetica-Bold");
620 puts("%%Creator: imagetops/" CUPS_SVERSION);
621 strftime(curdate, sizeof(curdate), "%c", curtm);
622 printf("%%%%CreationDate: %s\n", curdate);
623 WriteTextComment("Title", argv[3]);
624 WriteTextComment("For", argv[2]);
625 if (Orientation & 1)
626 puts("%%Orientation: Landscape");
627 else
628 puts("%%Orientation: Portrait");
629 puts("%%EndComments");
630 puts("%%BeginProlog");
631
632 if (ppd != NULL && ppd->patches != NULL)
633 puts(ppd->patches);
634
635 ppdEmit(ppd, stdout, PPD_ORDER_DOCUMENT);
636 ppdEmit(ppd, stdout, PPD_ORDER_ANY);
637 ppdEmit(ppd, stdout, PPD_ORDER_PROLOG);
638
639 if (g != 1.0 || b != 1.0)
640 printf("{ neg 1 add dup 0 lt { pop 1 } { %.3f exp neg 1 add } "
641 "ifelse %.3f mul } bind settransfer\n", g, b);
642
643 WriteCommon();
644 switch (Orientation)
645 {
646 case 0 :
647 WriteLabelProlog(cupsGetOption("page-label", num_options, options),
648 PageBottom, PageTop, PageWidth);
649 break;
650
651 case 1 :
652 WriteLabelProlog(cupsGetOption("page-label", num_options, options),
653 PageLeft, PageRight, PageLength);
654 break;
655
656 case 2 :
657 WriteLabelProlog(cupsGetOption("page-label", num_options, options),
658 PageLength - PageTop, PageLength - PageBottom,
659 PageWidth);
660 break;
661
662 case 3 :
663 WriteLabelProlog(cupsGetOption("page-label", num_options, options),
664 PageWidth - PageRight, PageWidth - PageLeft,
665 PageLength);
666 break;
667 }
668
669 if (realcopies > 1)
670 {
671 if (ppd == NULL || ppd->language_level == 1)
672 printf("/#copies %d def\n", realcopies);
673 else
674 printf("<</NumCopies %d>>setpagedevice\n", realcopies);
675 }
676
677 puts("%%EndProlog");
678
679 /*
680 * Output the pages...
681 */
682
683 row = malloc(cupsImageGetWidth(img) * abs(colorspace) + 3);
684
685 fprintf(stderr, "DEBUG: XPosition=%d, YPosition=%d, Orientation=%d\n",
686 XPosition, YPosition, Orientation);
687 fprintf(stderr, "DEBUG: xprint=%.0f, yprint=%.0f\n", xprint, yprint);
688 fprintf(stderr, "DEBUG: PageLeft=%.0f, PageRight=%.0f, PageWidth=%.0f\n",
689 PageLeft, PageRight, PageWidth);
690 fprintf(stderr, "DEBUG: PageBottom=%.0f, PageTop=%.0f, PageLength=%.0f\n",
691 PageBottom, PageTop, PageLength);
692
693 switch (Orientation)
694 {
695 default :
696 switch (XPosition)
697 {
698 case -1 :
699 left = PageLeft;
700 break;
701 default :
702 left = (PageRight + PageLeft - xprint * 72) / 2;
703 break;
704 case 1 :
705 left = PageRight - xprint * 72;
706 break;
707 }
708
709 switch (YPosition)
710 {
711 case -1 :
712 top = PageBottom + yprint * 72;
713 break;
714 default :
715 top = (PageTop + PageBottom + yprint * 72) / 2;
716 break;
717 case 1 :
718 top = PageTop;
719 break;
720 }
721 break;
722
723 case 1 :
724 switch (XPosition)
725 {
726 case -1 :
727 left = PageBottom;
728 break;
729 default :
730 left = (PageTop + PageBottom - xprint * 72) / 2;
731 break;
732 case 1 :
733 left = PageTop - xprint * 72;
734 break;
735 }
736
737 switch (YPosition)
738 {
739 case -1 :
740 top = PageLeft + yprint * 72;
741 break;
742 default :
743 top = (PageRight + PageLeft + yprint * 72) / 2;
744 break;
745 case 1 :
746 top = PageRight;
747 break;
748 }
749 break;
750
751 case 2 :
752 switch (XPosition)
753 {
754 case 1 :
755 left = PageLeft;
756 break;
757 default :
758 left = (PageRight + PageLeft - xprint * 72) / 2;
759 break;
760 case -1 :
761 left = PageRight - xprint * 72;
762 break;
763 }
764
765 switch (YPosition)
766 {
767 case 1 :
768 top = PageBottom + yprint * 72;
769 break;
770 default :
771 top = (PageTop + PageBottom + yprint * 72) / 2;
772 break;
773 case -1 :
774 top = PageTop;
775 break;
776 }
777 break;
778
779 case 3 :
780 switch (XPosition)
781 {
782 case 1 :
783 left = PageBottom;
784 break;
785 default :
786 left = (PageTop + PageBottom - xprint * 72) / 2;
787 break;
788 case -1 :
789 left = PageTop - xprint * 72;
790 break;
791 }
792
793 switch (YPosition)
794 {
795 case 1 :
796 top = PageLeft + yprint * 72;
797 break;
798 default :
799 top = (PageRight + PageLeft + yprint * 72) / 2;
800 break;
801 case -1 :
802 top = PageRight;
803 break;
804 }
805 break;
806 }
807
808 fprintf(stderr, "DEBUG: left=%.2f, top=%.2f\n", left, top);
809
810 for (page = 1; Copies > 0; Copies --)
811 for (xpage = 0; xpage < xpages; xpage ++)
812 for (ypage = 0; ypage < ypages; ypage ++, page ++)
813 {
814 if (ppd && ppd->num_filters == 0)
815 fprintf(stderr, "PAGE: %d %d\n", page, realcopies);
816
817 _cupsLangPrintFilter(stderr, "INFO", _("Printing page %d."), page);
818
819 printf("%%%%Page: %d %d\n", page, page);
820
821 ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
822
823 puts("gsave");
824
825 if (Flip)
826 printf("%.0f 0 translate -1 1 scale\n", PageWidth);
827
828 switch (Orientation)
829 {
830 case 1 : /* Landscape */
831 printf("%.0f 0 translate 90 rotate\n", PageWidth);
832 break;
833 case 2 : /* Reverse Portrait */
834 printf("%.0f %.0f translate 180 rotate\n", PageWidth, PageLength);
835 break;
836 case 3 : /* Reverse Landscape */
837 printf("0 %.0f translate -90 rotate\n", PageLength);
838 break;
839 }
840
841 puts("gsave");
842
843 xc0 = cupsImageGetWidth(img) * xpage / xpages;
844 xc1 = cupsImageGetWidth(img) * (xpage + 1) / xpages - 1;
845 yc0 = cupsImageGetHeight(img) * ypage / ypages;
846 yc1 = cupsImageGetHeight(img) * (ypage + 1) / ypages - 1;
847
848 printf("%.1f %.1f translate\n", left, top);
849
850 printf("%.3f %.3f scale\n\n",
851 xprint * 72.0 / (xc1 - xc0 + 1),
852 yprint * 72.0 / (yc1 - yc0 + 1));
853
854 if (LanguageLevel == 1)
855 {
856 printf("/picture %d string def\n", (xc1 - xc0 + 1) * abs(colorspace));
857 printf("%d %d 8[1 0 0 -1 0 1]", (xc1 - xc0 + 1), (yc1 - yc0 + 1));
858
859 if (colorspace == CUPS_IMAGE_WHITE)
860 puts("{currentfile picture readhexstring pop} image");
861 else
862 printf("{currentfile picture readhexstring pop} false %d colorimage\n",
863 abs(colorspace));
864
865 for (y = yc0; y <= yc1; y ++)
866 {
867 cupsImageGetRow(img, xc0, y, xc1 - xc0 + 1, row);
868 ps_hex(row, (xc1 - xc0 + 1) * abs(colorspace), y == yc1);
869 }
870 }
871 else
872 {
873 switch (colorspace)
874 {
875 case CUPS_IMAGE_WHITE :
876 puts("/DeviceGray setcolorspace");
877 break;
878 case CUPS_IMAGE_RGB :
879 puts("/DeviceRGB setcolorspace");
880 break;
881 case CUPS_IMAGE_CMYK :
882 puts("/DeviceCMYK setcolorspace");
883 break;
884 }
885
886 printf("<<"
887 "/ImageType 1"
888 "/Width %d"
889 "/Height %d"
890 "/BitsPerComponent 8",
891 xc1 - xc0 + 1, yc1 - yc0 + 1);
892
893 switch (colorspace)
894 {
895 case CUPS_IMAGE_WHITE :
896 fputs("/Decode[0 1]", stdout);
897 break;
898 case CUPS_IMAGE_RGB :
899 fputs("/Decode[0 1 0 1 0 1]", stdout);
900 break;
901 case CUPS_IMAGE_CMYK :
902 fputs("/Decode[0 1 0 1 0 1 0 1]", stdout);
903 break;
904 }
905
906 fputs("\n/DataSource currentfile/ASCII85Decode filter", stdout);
907
908 if (((xc1 - xc0 + 1) / xprint) < 100.0)
909 fputs("/Interpolate true", stdout);
910
911 puts("/ImageMatrix[1 0 0 -1 0 1]>>image");
912
913 for (y = yc0, out_offset = 0; y <= yc1; y ++)
914 {
915 cupsImageGetRow(img, xc0, y, xc1 - xc0 + 1, row + out_offset);
916
917 out_length = (xc1 - xc0 + 1) * abs(colorspace) + out_offset;
918 out_offset = out_length & 3;
919
920 ps_ascii85(row, out_length, y == yc1);
921
922 if (out_offset > 0)
923 memcpy(row, row + out_length - out_offset, out_offset);
924 }
925 }
926
927 puts("grestore");
928 WriteLabels(0);
929 puts("grestore");
930 puts("showpage");
931 }
932
933 puts("%%EOF");
934
935 /*
936 * End the job with the appropriate JCL command or CTRL-D otherwise.
937 */
938
939 if (emit_jcl)
940 {
941 if (ppd && ppd->jcl_end)
942 ppdEmitJCLEnd(ppd, stdout);
943 else
944 putchar(0x04);
945 }
946
947 /*
948 * Close files...
949 */
950
951 cupsImageClose(img);
952 ppdClose(ppd);
953
954 return (0);
955 }
956
957
958 /*
959 * 'ps_hex()' - Print binary data as a series of hexadecimal numbers.
960 */
961
962 static void
963 ps_hex(cups_ib_t *data, /* I - Data to print */
964 int length, /* I - Number of bytes to print */
965 int last_line) /* I - Last line of raster data? */
966 {
967 static int col = 0; /* Current column */
968 static char *hex = "0123456789ABCDEF";
969 /* Hex digits */
970
971
972 while (length > 0)
973 {
974 /*
975 * Put the hex chars out to the file; note that we don't use printf()
976 * for speed reasons...
977 */
978
979 putchar(hex[*data >> 4]);
980 putchar(hex[*data & 15]);
981
982 data ++;
983 length --;
984
985 col += 2;
986 if (col > 78)
987 {
988 putchar('\n');
989 col = 0;
990 }
991 }
992
993 if (last_line && col)
994 {
995 putchar('\n');
996 col = 0;
997 }
998 }
999
1000
1001 /*
1002 * 'ps_ascii85()' - Print binary data as a series of base-85 numbers.
1003 */
1004
1005 static void
1006 ps_ascii85(cups_ib_t *data, /* I - Data to print */
1007 int length, /* I - Number of bytes to print */
1008 int last_line) /* I - Last line of raster data? */
1009 {
1010 unsigned b; /* Binary data word */
1011 unsigned char c[5]; /* ASCII85 encoded chars */
1012 static int col = 0; /* Current column */
1013
1014
1015 while (length > 3)
1016 {
1017 b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
1018
1019 if (b == 0)
1020 {
1021 putchar('z');
1022 col ++;
1023 }
1024 else
1025 {
1026 c[4] = (b % 85) + '!';
1027 b /= 85;
1028 c[3] = (b % 85) + '!';
1029 b /= 85;
1030 c[2] = (b % 85) + '!';
1031 b /= 85;
1032 c[1] = (b % 85) + '!';
1033 b /= 85;
1034 c[0] = b + '!';
1035
1036 fwrite(c, 5, 1, stdout);
1037 col += 5;
1038 }
1039
1040 data += 4;
1041 length -= 4;
1042
1043 if (col >= 75)
1044 {
1045 putchar('\n');
1046 col = 0;
1047 }
1048 }
1049
1050 if (last_line)
1051 {
1052 if (length > 0)
1053 {
1054 memset(data + length, 0, 4 - length);
1055 b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
1056
1057 c[4] = (b % 85) + '!';
1058 b /= 85;
1059 c[3] = (b % 85) + '!';
1060 b /= 85;
1061 c[2] = (b % 85) + '!';
1062 b /= 85;
1063 c[1] = (b % 85) + '!';
1064 b /= 85;
1065 c[0] = b + '!';
1066
1067 fwrite(c, length + 1, 1, stdout);
1068 }
1069
1070 puts("~>");
1071 col = 0;
1072 }
1073 }
1074
1075
1076 /*
1077 * End of "$Id: imagetops.c 6649 2007-07-11 21:46:42Z mike $".
1078 */