/* * Page size functions for CUPS. * * Copyright 2007-2015 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * Licensed under Apache License v2.0. See the file "LICENSE" for more * information. * * PostScript is a trademark of Adobe Systems, Inc. */ /* * Include necessary headers... */ #include "string-private.h" #include "debug-internal.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); }