Coverage Report

Created: 2026-04-01 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cups/cups/ppd-page.c
Line
Count
Source
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 */
32
ppdPageSize(ppd_file_t *ppd,    /* I - PPD file record */
33
            const char *name)   /* I - Size name */
34
0
{
35
0
  int   i;      /* Looping var */
36
0
  ppd_size_t  *size;      /* Current page size */
37
0
  double  w, l;     /* Width and length of page */
38
0
  char    *nameptr;   /* Pointer into name */
39
0
  struct lconv  *loc;     /* Locale data */
40
0
  ppd_coption_t *coption;   /* Custom option for page size */
41
0
  ppd_cparam_t  *cparam;    /* Custom option parameter */
42
43
44
0
  DEBUG_printf(("2ppdPageSize(ppd=%p, name=\"%s\")", ppd, name));
45
46
0
  if (!ppd)
47
0
  {
48
0
    DEBUG_puts("3ppdPageSize: Bad PPD pointer, returning NULL...");
49
0
    return (NULL);
50
0
  }
51
52
0
  if (name)
53
0
  {
54
0
    if (!strncmp(name, "Custom.", 7) && ppd->variable_sizes)
55
0
    {
56
     /*
57
      * Find the custom page size...
58
      */
59
60
0
      for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
61
0
  if (!strcmp("Custom", size->name))
62
0
          break;
63
64
0
      if (!i)
65
0
      {
66
0
  DEBUG_puts("3ppdPageSize: No custom sizes, returning NULL...");
67
0
        return (NULL);
68
0
      }
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
0
      loc = localeconv();
82
0
      w   = _cupsStrScand(name + 7, &nameptr, loc);
83
0
      if (!nameptr || *nameptr != 'x')
84
0
        return (NULL);
85
86
0
      l = _cupsStrScand(nameptr + 1, &nameptr, loc);
87
0
      if (!nameptr)
88
0
        return (NULL);
89
90
0
      if (!_cups_strcasecmp(nameptr, "in"))
91
0
      {
92
0
        w *= 72.0;
93
0
  l *= 72.0;
94
0
      }
95
0
      else if (!_cups_strcasecmp(nameptr, "ft"))
96
0
      {
97
0
        w *= 12.0 * 72.0;
98
0
  l *= 12.0 * 72.0;
99
0
      }
100
0
      else if (!_cups_strcasecmp(nameptr, "mm"))
101
0
      {
102
0
        w *= 72.0 / 25.4;
103
0
        l *= 72.0 / 25.4;
104
0
      }
105
0
      else if (!_cups_strcasecmp(nameptr, "cm"))
106
0
      {
107
0
        w *= 72.0 / 2.54;
108
0
        l *= 72.0 / 2.54;
109
0
      }
110
0
      else if (!_cups_strcasecmp(nameptr, "m"))
111
0
      {
112
0
        w *= 72.0 / 0.0254;
113
0
        l *= 72.0 / 0.0254;
114
0
      }
115
116
0
      size->width  = (float)w;
117
0
      size->length = (float)l;
118
0
      size->left   = ppd->custom_margins[0];
119
0
      size->bottom = ppd->custom_margins[1];
120
0
      size->right  = (float)(w - ppd->custom_margins[2]);
121
0
      size->top    = (float)(l - ppd->custom_margins[3]);
122
123
     /*
124
      * Update the custom option records for the page size, too...
125
      */
126
127
0
      if ((coption = ppdFindCustomOption(ppd, "PageSize")) != NULL)
128
0
      {
129
0
        if ((cparam = ppdFindCustomParam(coption, "Width")) != NULL)
130
0
    cparam->current.custom_points = (float)w;
131
132
0
        if ((cparam = ppdFindCustomParam(coption, "Height")) != NULL)
133
0
    cparam->current.custom_points = (float)l;
134
0
      }
135
136
     /*
137
      * Return the page size...
138
      */
139
140
0
      DEBUG_printf(("3ppdPageSize: Returning %p (\"%s\", %gx%g)", size,
141
0
                    size->name, size->width, size->length));
142
143
0
      return (size);
144
0
    }
145
0
    else
146
0
    {
147
     /*
148
      * Lookup by name...
149
      */
150
151
0
      for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
152
0
  if (!_cups_strcasecmp(name, size->name))
153
0
  {
154
0
    DEBUG_printf(("3ppdPageSize: Returning %p (\"%s\", %gx%g)", size,
155
0
      size->name, size->width, size->length));
156
157
0
          return (size);
158
0
  }
159
0
    }
160
0
  }
161
0
  else
162
0
  {
163
   /*
164
    * Find default...
165
    */
166
167
0
    for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
168
0
      if (size->marked)
169
0
      {
170
0
  DEBUG_printf(("3ppdPageSize: Returning %p (\"%s\", %gx%g)", size,
171
0
          size->name, size->width, size->length));
172
173
0
        return (size);
174
0
      }
175
0
  }
176
177
0
  DEBUG_puts("3ppdPageSize: Size not found, returning NULL");
178
179
0
  return (NULL);
180
0
}
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 */
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
0
{
200
0
  ppd_choice_t  *qualifier2,    /* Second media qualifier */
201
0
    *qualifier3;    /* Third media qualifier */
202
0
  ppd_attr_t  *attr;      /* Attribute */
203
0
  float   width,      /* Min/max width */
204
0
    length;     /* Min/max length */
205
0
  char    spec[PPD_MAX_NAME]; /* Selector for min/max */
206
207
208
 /*
209
  * Range check input...
210
  */
211
212
0
  if (!ppd || !ppd->variable_sizes || !minimum || !maximum)
213
0
  {
214
0
    if (minimum)
215
0
      memset(minimum, 0, sizeof(ppd_size_t));
216
217
0
    if (maximum)
218
0
      memset(maximum, 0, sizeof(ppd_size_t));
219
220
0
    return (0);
221
0
  }
222
223
 /*
224
  * See if we have the cupsMediaQualifier2 and cupsMediaQualifier3 attributes...
225
  */
226
227
0
  cupsArraySave(ppd->sorted_attrs);
228
229
0
  if ((attr = ppdFindAttr(ppd, "cupsMediaQualifier2", NULL)) != NULL &&
230
0
      attr->value)
231
0
    qualifier2 = ppdFindMarkedChoice(ppd, attr->value);
232
0
  else
233
0
    qualifier2 = NULL;
234
235
0
  if ((attr = ppdFindAttr(ppd, "cupsMediaQualifier3", NULL)) != NULL &&
236
0
      attr->value)
237
0
    qualifier3 = ppdFindMarkedChoice(ppd, attr->value);
238
0
  else
239
0
    qualifier3 = NULL;
240
241
 /*
242
  * Figure out the current minimum width and length...
243
  */
244
245
0
  width  = ppd->custom_min[0];
246
0
  length = ppd->custom_min[1];
247
248
0
  if (qualifier2)
249
0
  {
250
   /*
251
    * Try getting cupsMinSize...
252
    */
253
254
0
    if (qualifier3)
255
0
    {
256
0
      snprintf(spec, sizeof(spec), ".%s.%s", qualifier2->choice,
257
0
         qualifier3->choice);
258
0
      attr = ppdFindAttr(ppd, "cupsMinSize", spec);
259
0
    }
260
0
    else
261
0
      attr = NULL;
262
263
0
    if (!attr)
264
0
    {
265
0
      snprintf(spec, sizeof(spec), ".%s.", qualifier2->choice);
266
0
      attr = ppdFindAttr(ppd, "cupsMinSize", spec);
267
0
    }
268
269
0
    if (!attr && qualifier3)
270
0
    {
271
0
      snprintf(spec, sizeof(spec), "..%s", qualifier3->choice);
272
0
      attr = ppdFindAttr(ppd, "cupsMinSize", spec);
273
0
    }
274
275
0
    if ((attr && attr->value &&
276
0
         sscanf(attr->value, "%f%f", &width, &length) != 2) || !attr)
277
0
    {
278
0
      width  = ppd->custom_min[0];
279
0
      length = ppd->custom_min[1];
280
0
    }
281
0
  }
282
283
0
  minimum->width  = width;
284
0
  minimum->length = length;
285
0
  minimum->left   = ppd->custom_margins[0];
286
0
  minimum->bottom = ppd->custom_margins[1];
287
0
  minimum->right  = width - ppd->custom_margins[2];
288
0
  minimum->top    = length - ppd->custom_margins[3];
289
290
 /*
291
  * Figure out the current maximum width and length...
292
  */
293
294
0
  width  = ppd->custom_max[0];
295
0
  length = ppd->custom_max[1];
296
297
0
  if (qualifier2)
298
0
  {
299
   /*
300
    * Try getting cupsMaxSize...
301
    */
302
303
0
    if (qualifier3)
304
0
    {
305
0
      snprintf(spec, sizeof(spec), ".%s.%s", qualifier2->choice,
306
0
         qualifier3->choice);
307
0
      attr = ppdFindAttr(ppd, "cupsMaxSize", spec);
308
0
    }
309
0
    else
310
0
      attr = NULL;
311
312
0
    if (!attr)
313
0
    {
314
0
      snprintf(spec, sizeof(spec), ".%s.", qualifier2->choice);
315
0
      attr = ppdFindAttr(ppd, "cupsMaxSize", spec);
316
0
    }
317
318
0
    if (!attr && qualifier3)
319
0
    {
320
0
      snprintf(spec, sizeof(spec), "..%s", qualifier3->choice);
321
0
      attr = ppdFindAttr(ppd, "cupsMaxSize", spec);
322
0
    }
323
324
0
    if (!attr ||
325
0
        (attr->value && sscanf(attr->value, "%f%f", &width, &length) != 2))
326
0
    {
327
0
      width  = ppd->custom_max[0];
328
0
      length = ppd->custom_max[1];
329
0
    }
330
0
  }
331
332
0
  maximum->width  = width;
333
0
  maximum->length = length;
334
0
  maximum->left   = ppd->custom_margins[0];
335
0
  maximum->bottom = ppd->custom_margins[1];
336
0
  maximum->right  = width - ppd->custom_margins[2];
337
0
  maximum->top    = length - ppd->custom_margins[3];
338
339
 /*
340
  * Return the min and max...
341
  */
342
343
0
  cupsArrayRestore(ppd->sorted_attrs);
344
345
0
  return (1);
346
0
}
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 */
354
ppdPageWidth(ppd_file_t *ppd, /* I - PPD file record */
355
             const char *name)  /* I - Size name */
356
0
{
357
0
  ppd_size_t  *size;    /* Page size */
358
359
360
0
  if ((size = ppdPageSize(ppd, name)) == NULL)
361
0
    return (0.0);
362
0
  else
363
0
    return (size->width);
364
0
}
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 */
372
ppdPageLength(ppd_file_t *ppd,  /* I - PPD file */
373
              const char *name) /* I - Size name */
374
0
{
375
0
  ppd_size_t  *size;    /* Page size */
376
377
378
0
  if ((size = ppdPageSize(ppd, name)) == NULL)
379
0
    return (0.0);
380
0
  else
381
0
    return (size->length);
382
0
}