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