• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Common filter routines for CUPS.
3  *
4  * Copyright 2007-2014 by Apple Inc.
5  * Copyright 1997-2006 by Easy Software Products.
6  *
7  * These coded instructions, statements, and computer programs are the
8  * property of Apple Inc. and are protected by Federal copyright
9  * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
10  * which should have been included with this file.  If this file is
11  * missing or damaged, see the license at "http://www.cups.org/".
12  *
13  * This file is subject to the Apple OS-Developed Software exception.
14  */
15 
16 /*
17  * Include necessary headers...
18  */
19 
20 #include "common.h"
21 #include <locale.h>
22 
23 
24 /*
25  * Globals...
26  */
27 
28 int	Orientation = 0,		/* 0 = portrait, 1 = landscape, etc. */
29 	Duplex = 0,			/* Duplexed? */
30 	LanguageLevel = 1,		/* Language level of printer */
31 	ColorDevice = 1;		/* Do color text? */
32 float	PageLeft = 18.0f,		/* Left margin */
33 	PageRight = 594.0f,		/* Right margin */
34 	PageBottom = 36.0f,		/* Bottom margin */
35 	PageTop = 756.0f,		/* Top margin */
36 	PageWidth = 612.0f,		/* Total page width */
37 	PageLength = 792.0f;		/* Total page length */
38 
39 
40 /*
41  * 'SetCommonOptions()' - Set common filter options for media size, etc.
42  */
43 
44 ppd_file_t *				/* O - PPD file */
SetCommonOptions(int num_options,cups_option_t * options,int change_size)45 SetCommonOptions(
46     int           num_options,		/* I - Number of options */
47     cups_option_t *options,		/* I - Options */
48     int           change_size)		/* I - Change page size? */
49 {
50   ppd_file_t	*ppd;			/* PPD file */
51   ppd_size_t	*pagesize;		/* Current page size */
52   const char	*val;			/* Option value */
53 
54 
55 #ifdef LC_TIME
56   setlocale(LC_TIME, "");
57 #endif /* LC_TIME */
58 
59   ppd = ppdOpenFile(getenv("PPD"));
60 
61   ppdMarkDefaults(ppd);
62   cupsMarkOptions(ppd, num_options, options);
63 
64   if ((pagesize = ppdPageSize(ppd, NULL)) != NULL)
65   {
66     PageWidth  = pagesize->width;
67     PageLength = pagesize->length;
68     PageTop    = pagesize->top;
69     PageBottom = pagesize->bottom;
70     PageLeft   = pagesize->left;
71     PageRight  = pagesize->right;
72 
73     fprintf(stderr, "DEBUG: Page = %.0fx%.0f; %.0f,%.0f to %.0f,%.0f\n",
74             PageWidth, PageLength, PageLeft, PageBottom, PageRight, PageTop);
75   }
76 
77   if (ppd != NULL)
78   {
79     ColorDevice   = ppd->color_device;
80     LanguageLevel = ppd->language_level;
81   }
82 
83   if ((val = cupsGetOption("landscape", num_options, options)) != NULL)
84   {
85     if (_cups_strcasecmp(val, "no") != 0 && _cups_strcasecmp(val, "off") != 0 &&
86         _cups_strcasecmp(val, "false") != 0)
87     {
88       if (ppd && ppd->landscape > 0)
89         Orientation = 1;
90       else
91         Orientation = 3;
92     }
93   }
94   else if ((val = cupsGetOption("orientation-requested", num_options, options)) != NULL)
95   {
96    /*
97     * Map IPP orientation values to 0 to 3:
98     *
99     *   3 = 0 degrees   = 0
100     *   4 = 90 degrees  = 1
101     *   5 = -90 degrees = 3
102     *   6 = 180 degrees = 2
103     */
104 
105     Orientation = atoi(val) - 3;
106     if (Orientation >= 2)
107       Orientation ^= 1;
108   }
109 
110   if ((val = cupsGetOption("page-left", num_options, options)) != NULL)
111   {
112     switch (Orientation & 3)
113     {
114       case 0 :
115           PageLeft = (float)atof(val);
116 	  break;
117       case 1 :
118           PageBottom = (float)atof(val);
119 	  break;
120       case 2 :
121           PageRight = PageWidth - (float)atof(val);
122 	  break;
123       case 3 :
124           PageTop = PageLength - (float)atof(val);
125 	  break;
126     }
127   }
128 
129   if ((val = cupsGetOption("page-right", num_options, options)) != NULL)
130   {
131     switch (Orientation & 3)
132     {
133       case 0 :
134           PageRight = PageWidth - (float)atof(val);
135 	  break;
136       case 1 :
137           PageTop = PageLength - (float)atof(val);
138 	  break;
139       case 2 :
140           PageLeft = (float)atof(val);
141 	  break;
142       case 3 :
143           PageBottom = (float)atof(val);
144 	  break;
145     }
146   }
147 
148   if ((val = cupsGetOption("page-bottom", num_options, options)) != NULL)
149   {
150     switch (Orientation & 3)
151     {
152       case 0 :
153           PageBottom = (float)atof(val);
154 	  break;
155       case 1 :
156           PageLeft = (float)atof(val);
157 	  break;
158       case 2 :
159           PageTop = PageLength - (float)atof(val);
160 	  break;
161       case 3 :
162           PageRight = PageWidth - (float)atof(val);
163 	  break;
164     }
165   }
166 
167   if ((val = cupsGetOption("page-top", num_options, options)) != NULL)
168   {
169     switch (Orientation & 3)
170     {
171       case 0 :
172           PageTop = PageLength - (float)atof(val);
173 	  break;
174       case 1 :
175           PageRight = PageWidth - (float)atof(val);
176 	  break;
177       case 2 :
178           PageBottom = (float)atof(val);
179 	  break;
180       case 3 :
181           PageLeft = (float)atof(val);
182 	  break;
183     }
184   }
185 
186   if (change_size)
187     UpdatePageVars();
188 
189   if (ppdIsMarked(ppd, "Duplex", "DuplexNoTumble") ||
190       ppdIsMarked(ppd, "Duplex", "DuplexTumble") ||
191       ppdIsMarked(ppd, "JCLDuplex", "DuplexNoTumble") ||
192       ppdIsMarked(ppd, "JCLDuplex", "DuplexTumble") ||
193       ppdIsMarked(ppd, "EFDuplex", "DuplexNoTumble") ||
194       ppdIsMarked(ppd, "EFDuplex", "DuplexTumble") ||
195       ppdIsMarked(ppd, "KD03Duplex", "DuplexNoTumble") ||
196       ppdIsMarked(ppd, "KD03Duplex", "DuplexTumble"))
197     Duplex = 1;
198 
199   return (ppd);
200 }
201 
202 
203 /*
204  * 'UpdatePageVars()' - Update the page variables for the orientation.
205  */
206 
207 void
UpdatePageVars(void)208 UpdatePageVars(void)
209 {
210   float		temp;			/* Swapping variable */
211 
212 
213   switch (Orientation & 3)
214   {
215     case 0 : /* Portait */
216         break;
217 
218     case 1 : /* Landscape */
219 	temp       = PageLeft;
220 	PageLeft   = PageBottom;
221 	PageBottom = temp;
222 
223 	temp       = PageRight;
224 	PageRight  = PageTop;
225 	PageTop    = temp;
226 
227 	temp       = PageWidth;
228 	PageWidth  = PageLength;
229 	PageLength = temp;
230 	break;
231 
232     case 2 : /* Reverse Portrait */
233 	temp       = PageWidth - PageLeft;
234 	PageLeft   = PageWidth - PageRight;
235 	PageRight  = temp;
236 
237 	temp       = PageLength - PageBottom;
238 	PageBottom = PageLength - PageTop;
239 	PageTop    = temp;
240         break;
241 
242     case 3 : /* Reverse Landscape */
243 	temp       = PageWidth - PageLeft;
244 	PageLeft   = PageWidth - PageRight;
245 	PageRight  = temp;
246 
247 	temp       = PageLength - PageBottom;
248 	PageBottom = PageLength - PageTop;
249 	PageTop    = temp;
250 
251 	temp       = PageLeft;
252 	PageLeft   = PageBottom;
253 	PageBottom = temp;
254 
255 	temp       = PageRight;
256 	PageRight  = PageTop;
257 	PageTop    = temp;
258 
259 	temp       = PageWidth;
260 	PageWidth  = PageLength;
261 	PageLength = temp;
262 	break;
263   }
264 }
265 
266 
267 /*
268  * 'WriteCommon()' - Write common procedures...
269  */
270 
271 void
WriteCommon(void)272 WriteCommon(void)
273 {
274   puts("% x y w h ESPrc - Clip to a rectangle.\n"
275        "userdict/ESPrc/rectclip where{pop/rectclip load}\n"
276        "{{newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
277        "neg 0 rlineto closepath clip newpath}bind}ifelse put");
278   puts("% x y w h ESPrf - Fill a rectangle.\n"
279        "userdict/ESPrf/rectfill where{pop/rectfill load}\n"
280        "{{gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
281        "neg 0 rlineto closepath fill grestore}bind}ifelse put");
282   puts("% x y w h ESPrs - Stroke a rectangle.\n"
283        "userdict/ESPrs/rectstroke where{pop/rectstroke load}\n"
284        "{{gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
285        "neg 0 rlineto closepath stroke grestore}bind}ifelse put");
286 }
287 
288 
289 /*
290  * 'WriteLabelProlog()' - Write the prolog with the classification
291  *                        and page label.
292  */
293 
294 void
WriteLabelProlog(const char * label,float bottom,float top,float width)295 WriteLabelProlog(const char *label,	/* I - Page label */
296 		 float      bottom,	/* I - Bottom position in points */
297 		 float      top,	/* I - Top position in points */
298 		 float      width)	/* I - Width in points */
299 {
300   const char	*classification;	/* CLASSIFICATION environment variable */
301   const char	*ptr;			/* Temporary string pointer */
302 
303 
304  /*
305   * First get the current classification...
306   */
307 
308   if ((classification = getenv("CLASSIFICATION")) == NULL)
309     classification = "";
310   if (strcmp(classification, "none") == 0)
311     classification = "";
312 
313  /*
314   * If there is nothing to show, bind an empty 'write labels' procedure
315   * and return...
316   */
317 
318   if (!classification[0] && (label == NULL || !label[0]))
319   {
320     puts("userdict/ESPwl{}bind put");
321     return;
322   }
323 
324  /*
325   * Set the classification + page label string...
326   */
327 
328   printf("userdict");
329   if (strcmp(classification, "confidential") == 0)
330     printf("/ESPpl(CONFIDENTIAL");
331   else if (strcmp(classification, "classified") == 0)
332     printf("/ESPpl(CLASSIFIED");
333   else if (strcmp(classification, "secret") == 0)
334     printf("/ESPpl(SECRET");
335   else if (strcmp(classification, "topsecret") == 0)
336     printf("/ESPpl(TOP SECRET");
337   else if (strcmp(classification, "unclassified") == 0)
338     printf("/ESPpl(UNCLASSIFIED");
339   else
340   {
341     printf("/ESPpl(");
342 
343     for (ptr = classification; *ptr; ptr ++)
344       if (*ptr < 32 || *ptr > 126)
345         printf("\\%03o", *ptr);
346       else if (*ptr == '_')
347         putchar(' ');
348       else
349       {
350 	if (*ptr == '(' || *ptr == ')' || *ptr == '\\')
351 	  putchar('\\');
352 
353 	putchar(*ptr);
354       }
355   }
356 
357   if (label)
358   {
359     if (classification[0])
360       printf(" - ");
361 
362    /*
363     * Quote the label string as needed...
364     */
365 
366     for (ptr = label; *ptr; ptr ++)
367       if (*ptr < 32 || *ptr > 126)
368         printf("\\%03o", *ptr);
369       else
370       {
371 	if (*ptr == '(' || *ptr == ')' || *ptr == '\\')
372 	  putchar('\\');
373 
374 	putchar(*ptr);
375       }
376   }
377 
378   puts(")put");
379 
380  /*
381   * Then get a 14 point Helvetica-Bold font...
382   */
383 
384   puts("userdict/ESPpf /Helvetica-Bold findfont 14 scalefont put");
385 
386  /*
387   * Finally, the procedure to write the labels on the page...
388   */
389 
390   puts("userdict/ESPwl{");
391   puts("  ESPpf setfont");
392   printf("  ESPpl stringwidth pop dup 12 add exch -0.5 mul %.0f add\n",
393          width * 0.5f);
394   puts("  1 setgray");
395   printf("  dup 6 sub %.0f 3 index 20 ESPrf\n", bottom - 2.0);
396   printf("  dup 6 sub %.0f 3 index 20 ESPrf\n", top - 18.0);
397   puts("  0 setgray");
398   printf("  dup 6 sub %.0f 3 index 20 ESPrs\n", bottom - 2.0);
399   printf("  dup 6 sub %.0f 3 index 20 ESPrs\n", top - 18.0);
400   printf("  dup %.0f moveto ESPpl show\n", bottom + 2.0);
401   printf("  %.0f moveto ESPpl show\n", top - 14.0);
402   puts("pop");
403   puts("}bind put");
404 }
405 
406 
407 /*
408  * 'WriteLabels()' - Write the actual page labels.
409  */
410 
411 void
WriteLabels(int orient)412 WriteLabels(int orient)	/* I - Orientation of the page */
413 {
414   float	width,		/* Width of page */
415 	length;		/* Length of page */
416 
417 
418   puts("gsave");
419 
420   if ((orient ^ Orientation) & 1)
421   {
422     width  = PageLength;
423     length = PageWidth;
424   }
425   else
426   {
427     width  = PageWidth;
428     length = PageLength;
429   }
430 
431   switch (orient & 3)
432   {
433     case 1 : /* Landscape */
434         printf("%.1f 0.0 translate 90 rotate\n", length);
435         break;
436     case 2 : /* Reverse Portrait */
437         printf("%.1f %.1f translate 180 rotate\n", width, length);
438         break;
439     case 3 : /* Reverse Landscape */
440         printf("0.0 %.1f translate -90 rotate\n", width);
441         break;
442   }
443 
444   puts("ESPwl");
445   puts("grestore");
446 }
447 
448 
449 /*
450  * 'WriteTextComment()' - Write a DSC text comment.
451  */
452 
453 void
WriteTextComment(const char * name,const char * value)454 WriteTextComment(const char *name,	/* I - Comment name ("Title", etc.) */
455                  const char *value)	/* I - Comment value */
456 {
457   int	len;				/* Current line length */
458 
459 
460  /*
461   * DSC comments are of the form:
462   *
463   *   %%name: value
464   *
465   * The name and value must be limited to 7-bit ASCII for most printers,
466   * so we escape all non-ASCII and ASCII control characters as described
467   * in the Adobe Document Structuring Conventions specification.
468   */
469 
470   printf("%%%%%s: (", name);
471   len = 5 + (int)strlen(name);
472 
473   while (*value)
474   {
475     if (*value < ' ' || *value >= 127)
476     {
477      /*
478       * Escape this character value...
479       */
480 
481       if (len >= 251)			/* Keep line < 254 chars */
482         break;
483 
484       printf("\\%03o", *value & 255);
485       len += 4;
486     }
487     else if (*value == '\\')
488     {
489      /*
490       * Escape the backslash...
491       */
492 
493       if (len >= 253)			/* Keep line < 254 chars */
494         break;
495 
496       putchar('\\');
497       putchar('\\');
498       len += 2;
499     }
500     else
501     {
502      /*
503       * Put this character literally...
504       */
505 
506       if (len >= 254)			/* Keep line < 254 chars */
507         break;
508 
509       putchar(*value);
510       len ++;
511     }
512 
513     value ++;
514   }
515 
516   puts(")");
517 }
518