]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/pwg-ppd.c
Merge changes from CUPS 1.5svn-r9041.
[thirdparty/cups.git] / cups / pwg-ppd.c
1 /*
2 * "$Id$"
3 *
4 * PWG PPD mapping API implementation for CUPS.
5 *
6 * Copyright 2010 by Apple Inc.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Apple Inc. and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
11 * which should have been included with this file. If this file is
12 * file is missing or damaged, see the license at "http://www.cups.org/".
13 *
14 * This file is subject to the Apple OS-Developed Software exception.
15 *
16 * Contents:
17 *
18 * _pwgCreateWithPPD() - Create PWG mapping data from a PPD file.
19 * _pwgGetInputSlot() - Get the PPD InputSlot associated with the job
20 * attributes or a keyword string.
21 * _pwgGetMediaType() - Get the PPD MediaType associated with the job
22 * attributes or a keyword string.
23 * _pwgGetPageSize() - Get the PPD PageSize associated with the job
24 * attributes or a keyword string.
25 * _pwgGetSize() - Get the PWG size associated with a PPD PageSize.
26 * _pwgGetSource() - Get the PWG media-source associated with a PPD
27 * InputSlot.
28 * _pwgGetType() - Get the PWG media-type associated with a PPD
29 * MediaType.
30 * _pwgInputSlotForSource() - Get the InputSlot name for the given PWG source.
31 * _pwgMediaTypeForType() - Get the MediaType name for the given PWG type.
32 * _pwgPageSizeForMedia() - Get the PageSize name for the given media.
33 * pwg_ppdize_name() - Convert an IPP keyword to a PPD keyword.
34 * pwg_unppdize_name() - Convert a PPD keyword to a lowercase IPP
35 * keyword.
36 */
37
38 /*
39 * Include necessary headers...
40 */
41
42 #include "pwg-private.h"
43 #include "globals.h"
44 #include "string.h"
45 #include "debug.h"
46 #include <math.h>
47
48
49 /*
50 * Local functions...
51 */
52
53 static void pwg_ppdize_name(const char *ipp, char *name, size_t namesize);
54 static void pwg_unppdize_name(const char *ppd, char *name, size_t namesize);
55
56
57 /*
58 * '_pwgCreateWithPPD()' - Create PWG mapping data from a PPD file.
59 */
60
61 _pwg_t * /* O - PWG mapping data */
62 _pwgCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */
63 {
64 int i, j; /* Looping vars */
65 _pwg_t *pwg; /* PWG mapping data */
66 ppd_option_t *input_slot, /* InputSlot option */
67 *media_type; /* MediaType option */
68 ppd_choice_t *choice; /* Current InputSlot/MediaType */
69 _pwg_map_t *map; /* Current source/type map */
70 ppd_size_t *ppd_size; /* Current PPD size */
71 _pwg_size_t *pwg_size; /* Current PWG size */
72 char pwg_keyword[3 + PPD_MAX_NAME + 1 + 12 + 1 + 12 + 3],
73 /* PWG keyword string */
74 ppd_name[PPD_MAX_NAME]; /* Normalized PPD name */
75 const char *pwg_name; /* Standard PWG media name */
76 _pwg_media_t *pwg_media; /* PWG media data */
77 struct lconv *loc; /* Locale conversion data */
78
79
80 DEBUG_printf(("_pwgCreateWithPPD(ppd=%p)", ppd));
81
82 /*
83 * Range check input...
84 */
85
86 if (!ppd)
87 return (NULL);
88
89 /*
90 * Allocate memory...
91 */
92
93 if ((pwg = calloc(1, sizeof(_pwg_t))) == NULL)
94 {
95 DEBUG_puts("_pwgCreateWithPPD: Unable to allocate _pwg_t.");
96 goto create_error;
97 }
98
99 /*
100 * Copy and convert size data...
101 */
102
103 if (ppd->num_sizes == 0)
104 {
105 DEBUG_puts("_pwgCreateWithPPD: No page sizes in PPD.");
106 goto create_error;
107 }
108
109 if ((pwg->sizes = calloc(ppd->num_sizes, sizeof(_pwg_size_t))) == NULL)
110 {
111 DEBUG_printf(("_pwgCreateWithPPD: Unable to allocate %d _pwg_size_t's.",
112 ppd->num_sizes));
113 goto create_error;
114 }
115
116 loc = localeconv();
117
118 for (i = ppd->num_sizes, pwg_size = pwg->sizes, ppd_size = ppd->sizes;
119 i > 0;
120 i --, ppd_size ++)
121 {
122 /*
123 * Don't copy over custom size...
124 */
125
126 if (!strcasecmp(ppd_size->name, "Custom"))
127 continue;
128
129 /*
130 * Convert the PPD size name to the corresponding PWG keyword name.
131 */
132
133 if ((pwg_media = _pwgMediaForPPD(ppd_size->name)) != NULL)
134 {
135 /*
136 * Standard name, do we have conflicts?
137 */
138
139 for (j = 0; j < pwg->num_sizes; j ++)
140 if (!strcmp(pwg->sizes[j].map.pwg, pwg_media->pwg))
141 {
142 pwg_media = NULL;
143 break;
144 }
145 }
146
147 if (pwg_media)
148 {
149 /*
150 * Standard name and no conflicts, use it!
151 */
152
153 pwg_name = pwg_media->pwg;
154 }
155 else
156 {
157 /*
158 * Not a standard name; convert it to a PWG vendor name of the form:
159 *
160 * pp_lowerppd_WIDTHxHEIGHTuu
161 */
162
163 pwg_name = pwg_keyword;
164
165 pwg_unppdize_name(ppd_size->name, ppd_name, sizeof(ppd_name));
166 _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), NULL, ppd_name,
167 _PWG_FROMPTS(ppd_size->width),
168 _PWG_FROMPTS(ppd_size->length));
169 }
170
171 /*
172 * Save this size...
173 */
174
175 pwg_size->map.ppd = _cupsStrAlloc(ppd_size->name);
176 pwg_size->map.pwg = _cupsStrAlloc(pwg_name);
177 pwg_size->width = _PWG_FROMPTS(ppd_size->width);
178 pwg_size->length = _PWG_FROMPTS(ppd_size->length);
179 pwg_size->left = _PWG_FROMPTS(ppd_size->left);
180 pwg_size->bottom = _PWG_FROMPTS(ppd_size->bottom);
181 pwg_size->right = _PWG_FROMPTS(ppd_size->width - ppd_size->right);
182 pwg_size->top = _PWG_FROMPTS(ppd_size->length - ppd_size->top);
183
184 pwg->num_sizes ++;
185 pwg_size ++;
186 }
187
188 if (ppd->variable_sizes)
189 {
190 /*
191 * Generate custom size data...
192 */
193
194 _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "max",
195 _PWG_FROMPTS(ppd->custom_max[0]),
196 _PWG_FROMPTS(ppd->custom_max[1]));
197 pwg->custom_max_keyword = _cupsStrAlloc(pwg_keyword);
198 pwg->custom_max_width = _PWG_FROMPTS(ppd->custom_max[0]);
199 pwg->custom_max_length = _PWG_FROMPTS(ppd->custom_max[1]);
200
201 _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "min",
202 _PWG_FROMPTS(ppd->custom_min[0]),
203 _PWG_FROMPTS(ppd->custom_min[1]));
204 pwg->custom_min_keyword = _cupsStrAlloc(pwg_keyword);
205 pwg->custom_min_width = _PWG_FROMPTS(ppd->custom_min[0]);
206 pwg->custom_min_length = _PWG_FROMPTS(ppd->custom_min[1]);
207
208 pwg->custom_size.left = _PWG_FROMPTS(ppd->custom_margins[0]);
209 pwg->custom_size.bottom = _PWG_FROMPTS(ppd->custom_margins[1]);
210 pwg->custom_size.right = _PWG_FROMPTS(ppd->custom_margins[2]);
211 pwg->custom_size.top = _PWG_FROMPTS(ppd->custom_margins[3]);
212 }
213
214 /*
215 * Copy and convert InputSlot data...
216 */
217
218 if ((input_slot = ppdFindOption(ppd, "InputSlot")) != NULL)
219 {
220 if ((pwg->sources = calloc(input_slot->num_choices,
221 sizeof(_pwg_map_t))) == NULL)
222 {
223 DEBUG_printf(("_pwgCreateWithPPD: Unable to allocate %d _pwg_map_t's "
224 "for InputSlot.", input_slot->num_choices));
225 goto create_error;
226 }
227
228 pwg->num_sources = input_slot->num_choices;
229
230 for (i = input_slot->num_choices, choice = input_slot->choices,
231 map = pwg->sources;
232 i > 0;
233 i --, choice ++, map ++)
234 {
235 if (!strncasecmp(choice->choice, "Auto", 4) ||
236 !strcasecmp(choice->choice, "Default"))
237 pwg_name = "auto";
238 else if (!strcasecmp(choice->choice, "Cassette"))
239 pwg_name = "main-tray";
240 else if (!strncasecmp(choice->choice, "Multipurpose", 12) ||
241 !strcasecmp(choice->choice, "MP") ||
242 !strcasecmp(choice->choice, "MPTray"))
243 pwg_name = "alternate-tray";
244 else if (!strcasecmp(choice->choice, "LargeCapacity"))
245 pwg_name = "large-capacity-tray";
246 else if (!strncasecmp(choice->choice, "Lower", 5))
247 pwg_name = "bottom-tray";
248 else if (!strncasecmp(choice->choice, "Middle", 6))
249 pwg_name = "middle-tray";
250 else if (!strncasecmp(choice->choice, "Upper", 5))
251 pwg_name = "top-tray";
252 else if (!strcasecmp(choice->choice, "Rear"))
253 pwg_name = "rear-feed";
254 else if (!strncasecmp(choice->choice, "Side", 4))
255 pwg_name = "side-feed";
256 else if (!strcasecmp(choice->choice, "Envelope"))
257 pwg_name = "envelope-feed";
258 else if (!strcasecmp(choice->choice, "Manual"))
259 pwg_name = "manual-feed";
260 else if (!strcasecmp(choice->choice, "Roll") ||
261 !strcasecmp(choice->choice, "Roll"))
262 pwg_name = "main-roll";
263 else if (!strcasecmp(choice->choice, "Roll2"))
264 pwg_name = "alternate-roll";
265 else
266 {
267 /*
268 * Convert PPD name to lowercase...
269 */
270
271 pwg_name = pwg_keyword;
272 pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword));
273 }
274
275 map->pwg = _cupsStrAlloc(pwg_name);
276 map->ppd = _cupsStrAlloc(choice->choice);
277 }
278 }
279
280 /*
281 * Copy and convert MediaType data...
282 */
283
284 if ((media_type = ppdFindOption(ppd, "MediaType")) != NULL)
285 {
286 if ((pwg->types = calloc(media_type->num_choices,
287 sizeof(_pwg_map_t))) == NULL)
288 {
289 DEBUG_printf(("_pwgCreateWithPPD: Unable to allocate %d _pwg_map_t's "
290 "for MediaType.", input_slot->num_choices));
291 goto create_error;
292 }
293
294 pwg->num_types = media_type->num_choices;
295
296 for (i = media_type->num_choices, choice = media_type->choices,
297 map = pwg->types;
298 i > 0;
299 i --, choice ++, map ++)
300 {
301 if (!strncasecmp(choice->choice, "Auto", 4) ||
302 !strcasecmp(choice->choice, "Any") ||
303 !strcasecmp(choice->choice, "Default"))
304 pwg_name = "auto";
305 else if (!strncasecmp(choice->choice, "Card", 4))
306 pwg_name = "cardstock";
307 else if (!strncasecmp(choice->choice, "Env", 3))
308 pwg_name = "envelope";
309 else if (!strncasecmp(choice->choice, "Gloss", 5))
310 pwg_name = "photographic-glossy";
311 else if (!strcasecmp(choice->choice, "HighGloss"))
312 pwg_name = "photographic-high-gloss";
313 else if (!strcasecmp(choice->choice, "Matte"))
314 pwg_name = "photographic-matte";
315 else if (!strncasecmp(choice->choice, "Plain", 5))
316 pwg_name = "stationery";
317 else if (!strncasecmp(choice->choice, "Coated", 6))
318 pwg_name = "stationery-coated";
319 else if (!strcasecmp(choice->choice, "Inkjet"))
320 pwg_name = "stationery-inkjet";
321 else if (!strcasecmp(choice->choice, "Letterhead"))
322 pwg_name = "stationery-letterhead";
323 else if (!strncasecmp(choice->choice, "Preprint", 8))
324 pwg_name = "stationery-preprinted";
325 else if (!strncasecmp(choice->choice, "Transparen", 10))
326 pwg_name = "transparency";
327 else
328 {
329 /*
330 * Convert PPD name to lowercase...
331 */
332
333 pwg_name = pwg_keyword;
334 pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword));
335 }
336
337 map->pwg = _cupsStrAlloc(pwg_name);
338 map->ppd = _cupsStrAlloc(choice->choice);
339 }
340 }
341
342 return (pwg);
343
344 /*
345 * If we get here we need to destroy the PWG mapping data and return NULL...
346 */
347
348 create_error:
349
350 _cupsSetError(IPP_INTERNAL_ERROR, _("Out of memory."), 1);
351 _pwgDestroy(pwg);
352
353 return (NULL);
354 }
355
356
357 /*
358 * '_pwgGetInputSlot()' - Get the PPD InputSlot associated with the job
359 * attributes or a keyword string.
360 */
361
362 const char * /* O - PPD InputSlot or NULL */
363 _pwgGetInputSlot(_pwg_t *pwg, /* I - PWG mapping data */
364 ipp_t *job, /* I - Job attributes or NULL */
365 const char *keyword) /* I - Keyword string or NULL */
366 {
367 /*
368 * Range check input...
369 */
370
371 if (!pwg || pwg->num_sources == 0 || (!job && !keyword))
372 return (NULL);
373
374 if (job && !keyword)
375 {
376 /*
377 * Lookup the media-col attribute and any media-source found there...
378 */
379
380 ipp_attribute_t *media_col, /* media-col attribute */
381 *media_source; /* media-source attribute */
382
383 media_col = ippFindAttribute(job, "media-col", IPP_TAG_BEGIN_COLLECTION);
384 if (media_col &&
385 (media_source = ippFindAttribute(media_col->values[0].collection,
386 "media-source",
387 IPP_TAG_KEYWORD)) != NULL)
388 keyword = media_source->values[0].string.text;
389 }
390
391 if (keyword)
392 {
393 int i; /* Looping var */
394
395 for (i = 0; i < pwg->num_sources; i ++)
396 if (!strcasecmp(keyword, pwg->sources[i].pwg))
397 return (pwg->sources[i].ppd);
398 }
399
400 return (NULL);
401 }
402
403
404 /*
405 * '_pwgGetMediaType()' - Get the PPD MediaType associated with the job
406 * attributes or a keyword string.
407 */
408
409 const char * /* O - PPD MediaType or NULL */
410 _pwgGetMediaType(_pwg_t *pwg, /* I - PWG mapping data */
411 ipp_t *job, /* I - Job attributes or NULL */
412 const char *keyword) /* I - Keyword string or NULL */
413 {
414 /*
415 * Range check input...
416 */
417
418 if (!pwg || pwg->num_types == 0 || (!job && !keyword))
419 return (NULL);
420
421 if (job && !keyword)
422 {
423 /*
424 * Lookup the media-col attribute and any media-source found there...
425 */
426
427 ipp_attribute_t *media_col, /* media-col attribute */
428 *media_type; /* media-type attribute */
429
430 media_col = ippFindAttribute(job, "media-col", IPP_TAG_BEGIN_COLLECTION);
431 if (media_col)
432 {
433 if ((media_type = ippFindAttribute(media_col->values[0].collection,
434 "media-type",
435 IPP_TAG_KEYWORD)) == NULL)
436 media_type = ippFindAttribute(media_col->values[0].collection,
437 "media-type", IPP_TAG_NAME);
438
439 if (media_type)
440 keyword = media_type->values[0].string.text;
441 }
442 }
443
444 if (keyword)
445 {
446 int i; /* Looping var */
447
448 for (i = 0; i < pwg->num_types; i ++)
449 if (!strcasecmp(keyword, pwg->types[i].pwg))
450 return (pwg->types[i].ppd);
451 }
452
453 return (NULL);
454 }
455
456
457 /*
458 * '_pwgGetPageSize()' - Get the PPD PageSize associated with the job
459 * attributes or a keyword string.
460 */
461
462 const char * /* O - PPD PageSize or NULL */
463 _pwgGetPageSize(_pwg_t *pwg, /* I - PWG mapping data */
464 ipp_t *job, /* I - Job attributes or NULL */
465 const char *keyword, /* I - Keyword string or NULL */
466 int *exact) /* I - 1 if exact match, 0 otherwise */
467 {
468 int i; /* Looping var */
469 _pwg_size_t *size, /* Current size */
470 *closest, /* Closest size */
471 jobsize; /* Size data from job */
472 int margins_set, /* Were the margins set? */
473 dwidth, /* Difference in width */
474 dlength, /* Difference in length */
475 dleft, /* Difference in left margins */
476 dright, /* Difference in right margins */
477 dbottom, /* Difference in bottom margins */
478 dtop, /* Difference in top margins */
479 dmin, /* Minimum difference */
480 dclosest; /* Closest difference */
481
482
483 /*
484 * Range check input...
485 */
486
487 if (!pwg || (!job && !keyword))
488 return (NULL);
489
490 if (exact)
491 *exact = 0;
492
493 if (job && !keyword)
494 {
495 /*
496 * Get the size using media-col or media, with the preference being
497 * media-col.
498 */
499
500 if (!_pwgInitSize(&jobsize, job, &margins_set))
501 return (NULL);
502 }
503 else
504 {
505 /*
506 * Get the size using a media keyword...
507 */
508
509 _pwg_media_t *media; /* Media definition */
510
511
512 if ((media = _pwgMediaForPWG(keyword)) == NULL)
513 if ((media = _pwgMediaForLegacy(keyword)) == NULL)
514 return (NULL);
515
516 jobsize.width = media->width;
517 jobsize.length = media->length;
518 margins_set = 0;
519 }
520
521 /*
522 * Now that we have the dimensions and possibly the margins, look at the
523 * available sizes and find the match...
524 */
525
526 closest = NULL;
527 dclosest = 999999999;
528
529 for (i = pwg->num_sizes, size = pwg->sizes; i > 0; i --, size ++)
530 {
531 /*
532 * Adobe uses a size matching algorithm with an epsilon of 5 points, which
533 * is just about 176/2540ths...
534 */
535
536 dwidth = size->width - jobsize.width;
537 dlength = size->length - jobsize.length;
538
539 if (dwidth <= -176 || dwidth >= 176 || dlength <= -176 || dlength >= 176)
540 continue;
541
542 if (margins_set)
543 {
544 /*
545 * Use a tighter epsilon of 1 point (35/2540ths) for margins...
546 */
547
548 dleft = size->left - jobsize.left;
549 dright = size->right - jobsize.right;
550 dtop = size->top - jobsize.top;
551 dbottom = size->bottom - jobsize.bottom;
552
553 if (dleft <= -35 || dleft >= 35 || dright <= -35 || dright >= 35 ||
554 dtop <= -35 || dtop >= 35 || dbottom <= -35 || dbottom >= 35)
555 {
556 dleft = dleft < 0 ? -dleft : dleft;
557 dright = dright < 0 ? -dright : dright;
558 dbottom = dbottom < 0 ? -dbottom : dbottom;
559 dtop = dtop < 0 ? -dtop : dtop;
560 dmin = dleft + dright + dbottom + dtop;
561
562 if (dmin < dclosest)
563 {
564 dclosest = dmin;
565 closest = size;
566 }
567
568 continue;
569 }
570 }
571
572 if (exact)
573 *exact = 1;
574
575 return (size->map.ppd);
576 }
577
578 if (closest)
579 return (closest->map.ppd);
580
581 /*
582 * If we get here we need to check for custom page size support...
583 */
584
585 if (jobsize.width >= pwg->custom_min_width &&
586 jobsize.width <= pwg->custom_max_width &&
587 jobsize.length >= pwg->custom_min_length &&
588 jobsize.length <= pwg->custom_max_length)
589 {
590 /*
591 * In range, format as Custom.WWWWxLLLL (points).
592 */
593
594 snprintf(pwg->custom_ppd_size, sizeof(pwg->custom_ppd_size), "Custom.%dx%d",
595 (int)_PWG_TOPTS(jobsize.width), (int)_PWG_TOPTS(jobsize.length));
596
597 if (margins_set && exact)
598 {
599 dleft = pwg->custom_size.left - jobsize.left;
600 dright = pwg->custom_size.right - jobsize.right;
601 dtop = pwg->custom_size.top - jobsize.top;
602 dbottom = pwg->custom_size.bottom - jobsize.bottom;
603
604 if (dleft > -35 && dleft < 35 && dright > -35 && dright < 35 &&
605 dtop > -35 && dtop < 35 && dbottom > -35 && dbottom < 35)
606 *exact = 1;
607 }
608 else if (exact)
609 *exact = 1;
610
611 return (pwg->custom_ppd_size);
612 }
613
614 /*
615 * No custom page size support or the size is out of range - return NULL.
616 */
617
618 return (NULL);
619 }
620
621
622 /*
623 * '_pwgGetSize()' - Get the PWG size associated with a PPD PageSize.
624 */
625
626 _pwg_size_t * /* O - PWG size or NULL */
627 _pwgGetSize(_pwg_t *pwg, /* I - PWG mapping data */
628 const char *page_size) /* I - PPD PageSize */
629 {
630 int i;
631 _pwg_size_t *size; /* Current size */
632
633
634 if (!strncasecmp(page_size, "Custom.", 7))
635 {
636 /*
637 * Custom size; size name can be one of the following:
638 *
639 * Custom.WIDTHxLENGTHin - Size in inches
640 * Custom.WIDTHxLENGTHft - Size in feet
641 * Custom.WIDTHxLENGTHcm - Size in centimeters
642 * Custom.WIDTHxLENGTHmm - Size in millimeters
643 * Custom.WIDTHxLENGTHm - Size in meters
644 * Custom.WIDTHxLENGTH[pt] - Size in points
645 */
646
647 double w, l; /* Width and length of page */
648 char *ptr; /* Pointer into PageSize */
649 struct lconv *loc; /* Locale data */
650
651 loc = localeconv();
652 w = (float)_cupsStrScand(page_size + 7, &ptr, loc);
653 if (!ptr || *ptr != 'x')
654 return (NULL);
655
656 l = (float)_cupsStrScand(ptr + 1, &ptr, loc);
657 if (!ptr)
658 return (NULL);
659
660 if (!strcasecmp(ptr, "in"))
661 {
662 w *= 2540.0;
663 l *= 2540.0;
664 }
665 else if (!strcasecmp(ptr, "ft"))
666 {
667 w *= 12.0 * 2540.0;
668 l *= 12.0 * 2540.0;
669 }
670 else if (!strcasecmp(ptr, "mm"))
671 {
672 w *= 100.0;
673 l *= 100.0;
674 }
675 else if (!strcasecmp(ptr, "cm"))
676 {
677 w *= 1000.0;
678 l *= 1000.0;
679 }
680 else if (!strcasecmp(ptr, "m"))
681 {
682 w *= 100000.0;
683 l *= 100000.0;
684 }
685 else
686 {
687 w *= 2540.0 / 72.0;
688 l *= 2540.0 / 72.0;
689 }
690
691 pwg->custom_size.width = (int)w;
692 pwg->custom_size.length = (int)l;
693
694 return (&(pwg->custom_size));
695 }
696
697 /*
698 * Not a custom size - look it up...
699 */
700
701 for (i = pwg->num_sizes, size = pwg->sizes; i > 0; i --, size ++)
702 if (!strcasecmp(page_size, size->map.ppd))
703 return (size);
704
705 return (NULL);
706 }
707
708
709 /*
710 * '_pwgGetSource()' - Get the PWG media-source associated with a PPD InputSlot.
711 */
712
713 const char * /* O - PWG media-source keyword */
714 _pwgGetSource(_pwg_t *pwg, /* I - PWG mapping data */
715 const char *input_slot) /* I - PPD InputSlot */
716 {
717 int i; /* Looping var */
718 _pwg_map_t *source; /* Current source */
719
720
721 for (i = pwg->num_sources, source = pwg->sources; i > 0; i --, source ++)
722 if (!strcasecmp(input_slot, source->ppd))
723 return (source->pwg);
724
725 return (NULL);
726 }
727
728
729 /*
730 * '_pwgGetType()' - Get the PWG media-type associated with a PPD MediaType.
731 */
732
733 const char * /* O - PWG media-type keyword */
734 _pwgGetType(_pwg_t *pwg, /* I - PWG mapping data */
735 const char *media_type) /* I - PPD MediaType */
736 {
737 int i; /* Looping var */
738 _pwg_map_t *type; /* Current type */
739
740
741 for (i = pwg->num_types, type = pwg->types; i > 0; i --, type ++)
742 if (!strcasecmp(media_type, type->ppd))
743 return (type->pwg);
744
745 return (NULL);
746 }
747
748
749 /*
750 * '_pwgInputSlotForSource()' - Get the InputSlot name for the given PWG source.
751 */
752
753 const char * /* O - InputSlot name */
754 _pwgInputSlotForSource(
755 const char *media_source, /* I - PWG media-source */
756 char *name, /* I - Name buffer */
757 size_t namesize) /* I - Size of name buffer */
758 {
759 if (strcasecmp(media_source, "main-tray"))
760 strlcpy(name, "Cassette", namesize);
761 else if (strcasecmp(media_source, "alternate-tray"))
762 strlcpy(name, "Multipurpose", namesize);
763 else if (strcasecmp(media_source, "large-capacity-tray"))
764 strlcpy(name, "LargeCapacity", namesize);
765 else if (strcasecmp(media_source, "bottom-tray"))
766 strlcpy(name, "Lower", namesize);
767 else if (strcasecmp(media_source, "middle-tray"))
768 strlcpy(name, "Middle", namesize);
769 else if (strcasecmp(media_source, "top-tray"))
770 strlcpy(name, "Upper", namesize);
771 else if (strcasecmp(media_source, "rear-feed"))
772 strlcpy(name, "Rear", namesize);
773 else if (strcasecmp(media_source, "side-feed"))
774 strlcpy(name, "Side", namesize);
775 else if (strcasecmp(media_source, "envelope-feed"))
776 strlcpy(name, "Envelope", namesize);
777 else if (strcasecmp(media_source, "main-roll"))
778 strlcpy(name, "Roll", namesize);
779 else if (strcasecmp(media_source, "alternate-roll"))
780 strlcpy(name, "Roll2", namesize);
781 else
782 pwg_ppdize_name(media_source, name, namesize);
783
784 return (name);
785 }
786
787
788 /*
789 * '_pwgMediaTypeForType()' - Get the MediaType name for the given PWG type.
790 */
791
792 const char * /* O - MediaType name */
793 _pwgMediaTypeForType(
794 const char *media_type, /* I - PWG media-source */
795 char *name, /* I - Name buffer */
796 size_t namesize) /* I - Size of name buffer */
797 {
798 if (strcasecmp(media_type, "auto"))
799 strlcpy(name, "Auto", namesize);
800 else if (strcasecmp(media_type, "cardstock"))
801 strlcpy(name, "Cardstock", namesize);
802 else if (strcasecmp(media_type, "envelope"))
803 strlcpy(name, "Envelope", namesize);
804 else if (strcasecmp(media_type, "photographic-glossy"))
805 strlcpy(name, "Glossy", namesize);
806 else if (strcasecmp(media_type, "photographic-high-gloss"))
807 strlcpy(name, "HighGloss", namesize);
808 else if (strcasecmp(media_type, "photographic-matte"))
809 strlcpy(name, "Matte", namesize);
810 else if (strcasecmp(media_type, "stationery"))
811 strlcpy(name, "Plain", namesize);
812 else if (strcasecmp(media_type, "stationery-coated"))
813 strlcpy(name, "Coated", namesize);
814 else if (strcasecmp(media_type, "stationery-inkjet"))
815 strlcpy(name, "Inkjet", namesize);
816 else if (strcasecmp(media_type, "stationery-letterhead"))
817 strlcpy(name, "Letterhead", namesize);
818 else if (strcasecmp(media_type, "stationery-preprinted"))
819 strlcpy(name, "Preprinted", namesize);
820 else if (strcasecmp(media_type, "transparency"))
821 strlcpy(name, "Transparency", namesize);
822 else
823 pwg_ppdize_name(media_type, name, namesize);
824
825 return (name);
826 }
827
828
829 /*
830 * '_pwgPageSizeForMedia()' - Get the PageSize name for the given media.
831 */
832
833 const char * /* O - PageSize name */
834 _pwgPageSizeForMedia(
835 _pwg_media_t *media, /* I - Media */
836 char *name, /* I - PageSize name buffer */
837 size_t namesize) /* I - Size of name buffer */
838 {
839 const char *sizeptr, /* Pointer to size in PWG name */
840 *dimptr; /* Pointer to dimensions in PWG name */
841
842
843 /*
844 * Range check input...
845 */
846
847 if (!media || !name || namesize < PPD_MAX_NAME)
848 return (NULL);
849
850 /*
851 * Copy or generate a PageSize name...
852 */
853
854 if (media->ppd)
855 {
856 /*
857 * Use a standard Adobe name...
858 */
859
860 strlcpy(name, media->ppd, namesize);
861 }
862 else if (!media->pwg || !strncmp(media->pwg, "custom_", 7) ||
863 (sizeptr = strchr(media->pwg, '_')) == NULL ||
864 (dimptr = strchr(sizeptr + 1, '_')) == NULL ||
865 (dimptr - sizeptr) > namesize)
866 {
867 /*
868 * Use a name of the form "wNNNhNNN"...
869 */
870
871 snprintf(name, namesize, "w%dh%d", (int)_PWG_TOPTS(media->width),
872 (int)_PWG_TOPTS(media->length));
873 }
874 else
875 {
876 /*
877 * Copy the size name from class_sizename_dimensions...
878 */
879
880 memcpy(name, sizeptr + 1, dimptr - sizeptr - 1);
881 name[dimptr - sizeptr - 1] = '\0';
882 }
883
884 return (name);
885 }
886
887
888 /*
889 * 'pwg_ppdize_name()' - Convert an IPP keyword to a PPD keyword.
890 */
891
892 static void
893 pwg_ppdize_name(const char *ipp, /* I - IPP keyword */
894 char *name, /* I - Name buffer */
895 size_t namesize) /* I - Size of name buffer */
896 {
897 char *ptr, /* Pointer into name buffer */
898 *end; /* End of name buffer */
899
900
901 *name = toupper(*ipp++);
902
903 for (ptr = name + 1, end = name + namesize - 1; *ipp && ptr < end;)
904 {
905 if (*ipp == '-' && isalpha(ipp[1] & 255))
906 {
907 ipp ++;
908 *ptr++ = toupper(*ipp++ & 255);
909 }
910 else
911 *ptr++ = *ipp++;
912 }
913
914 *ptr = '\0';
915 }
916
917
918 /*
919 * 'pwg_unppdize_name()' - Convert a PPD keyword to a lowercase IPP keyword.
920 */
921
922 static void
923 pwg_unppdize_name(const char *ppd, /* I - PPD keyword */
924 char *name, /* I - Name buffer */
925 size_t namesize) /* I - Size of name buffer */
926 {
927 char *ptr, /* Pointer into name buffer */
928 *end; /* End of name buffer */
929
930
931 for (ptr = name, end = name + namesize - 1; *ppd && ptr < end; ppd ++)
932 {
933 if (isalnum(*ppd & 255) || *ppd == '-' || *ppd == '.')
934 *ptr++ = tolower(*ppd & 255);
935 else if (*ppd == '_')
936 *ptr++ = '-';
937
938 if (!isupper(*ppd & 255) && isalnum(*ppd & 255) &&
939 isupper(ppd[1] & 255) && ptr < end)
940 *ptr++ = '-';
941 }
942
943 *ptr = '\0';
944 }
945
946
947 /*
948 * End of "$Id$".
949 */