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