You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
382 lines
9.2 KiB
382 lines
9.2 KiB
/* |
|
* 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); |
|
}
|
|
|