ALT Linux repositórios
S: | 2.4.7-alt1 |
5.0: | 1.3.10-alt1 |
4.1: | 1.3.10-alt0.M41.4 |
+updates: | 1.3.9-alt1.M41.1 |
4.0: | 1.2.12-alt6.M40.9 |
+updates: | 1.2.12-alt6.M40.8 |
3.0: | 1.1.20-alt14.1 |
Group :: Sistema/Servidores
RPM: cups
Main Changelog Spec Patches Sources Download Gear Bugs e FR Repocop
Patch: Ubuntu-9100-ppd-cache-add-auto-presets.patch
Download
Download
--- a/cups/ppd-cache.c
+++ b/cups/ppd-cache.c
@@ -504,6 +504,8 @@
_pwg_print_color_mode_t print_color_mode;
/* Print color mode for preset */
_pwg_print_quality_t print_quality; /* Print quality for preset */
+ _pwg_print_content_optimize_t print_content_optimize;
+ /* Content optimize for preset */
DEBUG_printf(("_ppdCacheCreateWithFile(filename=\"%s\")", filename));
@@ -929,6 +931,28 @@
cupsParseOptions(valueptr, 0,
pc->presets[print_color_mode] + print_quality);
}
+ else if (!_cups_strcasecmp(line, "OptimizePreset"))
+ {
+ /*
+ * Preset print_content_optimize name=value ...
+ */
+
+ print_content_optimize = (_pwg_print_content_optimize_t)strtol(value, &valueptr, 10);
+
+ if (print_content_optimize < _PWG_PRINT_CONTENT_OPTIMIZE_AUTO ||
+ print_content_optimize >= _PWG_PRINT_CONTENT_OPTIMIZE_MAX ||
+ valueptr == value || !*valueptr)
+ {
+ DEBUG_printf(("ppdCacheCreateWithFile: Bad Optimize Preset on line %d.",
+ linenum));
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ pc->num_optimize_presets[print_content_optimize] =
+ cupsParseOptions(valueptr, 0,
+ pc->optimize_presets + print_content_optimize);
+ }
else if (!_cups_strcasecmp(line, "SidesOption"))
pc->sides_option = strdup(value);
else if (!_cups_strcasecmp(line, "Sides1Sided"))
@@ -1056,6 +1080,7 @@
*ppd_option; /* Other PPD option */
ppd_choice_t *choice; /* Current InputSlot/MediaType */
pwg_map_t *map; /* Current source/type map */
+ int preset_added = 0; /* Preset definition found in PPD? */
ppd_attr_t *ppd_attr; /* Current PPD preset attribute */
int num_options; /* Number of preset options and props */
cups_option_t *options; /* Preset options and properties */
@@ -1512,6 +1537,10 @@
if ((ppd_attr = ppdFindAttr(ppd, "APPrinterPreset", NULL)) != NULL)
{
/*
+ * "Classic" Mac OS approach
+ */
+
+ /*
* Copy and convert APPrinterPreset (output-mode + print-quality) data...
*/
@@ -1611,114 +1640,133 @@
_ppdParseOptions(ppd_attr->value, 0,
pc->presets[pwg_print_color_mode] +
pwg_print_quality, _PPD_PARSE_OPTIONS);
+ preset_added = 1;
}
cupsFreeOptions(num_options, options);
}
while ((ppd_attr = ppdFindNextAttr(ppd, "APPrinterPreset", NULL)) != NULL);
- }
- if (!pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][_PWG_PRINT_QUALITY_DRAFT] &&
- !pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][_PWG_PRINT_QUALITY_NORMAL] &&
- !pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][_PWG_PRINT_QUALITY_HIGH])
- {
- /*
- * Try adding some common color options to create grayscale presets. These
- * are listed in order of popularity...
- */
-
- const char *color_option = NULL, /* Color control option */
- *gray_choice = NULL; /* Choice to select grayscale */
-
- if ((color_model = ppdFindOption(ppd, "ColorModel")) != NULL &&
- ppdFindChoice(color_model, "Gray"))
- {
- color_option = "ColorModel";
- gray_choice = "Gray";
- }
- else if ((color_model = ppdFindOption(ppd, "HPColorMode")) != NULL &&
- ppdFindChoice(color_model, "grayscale"))
- {
- color_option = "HPColorMode";
- gray_choice = "grayscale";
- }
- else if ((color_model = ppdFindOption(ppd, "BRMonoColor")) != NULL &&
- ppdFindChoice(color_model, "Mono"))
- {
- color_option = "BRMonoColor";
- gray_choice = "Mono";
- }
- else if ((color_model = ppdFindOption(ppd, "CNIJSGrayScale")) != NULL &&
- ppdFindChoice(color_model, "1"))
- {
- color_option = "CNIJSGrayScale";
- gray_choice = "1";
- }
- else if ((color_model = ppdFindOption(ppd, "HPColorAsGray")) != NULL &&
- ppdFindChoice(color_model, "True"))
- {
- color_option = "HPColorAsGray";
- gray_choice = "True";
- }
-
- if (color_option && gray_choice)
+ if (preset_added &&
+ !pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][_PWG_PRINT_QUALITY_DRAFT] &&
+ !pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][_PWG_PRINT_QUALITY_NORMAL] &&
+ !pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][_PWG_PRINT_QUALITY_HIGH])
{
/*
- * Copy and convert ColorModel (output-mode) data...
+ * Try adding some common color options to create grayscale presets. These
+ * are listed in order of popularity...
*/
- cups_option_t *coption, /* Color option */
- *moption; /* Monochrome option */
+ const char *color_option = NULL, /* Color control option */
+ *gray_choice = NULL; /* Choice to select grayscale */
- for (pwg_print_quality = _PWG_PRINT_QUALITY_DRAFT;
- pwg_print_quality < _PWG_PRINT_QUALITY_MAX;
- pwg_print_quality ++)
+ if ((color_model = ppdFindOption(ppd, "ColorModel")) != NULL &&
+ ppdFindChoice(color_model, "Gray"))
{
- if (pc->num_presets[_PWG_PRINT_COLOR_MODE_COLOR][pwg_print_quality])
- {
- /*
- * Copy the color options...
- */
+ color_option = "ColorModel";
+ gray_choice = "Gray";
+ }
+ else if ((color_model = ppdFindOption(ppd, "HPColorMode")) != NULL &&
+ ppdFindChoice(color_model, "grayscale"))
+ {
+ color_option = "HPColorMode";
+ gray_choice = "grayscale";
+ }
+ else if ((color_model = ppdFindOption(ppd, "BRMonoColor")) != NULL &&
+ ppdFindChoice(color_model, "Mono"))
+ {
+ color_option = "BRMonoColor";
+ gray_choice = "Mono";
+ }
+ else if ((color_model = ppdFindOption(ppd, "CNIJSGrayScale")) != NULL &&
+ ppdFindChoice(color_model, "1"))
+ {
+ color_option = "CNIJSGrayScale";
+ gray_choice = "1";
+ }
+ else if ((color_model = ppdFindOption(ppd, "HPColorAsGray")) != NULL &&
+ ppdFindChoice(color_model, "True"))
+ {
+ color_option = "HPColorAsGray";
+ gray_choice = "True";
+ }
+
+ if (color_option && gray_choice)
+ {
+ /*
+ * Copy and convert ColorModel (output-mode) data...
+ */
+
+ cups_option_t *coption, /* Color option */
+ *moption; /* Monochrome option */
+
+ for (pwg_print_quality = _PWG_PRINT_QUALITY_DRAFT;
+ pwg_print_quality < _PWG_PRINT_QUALITY_MAX;
+ pwg_print_quality ++)
+ {
+ if (pc->num_presets[_PWG_PRINT_COLOR_MODE_COLOR][pwg_print_quality])
+ {
+ /*
+ * Copy the color options...
+ */
+
+ num_options = pc->num_presets[_PWG_PRINT_COLOR_MODE_COLOR]
+ [pwg_print_quality];
+ options = calloc(sizeof(cups_option_t), (size_t)num_options);
- num_options = pc->num_presets[_PWG_PRINT_COLOR_MODE_COLOR]
- [pwg_print_quality];
- options = calloc((size_t)num_options, sizeof(cups_option_t));
-
- if (options)
- {
- for (i = num_options, moption = options,
- coption = pc->presets[_PWG_PRINT_COLOR_MODE_COLOR]
- [pwg_print_quality];
- i > 0;
- i --, moption ++, coption ++)
+ if (options)
{
- moption->name = _cupsStrRetain(coption->name);
- moption->value = _cupsStrRetain(coption->value);
- }
+ for (i = num_options, moption = options,
+ coption = pc->presets[_PWG_PRINT_COLOR_MODE_COLOR]
+ [pwg_print_quality];
+ i > 0;
+ i --, moption ++, coption ++)
+ {
+ moption->name = _cupsStrRetain(coption->name);
+ moption->value = _cupsStrRetain(coption->value);
+ }
- pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][pwg_print_quality] =
+ pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][pwg_print_quality] =
num_options;
- pc->presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][pwg_print_quality] =
+ pc->presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][pwg_print_quality] =
options;
+ }
}
- }
- else if (pwg_print_quality != _PWG_PRINT_QUALITY_NORMAL)
- continue;
-
- /*
- * Add the grayscale option to the preset...
- */
+ else if (pwg_print_quality != _PWG_PRINT_QUALITY_NORMAL)
+ continue;
- pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][pwg_print_quality] =
- cupsAddOption(color_option, gray_choice,
- pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME]
- [pwg_print_quality],
- pc->presets[_PWG_PRINT_COLOR_MODE_MONOCHROME] +
+ /*
+ * Add the grayscale option to the preset...
+ */
+
+ pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][pwg_print_quality] =
+ cupsAddOption(color_option, gray_choice,
+ pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME]
+ [pwg_print_quality],
+ pc->presets[_PWG_PRINT_COLOR_MODE_MONOCHROME] +
pwg_print_quality);
+ }
}
}
}
+ if (!preset_added)
+ {
+ /*
+ * Auto-association of PPD file option settings with the IPP job attributes
+ * print-color-mode, print-quality, and print-content-optimize
+ *
+ * This is used to retro-fit PPD files and classic CUPS drivers into
+ * Printer Applications, which are IPP printers for the clients and so
+ * should get controlled by standard IPP attributes as far as possible
+ *
+ * Note that settings assigned to print-content-optimize are only used
+ * when printing with "high" print-quality
+ */
+
+ _ppdCacheAssignPresets(ppd, pc);
+ }
+
/*
* Copy and convert Duplex (sides) data...
*/
@@ -2052,13 +2100,996 @@
/*
+ * '_ppdCacheAssignPresets()' - Go through all the options and choices in
+ * the PPD to find out which influence
+ * color/bw, print quality, and content
+ * optimizations to assign them to the prsets
+ * so that jobs can easily be controlled with
+ * standard IPP attributes
+ */
+
+void
+_ppdCacheAssignPresets(ppd_file_t *ppd,
+ _ppd_cache_t *pc)
+{
+ /* properties and scores for each choice of the option under evaluation */
+ typedef struct choice_properties_s
+ {
+ int sets_mono, /* Does this choice switch to monochrome printing? */
+ sets_color, /* ... to color printing? */
+ sets_draft, /* ... to draft/lower quality? */
+ sets_normal, /* ... to standard/normal quality? */
+ sets_high, /* ... to high/better quality? */
+ for_photo, /* Does this choice improve photo printing? */
+ for_graphics, /* ... graphics printing? */
+ for_text, /* ... text printing? */
+ for_tg, /* ... text & graphics printing? */
+ is_default; /* Is this choice the PPD default? */
+ unsigned int res_x,/* Does this choice set resolution (0 if not)? */
+ res_y;
+ } choice_properties_t;
+ int i, j, k, l;
+ unsigned int m; /* Ratio for lowering or improving
+ resolution */
+ int pass; /* Passes to go through to find best
+ choice */
+ ppd_group_t *group; /* PPD option group */
+ ppd_option_t *option; /* PPD option */
+ int is_color; /* Is this PPD for a color printer */
+ unsigned int base_res_x = 0, /* Base resolution of the pPD file */
+ base_res_y = 0;
+ cups_page_header2_t header, /* CUPS Raster header to investigate
+ embedded code in PPD */
+ optheader; /* CUPS Raster header to investigate
+ embedded code in one PPD option */
+ int preferred_bits; /* for _cupsRasterExecPS() function
+ call */
+ ppd_attr_t *ppd_attr; /* PPD attribute */
+ int res_factor = 1; /* Weights of the scores for the */
+ int name_factor = 10; /* print quality */
+ int color_factor = 1000;
+
+ /* Do we have a color printer ? */
+ is_color = (ppd->color_device ? 1 : 0);
+
+ /* what is the base/default resolution for this PPD? */
+ ppdMarkDefaults(ppd);
+ cupsRasterInterpretPPD(&header, ppd, 0, NULL, NULL);
+ if (header.HWResolution[0] != 100 || header.HWResolution[1] != 100)
+ {
+ base_res_x = header.HWResolution[0];
+ base_res_y = header.HWResolution[1];
+ }
+ else if ((ppd_attr = ppdFindAttr(ppd, "DefaultResolution", NULL)) != NULL)
+ {
+ /* Use the PPD-defined default resolution... */
+ if (sscanf(ppd_attr->value, "%dx%d", &base_res_x, &base_res_y) == 1)
+ base_res_y = base_res_x;
+ }
+
+ /* Go through all options of the PPD file */
+ for (i = ppd->num_groups, group = ppd->groups;
+ i > 0;
+ i --, group ++)
+ {
+ /* Skip the "Installable Options" group */
+ if (_cups_strncasecmp(group->name, "Installable", 11) == 0)
+ continue;
+
+ for (j = group->num_options, option = group->options;
+ j > 0;
+ j --, option ++)
+ {
+ int sets_color_mode = 0, /* Scores for current choice */
+ sets_quality = 0,
+ sets_optimization = 0;
+ int best_mono_draft = 0, /* Best score for each preset for this
+ option */
+ best_mono_normal = 0,
+ best_mono_high = 0,
+ best_color_draft = 0,
+ best_color_normal = 0,
+ best_color_high = 0,
+ best_photo = 0,
+ best_graphics = 0,
+ best_text = 0,
+ best_tg = 0;
+ int default_ch = -1, /* Index of default choice */
+ best_mono_draft_ch = -1, /* Index of choice with best score */
+ best_mono_normal_ch = -1,
+ best_mono_high_ch = -1,
+ best_color_draft_ch = -1,
+ best_color_normal_ch = -1,
+ best_color_high_ch = -1,
+ best_photo_ch = -1,
+ best_graphics_ch = -1,
+ best_text_ch = -1,
+ best_tg_ch = -1;
+ cups_array_t *choice_properties; /* Array of properties of all choices
+ of this option */
+ choice_properties_t *properties; /* Properties of current choice */
+ char *o, /* Name of current option */
+ *c, /* Name of current choice */
+ *p; /* Pointer into string */
+ int score; /* Temp variable for score
+ calculations */
+
+ o = option->keyword;
+
+ /* Skip options which do not change color mode and quality or
+ generally do not make sense in presets */
+ if (_cups_strcasecmp(o, "PageSize") == 0 ||
+ _cups_strcasecmp(o, "PageRegion") == 0 ||
+ _cups_strcasecmp(o, "InputSlot") == 0 ||
+ _cups_strcasecmp(o, "MediaSource") == 0 ||
+ _cups_strcasecmp(o, "MediaType") == 0 ||
+ _cups_strcasecmp(o, "OutputBin") == 0 ||
+ _cups_strcasecmp(o, "Duplex") == 0 ||
+ _cups_strcasecmp(o, "JCLDuplex") == 0 ||
+ _cups_strcasecmp(o, "EFDuplex") == 0 ||
+ _cups_strcasecmp(o, "EFDuplexing") == 0 ||
+ _cups_strcasecmp(o, "ARDuplex") == 0 ||
+ _cups_strcasecmp(o, "KD03Duplex") == 0 ||
+ _cups_strcasecmp(o, "Collate") == 0)
+ continue;
+
+ /* Set members options of composite options in Foomatic to stay
+ controlled by the composite option */
+
+ /* Composite options in Foomatic are options which set a number
+ of other options, so each choice of them is the same as a
+ preset in CUPS. In addition, some PPDs in Foomatic have a
+ composite option named "PrintoutMode" with 6 choices, exactly
+ the 6 of the grid of CUPS presets, color/mono in draft,
+ mediaum, and high quality. The composite options are created
+ by hand, so they surely do for what they are intended for and
+ so they are safer as this preset auto-generation
+ algorithm. Therefore we only let the composite option be set
+ in our presets and set the member options to leave the
+ control at the composite option */
+
+ if (strstr(ppd->nickname, "Foomatic") &&
+ !strncmp(option->choices[0].choice, "From", 4) &&
+ ppdFindOption(ppd, option->choices[0].choice + 4))
+ {
+ for (k = 0; k < 2; k ++)
+ for (l = 0; l < 3; l ++)
+ if (cupsGetOption(option->choices[0].choice + 4,
+ pc->num_presets[k][l], pc->presets[k][l]))
+ pc->num_presets[k][l] =
+ cupsAddOption(o, option->choices[0].choice,
+ pc->num_presets[k][l], &(pc->presets[k][l]));
+ for (k = 0; k < 5; k ++)
+ if (cupsGetOption(option->choices[0].choice + 4,
+ pc->num_optimize_presets[k],
+ pc->optimize_presets[k]))
+ pc->num_optimize_presets[k] =
+ cupsAddOption(o, option->choices[0].choice,
+ pc->num_optimize_presets[k],
+ &(pc->optimize_presets[k]));
+ continue;
+ }
+
+ /* Array for properties of the choices */
+ choice_properties = cupsArrayNew(NULL, NULL);
+
+ /*
+ * Gather the data for each choice
+ */
+
+ for (k = 0; k < option->num_choices; k ++)
+ {
+ properties =
+ (choice_properties_t *)calloc(1, sizeof(choice_properties_t));
+
+ c = option->choices[k].choice;
+
+ /* Is this the default choice? (preferred for "normal" quality,
+ used for color if no choice name suggests being color */
+ if (strcmp(c, option->defchoice) == 0)
+ {
+ properties->is_default = 1;
+ default_ch = k;
+ }
+
+ /*
+ * Color/Gray - print-color-mode
+ */
+
+ /* If we have a color device, check whether this option sets mono or
+ color printing */
+ if (is_color)
+ {
+ if (_cups_strcasecmp(o, "CNIJSGrayScale") == 0)
+ {
+ if (_cups_strcasecmp(c, "1") == 0)
+ properties->sets_mono = 2;
+ else
+ properties->sets_color = 1;
+ }
+ else if (_cups_strcasecmp(o, "HPColorAsGray") == 0 || /* HP PostScript */
+ _cups_strcasecmp(o, "HPPJLColorAsGray") == 0) /* HP PostScript */
+ {
+ if (_cups_strcasecmp(c, "True") == 0 ||
+ _cups_strcasecmp(c, "yes") == 0)
+ properties->sets_mono = 2;
+ else
+ properties->sets_color = 1;
+ }
+ else if (_cups_strcasecmp(o, "ColorModel") == 0 ||
+ _cups_strcasecmp(o, "ColorMode") == 0 ||
+ _cups_strcasecmp(o, "OutputMode") == 0 ||
+ _cups_strcasecmp(o, "PrintoutMode") == 0 ||
+ _cups_strcasecmp(o, "ARCMode") == 0 || /* Sharp */
+ _cups_strcasestr(o, "ColorMode") ||
+ _cups_strcasecmp(o, "ColorResType") == 0 || /* Toshiba */
+ _cups_strcasestr(o, "MonoColor")) /* Brother */
+ {
+ /* Monochrome/grayscale printing */
+ if (_cups_strcasestr(c, "Mono") ||
+ _cups_strcasecmp(c, "Black") == 0 ||
+ ((p = _cups_strcasestr(c, "Black")) && _cups_strcasestr(p, "White")) ||
+ (_cups_strncasecmp(c, "BW", 2) == 0 && !isalpha(c[2])))
+ properties->sets_mono = 2;
+ else if (_cups_strcasestr(c, "Gray") ||
+ _cups_strcasestr(c, "Grey") ||
+ _cups_strcasecmp(c, "BlackOnly") == 0) /* Lexmark */
+ properties->sets_mono = 3;
+
+ /* Color printing */
+ if (((p = _cups_strcasestr(c, "CMY")) && !_cups_strcasestr(p, "Gray")) ||
+ _cups_strcasecmp(c, "ColorOnly") == 0 || /* Lexmark */
+ ((p = _cups_strcasestr(c, "Adobe")) && _cups_strcasestr(p, "RGB")))
+ properties->sets_color = 2;
+ else if (_cups_strcasestr(c, "sRGB"))
+ properties->sets_color = 4;
+ else if (_cups_strcasestr(c, "RGB") ||
+ _cups_strcasestr(c, "Color"))
+ properties->sets_color = 3;
+ }
+
+ /* This option actually sets color mode */
+ if (properties->sets_mono || properties->sets_color)
+ sets_color_mode = 1;
+ }
+
+ /*
+ * Output Quality - print-quality
+ */
+
+ /* check whether this option affects print quality or content
+ optimization */
+
+ /* Determine influence of the options and choices on the print
+ quality by their names */
+
+ /* Vendor-specific option and choice names */
+ if (_cups_strcasecmp(o, "ARCPPriority") == 0) /* Sharp */
+ {
+ if (_cups_strcasecmp(c, "Quality") == 0)
+ properties->sets_high = 10;
+ else if (_cups_strcasecmp(c, "Speed") == 0)
+ properties->sets_draft = 10;
+ }
+ else if (_cups_strcasecmp(o, "BRJpeg") == 0) /* Brother */
+ {
+ if (_cups_strcasecmp(c, "QualityPrior") == 0)
+ properties->sets_high = 10;
+ else if (_cups_strcasecmp(c, "SpeedPrior") == 0)
+ properties->sets_draft = 10;
+ }
+ else if (_cups_strcasecmp(o, "RIPrintMode") == 0) /* Ricoh & OEM */
+ {
+ if (_cups_strcasecmp(c, "1rhit") == 0)
+ properties->sets_high = 7;
+ else if (_cups_strcasecmp(c, "6rhit") == 0)
+ properties->sets_high = 10;
+ else if (_cups_strcasecmp(c, "3rhit") == 0 ||
+ _cups_strcasecmp(c, "4rhit") == 0 ||
+ _cups_strcasecmp(c, "5rhit") == 0)
+ properties->sets_draft = 10;
+ else if (_cups_strcasecmp(c, "0rhit") == 0)
+ properties->sets_normal = 10;
+ }
+ else if (_cups_strcasecmp(o, "EconoMode") == 0 || /* Foomatic */
+ _cups_strcasecmp(o, "EconoFast") == 0) /* Foomatic (HP PPA) */
+ {
+ if (_cups_strcasecmp(c, "Off") == 0 ||
+ _cups_strcasecmp(c, "False") == 0)
+ properties->sets_high = 1;
+ else if (_cups_strcasecmp(c, "On") == 0 ||
+ _cups_strcasecmp(c, "True") == 0 ||
+ _cups_strcasecmp(c, "Low") == 0)
+ properties->sets_draft = 10;
+ else if (_cups_strcasecmp(c, "High") == 0)
+ properties->sets_draft = 11;
+ }
+ else if (_cups_strcasestr(o, "ColorPrecision")) /* Gutenprint */
+ {
+ if (_cups_strcasecmp(c, "best") == 0)
+ properties->sets_high = 10;
+ }
+ /* Generic boolean options which enhance quality if true */
+ else if (((p = _cups_strcasestr(o, "slow")) && _cups_strcasestr(p, "dry")) ||
+ ((p = _cups_strcasestr(o, "color")) && _cups_strcasestr(p, "enhance")) ||
+ ((p = _cups_strcasestr(o, "resolution")) &&
+ !_cups_strcasestr(p, "enhance")) ||
+ _cups_strcasecmp(o, "RET") == 0 ||
+ _cups_strcasecmp(o, "Smoothing") == 0 || /* HPLIP */
+ ((p = _cups_strcasestr(o, "uni")) && _cups_strcasestr(p, "direction")))
+ {
+ if (_cups_strcasecmp(c, "True") == 0 ||
+ _cups_strcasecmp(c, "On") == 0 ||
+ _cups_strcasecmp(c, "Yes") == 0 ||
+ _cups_strcasecmp(c, "1") == 0 ||
+ _cups_strcasecmp(c, "Medium") == 0) /* Resolution Enhancement/RET (HP)*/
+ properties->sets_high = 3;
+ else if (_cups_strcasecmp(c, "False") == 0 ||
+ _cups_strcasecmp(c, "Off") == 0 ||
+ _cups_strcasecmp(c, "No") == 0 ||
+ _cups_strcasecmp(c, "0") == 0)
+ properties->sets_draft = 3;
+ }
+ /* Generic boolean options which reduce quality if true */
+ else if (_cups_strcasestr(o, "draft") ||
+ _cups_strcasestr(o, "economy") ||
+ ((p = _cups_strcasestr(o, "eco")) && _cups_strcasestr(p, "mode")) ||
+ ((p = _cups_strcasestr(o, "toner")) && _cups_strcasestr(p, "sav")) ||
+ ((p = _cups_strcasestr(o, "bi")) && _cups_strcasestr(p, "direction")) ||
+ _cups_strcasecmp(o, "EcoBlack") == 0 || /* Foomatic (Alps) */
+ _cups_strcasecmp(o, "bidi") == 0 ||
+ _cups_strcasecmp(o, "bi-di") == 0)
+ {
+ if (_cups_strcasecmp(c, "True") == 0 ||
+ _cups_strcasecmp(c, "On") == 0 ||
+ _cups_strcasecmp(c, "Yes") == 0 ||
+ _cups_strcasecmp(c, "1") == 0 ||
+ _cups_strcasecmp(c, "Medium") == 0) /* EconomyMode (Brother) */
+ properties->sets_draft = 3;
+ else if (_cups_strcasecmp(c, "False") == 0 ||
+ _cups_strcasecmp(c, "Off") == 0 ||
+ _cups_strcasecmp(c, "No") == 0 ||
+ _cups_strcasecmp(c, "0") == 0)
+ properties->sets_high = 3;
+ }
+ /* Generic enumerated choice option and choice names */
+ else if (_cups_strcasecmp(o, "ColorModel") == 0 ||
+ _cups_strcasecmp(o, "ColorMode") == 0 ||
+ _cups_strcasecmp(o, "OutputMode") == 0 || /* HPLIP hpcups */
+ _cups_strcasecmp(o, "PrintoutMode") == 0 || /* Foomatic */
+ _cups_strcasecmp(o, "PrintQuality") == 0 ||
+ _cups_strcasecmp(o, "PrintMode") == 0 ||
+ _cups_strcasestr(o, "ColorMode") ||
+ _cups_strcasestr(o, "HalfTone") || /* HPLIP */
+ _cups_strcasecmp(o, "ColorResType") == 0 || /* Toshiba */
+ _cups_strcasestr(o, "MonoColor") || /* Brother */
+ _cups_strcasestr(o, "Quality") ||
+ _cups_strcasestr(o, "Resolution") ||
+ _cups_strcasestr(o, "Precision") || /* ex. stpColorPrecision
+ in Gutenprint */
+ _cups_strcasestr(o, "PrintingDirection")) /* Gutenprint */
+ {
+ /* High quality */
+ if (_cups_strcasecmp(c, "Quality") == 0 ||
+ _cups_strcasecmp(c, "5") == 0)
+ properties->sets_high = 1;
+ else if (_cups_strcasestr(c, "Photo") ||
+ _cups_strcasestr(c, "Enhance") ||
+ _cups_strcasestr(c, "slow") ||
+ _cups_strncasecmp(c, "ProRes", 6) == 0 || /* HPLIP */
+ _cups_strncasecmp(c, "ImageREt", 8) == 0 || /* HPLIP */
+ ((p = _cups_strcasestr(c, "low")) && _cups_strcasestr(p, "speed")))
+ properties->sets_high = 2;
+ else if (_cups_strcasestr(c, "fine") ||
+ _cups_strcasestr(c, "deep") ||
+ ((p = _cups_strcasestr(c, "high")) && !_cups_strcasestr(p, "speed")) ||
+ _cups_strcasestr(c, "HQ") ||
+ _cups_strcasecmp(c, "ProRes600") == 0 || /* HPLIP */
+ _cups_strcasecmp(c, "ImageREt1200") == 0 || /* HPLIP */
+ _cups_strcasecmp(c, "Enhanced") == 0)
+ properties->sets_high = 3;
+ else if (_cups_strcasestr(c, "best") ||
+ _cups_strcasecmp(c, "high") == 0 ||
+ _cups_strcasecmp(c, "fine") == 0 ||
+ _cups_strcasecmp(c, "HQ") == 0 ||
+ _cups_strcasecmp(c, "CMYGray") == 0 || /* HPLIP */
+ _cups_strcasecmp(c, "ProRes1200") == 0 || /* HPLIP */
+ _cups_strcasecmp(c, "ImageREt2400") == 0 || /* HPLIP */
+ _cups_strcasestr(c, "unidir"))
+ properties->sets_high = 4;
+ else if (_cups_strcasecmp(c, "best") == 0 ||
+ _cups_strcasecmp(c, "ProRes2400") == 0 || /* HPLIP */
+ _cups_strcasecmp(c, "monolowdetail") == 0) /* Toshiba */
+ properties->sets_high = 5;
+
+ /* Low/Draft quality */
+ if (_cups_strcasecmp(c, "monolowdetail") == 0 || /* Toshiba */
+ _cups_strcasecmp(c, "3") == 0)
+ properties->sets_draft = 1;
+ else if (((p = _cups_strcasestr(c, "fast")) && _cups_strcasestr(p, "draft")) ||
+ ((p = _cups_strcasestr(c, "high")) && _cups_strcasestr(p, "speed")) ||
+ (_cups_strcasestr(c, "speed") && !_cups_strcasestr(c, "low")))
+ properties->sets_draft = 2;
+ else if (_cups_strcasestr(c, "quick") ||
+ (_cups_strcasestr(c, "fast") &&
+ !(_cups_strncasecmp(c, "FastRes", 7) == 0 && isdigit(*(c + 7)))))
+ /* HPLIP has FastRes600, FastRes1200, ... which are not draft */
+ properties->sets_draft = 3;
+ else if (_cups_strcasecmp(c, "quick") == 0 ||
+ _cups_strcasecmp(c, "fast") == 0 ||
+ _cups_strcasestr(c, "draft") ||
+ (_cups_strcasestr(c, "low") && !_cups_strcasestr(c, "slow")) ||
+ _cups_strcasestr(c, "coarse"))
+ properties->sets_draft = 4;
+ else if (_cups_strcasecmp(c, "draft") == 0 ||
+ _cups_strcasecmp(c, "low") == 0 ||
+ _cups_strcasecmp(c, "coarse") == 0 ||
+ _cups_strcasestr(c, "bidir"))
+ properties->sets_draft = 5;
+
+ /* Use high or low quality but not the extremes */
+ if (_cups_strcasestr(c, "ultra") ||
+ _cups_strcasestr(c, "very") ||
+ _cups_strcasestr(c, "super"))
+ {
+ if (properties->sets_high > 1)
+ properties->sets_high --;
+ if (properties->sets_draft > 1)
+ properties->sets_draft --;
+ }
+
+ /* Normal quality */
+ if (_cups_strcasestr(c, "automatic") ||
+ _cups_strcasecmp(c, "none") == 0 ||
+ _cups_strcasecmp(c, "4") == 0 ||
+ _cups_strcasecmp(c, "FastRes1200") == 0) /* HPLIP */
+ properties->sets_normal = 1;
+ else if (_cups_strcasestr(c, "normal") ||
+ _cups_strcasestr(c, "standard") ||
+ _cups_strcasestr(c, "default") ||
+ _cups_strcasecmp(c, "FastRes600") == 0) /* HPLIP */
+ properties->sets_normal = 2;
+ else if (_cups_strcasecmp(c, "normal") == 0 ||
+ _cups_strcasecmp(c, "standard") == 0 ||
+ _cups_strcasecmp(c, "default") == 0)
+ properties->sets_normal = 4;
+ }
+
+ /* Apply the weight factor for option/choice-name-related scores */
+ properties->sets_high *= name_factor;
+ properties->sets_draft *= name_factor;
+ properties->sets_normal *= name_factor;
+
+ /* Determine influence of the options and choices on the print
+ quality by how they change the output resolution compared to
+ the base/default resolution */
+ if (base_res_x && base_res_y)
+ {
+ /* First, analyse the code snippet (PostScript, PJL) assigned
+ to each choice of the option whether it sets resolution */
+ if (option->choices[k].code && option->choices[k].code[0])
+ {
+ /* Assume code to be PostScript (also used for CUPS Raster) */
+ preferred_bits = 0;
+ optheader = header;
+ if (_cupsRasterExecPS(&optheader, &preferred_bits,
+ option->choices[k].code) == 0)
+ {
+ properties->res_x = optheader.HWResolution[0];
+ properties->res_y = optheader.HWResolution[1];
+ }
+ else
+ properties->res_x = properties->res_y = 0; /* invalid */
+ if (properties->res_x == 0 || properties->res_y == 0)
+ {
+ /* Now try PJL */
+ if ((p = strstr(option->choices[k].code, "SET")) &&
+ isspace(*(p + 3)) && (p = strstr(p + 4, "RESOLUTION=")))
+ {
+ p += 11;
+ if (sscanf(p, "%dX%d",
+ &(properties->res_x), &(properties->res_y)) == 1)
+ properties->res_y = properties->res_x;
+ }
+ }
+ if (properties->res_x == 100 && properties->res_y == 100)
+ properties->res_x = properties->res_y = 0; /* Code does not
+ set resolution */
+ }
+ else
+ properties->res_x = properties->res_y = 0; /* invalid */
+
+ /* Then parse the choice name whether it contains a
+ resolution value (Must have "dpi", as otherwise can be
+ something else, like a page size */
+ if ((properties->res_x == 0 || properties->res_y == 0) &&
+ (p = _cups_strcasestr(c, "dpi")) != NULL)
+ {
+ if (p > c)
+ {
+ p --;
+ while (p > c && isspace(*p))
+ p --;
+ if (p > c && isdigit(*p))
+ {
+ char x;
+ while (p > c && isdigit(*p))
+ p --;
+ if (p > c && (*p == 'x' || *p == 'X'))
+ p --;
+ while (p > c && isdigit(*p))
+ p --;
+ while (!isdigit(*p))
+ p ++;
+ if (sscanf(p, "%d%c%d",
+ &(properties->res_x), &x, &(properties->res_y)) == 2)
+ properties->res_y = properties->res_x;
+ }
+ }
+ }
+
+ if (properties->res_x != 0 && properties->res_y != 0)
+ {
+ /* Choice suggests to set the resolution */
+ /* Raising resolution compared to default? */
+ m = (properties->res_x * properties->res_y) /
+ (base_res_x * base_res_y);
+ /* No or small change -> Normal quality */
+ if (m == 1)
+ properties->sets_normal += res_factor * 4;
+ /* At least double the pixels -> High quality */
+ else if (m == 2)
+ properties->sets_high += res_factor * 3;
+ else if (m > 2 && m <= 8)
+ properties->sets_high += res_factor * 4;
+ else if (m > 8 && m <= 32)
+ properties->sets_high += res_factor * 2;
+ else if (m > 32)
+ properties->sets_high += res_factor * 1;
+ else if (m < 1)
+ {
+ /* Reducing resolution compared to default? */
+ m = (base_res_x * base_res_y) /
+ (properties->res_x * properties->res_y);
+ /* No or small change -> Normal quality */
+ if (m == 1)
+ properties->sets_normal += res_factor * 1;
+ /* At most half the pixels -> Draft quality */
+ else if (m == 2)
+ properties->sets_draft += res_factor * 3;
+ else if (m > 2 && m < 8)
+ properties->sets_draft += res_factor * 4;
+ else if (m >= 8 && m < 32)
+ properties->sets_draft += res_factor * 2;
+ else if (m >= 32)
+ properties->sets_draft += res_factor * 1;
+ }
+ }
+ }
+
+ /* This option actually sets print quality */
+ if (properties->sets_draft || properties->sets_high)
+ sets_quality = 1;
+
+ /* Add the properties of this choice */
+ cupsArrayAdd(choice_properties, properties);
+ }
+
+ /*
+ * Find the best choice for each field of the color/quality preset
+ * grid
+ */
+
+ for (pass = 0; pass < 3; pass ++)
+ {
+ for (k = 0; k < option->num_choices; k ++)
+ {
+ properties = cupsArrayIndex(choice_properties, k);
+
+ /* presets[0][0]: Mono/Draft */
+ if (best_mono_draft >= 0 &&
+ !properties->sets_color &&
+ (!properties->sets_high || pass > 0))
+ {
+ score = color_factor * properties->sets_mono +
+ properties->sets_draft;
+ if (score > best_mono_draft)
+ {
+ best_mono_draft = score;
+ best_mono_draft_ch = k;
+ }
+ }
+
+ /* presets[0][1]: Mono/Normal */
+ if (best_mono_normal >= 0 &&
+ !properties->sets_color &&
+ (!properties->sets_draft || pass > 1) &&
+ (!properties->sets_high || pass > 0))
+ {
+ score = color_factor * properties->sets_mono +
+ properties->sets_normal;
+ if (score > best_mono_normal)
+ {
+ best_mono_normal = score;
+ best_mono_normal_ch = k;
+ }
+ }
+
+ /* presets[0][2]: Mono/High */
+ if (best_mono_high >= 0 &&
+ !properties->sets_color &&
+ (!properties->sets_draft || pass > 0))
+ {
+ score = color_factor * properties->sets_mono +
+ properties->sets_high;
+ if (score > best_mono_high)
+ {
+ best_mono_high = score;
+ best_mono_high_ch = k;
+ }
+ }
+
+ /* presets[1][0]: Color/Draft */
+ if (best_color_draft >= 0 &&
+ !properties->sets_mono &&
+ (!properties->sets_high || pass > 0))
+ {
+ score = color_factor * properties->sets_color +
+ properties->sets_draft;
+ if (score > best_color_draft)
+ {
+ best_color_draft = score;
+ best_color_draft_ch = k;
+ }
+ }
+
+ /* presets[1][1]: Color/Normal */
+ if (best_color_normal >= 0 &&
+ !properties->sets_mono &&
+ (!properties->sets_draft || pass > 1) &&
+ (!properties->sets_high || pass > 0))
+ {
+ score = color_factor * properties->sets_color +
+ properties->sets_normal;
+ if (score > best_color_normal)
+ {
+ best_color_normal = score;
+ best_color_normal_ch = k;
+ }
+ }
+
+ /* presets[1][2]: Color/High */
+ if (best_color_high >= 0 &&
+ !properties->sets_mono &&
+ (!properties->sets_draft || pass > 0))
+ {
+ score = color_factor * properties->sets_color +
+ properties->sets_high;
+ if (score > best_color_high)
+ {
+ best_color_high = score;
+ best_color_high_ch = k;
+ }
+ }
+ }
+ /* Block next passes for the presets where we are done */
+ if (best_mono_draft_ch >= 0)
+ best_mono_draft = -1;
+ if (best_mono_normal_ch >= 0)
+ best_mono_normal = -1;
+ if (best_mono_high_ch >= 0)
+ best_mono_high = -1;
+ if (best_color_draft_ch >= 0)
+ best_color_draft = -1;
+ if (best_color_normal_ch >= 0)
+ best_color_normal = -1;
+ if (best_color_high_ch >= 0)
+ best_color_high = -1;
+ }
+
+ /*
+ * Content Optimization - print-content-optimize
+ */
+
+ for (k = 0; k < option->num_choices; k ++)
+ {
+ properties = cupsArrayIndex(choice_properties, k);
+ c = option->choices[k].choice;
+
+ /* Vendor-specific options */
+ if (_cups_strcasecmp(o, "ARCOType") == 0) /* Sharp */
+ {
+ if (_cups_strcasecmp(c, "COTDrawing") == 0)
+ {
+ properties->for_text = 3;
+ properties->for_graphics = 2;
+ properties->for_tg = 2;
+ }
+ else if (_cups_strcasecmp(c, "COTGraphics") == 0)
+ {
+ properties->for_graphics = 3;
+ properties->for_tg = 3;
+ }
+ else if (_cups_strcasecmp(c, "COTPhoto") == 0)
+ properties->for_photo = 3;
+ }
+ else if (_cups_strcasecmp(o, "HPRGBEmulation") == 0) /* HP */
+ {
+ if (_cups_strcasecmp(c, "DefaultSRGB") == 0)
+ properties->for_text = 3;
+ else if (_cups_strcasecmp(c, "VividSRGB") == 0)
+ {
+ properties->for_graphics = 3;
+ properties->for_tg = 3;
+ }
+ else if (_cups_strcasecmp(c, "PhotoSRGB") == 0)
+ properties->for_photo = 3;
+ }
+ else
+ /* Generic choice names */
+ {
+ if (_cups_strcasestr(c, "photo"))
+ properties->for_photo = 6;
+ else if (_cups_strcasecmp(c, "photo") == 0)
+ properties->for_photo = 7;
+
+ if (_cups_strcasestr(c, "graphic"))
+ properties->for_graphics = 6;
+ else if (_cups_strcasecmp(c, "graphic") == 0 ||
+ _cups_strcasecmp(c, "graphics") == 0)
+ properties->for_graphics = 7;
+
+ if (_cups_strcasestr(c, "text"))
+ {
+ if (_cups_strcasestr(c, "graphic"))
+ properties->for_tg = 7;
+ else
+ properties->for_text = 6;
+ }
+ else if (_cups_strcasecmp(c, "text") == 0)
+ properties->for_text = 7;
+
+ if (_cups_strcasestr(c, "presentation"))
+ {
+ properties->for_text = 4;
+ properties->for_graphics = 4;
+ properties->for_tg = 4;
+ }
+ else if (_cups_strcasecmp(c, "presentation") == 0)
+ {
+ properties->for_text = 5;
+ properties->for_graphics = 5;
+ properties->for_tg = 5;
+ }
+
+ if (_cups_strcasestr(c, "lineart"))
+ {
+ properties->for_graphics = 2;
+ properties->for_tg = 2;
+ }
+ else if (_cups_strcasecmp(c, "lineart") == 0)
+ {
+ properties->for_graphics = 3;
+ properties->for_tg = 3;
+ }
+
+ if (_cups_strcasestr(c, "drawing"))
+ {
+ properties->for_graphics = 4;
+ properties->for_tg = 4;
+ }
+ else if (_cups_strcasecmp(c, "drawing") == 0)
+ {
+ properties->for_graphics = 5;
+ properties->for_tg = 5;
+ }
+
+ if (_cups_strcasestr(c, "natural"))
+ properties->for_photo = 2;
+ else if (_cups_strcasecmp(c, "natural") == 0)
+ properties->for_photo = 3;
+
+ if (_cups_strcasestr(c, "vivid"))
+ {
+ properties->for_text = 2;
+ properties->for_graphics = 2;
+ properties->for_tg = 2;
+ }
+ else if (_cups_strcasecmp(c, "vivid") == 0)
+ {
+ properties->for_text = 3;
+ properties->for_graphics = 3;
+ properties->for_tg = 3;
+ }
+ }
+
+ /* We apply these optimizations only in high quality mode
+ therefore we prefer settings for high quality */
+ if (properties->sets_high && !properties->sets_draft)
+ {
+ if (properties->for_photo)
+ properties->for_photo += 10;
+ if (properties->for_graphics)
+ properties->for_graphics += 10;
+ if (properties->for_text)
+ properties->for_text += 10;
+ if (properties->for_tg)
+ properties->for_tg += 10;
+ }
+
+ /*
+ * Find the best choice for each field of the content optimize presets
+ */
+
+ /* Find best choice for each task */
+ /* optimize_presets[1]: Photo */
+ if (properties->for_photo > best_photo)
+ {
+ best_photo = properties->for_photo;
+ best_photo_ch = k;
+ }
+ /* optimize_presets[2]: Graphics */
+ if (properties->for_graphics > best_graphics)
+ {
+ best_graphics = properties->for_graphics;
+ best_graphics_ch = k;
+ }
+ /* optimize_presets[3]: Text */
+ if (properties->for_text > best_text)
+ {
+ best_text = properties->for_text;
+ best_text_ch = k;
+ }
+ /* optimize_presets[4]: Text and Graphics */
+ if (properties->for_tg > best_tg)
+ {
+ best_tg = properties->for_tg;
+ best_tg_ch = k;
+ }
+
+ /* This option actually does content optimization */
+ if (properties->for_text || properties->for_graphics ||
+ properties->for_tg || properties->for_photo)
+ sets_optimization = 1;
+ }
+
+ /*
+ * Fill in the presets
+ */
+
+ if (sets_color_mode || sets_quality)
+ {
+ /* presets[0][0]: Mono/Draft */
+ if (best_mono_draft_ch < 0)
+ best_mono_draft_ch = default_ch;
+ if (best_mono_draft_ch >= 0)
+ pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME]
+ [_PWG_PRINT_QUALITY_DRAFT] =
+ cupsAddOption(o, option->choices[best_mono_draft_ch].choice,
+ pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME]
+ [_PWG_PRINT_QUALITY_DRAFT],
+ &(pc->presets[_PWG_PRINT_COLOR_MODE_MONOCHROME]
+ [_PWG_PRINT_QUALITY_DRAFT]));
+
+ /* presets[0][1]: Mono/Normal */
+ if (best_mono_normal_ch < 0)
+ best_mono_normal_ch = default_ch;
+ if (best_mono_normal_ch >= 0)
+ pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME]
+ [_PWG_PRINT_QUALITY_NORMAL] =
+ cupsAddOption(o, option->choices[best_mono_normal_ch].choice,
+ pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME]
+ [_PWG_PRINT_QUALITY_NORMAL],
+ &(pc->presets[_PWG_PRINT_COLOR_MODE_MONOCHROME]
+ [_PWG_PRINT_QUALITY_NORMAL]));
+
+ /* presets[0][2]: Mono/High */
+ if (best_mono_high_ch < 0)
+ best_mono_high_ch = default_ch;
+ if (best_mono_high_ch >= 0)
+ pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME]
+ [_PWG_PRINT_QUALITY_HIGH] =
+ cupsAddOption(o, option->choices[best_mono_high_ch].choice,
+ pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME]
+ [_PWG_PRINT_QUALITY_HIGH],
+ &(pc->presets[_PWG_PRINT_COLOR_MODE_MONOCHROME]
+ [_PWG_PRINT_QUALITY_HIGH]));
+
+ /* presets[1][0]: Color/Draft */
+ if (best_color_draft_ch < 0)
+ best_color_draft_ch = default_ch;
+ if (best_color_draft_ch >= 0)
+ pc->num_presets[_PWG_PRINT_COLOR_MODE_COLOR]
+ [_PWG_PRINT_QUALITY_DRAFT] =
+ cupsAddOption(o, option->choices[best_color_draft_ch].choice,
+ pc->num_presets[_PWG_PRINT_COLOR_MODE_COLOR]
+ [_PWG_PRINT_QUALITY_DRAFT],
+ &(pc->presets[_PWG_PRINT_COLOR_MODE_COLOR]
+ [_PWG_PRINT_QUALITY_DRAFT]));
+
+ /* presets[1][1]: Color/Normal */
+ if (best_color_normal_ch < 0)
+ best_color_normal_ch = default_ch;
+ if (best_color_normal_ch >= 0)
+ pc->num_presets[_PWG_PRINT_COLOR_MODE_COLOR]
+ [_PWG_PRINT_QUALITY_NORMAL] =
+ cupsAddOption(o, option->choices[best_color_normal_ch].choice,
+ pc->num_presets[_PWG_PRINT_COLOR_MODE_COLOR]
+ [_PWG_PRINT_QUALITY_NORMAL],
+ &(pc->presets[_PWG_PRINT_COLOR_MODE_COLOR]
+ [_PWG_PRINT_QUALITY_NORMAL]));
+
+ /* presets[1][2]: Color/High */
+ if (best_color_high_ch < 0)
+ best_color_high_ch = default_ch;
+ if (best_color_high_ch >= 0)
+ pc->num_presets[_PWG_PRINT_COLOR_MODE_COLOR]
+ [_PWG_PRINT_QUALITY_HIGH] =
+ cupsAddOption(o, option->choices[best_color_high_ch].choice,
+ pc->num_presets[_PWG_PRINT_COLOR_MODE_COLOR]
+ [_PWG_PRINT_QUALITY_HIGH],
+ &(pc->presets[_PWG_PRINT_COLOR_MODE_COLOR]
+ [_PWG_PRINT_QUALITY_HIGH]));
+
+ }
+
+ if (sets_optimization)
+ {
+
+ /* optimize_presets[1]: Photo */
+ if (best_photo_ch >= 0)
+ pc->num_optimize_presets[_PWG_PRINT_CONTENT_OPTIMIZE_PHOTO] =
+ cupsAddOption
+ (o, option->choices[best_photo_ch].choice,
+ pc->num_optimize_presets[_PWG_PRINT_CONTENT_OPTIMIZE_PHOTO],
+ &(pc->optimize_presets[_PWG_PRINT_CONTENT_OPTIMIZE_PHOTO]));
+
+ /* optimize_presets[2]: Graphics */
+ if (best_graphics_ch >= 0)
+ pc->num_optimize_presets[_PWG_PRINT_CONTENT_OPTIMIZE_GRAPHICS] =
+ cupsAddOption
+ (o, option->choices[best_graphics_ch].choice,
+ pc->num_optimize_presets
+ [_PWG_PRINT_CONTENT_OPTIMIZE_GRAPHICS],
+ &(pc->optimize_presets
+ [_PWG_PRINT_CONTENT_OPTIMIZE_GRAPHICS]));
+
+ /* optimize_presets[1]: Text */
+ if (best_text_ch >= 0)
+ pc->num_optimize_presets[_PWG_PRINT_CONTENT_OPTIMIZE_TEXT] =
+ cupsAddOption
+ (o, option->choices[best_text_ch].choice,
+ pc->num_optimize_presets[_PWG_PRINT_CONTENT_OPTIMIZE_TEXT],
+ &(pc->optimize_presets[_PWG_PRINT_CONTENT_OPTIMIZE_TEXT]));
+
+ /* optimize_presets[1]: Text and Graphics */
+ if (best_tg_ch >= 0)
+ pc->num_optimize_presets
+ [_PWG_PRINT_CONTENT_OPTIMIZE_TEXT_AND_GRAPHICS] =
+ cupsAddOption
+ (o, option->choices[best_tg_ch].choice,
+ pc->num_optimize_presets
+ [_PWG_PRINT_CONTENT_OPTIMIZE_TEXT_AND_GRAPHICS],
+ &(pc->optimize_presets
+ [_PWG_PRINT_CONTENT_OPTIMIZE_TEXT_AND_GRAPHICS]));
+
+ }
+
+ for (k = 0; k < option->num_choices; k ++)
+ free(cupsArrayIndex(choice_properties, k));
+ cupsArrayDelete(choice_properties);
+ }
+ }
+}
+
+/*
* '_ppdCacheDestroy()' - Free all memory used for PWG mapping data.
*/
void
_ppdCacheDestroy(_ppd_cache_t *pc) /* I - PPD cache and mapping data */
{
- int i; /* Looping var */
+ int i, j; /* Looping vars */
pwg_map_t *map; /* Current map */
pwg_size_t *size; /* Current size */
@@ -2137,6 +3168,15 @@
cupsArrayDelete(pc->strings);
+ for (i = _PWG_PRINT_COLOR_MODE_MONOCHROME; i < _PWG_PRINT_COLOR_MODE_MAX; i ++)
+ for (j = _PWG_PRINT_QUALITY_DRAFT; j < _PWG_PRINT_QUALITY_MAX; j ++)
+ if (pc->num_presets[i][j])
+ cupsFreeOptions(pc->num_presets[i][j], pc->presets[i][j]);
+
+ for (i = _PWG_PRINT_CONTENT_OPTIMIZE_AUTO; i < _PWG_PRINT_CONTENT_OPTIMIZE_MAX; i ++)
+ if (pc->num_optimize_presets[i])
+ cupsFreeOptions(pc->num_optimize_presets[i], pc->optimize_presets[i]);
+
free(pc);
}
@@ -3025,6 +4065,21 @@
}
/*
+ * Optimization Presets...
+ */
+
+ for (i = _PWG_PRINT_CONTENT_OPTIMIZE_AUTO; i < _PWG_PRINT_CONTENT_OPTIMIZE_MAX; i ++)
+ if (pc->num_optimize_presets[i])
+ {
+ cupsFilePrintf(fp, "OptimizePreset %d", i);
+ for (k = pc->num_optimize_presets[i], option = pc->optimize_presets[i];
+ k > 0;
+ k --, option ++)
+ cupsFilePrintf(fp, " %s=%s", option->name, option->value);
+ cupsFilePutChar(fp, '\n');
+ }
+
+ /*
* Duplex/sides...
*/
--- a/cups/ppd-private.h
+++ b/cups/ppd-private.h
@@ -36,7 +36,7 @@
* Constants...
*/
-# define _PPD_CACHE_VERSION 11 /* Version number in cache file */
+# define _PPD_CACHE_VERSION 12 /* Version number in cache file */
/*
@@ -101,6 +101,16 @@
_PWG_PRINT_QUALITY_MAX
} _pwg_print_quality_t;
+typedef enum _pwg_print_content_optimize_e /** PWG print-content-optimize **/
+{
+ _PWG_PRINT_CONTENT_OPTIMIZE_AUTO = 0, /* print-content-optimize=auto */
+ _PWG_PRINT_CONTENT_OPTIMIZE_PHOTO, /* print-content-optimize=photo */
+ _PWG_PRINT_CONTENT_OPTIMIZE_GRAPHICS, /* print-content-optimize=graphics */
+ _PWG_PRINT_CONTENT_OPTIMIZE_TEXT, /* print-content-optimize=text */
+ _PWG_PRINT_CONTENT_OPTIMIZE_TEXT_AND_GRAPHICS, /* ...=text-and-graphics */
+ _PWG_PRINT_CONTENT_OPTIMIZE_MAX
+} _pwg_print_content_optimize_t;
+
typedef struct _pwg_finishings_s /**** PWG finishings mapping data ****/
{
ipp_finishings_t value; /* finishings value */
@@ -131,6 +141,11 @@
/* Number of print-color-mode/print-quality options */
cups_option_t *presets[_PWG_PRINT_COLOR_MODE_MAX][_PWG_PRINT_QUALITY_MAX];
/* print-color-mode/print-quality options */
+ int num_optimize_presets[_PWG_PRINT_CONTENT_OPTIMIZE_MAX];
+ /* Number of print-content-optimize
+ options */
+ cups_option_t *optimize_presets[_PWG_PRINT_CONTENT_OPTIMIZE_MAX];
+ /* print-content-optimize options */
char *sides_option, /* PPD option for sides */
*sides_1sided, /* Choice for one-sided */
*sides_2sided_long, /* Choice for two-sided-long-edge */
@@ -214,6 +229,8 @@
extern const char *_pwgPageSizeForMedia(pwg_media_t *media,
char *name, size_t namesize) _CUPS_PRIVATE;
+extern void _ppdCacheAssignPresets(ppd_file_t *ppd, _ppd_cache_t *pc) _CUPS_PRIVATE;
+
/*
* C++ magic...
--- a/cups/string-private.h
+++ b/cups/string-private.h
@@ -150,6 +150,8 @@
extern int _cups_strncasecmp(const char *, const char *, size_t n) _CUPS_PRIVATE;
+extern char *_cups_strcasestr(const char *, const char *) _CUPS_PRIVATE;
+
# ifndef HAVE_STRLCAT
extern size_t _cups_strlcat(char *, const char *, size_t) _CUPS_PRIVATE;
# define strlcat _cups_strlcat
--- a/cups/string.c
+++ b/cups/string.c
@@ -671,6 +671,36 @@
return (-1);
}
+/*
+ * '_cups_strcasestr()' - Do a case-insensitive search for a sub-string.
+ */
+
+char * /* O - Pointer to found sub-string or
+ NULL if not found */
+_cups_strcasestr(const char *haystack, /* I - String in which to searh */
+ const char *needle) /* I - Sub-string */
+{
+ char cn, /* Character in needle */
+ ch; /* Character in haystack */
+ size_t len; /* Length of needle */
+
+ if ((cn = *needle++) != 0)
+ {
+ cn = _cups_tolower(cn);
+ len = strlen(needle);
+ do
+ {
+ do
+ {
+ if ((ch = *haystack++) == 0)
+ return (NULL);
+ } while (_cups_tolower(ch) != cn);
+ } while (_cups_strncasecmp(haystack, needle, len) != 0);
+ haystack --;
+ }
+ return ((char *)haystack);
+}
+
#ifndef HAVE_STRLCAT
/*
--- a/scheduler/job.c
+++ b/scheduler/job.c
@@ -3653,9 +3653,13 @@
cups_option_t *pwgppds, /* PWG->PPD options */
*pwgppd, /* Current PWG->PPD option */
*preset; /* Current preset option */
- int print_color_mode,
+ int print_color_mode = _PWG_PRINT_COLOR_MODE_COLOR,
/* Output mode (if any) */
- print_quality; /* Print quality (if any) */
+ print_quality = _PWG_PRINT_QUALITY_NORMAL,
+ /* Print quality (if any) */
+ print_content_optimize =
+ _PWG_PRINT_CONTENT_OPTIMIZE_AUTO;
+ /* Print content type (if any)*/
const char *ppd; /* PPD option choice */
int exact; /* Did we get an exact match? */
static char *options = NULL;/* Full list of options */
@@ -3677,7 +3681,7 @@
if (pc &&
!ippFindAttribute(job->attrs, "com.apple.print.DocumentTicket.PMSpoolFormat", IPP_TAG_ZERO) &&
!ippFindAttribute(job->attrs, "APPrinterPreset", IPP_TAG_ZERO) &&
- (ippFindAttribute(job->attrs, "print-color-mode", IPP_TAG_ZERO) || ippFindAttribute(job->attrs, "print-quality", IPP_TAG_ZERO) || ippFindAttribute(job->attrs, "cupsPrintQuality", IPP_TAG_ZERO)))
+ (ippFindAttribute(job->attrs, "print-color-mode", IPP_TAG_ZERO) || ippFindAttribute(job->attrs, "print-quality", IPP_TAG_ZERO) || ippFindAttribute(job->attrs, "print-content-optimize", IPP_TAG_ZERO) || ippFindAttribute(job->attrs, "cupsPrintQuality", IPP_TAG_ZERO)))
{
/*
* Map print-color-mode and print-quality to a preset...
@@ -3739,6 +3743,12 @@
}
}
+ cupsdLogJob(job, CUPSD_LOG_DEBUG,
+ "print-color-mode=%s, print-quality=%s",
+ print_color_mode == _PWG_PRINT_COLOR_MODE_MONOCHROME ?
+ "gray" : "color",
+ print_quality == _PWG_PRINT_QUALITY_DRAFT ? "draft" :
+ (print_quality == _PWG_PRINT_QUALITY_HIGH ? "high" : "normal"));
if (pc->num_presets[print_color_mode][print_quality] > 0)
{
/*
@@ -3753,7 +3763,72 @@
{
if (!ippFindAttribute(job->attrs, preset->name, IPP_TAG_ZERO))
{
- cupsdLogJob(job, CUPSD_LOG_DEBUG2, "Adding preset option %s=%s", preset->name, preset->value);
+ cupsdLogJob(job, CUPSD_LOG_DEBUG, "Adding preset option %s=%s", preset->name, preset->value);
+
+ num_pwgppds = cupsAddOption(preset->name, preset->value, num_pwgppds, &pwgppds);
+ }
+ }
+ }
+ }
+
+ if (pc &&
+ ippFindAttribute(job->attrs, "print-content-optimize", IPP_TAG_ZERO))
+ {
+ /*
+ * Map print-content-optimize to a preset...
+ */
+
+ if ((attr = ippFindAttribute(job->attrs, "print-content-optimize",
+ IPP_TAG_KEYWORD)) != NULL)
+ {
+ if (!strcmp(attr->values[0].string.text, "auto"))
+ print_content_optimize = _PWG_PRINT_CONTENT_OPTIMIZE_AUTO;
+ else if (!strcmp(attr->values[0].string.text, "photo"))
+ print_content_optimize = _PWG_PRINT_CONTENT_OPTIMIZE_PHOTO;
+ else if (!strcmp(attr->values[0].string.text, "graphics") ||
+ !strcmp(attr->values[0].string.text, "graphic"))
+ print_content_optimize = _PWG_PRINT_CONTENT_OPTIMIZE_GRAPHICS;
+ else if (!strcmp(attr->values[0].string.text, "text"))
+ print_content_optimize = _PWG_PRINT_CONTENT_OPTIMIZE_TEXT;
+ else if (!strcmp(attr->values[0].string.text, "text-and-graphics") ||
+ !strcmp(attr->values[0].string.text, "text-and-graphic"))
+ print_content_optimize = _PWG_PRINT_CONTENT_OPTIMIZE_TEXT_AND_GRAPHICS;
+ else
+ print_content_optimize = _PWG_PRINT_CONTENT_OPTIMIZE_AUTO;
+ }
+ else
+ print_content_optimize = _PWG_PRINT_CONTENT_OPTIMIZE_AUTO;
+
+ cupsdLogJob(job, CUPSD_LOG_DEBUG,
+ "print-content-optimize=%s",
+ (print_content_optimize == _PWG_PRINT_CONTENT_OPTIMIZE_AUTO ?
+ "automatic" :
+ (print_content_optimize == _PWG_PRINT_CONTENT_OPTIMIZE_PHOTO ?
+ "photo" :
+ (print_content_optimize == _PWG_PRINT_CONTENT_OPTIMIZE_GRAPHICS ?
+ "graphics" :
+ (print_content_optimize == _PWG_PRINT_CONTENT_OPTIMIZE_TEXT ?
+ "text" :
+ "text and graphics")))));
+ if (pc->num_optimize_presets[print_content_optimize] > 0)
+ {
+ /*
+ * Copy the preset options as long as the corresponding names are not
+ * already defined in the IPP request and also if it does not change
+ * the print quality preset (as long as we do not print in high quality)
+ * ...
+ */
+
+ for (i = pc->num_optimize_presets[print_content_optimize],
+ preset = pc->optimize_presets[print_content_optimize];
+ i > 0;
+ i --, preset ++)
+ {
+ if (!ippFindAttribute(job->attrs, preset->name, IPP_TAG_ZERO) &&
+ (print_quality == _PWG_PRINT_QUALITY_HIGH ||
+ cupsGetOption(preset->name, num_pwgppds, pwgppds) == NULL))
+ {
+ cupsdLogJob(job, CUPSD_LOG_DEBUG, "Adding content optimization preset option %s=%s", preset->name, preset->value);
num_pwgppds = cupsAddOption(preset->name, preset->value, num_pwgppds, &pwgppds);
}