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