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