/*
* Page size functions for CUPS.
*
* Copyright 2007-2015 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
* law. Distribution and use rights are outlined in the file "LICENSE.txt"
* which should have been included with this file. If this file is
* missing or damaged, see the license at "http://www.cups.org/".
*
* PostScript is a trademark of Adobe Systems, Inc.
*
* This file is subject to the Apple OS-Developed Software exception.
*/
/*
* Include necessary headers...
*/
#include "string-private.h"
#include "debug-private.h"
#include "ppd.h"
/*
* 'ppdPageSize()' - Get the page size record for the named size.
*/
ppd_size_t * /* O - Size record for page or NULL */
ppdPageSize(ppd_file_t *ppd, /* I - PPD file record */
const char *name) /* I - Size name */
{
int i; /* Looping var */
ppd_size_t *size; /* Current page size */
double w, l; /* Width and length of page */
char *nameptr; /* Pointer into name */
struct lconv *loc; /* Locale data */
ppd_coption_t *coption; /* Custom option for page size */
ppd_cparam_t *cparam; /* Custom option parameter */
DEBUG_printf(("2ppdPageSize(ppd=%p, name=\"%s\")", ppd, name));
if (!ppd)
{
DEBUG_puts("3ppdPageSize: Bad PPD pointer, returning NULL...");
return (NULL);
}
if (name)
{
if (!strncmp(name, "Custom.", 7) && ppd->variable_sizes)
{
/*
* Find the custom page size...
*/
for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
if (!strcmp("Custom", size->name))
break;
if (!i)
{
DEBUG_puts("3ppdPageSize: No custom sizes, returning NULL...");
return (NULL);
}
/*
* Variable size; size name can be one of the following:
*
* Custom.WIDTHxLENGTHin - Size in inches
* Custom.WIDTHxLENGTHft - Size in feet
* Custom.WIDTHxLENGTHcm - Size in centimeters
* Custom.WIDTHxLENGTHmm - Size in millimeters
* Custom.WIDTHxLENGTHm - Size in meters
* Custom.WIDTHxLENGTH[pt] - Size in points
*/
loc = localeconv();
w = _cupsStrScand(name + 7, &nameptr, loc);
if (!nameptr || *nameptr != 'x')
return (NULL);
l = _cupsStrScand(nameptr + 1, &nameptr, loc);
if (!nameptr)
return (NULL);
if (!_cups_strcasecmp(nameptr, "in"))
{
w *= 72.0;
l *= 72.0;
}
else if (!_cups_strcasecmp(nameptr, "ft"))
{
w *= 12.0 * 72.0;
l *= 12.0 * 72.0;
}
else if (!_cups_strcasecmp(nameptr, "mm"))
{
w *= 72.0 / 25.4;
l *= 72.0 / 25.4;
}
else if (!_cups_strcasecmp(nameptr, "cm"))
{
w *= 72.0 / 2.54;
l *= 72.0 / 2.54;
}
else if (!_cups_strcasecmp(nameptr, "m"))
{
w *= 72.0 / 0.0254;
l *= 72.0 / 0.0254;
}
size->width = (float)w;
size->length = (float)l;
size->left = ppd->custom_margins[0];
size->bottom = ppd->custom_margins[1];
size->right = (float)(w - ppd->custom_margins[2]);
size->top = (float)(l - ppd->custom_margins[3]);
/*
* Update the custom option records for the page size, too...
*/
if ((coption = ppdFindCustomOption(ppd, "PageSize")) != NULL)
{
if ((cparam = ppdFindCustomParam(coption, "Width")) != NULL)
cparam->current.custom_points = (float)w;
if ((cparam = ppdFindCustomParam(coption, "Height")) != NULL)
cparam->current.custom_points = (float)l;
}
/*
* Return the page size...
*/
DEBUG_printf(("3ppdPageSize: Returning %p (\"%s\", %gx%g)", size,
size->name, size->width, size->length));
return (size);
}
else
{
/*
* Lookup by name...
*/
for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
if (!_cups_strcasecmp(name, size->name))
{
DEBUG_printf(("3ppdPageSize: Returning %p (\"%s\", %gx%g)", size,
size->name, size->width, size->length));
return (size);
}
}
}
else
{
/*
* Find default...
*/
for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
if (size->marked)
{
DEBUG_printf(("3ppdPageSize: Returning %p (\"%s\", %gx%g)", size,
size->name, size->width, size->length));
return (size);
}
}
DEBUG_puts("3ppdPageSize: Size not found, returning NULL");
return (NULL);
}
/*
* 'ppdPageSizeLimits()' - Return the custom page size limits.
*
* This function returns the minimum and maximum custom page sizes and printable
* areas based on the currently-marked (selected) options.
*
* If the specified PPD file does not support custom page sizes, both
* "minimum" and "maximum" are filled with zeroes.
*
* @since CUPS 1.4/macOS 10.6@
*/
int /* O - 1 if custom sizes are supported, 0 otherwise */
ppdPageSizeLimits(ppd_file_t *ppd, /* I - PPD file record */
ppd_size_t *minimum, /* O - Minimum custom size */
ppd_size_t *maximum) /* O - Maximum custom size */
{
ppd_choice_t *qualifier2, /* Second media qualifier */
*qualifier3; /* Third media qualifier */
ppd_attr_t *attr; /* Attribute */
float width, /* Min/max width */
length; /* Min/max length */
char spec[PPD_MAX_NAME]; /* Selector for min/max */
/*
* Range check input...
*/
if (!ppd || !ppd->variable_sizes || !minimum || !maximum)
{
if (minimum)
memset(minimum, 0, sizeof(ppd_size_t));
if (maximum)
memset(maximum, 0, sizeof(ppd_size_t));
return (0);
}
/*
* See if we have the cupsMediaQualifier2 and cupsMediaQualifier3 attributes...
*/
cupsArraySave(ppd->sorted_attrs);
if ((attr = ppdFindAttr(ppd, "cupsMediaQualifier2", NULL)) != NULL &&
attr->value)
qualifier2 = ppdFindMarkedChoice(ppd, attr->value);
else
qualifier2 = NULL;
if ((attr = ppdFindAttr(ppd, "cupsMediaQualifier3", NULL)) != NULL &&
attr->value)
qualifier3 = ppdFindMarkedChoice(ppd, attr->value);
else
qualifier3 = NULL;
/*
* Figure out the current minimum width and length...
*/
width = ppd->custom_min[0];
length = ppd->custom_min[1];
if (qualifier2)
{
/*
* Try getting cupsMinSize...
*/
if (qualifier3)
{
snprintf(spec, sizeof(spec), ".%s.%s", qualifier2->choice,
qualifier3->choice);
attr = ppdFindAttr(ppd, "cupsMinSize", spec);
}
else
attr = NULL;
if (!attr)
{
snprintf(spec, sizeof(spec), ".%s.", qualifier2->choice);
attr = ppdFindAttr(ppd, "cupsMinSize", spec);
}
if (!attr && qualifier3)
{
snprintf(spec, sizeof(spec), "..%s", qualifier3->choice);
attr = ppdFindAttr(ppd, "cupsMinSize", spec);
}
if ((attr && attr->value &&
sscanf(attr->value, "%f%f", &width, &length) != 2) || !attr)
{
width = ppd->custom_min[0];
length = ppd->custom_min[1];
}
}
minimum->width = width;
minimum->length = length;
minimum->left = ppd->custom_margins[0];
minimum->bottom = ppd->custom_margins[1];
minimum->right = width - ppd->custom_margins[2];
minimum->top = length - ppd->custom_margins[3];
/*
* Figure out the current maximum width and length...
*/
width = ppd->custom_max[0];
length = ppd->custom_max[1];
if (qualifier2)
{
/*
* Try getting cupsMaxSize...
*/
if (qualifier3)
{
snprintf(spec, sizeof(spec), ".%s.%s", qualifier2->choice,
qualifier3->choice);
attr = ppdFindAttr(ppd, "cupsMaxSize", spec);
}
else
attr = NULL;
if (!attr)
{
snprintf(spec, sizeof(spec), ".%s.", qualifier2->choice);
attr = ppdFindAttr(ppd, "cupsMaxSize", spec);
}
if (!attr && qualifier3)
{
snprintf(spec, sizeof(spec), "..%s", qualifier3->choice);
attr = ppdFindAttr(ppd, "cupsMaxSize", spec);
}
if (!attr ||
(attr->value && sscanf(attr->value, "%f%f", &width, &length) != 2))
{
width = ppd->custom_max[0];
length = ppd->custom_max[1];
}
}
maximum->width = width;
maximum->length = length;
maximum->left = ppd->custom_margins[0];
maximum->bottom = ppd->custom_margins[1];
maximum->right = width - ppd->custom_margins[2];
maximum->top = length - ppd->custom_margins[3];
/*
* Return the min and max...
*/
cupsArrayRestore(ppd->sorted_attrs);
return (1);
}
/*
* 'ppdPageWidth()' - Get the page width for the given size.
*/
float /* O - Width of page in points or 0.0 */
ppdPageWidth(ppd_file_t *ppd, /* I - PPD file record */
const char *name) /* I - Size name */
{
ppd_size_t *size; /* Page size */
if ((size = ppdPageSize(ppd, name)) == NULL)
return (0.0);
else
return (size->width);
}
/*
* 'ppdPageLength()' - Get the page length for the given size.
*/
float /* O - Length of page in points or 0.0 */
ppdPageLength(ppd_file_t *ppd, /* I - PPD file */
const char *name) /* I - Size name */
{
ppd_size_t *size; /* Page size */
if ((size = ppdPageSize(ppd, name)) == NULL)
return (0.0);
else
return (size->length);
}