| /* |
| * 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 |
| * 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); |
| } |