From e6eb87edc4ad9473dde526fb70950518819ebd11 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 26 Apr 2017 00:05:12 -0700 Subject: [PATCH] win32, doc: fix PDF generation scripts for Windows Win32::Registry is obsolete, we need to use Win32::TieRegistry on current platforms. GhostScript uses # rather than = on Windows, it seems. Try to find GhostScript in the registry and add it to the PATH. Signed-off-by: H. Peter Anvin --- doc/findfont.ph | 96 +++++++++++++++++++++++++++------------------------------ doc/pspdf.pl | 60 +++++++++++++++++++++++++++++++++--- 2 files changed, 101 insertions(+), 55 deletions(-) diff --git a/doc/findfont.ph b/doc/findfont.ph index 8fa81dfb..60047b84 100644 --- a/doc/findfont.ph +++ b/doc/findfont.ph @@ -61,11 +61,11 @@ sub add_file_to_font_hash($) { my $fontdata; if ( $filename =~ /\.(otf|ttf)$/i ) { - $fontdata = parse_ttf_file($filename); + $fontdata = parse_ttf_file($filename); } elsif ( $filename =~ /\.(pfa|pfb)$/i ) { - if ( -f "${filestem}.afm" ) { - $fontdata = parse_afm_file($filestem, $fonttype); - } + if ( -f "${filestem}.afm" ) { + $fontdata = parse_afm_file($filestem, $fonttype); + } } return unless (defined($fontdata)); @@ -73,16 +73,14 @@ sub add_file_to_font_hash($) { my $oldinfo = $font_info_hash{$fontdata->{name}}; if (!defined($oldinfo) || - $prefs{$fontdata->{type}} < $prefs{$oldinfo->{type}}) { - $font_info_hash{$fontdata->{name}} = $fontdata; + $prefs{$fontdata->{type}} < $prefs{$oldinfo->{type}}) { + $font_info_hash{$fontdata->{name}} = $fontdata; } } my $win32_ok = eval { - require Win32::Registry; - Win32::Registry->import(); - require Win32; - Win32->import(); + require Win32::TieRegistry; + Win32::TieRegistry->import(); 1; }; @@ -95,26 +93,25 @@ my $win32_ok = eval { # This module is released under the terms of the Artistic License 2.0. # For details, see the full text of the license in the file LICENSE. sub scanfonts_win32() { - return undef unless ($win32_ok); + return unless ($win32_ok); - my $font_key = 'SOFTWARE\Microsoft\Windows' . - (Win32::IsWinNT() ? 'NT' : '') . '\CurrentVersion\Fonts'; - my($regfont, $list, $l, $file); - - $::HKEY_LOCAL_MACHINE->Open($font_key, $regfont); - $regfont->GetValues($list); + my $Reg = $::Registry->Open('', {Access=>'KEY_READ', Delimiter=>'/'}); + my $fd; + foreach my $win ('Windows NT', 'Windows') { + $fd = $Reg->{"HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/$win/CurrentVersion/Fonts"}; + last if (defined($fd)); + } + return unless (defined($fd)); - foreach my $l (keys(%$list)) { - my $fname = $list->{$l}[0]; - next unless ($fname =~ s/\((TrueType|OpenType)\)$//); - $file = File::Spec->rel2abs($list->{$l}[2], $ENV{'windir'}.'\fonts'); - add_file_to_font_hash($file) + foreach my $font (keys(%$fd)) { + my($fname, $ftype) = ($font =~ m:^/(.+?)(| \([^\(\)]+\))$:); + next unless ($ftype =~ / \((TrueType|OpenType)\)$/); + my $file = File::Spec->rel2abs($fd->{$font}, $ENV{'windir'}.'\\fonts'); + add_file_to_font_hash($file); } } -sub font_search_file() { - my($fontdata, $filestem, $fonttype); - +sub font_search_file { add_file_to_font_hash($_); } @@ -135,49 +132,46 @@ sub findfont($) { # NOTE: use a single string for the command here, or this # script dies horribly on Windows, even though this isn't really # applicable there... - if (!defined($file) && - open(my $fh, '-|', + if (open(my $fh, '-|', "fc-match -f \"%{file}\\n%{postscriptname}\\n\" ". - "\" : postscriptname=$fontname\"") { - chomp($file = <$fh>); - chomp($psname = <$fh>); - close($fh); - if ( -f $file ) { - if ($psname eq $fontname) { - add_file_to_font_hash($file); - } - if (!exists($font_info_hash{$fontname})) { - $font_info_hash{$fontname} = undef; - } - return $font_info_hash{$fontname}; - } + "\" : postscriptname=$fontname\"")) { + chomp($file = <$fh>); + chomp($psname = <$fh>); + close($fh); + if ( -f $file ) { + if ($psname eq $fontname) { + add_file_to_font_hash($file); + } + if (!exists($font_info_hash{$fontname})) { + $font_info_hash{$fontname} = undef; + } + return $font_info_hash{$fontname}; + } } if (exists($font_info_hash{$fontname})) { - return $font_info_hash{$fontname}; + return $font_info_hash{$fontname}; } elsif ($fonts_scanned >= 1) { - return $font_info_hash{$fontname} = undef; + return $font_info_hash{$fontname} = undef; } - if ($win32) { - scanfonts_win32(); - $fonts_scanned = 1; - } + scanfonts_win32(); + $fonts_scanned = 1; if (exists($font_info_hash{$fontname})) { - return $font_info_hash{$fontname}; + return $font_info_hash{$fontname}; } elsif ($fonts_scanned >= 2) { - return $font_info_hash{$fontname} = undef; + return $font_info_hash{$fontname} = undef; } # Search a set of possible locations for a file, from a few different # systems... - my @dirs = ('fonts', '/usr/share/fonts', '/Library/Fonts'); - push @dirs, $ENV{'windir'}.'\fonts' if (defined $ENV{'windir'}); + my @dirs = ('fonts', '/usr/share/fonts', '/usr/lib/fonts', '/Library/Fonts'); + push @dirs, $ENV{'windir'}.'\\fonts' if (defined $ENV{'windir'}); push @dirs, $ENV{'HOME'}.'/.fonts', $ENV{'HOME'}.'/Library/Fonts' if (defined $ENV{'HOME'}); - find({wanted => \font_search_file, follow=>1, no_chdir=>1}, @dirs); + find({wanted => \&font_search_file, follow=>1, no_chdir=>1}, @dirs); $fonts_scanned = 2; return $font_info_hash{$fontname}; diff --git a/doc/pspdf.pl b/doc/pspdf.pl index 961a8ae1..ae095576 100755 --- a/doc/pspdf.pl +++ b/doc/pspdf.pl @@ -4,9 +4,16 @@ # use strict; +use File::Spec; my $compress = 1; +my $win32_ok = eval { + require Win32::TieRegistry; + Win32::TieRegistry->import(); + 1; +}; + while ($ARGV[0] =~ /^-(.*)$/) { my $opt = $1; shift @ARGV; @@ -19,7 +26,48 @@ while ($ARGV[0] =~ /^-(.*)$/) { my ($in, $out) = @ARGV; if (!defined($out)) { - die "Usage: $0 [-nocompress] infile outfile\n"; + die "Usage: $0 [-nocompress] infile ou{ tfile\n"; +} + +# If Win32, help GhostScript out with some defaults +sub win32_gs_help() { + return if (!$win32_ok); + + use Sort::Versions; + use sort 'stable'; + + my $Reg = $::Registry->Open('', {Access => 'KEY_READ', Delimiter => '/'}); + my $dir; + my @gs; + + foreach my $k1 ('HKEY_CURRENT_USER/Software/', 'HKEY_LOCAL_MACHINE/SOFTWARE/') { + foreach my $k2 ('Artifex/', '') { + foreach my $k3 ('GPL Ghostscript/', 'AFPL Ghostscript/', 'Ghostscript/') { + my $r = $Reg->{$k1.$k2.$k3}; + if (ref($r) eq 'Win32::TieRegistry') { + foreach my $k (keys(%$r)) { + my $rk = $r->{$k}; + if (ref($rk) eq 'Win32::TieRegistry' && + defined($rk->{'/GS_LIB'})) { + push @gs, $rk; + } + } + } + } + } + } + + @gs = sort { + my($av) = $a->Path =~ m:^.*/([^/]+)/$:; + my($bv) = $b->Path =~ m:^.*/([^/]+)/$:; + versioncmp($av, $bv); + } @gs; + + return unless (scalar(@gs)); + + $ENV{'PATH'} .= ';' . $gs[0]->{'/GS_LIB'}; + $ENV{'GS_FONTPATH'} .= (defined($ENV{'GS_FONTPATH'}) ? ';' : '') + . $ENV{'windir'}.'\\fonts'; } # Remove output file @@ -30,9 +78,13 @@ my $r = system('acrodist', '-n', '-q', '--nosecurity', '-o', $out, $in); exit 0 if ( !$r && -f $out ); # 2. ps2pdf (from Ghostscript) -my $r = system('ps2pdf', '-dOptimize=true', '-dEmbedAllFonts=true', - '-dCompressPages=' . ($compress ? 'true' : 'false'), - '-dUseFlateCompression=true', $in, $out); +# The -I clause helps Ghostscript pick up the Fontdir file written by findfont.ph +# GhostScript uses # rather than - to separate options and values on Windows, it seems... +win32_gs_help(); +my $o = $win32_ok ? '#' : '-'; +my $r = system('ps2pdf', "-dOptimize${o}true", "-dEmbedAllFonts${o}true", + "-dCompressPages${o}" . ($compress ? 'true' : 'false'), + "-dUseFlateCompression${o}true", $in, $out); exit 0 if ( !$r && -f $out ); # 3. pstopdf (BSD/MacOS X utility) -- 2.11.4.GIT