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