/*
* "$Id$"
*
- * PWG media name API implementation for CUPS.
+ * PWG media name API implementation for CUPS.
*
- * Copyright 2009-2013 by Apple Inc.
+ * Copyright 2009-2014 by Apple Inc.
*
- * 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/".
+ * 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/".
*
- * This file is subject to the Apple OS-Developed Software exception.
- *
- * Contents:
- *
- * pwgFormatSizeName() - Generate a PWG self-describing media size name.
- * pwgInitSize() - Initialize a pwg_size_t structure using IPP Job
- * Template attributes.
- * pwgMediaForLegacy() - Find a PWG media size by ISO/IPP legacy name.
- * pwgMediaForPPD() - Find a PWG media size by Adobe PPD name.
- * pwgMediaForPWG() - Find a PWG media size by 5101.1 self-describing
- * name.
- * pwgMediaForSize() - Get the PWG media size for the given
- * dimensions.
- * pwg_compare_legacy() - Compare two sizes using the legacy names.
- * pwg_compare_ppd() - Compare two sizes using the PPD names.
- * pwg_compare_pwg() - Compare two sizes using the PWG names.
- * pwg_format_inches() - Convert and format PWG units as inches.
- * pwg_format_millimeters() - Convert and format PWG units as millimeters.
+ * This file is subject to the Apple OS-Developed Software exception.
*/
/*
static int pwg_compare_ppd(pwg_media_t *a, pwg_media_t *b);
static char *pwg_format_inches(char *buf, size_t bufsize, int val);
static char *pwg_format_millimeters(char *buf, size_t bufsize, int val);
+static int pwg_scan_measurement(const char *buf, char **bufptr, int numer,
+ int denom);
/*
_PWG_MEDIA_MM("prc_4_110x208mm", NULL, "EnvPRC4", 110, 208),
_PWG_MEDIA_MM("prc_8_120x309mm", NULL, "EnvPRC8", 120, 309),
_PWG_MEDIA_MM("prc_6_120x320mm", NULL, NULL, 120, 320),
- _PWG_MEDIA_MM("prc_3_125x176mm", NULL, "EnvPRC3", 125, 176),
_PWG_MEDIA_MM("prc_16k_146x215mm", NULL, "PRC16K", 146, 215),
_PWG_MEDIA_MM("prc_7_160x230mm", NULL, "EnvPRC7", 160, 230),
_PWG_MEDIA_MM("om_juuro-ku-kai_198x275mm", NULL, NULL, 198, 275),
_PWG_MEDIA_MM("om_pa-kai_267x389mm", NULL, NULL, 267, 389),
_PWG_MEDIA_MM("om_dai-pa-kai_275x395mm", NULL, NULL, 275, 395),
- _PWG_MEDIA_MM("prc_10_324x458mm", NULL, "EnvPRC10", 324, 458),
/* Chinese Standard Sheet Media Inch Sizes */
_PWG_MEDIA_IN("roc_16k_7.75x10.75in", NULL, "roc16k", 7.75, 10.75),
/* Other Metric Standard Sheet Media Sizes */
_PWG_MEDIA_MM("om_small-photo_100x150mm", NULL, "om_small-photo", 100, 150),
_PWG_MEDIA_MM("om_italian_110x230mm", NULL, "EnvItalian", 110, 230),
- _PWG_MEDIA_MM("om_postfix_114x229mm", NULL, NULL, 114, 229),
_PWG_MEDIA_MM("om_large-photo_200x300", NULL, "om_large-photo", 200, 300),
_PWG_MEDIA_MM("om_folio_210x330mm", "folio", "Folio", 210, 330),
_PWG_MEDIA_MM("om_folio-sp_215x315mm", NULL, "FolioSP", 215, 315),
* units string is @code NULL@, otherwise inches ("in") or millimeters ("mm")
* are used.
*
- * @since CUPS 1.7@
+ * @since CUPS 1.7/OS X 10.9@
*/
int /* O - 1 on success, 0 on failure */
*/
uptr = usize;
- (*format)(uptr, sizeof(usize) - (uptr - usize), width);
+ (*format)(uptr, sizeof(usize) - (size_t)(uptr - usize), width);
uptr += strlen(uptr);
*uptr++ = 'x';
- (*format)(uptr, sizeof(usize) - (uptr - usize), length);
+ (*format)(uptr, sizeof(usize) - (size_t)(uptr - usize), length);
uptr += strlen(uptr);
/*
* member attribute was specified in the "media-col" Job Template attribute,
* otherwise it is initialized to 0.
*
- * @since CUPS 1.7@
+ * @since CUPS 1.7/OS X 10.9@
*/
int /* O - 1 if size was initialized, 0 otherwise */
* The "name" argument specifies the legacy ISO media size name, for example
* "iso-a4" or "na-letter".
*
- * @since CUPS 1.7@
+ * @since CUPS 1.7/OS X 10.9@
*/
pwg_media_t * /* O - Matching size or NULL */
* thread. Custom names can be of the form "Custom.WIDTHxLENGTH[units]" or
* "WIDTHxLENGTH[units]".
*
- * @since CUPS 1.7@
+ * @since CUPS 1.7/OS X 10.9@
*/
pwg_media_t * /* O - Matching size or NULL */
* [Custom.]WIDTHxLENGTHpt[.FullBleed] - Size in points [borderless]
*/
- double w, l, /* Width and length of page */
- factor; /* Unit scaling factor */
+ int w, l, /* Width and length of page */
+ numer, /* Unit scaling factor */
+ denom; /* ... */
char *ptr; /* Pointer into name */
- struct lconv *loc; /* Locale data */
+ const char *units; /* Pointer to units */
int custom; /* Custom page size? */
+
if (!_cups_strncasecmp(ppd, "Custom.", 7))
{
custom = 1;
- factor = 2540.0 / 72.0;
+ numer = 2540;
+ denom = 72;
ptr = (char *)ppd + 7;
}
else
{
custom = 0;
- factor = 2540.0;
+ numer = 2540;
+ denom = 1;
ptr = (char *)ppd;
}
- loc = localeconv();
- w = _cupsStrScand(ptr, &ptr, loc);
+ /*
+ * Find any units in the size...
+ */
- if (ptr && ptr > ppd && *ptr == 'x')
+ units = strchr(ptr, '.');
+ while (units && isdigit(units[1] & 255))
+ units = strchr(units + 1, '.');
+
+ if (units)
+ units -= 2;
+ else
+ units = ptr + strlen(ptr) - 2;
+
+ if (units > ptr)
{
- l = _cupsStrScand(ptr + 1, &ptr, loc);
-
- if (ptr &&
- (!*ptr ||
- !_cups_strcasecmp(ptr, "FullBleed") ||
- !_cups_strcasecmp(ptr, ".FullBleed") ||
- !_cups_strcasecmp(ptr, "cm") ||
- !_cups_strcasecmp(ptr, "cm.FullBleed") ||
- !_cups_strcasecmp(ptr, "ft") ||
- !_cups_strcasecmp(ptr, "ft.FullBleed") ||
- !_cups_strcasecmp(ptr, "in") ||
- !_cups_strcasecmp(ptr, "in.FullBleed") ||
- !_cups_strcasecmp(ptr, "m") ||
- !_cups_strcasecmp(ptr, "m.FullBleed") ||
- !_cups_strcasecmp(ptr, "mm") ||
- !_cups_strcasecmp(ptr, "mm.FullBleed") ||
- !_cups_strcasecmp(ptr, "pt") ||
- !_cups_strcasecmp(ptr, "pt.FullBleed")))
+ if (isdigit(*units & 255) || *units == '.')
+ units ++;
+
+ if (!_cups_strncasecmp(units, "cm", 2))
+ {
+ numer = 1000;
+ denom = 1;
+ }
+ else if (!_cups_strncasecmp(units, "ft", 2))
+ {
+ numer = 2540 * 12;
+ denom = 1;
+ }
+ else if (!_cups_strncasecmp(units, "in", 2))
+ {
+ numer = 2540;
+ denom = 1;
+ }
+ else if (!_cups_strncasecmp(units, "mm", 2))
+ {
+ numer = 100;
+ denom = 1;
+ }
+ else if (*units == 'm' || *units == 'M')
{
- size = &(cg->pwg_media);
-
- if (!_cups_strncasecmp(ptr, "cm", 2))
- factor = 1000.0;
- else if (!_cups_strncasecmp(ptr, "ft", 2))
- factor = 2540.0 * 12.0;
- else if (!_cups_strncasecmp(ptr, "in", 2))
- factor = 2540.0;
- else if (!_cups_strncasecmp(ptr, "mm", 2))
- factor = 100.0;
- else if (*ptr == 'm' || *ptr == 'M')
- factor = 100000.0;
- else if (!_cups_strncasecmp(ptr, "pt", 2))
- factor = 2540.0 / 72.0;
+ numer = 100000;
+ denom = 1;
+ }
+ else if (!_cups_strncasecmp(units, "pt", 2))
+ {
+ numer = 2540;
+ denom = 72;
+ }
+ }
+
+ w = pwg_scan_measurement(ptr, &ptr, numer, denom);
+ if (ptr && ptr > ppd && *ptr == 'x')
+ {
+ l = pwg_scan_measurement(ptr + 1, &ptr, numer, denom);
+
+ if (ptr)
+ {
/*
* Not a standard size; convert it to a PWG custom name of the form:
*
* [oe|om]_WIDTHxHEIGHTuu_WIDTHxHEIGHTuu
*/
- size->width = (int)(w * factor);
- size->length = (int)(l * factor);
+ size = &(cg->pwg_media);
+ size->width = w;
+ size->length = l;
size->pwg = cg->pwg_name;
pwgFormatSizeName(cg->pwg_name, sizeof(cg->pwg_name),
* thread-local storage and is overwritten by each call to the function in the
* thread.
*
- * @since CUPS 1.7@
+ * @since CUPS 1.7/OS X 10.9@
*/
pwg_media_t * /* O - Matching size or NULL */
* class_name_WWWxHHHmm
*/
- double w, l; /* Width and length of page */
- struct lconv *loc; /* Locale data */
+ int w, l; /* Width and length of page */
+ int numer; /* Scale factor for units */
+ const char *units = ptr + strlen(ptr) - 2;
+ /* Units from size */
ptr ++;
- loc = localeconv();
- w = _cupsStrScand(ptr, &ptr, loc);
+
+ if (units >= ptr && !strcmp(units, "in"))
+ numer = 2540;
+ else
+ numer = 100;
+
+ w = pwg_scan_measurement(ptr, &ptr, numer, 1);
if (ptr && *ptr == 'x')
{
- l = _cupsStrScand(ptr + 1, &ptr, loc);
+ l = pwg_scan_measurement(ptr + 1, &ptr, numer, 1);
- if (ptr && (!strcmp(ptr, "in") || !strcmp(ptr, "mm")))
+ if (ptr)
{
- size = &(cg->pwg_media);
-
- if (!strcmp(ptr, "mm"))
- {
- size->width = (int)(w * 100 + 0.5);
- size->length = (int)(l * 100 + 0.5);
- }
- else
- {
- size->width = (int)(w * 2540 + 0.5);
- size->length = (int)(l * 2540 + 0.5);
- }
+ size = &(cg->pwg_media);
+ size->width = w;
+ size->length = l;
strlcpy(cg->pwg_name, pwg, sizeof(cg->pwg_name));
size->pwg = cg->pwg_name;
* thread-local storage and is overwritten by each call to the function in the
* thread.
*
- * @since CUPS 1.7@
+ * @since CUPS 1.7/OS X 10.9@
*/
pwg_media_t * /* O - PWG media name */
{ return (pwgMediaForSize(width, length)); }
+/*
+ * '_pwgMediaTable()' - Return the internal media size table.
+ */
+
+const pwg_media_t * /* O - Pointer to first entry */
+_pwgMediaTable(size_t *num_media) /* O - Number of entries */
+{
+ *num_media = sizeof(cups_pwg_media) / sizeof(cups_pwg_media[0]);
+
+ return (cups_pwg_media);
+}
+
+
/*
* 'pwg_compare_legacy()' - Compare two sizes using the legacy names.
*/
}
+/*
+ * 'pwg_scan_measurement()' - Scan a measurement in inches or millimeters.
+ *
+ * The "factor" argument specifies the scale factor for the units to convert to
+ * hundredths of millimeters. The returned value is NOT rounded but is an
+ * exact conversion of the fraction value (no floating point is used).
+ */
+
+static int /* O - Hundredths of millimeters */
+pwg_scan_measurement(
+ const char *buf, /* I - Number string */
+ char **bufptr, /* O - First byte after the number */
+ int numer, /* I - Numerator from units */
+ int denom) /* I - Denominator from units */
+{
+ int value = 0, /* Measurement value */
+ fractional = 0, /* Fractional value */
+ divisor = 1, /* Fractional divisor */
+ digits = 10 * numer * denom; /* Maximum fractional value to read */
+
+
+ /*
+ * Scan integer portion...
+ */
+
+ while (*buf >= '0' && *buf <= '9')
+ value = value * 10 + (*buf++) - '0';
+
+ if (*buf == '.')
+ {
+ /*
+ * Scan fractional portion...
+ */
+
+ buf ++;
+
+ while (divisor < digits && *buf >= '0' && *buf <= '9')
+ {
+ fractional = fractional * 10 + (*buf++) - '0';
+ divisor *= 10;
+ }
+
+ /*
+ * Skip trailing digits that won't contribute...
+ */
+
+ while (*buf >= '0' && *buf <= '9')
+ buf ++;
+ }
+
+ if (bufptr)
+ *bufptr = (char *)buf;
+
+ return (value * numer / denom + fractional * numer / denom / divisor);
+}
+
+
/*
* End of "$Id$".
*/