Revert manifest to default one
[external/cups.git] / cups / page.c
1 /*
2  * "$Id: page.c 9793 2011-05-20 03:49:49Z mike $"
3  *
4  *   Page size functions for CUPS.
5  *
6  *   Copyright 2007-2011 by Apple Inc.
7  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
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  *   PostScript is a trademark of Adobe Systems, Inc.
16  *
17  *   This file is subject to the Apple OS-Developed Software exception.
18  *
19  * Contents:
20  *
21  *   ppdPageSize()       - Get the page size record for the given size.
22  *   ppdPageSizeLimits() - Return the custom page size limits.
23  *   ppdPageWidth()      - Get the page width for the given size.
24  *   ppdPageLength()     - Get the page length for the given size.
25  */
26
27 /*
28  * Include necessary headers...
29  */
30
31 #include "string-private.h"
32 #include "debug-private.h"
33 #include "ppd.h"
34
35
36 /*
37  * 'ppdPageSize()' - Get the page size record for the given size.
38  */
39
40 ppd_size_t *                            /* O - Size record for page or NULL */
41 ppdPageSize(ppd_file_t *ppd,            /* I - PPD file record */
42             const char *name)           /* I - Size name */
43 {
44   int           i;                      /* Looping var */
45   ppd_size_t    *size;                  /* Current page size */
46   double        w, l;                   /* Width and length of page */
47   char          *nameptr;               /* Pointer into name */
48   struct lconv  *loc;                   /* Locale data */
49   ppd_coption_t *coption;               /* Custom option for page size */
50   ppd_cparam_t  *cparam;                /* Custom option parameter */
51
52
53   DEBUG_printf(("2ppdPageSize(ppd=%p, name=\"%s\")", ppd, name));
54
55   if (!ppd)
56   {
57     DEBUG_puts("3ppdPageSize: Bad PPD pointer, returning NULL...");
58     return (NULL);
59   }
60
61   if (name)
62   {
63     if (!strncmp(name, "Custom.", 7) && ppd->variable_sizes)
64     {
65      /*
66       * Find the custom page size...
67       */
68
69       for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
70         if (!strcmp("Custom", size->name))
71           break;
72
73       if (!i)
74       {
75         DEBUG_puts("3ppdPageSize: No custom sizes, returning NULL...");
76         return (NULL);
77       }
78
79      /*
80       * Variable size; size name can be one of the following:
81       *
82       *    Custom.WIDTHxLENGTHin    - Size in inches
83       *    Custom.WIDTHxLENGTHft    - Size in feet
84       *    Custom.WIDTHxLENGTHcm    - Size in centimeters
85       *    Custom.WIDTHxLENGTHmm    - Size in millimeters
86       *    Custom.WIDTHxLENGTHm     - Size in meters
87       *    Custom.WIDTHxLENGTH[pt]  - Size in points
88       */
89
90       loc = localeconv();
91       w   = _cupsStrScand(name + 7, &nameptr, loc);
92       if (!nameptr || *nameptr != 'x')
93         return (NULL);
94
95       l = _cupsStrScand(nameptr + 1, &nameptr, loc);
96       if (!nameptr)
97         return (NULL);
98
99       if (!_cups_strcasecmp(nameptr, "in"))
100       {
101         w *= 72.0;
102         l *= 72.0;
103       }
104       else if (!_cups_strcasecmp(nameptr, "ft"))
105       {
106         w *= 12.0 * 72.0;
107         l *= 12.0 * 72.0;
108       }
109       else if (!_cups_strcasecmp(nameptr, "mm"))
110       {
111         w *= 72.0 / 25.4;
112         l *= 72.0 / 25.4;
113       }
114       else if (!_cups_strcasecmp(nameptr, "cm"))
115       {
116         w *= 72.0 / 2.54;
117         l *= 72.0 / 2.54;
118       }
119       else if (!_cups_strcasecmp(nameptr, "m"))
120       {
121         w *= 72.0 / 0.0254;
122         l *= 72.0 / 0.0254;
123       }
124
125       size->width  = (float)w;
126       size->length = (float)l;
127       size->left   = ppd->custom_margins[0];
128       size->bottom = ppd->custom_margins[1];
129       size->right  = (float)(w - ppd->custom_margins[2]);
130       size->top    = (float)(l - ppd->custom_margins[3]);
131
132      /*
133       * Update the custom option records for the page size, too...
134       */
135
136       if ((coption = ppdFindCustomOption(ppd, "PageSize")) != NULL)
137       {
138         if ((cparam = ppdFindCustomParam(coption, "Width")) != NULL)
139           cparam->current.custom_points = (float)w;
140
141         if ((cparam = ppdFindCustomParam(coption, "Height")) != NULL)
142           cparam->current.custom_points = (float)l;
143       }
144
145      /*
146       * Return the page size...
147       */
148
149       DEBUG_printf(("3ppdPageSize: Returning %p (\"%s\", %gx%g)", size,
150                     size->name, size->width, size->length));
151
152       return (size);
153     }
154     else
155     {
156      /*
157       * Lookup by name...
158       */
159
160       for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
161         if (!_cups_strcasecmp(name, size->name))
162         {
163           DEBUG_printf(("3ppdPageSize: Returning %p (\"%s\", %gx%g)", size,
164                         size->name, size->width, size->length));
165
166           return (size);
167         }
168     }
169   }
170   else
171   {
172    /*
173     * Find default...
174     */
175
176     for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
177       if (size->marked)
178       {
179         DEBUG_printf(("3ppdPageSize: Returning %p (\"%s\", %gx%g)", size,
180                       size->name, size->width, size->length));
181
182         return (size);
183       }
184   }
185
186   DEBUG_puts("3ppdPageSize: Size not found, returning NULL");
187
188   return (NULL);
189 }
190
191
192 /*
193  * 'ppdPageSizeLimits()' - Return the custom page size limits.
194  *
195  * This function returns the minimum and maximum custom page sizes and printable
196  * areas based on the currently-marked (selected) options.
197  *
198  * If the specified PPD file does not support custom page sizes, both
199  * "minimum" and "maximum" are filled with zeroes.
200  *
201  * @since CUPS 1.4/Mac OS X 10.6@
202  */
203
204 int                                     /* O - 1 if custom sizes are supported, 0 otherwise */
205 ppdPageSizeLimits(ppd_file_t *ppd,      /* I - PPD file record */
206                   ppd_size_t *minimum,  /* O - Minimum custom size */
207                   ppd_size_t *maximum)  /* O - Maximum custom size */
208 {
209   ppd_choice_t  *qualifier2,            /* Second media qualifier */
210                 *qualifier3;            /* Third media qualifier */
211   ppd_attr_t    *attr;                  /* Attribute */
212   float         width,                  /* Min/max width */
213                 length;                 /* Min/max length */
214   char          spec[PPD_MAX_NAME];     /* Selector for min/max */
215
216
217  /*
218   * Range check input...
219   */
220
221   if (!ppd || !ppd->variable_sizes || !minimum || !maximum)
222   {
223     if (minimum)
224       memset(minimum, 0, sizeof(ppd_size_t));
225
226     if (maximum)
227       memset(maximum, 0, sizeof(ppd_size_t));
228
229     return (0);
230   }
231
232  /*
233   * See if we have the cupsMediaQualifier2 and cupsMediaQualifier3 attributes...
234   */
235
236   cupsArraySave(ppd->sorted_attrs);
237
238   if ((attr = ppdFindAttr(ppd, "cupsMediaQualifier2", NULL)) != NULL &&
239       attr->value)
240     qualifier2 = ppdFindMarkedChoice(ppd, attr->value);
241   else
242     qualifier2 = NULL;
243
244   if ((attr = ppdFindAttr(ppd, "cupsMediaQualifier3", NULL)) != NULL &&
245       attr->value)
246     qualifier3 = ppdFindMarkedChoice(ppd, attr->value);
247   else
248     qualifier3 = NULL;
249
250  /*
251   * Figure out the current minimum width and length...
252   */
253
254   width  = ppd->custom_min[0];
255   length = ppd->custom_min[1];
256
257   if (qualifier2)
258   {
259    /*
260     * Try getting cupsMinSize...
261     */
262
263     if (qualifier3)
264     {
265       snprintf(spec, sizeof(spec), ".%s.%s", qualifier2->choice,
266                qualifier3->choice);
267       attr = ppdFindAttr(ppd, "cupsMinSize", spec);
268     }
269     else
270       attr = NULL;
271
272     if (!attr)
273     {
274       snprintf(spec, sizeof(spec), ".%s.", qualifier2->choice);
275       attr = ppdFindAttr(ppd, "cupsMinSize", spec);
276     }
277
278     if (!attr && qualifier3)
279     {
280       snprintf(spec, sizeof(spec), "..%s", qualifier3->choice);
281       attr = ppdFindAttr(ppd, "cupsMinSize", spec);
282     }
283
284     if ((attr && attr->value &&
285          sscanf(attr->value, "%f%f", &width, &length) != 2) || !attr)
286     {
287       width  = ppd->custom_min[0];
288       length = ppd->custom_min[1];
289     }
290   }
291
292   minimum->width  = width;
293   minimum->length = length;
294   minimum->left   = ppd->custom_margins[0];
295   minimum->bottom = ppd->custom_margins[1];
296   minimum->right  = width - ppd->custom_margins[2];
297   minimum->top    = length - ppd->custom_margins[3];
298
299  /*
300   * Figure out the current maximum width and length...
301   */
302
303   width  = ppd->custom_max[0];
304   length = ppd->custom_max[1];
305
306   if (qualifier2)
307   {
308    /*
309     * Try getting cupsMaxSize...
310     */
311
312     if (qualifier3)
313     {
314       snprintf(spec, sizeof(spec), ".%s.%s", qualifier2->choice,
315                qualifier3->choice);
316       attr = ppdFindAttr(ppd, "cupsMaxSize", spec);
317     }
318     else
319       attr = NULL;
320
321     if (!attr)
322     {
323       snprintf(spec, sizeof(spec), ".%s.", qualifier2->choice);
324       attr = ppdFindAttr(ppd, "cupsMaxSize", spec);
325     }
326
327     if (!attr && qualifier3)
328     {
329       snprintf(spec, sizeof(spec), "..%s", qualifier3->choice);
330       attr = ppdFindAttr(ppd, "cupsMaxSize", spec);
331     }
332
333     if (!attr ||
334         (attr->value && sscanf(attr->value, "%f%f", &width, &length) != 2))
335     {
336       width  = ppd->custom_max[0];
337       length = ppd->custom_max[1];
338     }
339   }
340
341   maximum->width  = width;
342   maximum->length = length;
343   maximum->left   = ppd->custom_margins[0];
344   maximum->bottom = ppd->custom_margins[1];
345   maximum->right  = width - ppd->custom_margins[2];
346   maximum->top    = length - ppd->custom_margins[3];
347
348  /*
349   * Return the min and max...
350   */
351
352   cupsArrayRestore(ppd->sorted_attrs);
353
354   return (1);
355 }
356
357
358 /*
359  * 'ppdPageWidth()' - Get the page width for the given size.
360  */
361
362 float                           /* O - Width of page in points or 0.0 */
363 ppdPageWidth(ppd_file_t *ppd,   /* I - PPD file record */
364              const char *name)  /* I - Size name */
365 {
366   ppd_size_t    *size;          /* Page size */
367
368
369   if ((size = ppdPageSize(ppd, name)) == NULL)
370     return (0.0);
371   else
372     return (size->width);
373 }
374
375
376 /*
377  * 'ppdPageLength()' - Get the page length for the given size.
378  */
379
380 float                           /* O - Length of page in points or 0.0 */
381 ppdPageLength(ppd_file_t *ppd,  /* I - PPD file */
382               const char *name) /* I - Size name */
383 {
384   ppd_size_t    *size;          /* Page size */
385
386
387   if ((size = ppdPageSize(ppd, name)) == NULL)
388     return (0.0);
389   else
390     return (size->length);
391 }
392
393
394 /*
395  * End of "$Id: page.c 9793 2011-05-20 03:49:49Z mike $".
396  */