Home | History | Annotate | Download | only in cups
      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 {
     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 */
    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 */
    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 */
    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