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