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