#!@PERL@
# -*- perl -*-
# Get command line options
use Getopt::Long;
Getopt::Long::Configure("no_ignore_case", "pass_through");
GetOptions("t=s" => \$opt_t, # Template directory
"f=s" => \$opt_f, # Foomatic version
"d=s" => \@opt_d, # which Drivers?
"s" => \$opt_s, # Generate simplified data
"x" => \$opt_x); # Generate printer list
my $simplified = 0;
my $simplified_subopt = "";
my $simplified_suffix = "";
if ($opt_s) {
$simplified = 1;
$simplified_subopt = "-s";
$simplified_suffix = "-simplified";
}
my $templatedir;
$templatedir = $opt_t;
my @drivertypes = ("ijs");
exit 0 if ($#drivertypes < 0); # Nothing to be done, exit silently
# Do we have Foomatic 2.9 or newer
my $foomatic3 = ((defined($opt_f)) && ($opt_f >= 2.9));
# The following substitutions happen to the template XML files:
# @@STPVER@@ - the version number (e. g. "5.0.0-beta4")
# @@STPREL@@ - the version number (e. g. "5.0")
# @@REMAP@@ - option remappings (to shorten names)
# @@DRVNAME@@ - driver name (ie gutenprint)
# @@STPRINTERS@@ - ... clause for the driver
# @@OPTCONSTRAINTS@@ - ... object for the option
# @@ENUMVALS@@ - ... section for the enum option
# @@MINVAL@@ - minimum value for numeric setting
# @@MAXVAL@@ - maximum value for numeric setting
# @@DEFVAL@@ - default value for numeric setting
# For some things, there are option-specific root-around-n-writer
# functions. So we have a dispatch table:
#
# function arguments are: ('StpDriverOptionName')
my $funcs = { 'Model' => { 'OPTCONSTRAINTS' => \&build_model_cons,
'ENUMVALS' => \&build_model_ev },
'RenderResolution' => { 'OPTCONSTRAINTS' => \&build_resolution_cons,
'ENUMVALS' => \&build_resolution_ev },
'PrintoutMode' => { 'OPTCONSTRAINTS' =>
\&build_printoutmode_cons,
'ENUMVALS' =>
\&build_printoutmode_ev },
};
my $drivervals = { 'PageSize' => \&optmap_pagesize,
'Color' => \&optmap_color
};
my $debug = 0;
$colormap = { 'ijs' => { 'Grayscale' => 'DeviceGray',
'Color' => 'DeviceRGB',
'BlackAndWhite' =>
'DeviceGray -dBitsPerSample=1',
'RawCMYK' => 'DeviceCMYK' }
};
my $groupname_prefix = "Gutenprint";
my @parameter_class_names = (
"Printer Features",
"Output Control"
);
my @parameter_level_names = (
"Common",
"Extra 1",
"Extra 2",
"Extra 3",
"Extra 4",
"Extra 5"
);
my $option_remap = "";
my $opt_index = 0;
if (! $opt_x) {
open PIPE, "./printer_options $simplified_subopt|" or die "Cannot run printer_options: $!\n";
print STDERR "Loading options from ./printer_options $simplified_subopt...";
while() {
#print $_;
next if m!^#!;
eval $_;
}
close PIPE or die "Cannot run printer_options: $!\n";
print STDERR "done.\n";
if ($foomatic3) {
open PIPE, "./printer_margins $simplified_subopt|" or die "Cannot run printer_margins: $!\n";
print STDERR "Loading margins from ./printer_margins $simplified_subopt...";
while() {
#print $_;
next if m!^#!;
eval $_;
}
close PIPE or die "Cannot run printer_margins: $!\n";
print STDERR "done.\n";
}
}
%foomap = ();
%mapfoo = ();
$errors = 0;
open PIPE, "./printers|" or die "Cannot run printers: $!\n";
print STDERR "Loading printers from ./printers...";
while() {
#print $_;
next if m!^#!;
eval $_ or die "\nCan't parse `$_' $@\n";
}
close PIPE or die "Cannot run printers: $!\n";
die "\nCannot continue\n" if ($errors > 0);
print STDERR "done.\n";
if ($opt_x) {
my (%printer_long_name) = reverse %printer_name;
for (sort keys %printer_long_name) {
my ($pn) = $printer_long_name{$_};
next if $printer_family{$pn} eq "ps" || $printer_family{$pn} eq "raw";
printf("%s %s %s\n", $_, $pn, $foomap{$pn});
}
exit;
}
# OK, now %stpdata is a big honking thing, and %defaults is in there, too.
# Invert, to build %bar{$optionname} = [ choice1, choice2 ];
my ($a, $b, $otmp, $vtmp);
for $a (keys(%stpdata)) {
for $otmp (keys %{$stpdata{$a}}) {
for $vtmp (keys (%{$stpdata{$a}{$otmp}})) {
if (!$seen_evchoice{$otmp}{$vtmp}++) {
push (@{$ev_choices{$otmp}}, [ $vtmp,
$stpdata{$a}{$otmp}{$vtmp}]);
}
}
}
}
#print Dumper(%ev_choices);
if ($foomatic3) {
# Generate data for "PrintoutMode" option, only needed for
# Foomatic 2.9.x or newer
print STDERR "Generating data for \"PrintoutMode\" option...";
($printoutmode, $printoutmodechoices) = getprintoutmode();
print STDERR "done.\n";
# Foomatic >= 2.9: Make a list of all choice entries needed in the
# "PrintoutMode" option XML file. Note: every choice ("Draft",
# "Normal", ...) will appear several times, but with different
# strings in "". Constraints will make only the
# right choices getting into the PPD file. Assign a unique ID to
# each entry.
for $a (keys(%{$printoutmode})) {
for $vtmp (keys %{$printoutmode->{$a}}) {
my $mode = $printoutmode->{$a}{$vtmp};
if (!$seen_modes{$vtmp}{$mode}++) {
if (!defined($nums{$vtmp})) {
$nums{$vtmp} = 0;
}
$nums{$vtmp} ++;
$modes{$vtmp}{$mode} = "$vtmp-$nums{$vtmp}";
}
}
}
}
# Make list of needed Foomatic entries for the numerical options. If
# for one and the same numerical option there are printers with
# different value ranges, there must be made an extra Foomatic entry
# for each value range. Therefore the filenames of numerical options
# are numbered (eg. Contrast-1.xml).
for $a (keys(%stp_float_values)) {
for $otmp (keys %{$stp_float_values{$a}}) {
for $vtmp (keys %{$stp_float_values{$a}{$otmp}}) {
my $min = $stp_float_values{$a}{$otmp}{'MINVAL'};
my $max = $stp_float_values{$a}{$otmp}{'MAXVAL'};
my $def = $stp_float_values{$a}{$otmp}{'DEFVAL'};
# Skip options with invalid values, the library contains such
# options in the case when only one constant value is allowed
next if (($min >= $max) || ($def < $min) || ($def > $max));
my $minmax = "${min}_${max}";
if (!$seen_fnumopt{$otmp}{$minmax}++) {
if (!defined($fnums{$otmp})) {
$fnums{$otmp} = 0;
}
$fnums{$otmp} ++;
push (@floatnumopts_list, "${otmp}-$fnums{$otmp}");
$numopt_ranges{"${otmp}-$fnums{$otmp}"}{'MINVAL'} = $min;
$numopt_ranges{"${otmp}-$fnums{$otmp}"}{'MAXVAL'} = $max;
}
}
}
}
for $a (keys(%stp_int_values)) {
for $otmp (keys %{$stp_int_values{$a}}) {
for $vtmp (keys %{$stp_int_values{$a}{$otmp}}) {
my $min = $stp_int_values{$a}{$otmp}{'MINVAL'};
my $max = $stp_int_values{$a}{$otmp}{'MAXVAL'};
my $def = $stp_int_values{$a}{$otmp}{'DEFVAL'};
# Skip options with invalid values, the library contains such
# options in the case when only one constant value is allowed
next if (($min >= $max) || ($def < $min) || ($def > $max));
my $minmax = "${min}_${max}";
if (!$seen_inumopt{$otmp}{$minmax}++) {
if (!defined($inums{$otmp})) {
$inums{$otmp} = 0;
}
$inums{$otmp} ++;
push (@intnumopts_list, "${otmp}-$inums{$otmp}");
$numopt_ranges{"${otmp}-$inums{$otmp}"}{'MINVAL'} = $min;
$numopt_ranges{"${otmp}-$inums{$otmp}"}{'MAXVAL'} = $max;
}
}
}
}
for $a (keys(%stp_dimension_values)) {
for $otmp (keys %{$stp_dimension_values{$a}}) {
for $vtmp (keys %{$stp_dimension_values{$a}{$otmp}}) {
my $min = $stp_dimension_values{$a}{$otmp}{'MINVAL'};
my $max = $stp_dimension_values{$a}{$otmp}{'MAXVAL'};
my $def = $stp_dimension_values{$a}{$otmp}{'DEFVAL'};
# Skip options with invalid values, the library contains such
# options in the case when only one constant value is allowed
next if (($min >= $max) || ($def < $min) || ($def > $max));
my $minmax = "${min}_${max}";
if (!$seen_inumopt{$otmp}{$minmax}++) {
if (!defined($inums{$otmp})) {
$inums{$otmp} = 0;
}
$inums{$otmp} ++;
push (@dimensionnumopts_list, "${otmp}-$inums{$otmp}");
$numopt_ranges{"${otmp}-$inums{$otmp}"}{'MINVAL'} = $min;
$numopt_ranges{"${otmp}-$inums{$otmp}"}{'MAXVAL'} = $max;
}
}
}
}
#print join("\n", @floatnumopts_list);
#print join("\n", @intnumopts_list);
#print join("\n", @dimensionnumopts_list);
# Figure out version etc
open PIPE, "./gutenprint-version|" or die "Cannot run gutenprint-version: $!\n";
my $stpvers = ;
close PIPE or die "Cannot run gutenprint-version: $!\n";
chomp $stpvers;
open PIPE, "./gutenprint-version -|" or die "Cannot run gutenprint-version: $!\n";
my $stprel = ;
close PIPE or die "Cannot run gutenprint-version: $!\n";
chomp $stprel;
# Build clause...
my @printerlist = ();
push (@printerlist, " \n");
my $p1;
for $p1 (keys(%mapstp)) {
push (@printerlist, " \n");
for my $id (@{$mapstp{$p1}}) {
if ($foomatic3) {
# Add unprintable margins (only Foomatic 2.9.x)
push(@printerlist, " \n");
push(@printerlist, " $id\n");
push(@printerlist, " \n");
my ($cleft, $cright, $ctop, $cbottom) =
(undef, undef, undef, undef);
if (defined($imageableareas{$p1}{'Custom'})) {
$cleft = $imageableareas{$p1}{'Custom'}{'left'};
$cright = $imageableareas{$p1}{'Custom'}{'right'};
$ctop = $imageableareas{$p1}{'Custom'}{'top'};
$cbottom = $imageableareas{$p1}{'Custom'}{'bottom'};
push(@printerlist, " \n");
push(@printerlist, " \n");
push(@printerlist, " $cleft\n");
push(@printerlist, " $cright\n");
push(@printerlist, " $ctop\n");
push(@printerlist, " $cbottom\n");
push(@printerlist, " \n");
}
for my $ps (keys %{$imageableareas{$p1}}) {
next if $ps eq 'Custom'; # We have done "Custom" already
my ($left, $right, $top, $bottom, $width, $height);
$left = $imageableareas{$p1}{$ps}{'left'};
$right = $imageableareas{$p1}{$ps}{'right'};
$top = $imageableareas{$p1}{$ps}{'top'};
$bottom = $imageableareas{$p1}{$ps}{'bottom'};
$width = $imageableareas{$p1}{$ps}{'width'};
$height = $imageableareas{$p1}{$ps}{'height'};
# If the section serves for this paper size,
# do not define an
next if ((defined($cleft)) &&
($left == $cleft) &&
($right == $width - $cright) &&
($top == $height - $ctop) &&
($bottom == $cbottom));
push(@printerlist, " \n");
push(@printerlist, " \n");
if ($left != $cleft) {
push(@printerlist, " $left\n");
}
if ($right != $width - $cright) {
push(@printerlist, " $right\n");
}
if ($top != $height - $ctop) {
push(@printerlist, " $top\n");
}
if ($bottom != $cbottom) {
push(@printerlist, " $bottom" .
"\n");
}
push(@printerlist, " \n");
}
push(@printerlist, " \n");
push(@printerlist, " \n");
} else {
# Printer IDs only
push(@printerlist, " $id\n");
}
}
}
push (@printerlist, " \n");
$drivernameprefix = "gutenprint";
print STDERR "Using driver name prefix \"$drivernameprefix\"\n";
my $generalsubs = { 'STPVER' => $stpvers,
'STPREL' => $stprel,
'REMAP' => $option_remap,
'DRVNAME' => $drivernameprefix,
'STPRINTERS' => join('', @printerlist) };
my $optiongroups = { 'PageSize' => 'General',
'STP_InputSlot' => 'General',
'STP_MediaType' => 'General',
'PrintoutMode' => 'General',
'STP_RenderResolution' => 'General',
'STP_Quality' => 'General',
'Color' => 'General',
'STP_ImageType' => 'General'};
my @numericsubs = ('MINVAL', 'MAXVAL');
my $specialoutputfilenames = { 'Resolution' => 'PrinterResolution',
'RenderResolution' => 'Resolution' };
# OK, make the db directory...
mkdir "foomatic-db", 0755 or
die "Cannot create directory foomatic-db: $!\n"
unless -d "foomatic-db";
# Now do stuff, already. Do the substitution into each file...
my $tmpl;
for $drivertype (@drivertypes) {
$drivertypesuffix = "-$drivertype";
$drivertypesuffix =~ s/-gs//;
$drivertypesuffix .= "$simplified_suffix.$stprel";
my $drvname = "$drivernameprefix$drivertypesuffix";
$generalsubs->{'DRVNAME'} = $drvname;
print "Generating Foomatic data for driver \"$drvname\"...\n";
# OK, make the db heirarchy alongside the templates one...
mkdir "foomatic-db/$drvname", 0755 or
die "Cannot create directory foomatic-db/$drvname: $!\n"
unless -d "foomatic-db/$drvname";
mkdir "foomatic-db/$drvname/opt", 0755 or
die "Cannot create directory foomatic-db/$drvname/opt: $!\n"
unless -d "foomatic-db/$drvname/opt";
mkdir "foomatic-db/$drvname/driver", 0755 or
die "Cannot create directory foomatic-db/$drvname/driver: $!\n"
unless -d 'foomatic-db/$drvname/driver';
my $order = 1000;
my %numoptionorders;
# opendir TDIR, "$templatedir-$drivertype" or
# die "Cannot open templates directory: $!\n";
for $fooopt (sort(keys(%ev_choices)),
sort(@floatnumopts_list, @dimensionnumopts_list,
@intnumopts_list),
"PrintoutMode", "Model",
"RenderResolution", "gutenprint") {
# The "PrintoutMode" option is only supported by Foomatic 2.9.x or
# newer (preliminary skipped always, do not remove the
# infrastructure for "PrintoutMode", it will be re-activated later
# on)
next if ((!$foomatic3) && ($fooopt eq "PrintoutMode"));
# "x_resolution" and "y_resolution" appear in %ev_choices but are
# not option names, so skip them
next if $fooopt =~ /^[xy]_resolution$/;
my ($num_opt, $type, $tmpl);
if (member($fooopt, @floatnumopts_list)) {
$num_opt = 1;
$type = "float";
$tmpl = "NumericalOptions.xml";
} elsif (member($fooopt, @intnumopts_list)) {
$num_opt = 1;
$type = "int";
$tmpl = "NumericalOptions.xml";
} elsif (member($fooopt, @dimensionnumopts_list)) {
$num_opt = 1;
$type = "dimension";
$tmpl = "NumericalOptions.xml";
} else {
$num_opt = 0;
$type = "enum";
$tmpl = "${fooopt}.xml";
$tmpl = "OtherOptions.xml"
if ! -r "$templatedir-$drivertype/$tmpl";
}
# Remove number appended to the end of the file name of
# numerical options
my $shortname = $fooopt;
$shortname =~ s!-\d+$!!;
#my $stpopt = $argnamemap{$shortname};
#$stpopt = $shortname if ! defined ($stpopt);
my $stpopt = $shortname;
# print STDERR "Argnamemap '$fooopt' => '$stpopt'\n";
open TMPL, "$templatedir-$drivertype/$tmpl";
my @datafile = ;
close TMPL;
print STDERR "Processing \"$fooopt\"...";
my $template = join('',@datafile);
# First, do the generic substitutions.
my ($substr);
for $substr (keys(%$generalsubs)) {
my $substitution = $generalsubs->{$substr};
$template =~ s!\@\@$substr\@\@!$substitution!g;
}
# Put the options into PPD groups (Foomatic >= 2.9)
if ($foomatic3) {
my $group;
if (defined($optiongroups->{$shortname})) {
# Group names given by table (esp. "General" for special
# Options)
$group = $optiongroups->{$shortname};
} elsif (defined($param_classes{$shortname}) &&
defined($param_levels{$shortname}) &&
$parameter_class_names[$param_classes{$shortname}] &&
$parameter_level_names[$param_levels{$shortname}]) {
# Group names given by libgutenprint
$group = $groupname_prefix . " " .
$parameter_class_names[$param_classes{$shortname}] . " " .
$parameter_level_names[$param_levels{$shortname}];
# Remove the spaces (the name with spaces Foomatic will
# generate automatically)
$group =~ s! !!g;
} else {
# All the above did not assign a group name? Use
# "Miscellaneous" (Should usually not happen)
$group = "Miscellaneous";
}
my $substitution = "\n " .
$group . "";
$template =~ s!\@\@GROUP\@\@!$substitution!g;
} else {
$template =~ s!\@\@GROUP\@\@!!g;
}
# Now do the numeric substitutions
$template =~ s!\@\@TYPE\@\@!$type!g;
for $substr (@numericsubs) {
my $substitution;
my $substitution = $numopt_ranges{$fooopt}{$substr};
$template =~ s!\@\@$substr\@\@!$substitution!g;
}
# Substitutions for generic template files
my $lowercaseshortname = lc($fooopt);
my $subopt = $stpopt;
# The maximum length of the short name of an option is 31
# characters to be accepted in a PPD. The maximum length of a
# main keyword in a PPD is 40 characters, with
# "FoomaticRIPDefault" having 18, a short name of a numerical
# option (only those have "FoomaticRIPDefault" entries) is 22.
# We do not touch options whose names are short enough.
# As this problem did not occur with Gimp Print 4.2.7, none of
# the option names modified here already existed in
# Gimp-Print, all options concerned are new Gutenprint
# options. We also do not modify the parameters to be inserted
# in the GhostScript command line, so the Gutenprint library
# or the IJS server do not need to be modified.
my $maxlen = ($type eq "enum" ? 31 : 22);
my $shortopt = $subopt;
if (length($subopt) > $maxlen) {
my $nostpopt = $stpopt;
$nostpopt =~ s/^STP_//;
my $stropt = sprintf("%03d", $opt_index);
$shortopt = "STP_OPT_$stropt";
$opt_index++;
}
if ($tmpl !~ /^$fooopt/) {
$template =~ s!\@\@LOWERCASESHORTNAME\@\@!$lowercaseshortname!g;
$template =~ s!\@\@LONGNAME\@\@!$longnames{$shortname}!g;
$template =~ s!\@\@SHORTNAME\@\@!$shortopt!g;
if ($shortname =~ /^STP_Enable(.*)$/) {
$numoptionorders{$1} = $order;
$template =~ s!\@\@ORDER\@\@!$order!g;
$order += 10;
} else {
$shortname =~ /^STP_(.*)$/;
my $basename = $1;
if (my $enableorder = $numoptionorders{$basename}) {
$enableorder ++;
$template =~ s!\@\@ORDER\@\@!$enableorder!g;
} else {
$template =~ s!\@\@ORDER\@\@!$order!g;
$order += 10;
}
}
$template =~ s!\@\@SPOT\@\@!B!g;
$template =~ s!\@\@PROTO\@\@!$subopt=\%s,!g;
}
# Now do special-purpose substitutions
for $substr (keys(%{$funcs->{$fooopt}})) {
my $substitution = &{$funcs->{$fooopt}{$substr}}($stpopt);
if (defined($substitution)) {
$template =~ s!\@\@$substr\@\@!$substitution!g;
}
}
if ($template =~ m!\@\@OPTCONSTRAINTS\@\@!) {
my $substitution = ($num_opt ? build_num_cons($fooopt) :
build_cons($stpopt));
# Skip this option if there are no constraints (no printers
# using this option)
if ($substitution !~ m!!s) {
print STDERR "No printers using $fooopt\n";
next;
}
if (defined($substitution)) {
$template =~ s!\@\@OPTCONSTRAINTS\@\@!$substitution!g;
}
}
if ($template =~ m!\@\@ENUMVALS\@\@!) {
my $substitution = build_ev($stpopt);
# Skip this option if there are no choices (an enum option
# without choices does not make sense)
if ($substitution !~ m!!s) {
print STDERR "No choices for $fooopt\n";
next;
}
if (defined($substitution)) {
$template =~ s!\@\@ENUMVALS\@\@!$substitution!g;
}
}
# Any more?
grep (m!\@\@([^\@]+)\@\@!g
&& do { warn " Unknown substitution $1 in $fooopt!\n"; },
split("\n",$template));
# File name for the option XML file
$tmpl = "${fooopt}.xml" if $tmpl !~ /^$fooopt\.xml$/;
if (my $f = $specialoutputfilenames->{$fooopt}) {
$tmpl = "${f}.xml";
}
# Finally, write out the new file
# Options are under opt/
my $dbfilename = lc("foomatic-db/$drvname/opt/$drvname-$tmpl");
# Special case the actual driver file under driver/
$dbfilename = "foomatic-db/$drvname/driver/$drvname.xml"
if ($tmpl eq 'gutenprint.xml');
open NEWF, "> $dbfilename" or die "Cannot create $dbfilename: $!";
print STDERR "writing $dbfilename...";
print NEWF $template;
print STDERR "done.\n";
close NEWF;
}
closedir TDIR;
# The paper size and resolution maps must be regenerated for the next
# driver, because the "driverval"s are different for the different
# drivers. So delete the caches.
undef $pagemap;
undef %rescache;
}
# member( $a, @b ) returns 1 if $a is in @b, 0 otherwise.
sub member { my $e = shift; foreach (@_) { $e eq $_ and return 1 } 0 };
sub get_ev_shortname {
my ($val) = @_;
$val =~ s/ //g;
$val =~ s/\///g;
$val =~ s/\://g;
return $val;
}
sub get_ev_key {
my ($val, $drv) = @_;
return ("ev/$drv-" . get_ev_shortname($val));
}
sub build_ev {
my ($stpopt) = @_;
my $drvname = "$drivernameprefix$drivertypesuffix";
my @vals = ();
# OK, now for each enum_val
my $ev;
for $ev (@{$ev_choices{$stpopt}}) {
# Put in the basic choice info: ev names, etc
my $ev_longname = @$ev[1];
my $ev_shortname = @$ev[0];
my $ev_id = get_ev_key($ev_shortname, $drvname);
my $ev_driverval;
# Either call a per-option function to get the driverval, or
# just use the string choice name.
if (defined($drivervals->{$stpopt})) {
$ev_driverval = &{$drivervals->{$stpopt}}($ev_shortname);
die "Undefined driverval for option $stpopt value $ev_shortname!\n"
if (! defined($ev));
} else {
$ev_driverval = $ev_shortname;
}
# Remove "Roll" paper sizes, user has to use "Custom" instead.
next if (($stpopt eq "STP_PageSize") && ($ev_driverval eq ""));
push (@vals,
" \n",
" $ev_longname\n",
" $ev_shortname\n",
" $ev_driverval\n",
" \n",
" \n",
" \n",
" $drvname\n",
" \n");
# Build constraints for this particular choice
my $stpprn;
for $stpprn (keys(%stpdata)) {
my $fooprn;
for $fooprn (@{$mapstp{$stpprn}}) {
if ($stpdata{$stpprn}{$stpopt}{$ev_shortname}) {
# OK, this choice applies to this printer
push (@vals,
" \n",
" \n",
" $drvname\n",
" $fooprn\n",
" \n");
}
}
}
push (@vals,
" \n",
" \n");
}
return join('',
"\n",
@vals,
" \n");
}
sub build_cons {
my ($stpopt) = @_;
my $drvname = "$drivernameprefix$drivertypesuffix";
my @PNCONS = ();
# For each stp printer...
my $stpname;
for $stpname (keys(%stpdata)) {
if (0) {
print STDERR " Processing gutenprint printer $stpname...\n";
print STDERR
" There are no foomatic printers mapped to $stpname!?\n"
if !$mapstp{$stpname};
print STDERR " \%stpdata key is {$stpname}{$stpopt}\n";
}
# Add this printer to argument constraints?
if ($stpdata{$stpname}{$stpopt}) {
# What's the default value?
my $stpdef = $defaults{$stpname}{$stpopt};
# If there's no default, then this option doesn't apply to
# this printer.
if (defined($stpdef)) {
my $foodefval = get_ev_key($stpdef, $drvname);
if (0) {
print STDERR
" Default for $stpname/$stpopt is $stpdef aka $foodefval\n";
}
my $fooname;
for $fooname (@{$mapstp{$stpname}}) {
if (0) {
print STDERR
" Printer $fooname takes option $stpopt.\n";
}
push (@PNCONS,
" \n",
" $drvname\n",
" $fooname\n",
" $foodefval\n",
" \n");
}
}
}
}
return join('',
"\n",
@PNCONS,
" \n");
}
sub build_num_cons {
my ($foooptfile) = @_;
my $drvname = "$drivernameprefix$drivertypesuffix";
my @PNCONS = ();
# Do we have a float or an int option?
my $type;
if (member($foooptfile, @floatnumopts_list)) {
$type = "float";
} elsif (member($foooptfile, @dimensionnumopts_list)) {
$type = "dimension";
} else {
$type = "int";
}
# Name of the actual option
my $stpopt = $foooptfile;
$stpopt =~ s!-\d+$!!;
# For each stp printer...
my $stpname;
for $stpname (keys(%stpdata)) {
if (0) {
print STDERR " Processing gutenprint printer $stpname...\n";
print STDERR
" There are no foomatic printers mapped to $stpname!?\n"
if !$mapstp{$stpname};
}
# Add this printer to argument constraints? The printer must provide
# this option and a default value for it.
my $stpdef;
if ((defined($stpdef =
$stp_float_values{$stpname}{$stpopt}{"DEFVAL"})) ||
(defined($stpdef =
$stp_int_values{$stpname}{$stpopt}{"DEFVAL"})) ||
(defined($stpdef =
$stp_dimension_values{$stpname}{$stpopt}{"DEFVAL"}))) {
# Find minimum and maximum
my ($min, $max);
if ($type eq "float") {
$min = $stp_float_values{$stpname}{$stpopt}{"MINVAL"};
$max = $stp_float_values{$stpname}{$stpopt}{"MAXVAL"};
} elsif ($type eq "dimension") {
$min = $stp_dimension_values{$stpname}{$stpopt}{"MINVAL"};
$max = $stp_dimension_values{$stpname}{$stpopt}{"MAXVAL"};
} else {
$min = $stp_int_values{$stpname}{$stpopt}{"MINVAL"};
$max = $stp_int_values{$stpname}{$stpopt}{"MAXVAL"};
}
# Does the range of this option with this printer match
# the Foomatic option entry we are building currently?
if (defined($numopt_ranges{$foooptfile}{'MINVAL'}) &&
defined($numopt_ranges{$foooptfile}{'MAXVAL'}) &&
($min == $numopt_ranges{$foooptfile}{'MINVAL'}) &&
($max == $numopt_ranges{$foooptfile}{'MAXVAL'})) {
if (0) {
print STDERR
" Default for $stpname/$stpopt is $stpdef\n";
}
my $fooname;
for $fooname (@{$mapstp{$stpname}}) {
if (0) {
print STDERR
" Printer $fooname takes option $stpopt.\n";
}
push (@PNCONS,
" \n",
" $drvname\n",
" $fooname\n",
" $stpdef\n",
" \n");
}
}
}
}
return join('',
"\n",
@PNCONS,
" \n");
}
sub optmap_pagesize {
my ($value) = @_;
if (!defined $pagemap) {
open PUTIL, "./paper_sizes |" or die "Cannot run paper_sizes: $!\n";
while () {
chomp;
$_ =~ m!^\s*(.+\S)\s+([0-9]+)\s+([0-9]+)\s*$!;
my ($name, $width, $height) = ($1, $2, $3);
if (($width > 0 and $height > 0) or
($name eq "Custom")) {
$pagemap->{$name} = "-dDEVICEWIDTHPOINTS=$width -dDEVICEHEIGHTPOINTS=$height";
# print STDERR "PageSize '$name' driverval '$width $height'\n";
}
}
close PUTIL;
}
return $pagemap->{$value}
}
sub optmap_color {
my ($value) = @_;
if (defined $colormap->{$drivertype}{$value}) {
return $colormap->{$drivertype}{$value};
} else {
die "Cannot map output type '$value'\n";
}
}
sub build_model_cons {
my ($stpopt) = @_;
my $drvname = "$drivernameprefix$drivertypesuffix";
# OK, this is funky. For each stp model, we have a choice. That
# choice is valid for only the foo printers that correspond. For
# any given foo printer, there is *exactly one* available choice.
# The defval is the one available choice. Backends and
# applications do not show options with only one choice; they just
# select that choice. So we don't bother to make pretty option
# names or anything.
#
# See also build_model_ev()
my @PNCONS = ();
# For each stp printer...
my $stpname;
for $stpname (keys(%mapstp)) {
# For each possible foo name
my $fooname;
for $fooname (@{$mapstp{$stpname}}) {
# What's the default value?
my $foodefval = get_ev_key($stpname, $drvname);
push (@PNCONS,
" \n",
" $drvname\n",
" $fooname\n",
" $foodefval\n",
" \n");
}
}
return join('',
"\n",
@PNCONS,
" \n");
}
# See build_model_cons, above.
sub build_model_ev {
my ($stpopt) = @_;
my $drvname = "$drivernameprefix$drivertypesuffix";
my @vals = ();
# OK, now for each enum_val
my $ev;
for $ev (keys(%mapstp)) {
# Put in the basic choice info: ev names, etc
my $ev_shortname = $ev;
my $ev_longname = $printer_name{$ev};
my $make = $printer_make{$ev};
my $ev_shortname = get_ev_shortname($ev);
my $ev_id = get_ev_key($ev, $drvname);
my $ev_driverval;
$ev_driverval = "-sDeviceManufacturer=$make -sDeviceModel=$ev";
push (@vals,
" \n",
" $ev_longname\n",
" $ev_shortname\n",
" $ev_driverval\n",
" \n",
" \n",
" \n",
" $drvname\n",
" \n",
" \n",
);
# This stp Model value applies only to mapped foo printers
my $fooprn;
for $fooprn (@{$mapstp{$ev}}) {
# OK, this choice applies to this enum
push (@vals,
" \n",
" \n",
" $drvname\n",
" $fooprn\n",
" \n");
}
push (@vals,
" \n",
" \n");
}
return join('',
"\n",
@vals,
" \n");
}
# Stuff for Resolution.
#
# printer_options gives us Quality information. We examine this to
# determine what to do for the gs resolution argument.
sub compute_resolutions {
my ($stpname) = @_;
my $drvname = "$drivernameprefix$drivertypesuffix";
if (!defined($rescache{$stpname})) {
my @reslist = ();
my %hash;
my $defval;
my $qual;
for $qual (keys(%{$stpdata{$stpname}{'STP_Resolution'}})) {
my ($x) = $stpdata{$stpname}{'x_resolution'}{$qual};
my ($y) = $stpdata{$stpname}{'y_resolution'}{$qual};
my $r = {'x' => $x,
'y' => $y,
'driverval' => "${x}x${y}",
'ev_key' => get_ev_key("res-$x-$y", $drvname)
};
push (@reslist, $r);
# Default?
$defval = get_ev_key("res-$x-$y", $drvname)
if ($qual eq $defaults{$stpname}{'STP_Resolution'});
# Note that this resolution value exists
$resolutions{"$x $y"} = { 'x' => $x,
'y' => $y };
# Note that this printer takes this resolution
$hash{$x}{$y} = 1;
}
$rescache{$stpname}{'list'} = \@reslist;
$rescache{$stpname}{'defval'} = $defval;
$rescache{$stpname}{'takesit'} = \%hash;
}
return $rescache{$stpname};
}
sub do_all_res {
my $n;
for $n (keys(%mapstp)) {
compute_resolutions($n);
}
}
sub build_resolution_ev {
my ($stpopt) = @_;
my $drvname = "$drivernameprefix$drivertypesuffix";
my @vals = ();
do_all_res();
# OK, now for each possible resolution...
my $ev;
for $ev (keys(%resolutions)) {
my ($x, $y) = ($resolutions{$ev}{'x'}, $resolutions{$ev}{'y'});
# Put in the basic choice info: ev names, etc
my $ev_longname = "$x x $y dpi";
my $ev_shortname = get_ev_shortname($ev_longname);
my $ev_id = get_ev_key("res-$x-$y", $drvname);
my $ev_driverval = "${x}x${y}";
push (@vals,
" \n",
" $ev_longname\n",
" $ev_shortname\n",
" $ev_driverval\n",
" \n",
" \n",
" \n",
" $drvname\n",
" \n",
" \n",
);
# Now, for each printer, put in a constraint if this
# resolution makes sense or not...
my $stpprn;
for $stpprn (keys(%mapstp)) {
my $resobj = compute_resolutions($stpprn);
my $takesit = $resobj->{'takesit'}{$x}{$y};
if ($takesit) {
my $fooprn;
for $fooprn (@{$mapstp{$stpprn}}) {
# print STDERR "Printer $fooprn $stpprn uses ${x}x$y\n";
# OK, this choice applies to this enum
push (@vals,
" \n",
" $drvname\n",
" $fooprn\n",
" \n");
}
}
}
push (@vals,
" \n",
" \n");
}
return join('',
"\n",
@vals,
" \n");
}
sub build_resolution_cons {
my ($stpopt) = @_;
my $drvname = "$drivernameprefix$drivertypesuffix";
my @PNCONS = ();
# For each stp printer...
my $stpname;
for $stpname (keys(%mapstp)) {
# Get some resolution info
my $r = compute_resolutions($stpname);
# For each possible foo name
my $fooname;
for $fooname (@{$mapstp{$stpname}}) {
# What's the default value?
my $foodefval = $r->{'defval'};
push (@PNCONS,
" \n",
" $drvname\n",
" $fooname\n",
" $foodefval\n",
" \n");
}
}
return join('',
"\n",
@PNCONS,
" \n");
}
sub build_printoutmode_ev {
my ($stpopt) = @_;
my $drvname = "$drivernameprefix$drivertypesuffix";
my @vals = ();
# OK, now for each choice ("Draft", "Normal", ...) ...
my $choice;
for $choice (keys %modes) {
# ... and each possible "" for it
my $ev_driverval;
for $ev_driverval (keys %{$modes{$choice}}) {
# Put in the basic choice info: ev names, etc
my $ev_longname = $printoutmodechoices->{$choice};
my $ev_shortname = $choice;
my $ev_id =
get_ev_key($modes{$choice}{$ev_driverval}, $drvname);
push (@vals,
" \n",
" $ev_longname\n",
" $ev_shortname\n",
" $ev_driverval\n",
" \n",
" \n",
" \n",
" $drvname\n",
" \n");
# Build constraints for this particular ev_driverval
my $stpprn;
for $stpprn (keys(%stpdata)) {
my $fooprn;
for $fooprn (@{$mapstp{$stpprn}}) {
if ($printoutmode->{$stpprn}{$choice} eq
$ev_driverval) {
# OK, this choice applies to this printer
push (@vals,
" \n",
" \n",
" $drvname\n",
" $fooprn\n",
" \n");
}
}
}
push (@vals,
" \n",
" \n");
}
}
return join('',
"\n",
@vals,
" \n");
}
sub build_printoutmode_cons {
my ($stpopt) = @_;
my $drvname = "$drivernameprefix$drivertypesuffix";
my @PNCONS = ();
# For each stp printer...
my $stpname;
for $stpname (keys(%mapstp)) {
# For each possible foo name
my $fooname;
for $fooname (@{$mapstp{$stpname}}) {
# What's the default value (always the "Normal" mode)?
my $normalmode = $printoutmode->{$stpname}{'Normal'};
my $foodefval = get_ev_key($modes{'Normal'}{$normalmode},
$drvname);
push (@PNCONS,
" \n",
" $drvname\n",
" $fooname\n",
" $foodefval\n",
" \n");
}
}
return join('',
"\n",
@PNCONS,
" \n");
}
sub qualityorder {
# List of suffixes of the Quality choices
my @suffixes = (
# HP
"mono",
# General
"",
"dpi",
# Epson/Lexmark
"mw",
"mw2",
"sw",
"fol",
"fol2",
"fourp",
"uni",
"mwuni",
"mw2uni",
"swuni",
"foluni",
"fol2uni",
"fourpuni",
"hq",
"hquni",
"hq2",
"hq2uni",
"ov",
"oov",
# Canon
"dmt",
"dpi_high",
"dpi_high2",
"dpi_high3",
"dpi_high4",
"dpi_high5",
"dpi_highmono",
"dpi_highmono2",
"dpi_highmono3",
"dpi_highmono4",
"dpi_highmono5",
"dpi_mono",
"dpi_mono2",
"dpi_mono3",
"dpi_mono4",
"dpi_mono5",
"dpi_draft",
"dpi_draft2",
"dpi_draft3",
"dpi_draft4",
"dpi_draft5",
"dpi_std2",
"dpi_std3",
"dpi_std4",
"dpi_std5",
"dpi_draftmono",
"dpi_draftmono2",
"dpi_draftmono3",
"dpi_draftmono4",
"dpi_draftmono5",
"dpi_photohigh",
"dpi_photohigh2",
"dpi_photohigh3",
"dpi_photohigh4",
"dpi_photohigh5",
"dpi_tshirt",
"dpi_photomed",
"dpi_photomed2",
"dpi_photo",
"dpi_photo2",
"dpi_photo3",
"dpi_photo4",
"dpi_photo5",
"dpi_photodraft",
"dpi_photodraft2",
"dpi_photodraft3",
"dpi_photodraft4",
"dpi_photodraft5",
"dpi_photomonohigh",
"dpi_photomonohigh2",
"dpi_photomonomed",
"dpi_photomono",
"dpi_photomono2",
"dpi_photomonodraft",
"dpi_photomonodraft2",
"dpi_ohphigh",
"dpi_ohp",
# Dyesub
"x600",
"x300"
);
my ($a, $b) = @_;
# Bring the suffixes to lower case
my $first = lc($a);
my $second = lc($b);
# Check whether they are in the @suffixes list
my $i;
for ($i = 0; $i <= $#suffixes; $i++) {
my $firstinlist = ($first eq $suffixes[$i]);
my $secondinlist = ($second eq $suffixes[$i]);
if (($firstinlist) && (!$secondinlist)) {return -1};
if (($secondinlist) && (!$firstinlist)) {return 1};
if (($firstinlist) && ($secondinlist)) {return 0};
}
# Unknown qualities
die "The quality choice suffixes $a and $b are unknown!\n";
return 0;
}
sub getprintoutmode {
my $choicelongnames = {
'Draft' => 'Draft (Economy)',
'Draft.Gray' => 'Draft Grayscale (Economy)',
'Normal' => 'Normal',
'Normal.Gray' => 'Normal Grayscale',
'High' => 'High Quality',
'High.Gray' => 'High Quality Grayscale',
'VeryHigh' => 'Very High Quality',
'VeryHigh.Gray' => 'Very High Quality Grayscale',
'Photo' => 'Photo',
'Photo.Gray' => 'Photo Grayscale',
};
### BASIC RULES
# See mode-specific rules below
# There must be always a "Normal" mode, this will be the default.
# On black-and-white printers there are no modes with ".Gray"
# specifier, the standard modes are already grayscale.
# No "Photo" mode on laser printers.
# If on a PCL printer "600mono" is the chose quality, it will be
# replaced by "300dpi" in color mode (This can lead to a mode being
# removed by the following two rules).
# If "VeryHigh" has exactly the same settings as "High", "VeryHigh"
# is left out.
# If "High" has exactly the same settings as "Normal", "High"
# is left out.
# If nothing is found for a certain mode, this mode is left out.
my $modes = {};
# Treat all printers
my $stpprn;
for $stpprn (keys(%stpdata)) {
my $modeinfo = {};
my ($draftminres, $draftbestsymmetry, $draftlowestqualstr) =
(99999999, 99999999, "xxx");
my ($normalminres, $normalbestsymmetry, $normaluni,
$normallowestqualstr) =
(99999999, 99999999, 0, "xxx");
my ($highmaxres, $highbestsymmetry, $highbestqualstr) =
(0, 99999999, "");
my ($veryhighmaxres, $veryhighbestsymmetry, $veryhighbestqualstr) =
(0, 99999999, "");
my ($photomaxres, $photobestsymmetry, $photobestqualstr) =
(0, 99999999, "");
# Go through all choices of the "Quality" option and find the
# best values for the "PrintoutMode" option
my $quality;
for $quality (keys(%{$stpdata{$stpprn}{'STP_Resolution'}})) {
my ($xres, $yres, $qualstr);
if ($quality =~ /^(\d+)x(\d+)(\D.*)$/) {
$xres = $1;
$yres = $2;
$qualstr = $3;
} elsif ($quality =~ /^(\d+)(\D.*)$/) {
$xres = $1;
$yres = $1;
$qualstr = $2;
} else {
$xres = $stpdata{$stpprn}{'x_resolution'};
$yres = $stpdata{$stpprn}{'y_resolution'};
$qualstr = $quality;
}
# Resolution in dots per square inch
my $respersquareinch = $xres * $yres;
# Symmetry: Shows how far from symmetric a resolution is,
# the smaller, the more symmetric, symmetric resolutions (as
# 300x300 dpi) give zero.
my $symmetry = abs(log($yres/$xres));
### Mode: DRAFT
# Use always the lowest available resolution/quality,
# preferrably symmetric resolutions,
# Do not use resolutions with less than 150 dpi in both
# demensions.
# ImageType Text
my $qualitysetting =
(defined($stpdata{$stpprn}{'STP_Quality'}) ?
(defined($stpdata{$stpprn}{'STP_Quality'}{'Draft'}) ?
'Draft' :
(defined($stpdata{$stpprn}{'STP_Quality'}{'Economy'}) ?
'Economy' :
(defined($stpdata{$stpprn}{'STP_Quality'}{'FastEconomy'}) ?
'FastEconomy' :
(defined($stpdata{$stpprn}{'STP_Quality'}{'Standard'}) ?
'Standard' : 'ERROR' )))) : '');
die ("\n\n'STP_Quality' option without 'Draft', 'Economy', " .
"'FastEconomy', and 'Standard' choices for the '$stpprn' " .
"device class!\n")
if $qualitysetting eq 'ERROR';
my $imagesetting =
(defined($stpdata{$stpprn}{'STP_ImageType'}) ?
(defined($stpdata{$stpprn}{'STP_ImageType'}{'TextGraphics'}) ?
'TextGraphics' :
(defined($stpdata{$stpprn}{'STP_ImageType'}{'TextGraphics'}) ?
'TextGraphics' :
(defined($stpdata{$stpprn}{'STP_ImageType'}{'LineArt'}) ?
'LineArt' :
(defined($stpdata{$stpprn}{'STP_ImageType'}{'Graphics'}) ?
'Graphics' : 'ERROR' )))) : '');
die ("\n\n'STP_ImageType' option without 'TextGraphics', " .
"'LineArt', and 'Graphics' choices for the '$stpprn' " .
"device class!\n")
if $imagesetting eq 'ERROR';
if (($respersquareinch < $draftminres) ||
(($respersquareinch == $draftminres) &&
($symmetry < $draftbestsymmetry)) ||
(($respersquareinch == $draftminres) &&
($symmetry == $draftbestsymmetry) &&
(qualityorder($qualstr, $draftlowestqualstr) < 0))) {
unless (($xres < 150) && # Resolution not lower than
($yres < 150)) { # 150x150, 360x120 allowed
$draftbestsymmetry = $symmetry;
$draftminres = $respersquareinch;
$draftlowestqualstr = $qualstr;
$modeinfo->{'Draft'} = {
'stpres' => $quality,
'quality' => $qualitysetting,
'image' => $imagesetting,
'xres' => $xres,
'yres' => $yres
}
}
}
### Mode: NORMAL
# Lowest resolution which is at least 300x300 dpi (600x600 dpi
# for Lexmark Z..), low quality level, unidirectional if
# possible,
# ImageType TextGraphics
$qualitysetting =
(defined($stpdata{$stpprn}{'STP_Quality'}) ?
(defined($stpdata{$stpprn}{'STP_Quality'}{'Standard'}) ?
'Standard' :
(defined($stpdata{$stpprn}{'STP_Quality'}{'High'}) ?
'High' :
(defined($stpdata{$stpprn}{'STP_Quality'}{'Draft'}) ?
'Draft' : 'ERROR' ))) : '');
die ("\n\n'STP_Quality' option without 'Draft', 'Standard', and " .
"'High' choices for the '$stpprn' device class!\n")
if $qualitysetting eq 'ERROR';
$imagesetting =
(defined($stpdata{$stpprn}{'STP_ImageType'}) ?
(defined($stpdata{$stpprn}{'STP_ImageType'}{'TextGraphics'}) ?
'TextGraphics' :
(defined($stpdata{$stpprn}{'STP_ImageType'}{'Graphics'}) ?
'Graphics' :
(defined($stpdata{$stpprn}{'STP_ImageType'}{'LineArt'}) ?
'LineArt' :
(defined($stpdata{$stpprn}{'STP_ImageType'}{'Photo'}) ?
'Photo' : 'ERROR' )))) : '');
die ("\n\n'STP_ImageType' option without 'TextGraphics', 'Graphics', " .
"'LineArt', and 'Photo' choices for the '$stpprn' " .
"device class!\n")
if $imagesetting eq 'ERROR';
if (($respersquareinch < $normalminres) ||
(($respersquareinch == $normalminres) &&
($symmetry < $normalbestsymmetry)) ||
(($respersquareinch == $normalminres) &&
($symmetry == $normalbestsymmetry) &&
(($qualstr =~ /uni/) > $normaluni)) ||
(($respersquareinch == $normalminres) &&
($symmetry == $normalbestsymmetry) &&
(($qualstr =~ /uni/) == $normaluni) &&
(qualityorder($qualstr, $normallowestqualstr) < 0))) {
unless ((($xres < 300) || # Resolution not lower than
($yres < 300)) || # 300x300, (600x600 on Lexmark)
(($stpprn =~ /^lexmark\-z/) &&
(($xres < 600) ||
($yres < 600)))) {
$normalbestsymmetry = $symmetry;
$normalminres = $respersquareinch;
$normaluni = ($qualstr =~ /uni/);
$normallowestqualstr = $qualstr;
$modeinfo->{'Normal'} = {
'stpres' => $quality,
'quality' => $qualitysetting,
'image' => $imagesetting,
'xres' => $xres,
'yres' => $yres
}
}
}
### Mode: HIGH
# High: The highest resolution which is not higher than
# 720x720 dpi (Lexmark Z..: 1200x1200 dpi),
# unidirectional if possible,
# not "fol", "fourp", "hq", "hq2"
# ImageType TextGraphics
$qualitysetting =
(defined($stpdata{$stpprn}{'STP_Quality'}) ?
(defined($stpdata{$stpprn}{'STP_Quality'}{'High'}) ?
'High' :
(defined($stpdata{$stpprn}{'STP_Quality'}{'Best'}) ?
'Best' :
(defined($stpdata{$stpprn}{'STP_Quality'}{'Photo'}) ?
'Photo' :
(defined($stpdata{$stpprn}{'STP_Quality'}{'Standard'}) ?
'Standard' : 'ERROR' )))) : '');
die ("\n\n'STP_Quality' option without 'High', 'Best', " .
"'Photo', and 'Standard' choices for the '$stpprn' " .
"device class!\n")
if $qualitysetting eq 'ERROR';
$imagesetting =
(defined($stpdata{$stpprn}{'STP_ImageType'}) ?
(defined($stpdata{$stpprn}{'STP_ImageType'}{'TextGraphics'}) ?
'TextGraphics' :
(defined($stpdata{$stpprn}{'STP_ImageType'}{'Graphics'}) ?
'Graphics' :
(defined($stpdata{$stpprn}{'STP_ImageType'}{'Photo'}) ?
'Photo' :
(defined($stpdata{$stpprn}{'STP_ImageType'}{'LineArt'}) ?
'LineArt' : 'ERROR' )))) : '');
die ("\n\n'STP_ImageType' option without 'TextGraphics', 'Graphics', " .
"'LineArt', and 'Photo' choices for the '$stpprn' " .
"device class!\n")
if $imagesetting eq 'ERROR';
if (($respersquareinch > $highmaxres) ||
(($respersquareinch == $highmaxres) &&
($symmetry < $highbestsymmetry)) ||
(($respersquareinch == $highmaxres) &&
($symmetry == $highbestsymmetry) &&
(qualityorder($qualstr, $highbestqualstr) > 0))) {
unless ((($stpprn !~ /^lexmark\-z/) &&
(($xres > 720) || # Resolution not higher than
($yres > 720))) || # 720x720 for non Lexmark
($xres > 1200) || # not bigger than 1200x1200
($yres > 1200) || # in general
($qualstr =~ /^(hq.*|fo.*)$/)) { # Not "hq", "hq2",
# "fol", "fourp"
$highbestsymmetry = $symmetry;
$highmaxres = $respersquareinch;
$highbestqualstr = $qualstr;
$modeinfo->{'High'} = {
'stpres' => $quality,
'quality' => $qualitysetting,
'image' => $imagesetting,
'xres' => $xres,
'yres' => $yres
}
}
}
### Mode: VERY HIGH
# Use always the highest available resolution/quality,
# preferrably symmetric resolutions,
# On Epsons: Maximum 1440x720, not "hq2".
# ImageType TextGraphics
$qualitysetting =
(defined($stpdata{$stpprn}{'STP_Quality'}) ?
(defined($stpdata{$stpprn}{'STP_Quality'}{'Best'}) ?
'Best' :
(defined($stpdata{$stpprn}{'STP_Quality'}{'High'}) ?
'High' :
(defined($stpdata{$stpprn}{'STP_Quality'}{'Photo'}) ?
'Photo' :
(defined($stpdata{$stpprn}{'STP_Quality'}{'Standard'}) ?
'Standard' : 'ERROR' )))) : '');
die ("\n\n'STP_Quality' option without 'High', 'Best', " .
"'Photo', and 'Standard' choices for the '$stpprn' " .
"device class!\n")
if $qualitysetting eq 'ERROR';
$imagesetting =
(defined($stpdata{$stpprn}{'STP_ImageType'}) ?
(defined($stpdata{$stpprn}{'STP_ImageType'}{'TextGraphics'}) ?
'TextGraphics' :
(defined($stpdata{$stpprn}{'STP_ImageType'}{'Graphics'}) ?
'Graphics' :
(defined($stpdata{$stpprn}{'STP_ImageType'}{'Photo'}) ?
'Photo' :
(defined($stpdata{$stpprn}{'STP_ImageType'}{'LineArt'}) ?
'LineArt' : 'ERROR' )))) : '');
die ("\n\n'STP_ImageType' option without 'TextGraphics', 'Graphics', " .
"'LineArt', and 'Photo' choices for the '$stpprn' " .
"device class!\n")
if $imagesetting eq 'ERROR';
if (($respersquareinch > $veryhighmaxres) ||
(($respersquareinch == $veryhighmaxres) &&
($symmetry < $veryhighbestsymmetry)) ||
(($respersquareinch == $veryhighmaxres) &&
($symmetry == $veryhighbestsymmetry) &&
(qualityorder($qualstr, $veryhighbestqualstr) > 0))) {
unless (($xres > 1440) || # Resolution not higher than
($yres > 720) || # 1440x720
($qualstr eq "hq2")) { # Not "hq2"
$veryhighbestsymmetry = $symmetry;
$veryhighmaxres = $respersquareinch;
$veryhighbestqualstr = $qualstr;
$modeinfo->{'VeryHigh'} = {
'stpres' => $quality,
'quality' => $qualitysetting,
'image' => $imagesetting,
'xres' => $xres,
'yres' => $yres
}
}
}
### Mode: PHOTO
# High: The highest resolution which is not higher than
# 720x720 dpi (Lexmark Z..: 1200x1200 dpi),
# unidirectional if possible,
# ImageType Photographs
$qualitysetting =
(defined($stpdata{$stpprn}{'STP_Quality'}) ?
(defined($stpdata{$stpprn}{'STP_Quality'}{'HighPhoto'}) ?
'HighPhoto' :
(defined($stpdata{$stpprn}{'STP_Quality'}{'Photo'}) ?
'Photo' :
(defined($stpdata{$stpprn}{'STP_Quality'}{'UltraPhoto'}) ?
'UltraPhoto' :
(defined($stpdata{$stpprn}{'STP_Quality'}{'Best'}) ?
'Best' :
(defined($stpdata{$stpprn}{'STP_Quality'}{'High'}) ?
'High' :
(defined($stpdata{$stpprn}{'STP_Quality'}{'Standard'}) ?
'Standard' : 'ERROR' )))))) : '');
die ("\n\n'STP_Quality' option without 'HighPhoto', 'Photo', " .
"'UltraPhoto', 'Best', 'High', and 'Standard' choices " .
"for the '$stpprn' device class!\n")
if $qualitysetting eq 'ERROR';
$imagesetting =
(defined($stpdata{$stpprn}{'STP_ImageType'}) ?
(defined($stpdata{$stpprn}{'STP_ImageType'}{'Photo'}) ?
'Photo' :
(defined($stpdata{$stpprn}{'STP_ImageType'}{'Graphics'}) ?
'Graphics' :
(defined($stpdata{$stpprn}{'STP_ImageType'}{'TextGraphics'}) ?
'TextGraphics' :
(defined($stpdata{$stpprn}{'STP_ImageType'}{'LineArt'}) ?
'LineArt' : 'ERROR' )))) : '');
die ("\n\n'STP_ImageType' option without 'TextGraphics', 'Graphics', " .
"'LineArt', and 'Photo' choices for the '$stpprn' " .
"device class!\n")
if $imagesetting eq 'ERROR';
if (($respersquareinch > $photomaxres) ||
(($respersquareinch == $photomaxres) &&
($symmetry < $photobestsymmetry)) ||
(($respersquareinch == $photomaxres) &&
($symmetry == $photobestsymmetry) &&
(qualityorder($qualstr, $photobestqualstr) > 0))) {
unless ((($stpprn !~ /^lexmark\-z/) &&
(($xres > 720) || # Resolution not higher than
($yres > 720))) || # 720x720 for non Lexmark
($xres > 1200) || # not bigger than 1200x1200
($yres > 1200) || # in general
($qualstr =~ /^(hq2)$/)) { # Not "hq2"
$photobestsymmetry = $symmetry;
$photomaxres = $respersquareinch;
$photobestqualstr = $qualstr;
$modeinfo->{'Photo'} = {
'stpres' => $quality,
'quality' => $qualitysetting,
'image' => $imagesetting,
'xres' => $xres,
'yres' => $yres
}
}
}
}
# We must have a "Normal" mode for every printer.
if (!defined($modeinfo->{'Normal'}{'stpres'})) {
die "No 'Normal' mode for $stpprn!\n";
}
# Build the strings with the settings for the "PrintoutMode"
# option
for my $m (keys(%{$modeinfo})) {
# If we didn't find anything for a certain mode, skip this
# mode
next if (!defined($modeinfo->{$m}{'stpres'}));
my $modestr =
(defined($stpdata{$stpprn}{'STP_ImageType'}) ?
"STP_ImageType=$modeinfo->{$m}{'image'} " : "") .
(defined($stpdata{$stpprn}{'STP_Quality'}) ?
"STP_Quality=$modeinfo->{$m}{'quality'} " :
"STP_Resolution=$modeinfo->{$m}{'stpres'} ") .
"Resolution=$modeinfo->{$m}{'xres'}x" .
"$modeinfo->{$m}{'yres'}dpi";
if (defined($stpdata{$stpprn}{'Color'}{'Color'})) {
# Color printer
$modes->{$stpprn}{$m} = $modestr . " OutputType=Color";
if (defined($stpdata{$stpprn}{'Color'}{'Grayscale'})) {
$modes->{$stpprn}{"$m.Gray"} =
$modestr . " OutputType=Grayscale";
} elsif (defined($stpdata{$stpprn}{'Color'}{'BlackAndWhite'})) {
$modes->{$stpprn}{"$m.Gray"} =
$modestr . " OutputType=BlackAndWhite";
}
# Some HP inkjets have a "600mono" quality mode which
# is only available in Grayscale, replace this mode by
# "300dpi" in the settings for color printing
if ($modes->{$stpprn}{$m} =~ /600mono/) {
if(!defined($stpdata{$stpprn}{'STP_Resolution'}{'300dpi'})){
die "No '300dpi' mode for $stpprn!";
}
$modes->{$stpprn}{$m} =~ s/600x600dpi/300x300dpi/;
$modes->{$stpprn}{$m} =~ s/600mono/300dpi/;
}
} else {
# bw printer
if ($stpprn =~ /^pcl\-[2-6][vls]?i?$/) { # Laser printer
# No 'Photo' mode on laser printers
next if ($m eq 'Photo');
# Always "VeryFast" dithering on laser printers
$modestr =~ s/(Dither=)\S+/$1VeryFast/;
}
$modes->{$stpprn}{$m} = $modestr . " OutputType=Grayscale";
}
}
# Remove 'VeryHigh' and 'High' if they are identical to lower
# quality modes
if ($modes->{$stpprn}{'VeryHigh'} eq
$modes->{$stpprn}{'High'}) {
delete($modes->{$stpprn}{'VeryHigh'});
}
if ($modes->{$stpprn}{'High'} eq
$modes->{$stpprn}{'Normal'}) {
delete($modes->{$stpprn}{'High'});
}
if (defined($stpdata{$stpprn}{'Color'}{'Color'})) {
# Color printer
if ($modes->{$stpprn}{'VeryHigh.Gray'} eq
$modes->{$stpprn}{'High.Gray'}) {
delete($modes->{$stpprn}{'VeryHigh.Gray'});
}
if ($modes->{$stpprn}{'High.Gray'} eq
$modes->{$stpprn}{'Normal.Gray'}) {
delete($modes->{$stpprn}{'High.Gray'});
}
}
}
return ($modes, $choicelongnames)
}
exit(0);