File cidfont-x11-config of Package ghostscript-cjk

#!/usr/bin/perl -w
#
# Copyright (c) 2002 SuSE Linux AG, Nuernberg, Germany.  All rights reserved.
#
# Author: Mike Fabian <mfabian@suse.de>, 2002
#

=head1 NAME

cidfont-x11-config - configures CID keyed fonts for use with X11

=head1 SYNOPSIS

cidfont-x11-config [B<OPTION>]...

=head1 DESCRIPTION

Searches for CID keyed fonts in I</usr/share/ghostscript/Resource/CIDFont>
and configures them for use with X11 by creating some sub-directories,
files and symbolic links in I</usr/share/fonts/CID>. It also automatically
generates I</usr/share/fonts/CID/fonts.scale.auto> which is
then merged into I</usr/share/fonts/CID/fonts.scale> by SuSEconfig.

=head1 OPTIONS

=over 4

=item B<-v>, B<--verbose>

print some messages to standard output.

=item B<-f>, B<--force>

Force the update of the generated files even if all directories in
I</usr/share/ghostscript/Resource/> have the same time stamp
as I</usr/share/fonts/CID/fonts.scale.auto>.

When this script is finished, it gives all directories in
I</usr/share/ghostscript/Resource/> the same timestamp as
I</usr/share/fonts/CID/fonts.scale.auto> in order to avoid
wasting time doing useless updates when nothing has changed below
I</usr/share/ghostscript/Resource/> anyway.

=back

=head1 BUGS

none.

=head1 AUTHOR

Mike Fabian <I<mfabian@suse.de>>.

=cut

use English;
use Getopt::Long;

# check if we are started as root
# only one of UID and USER must be set correctly

if ($UID != 0 && $ENV{USER} !~ /root/) {
    print "You must be root to start $0\n";
    exit 1;
}

sub usage {
  print "Usage: cidfont-x11-config [--verbose|v] [--force|f]\n";
  exit 1;
}

# Process command line options
my %opt;
unless (GetOptions(\%opt,
		   'verbose|v', \$OPT_VERBOSE,
		   'force|f',   \$OPT_FORCE,
		  )) {
  &usage();
  exit 1;
}

# external binaries:
my $mkcfm_bin = search_executable ("/usr/bin/mkcfm", "/usr/X11R6/bin/mkcfm");

if (! $mkcfm_bin) {
  # if ($OPT_VERBOSE) {
  #   print "mkcfm has been dropped in recent Xorg releases. Exiting.\n";
  # }
  exit 1;
}

my $x11_cid_dir = "/usr/X11R6/lib/X11/fonts/CID";
if (-d "/usr/share/fonts/encodings") { # we have X11R7, fonts are in /usr/share/fonts
  $x11_cid_dir = "/usr/share/fonts/CID";
}
if (! -d "$x11_cid_dir" ) {
  mkdir("$x11_cid_dir") || die "can't create directory $x11_cid_dir: $!";
}
my $fonts_scale_file = "$x11_cid_dir/fonts.scale.auto";
my $gs_resource_dir = "/usr/share/ghostscript/Resource";

$registry = "Adobe";
@orderings = ("Japan1", "Japan2", "Korea1", "CNS1", "GB1");
%fonts_scale_entries = ();
@resource_dirs = ();

$need_update = 0;
opendir (GSDIR, "$gs_resource_dir")
  || die "can't opendir $gs_resource_dir: $!";
for my $subdir (readdir (GSDIR)) {
  if ( -d "$gs_resource_dir/$subdir" ) {
    $resource_dirs[$#resource_dirs + 1] = "$gs_resource_dir/$subdir";
    if (mtime_differs_or_missing ("$gs_resource_dir/$subdir","$fonts_scale_file")) {
	$need_update = 1;
    }
  }
}
closedir (GSDIR);

if ($need_update || $OPT_FORCE) {
  configure_cid_keyed_fonts_for_x11();
  # success, mark this by giving the directories in the Ghostscript Resource directory
  # the same time stamp as the created fonts.scale file:
  for my $subdir (@resource_dirs) {
    system("touch -r $fonts_scale_file $subdir");
  }
}

exit 0;

sub configure_cid_keyed_fonts_for_x11 {
            
  system ("rm -rf $x11_cid_dir/Adobe-*");

  make_subdirs ();
  
  config_resource("CIDFont");

  config_resource("CMap");

  if ($OPT_VERBOSE) { print "calling mkcfm ...\n"; }
  system("mkcfm $x11_cid_dir");

  write_fonts_scale();

}

sub mkdir_p {
  my $dir = shift;

  return 1 if -d $dir;
  if ($dir =~ /^(.*)\//) {
    mkdir_p($1) || return undef;
  }
  if (!mkdir($dir, 0777)) {
    error("mkdir_p: $dir: $!\n");
    return undef;
  }
  return 1;
}

sub make_subdirs {
  if ($OPT_VERBOSE) { print "making subdirs ...\n"; }
  for my $ordering (@orderings) {
    mkdir_p ("$x11_cid_dir/$registry-$ordering")
      || die "can't mkdir $x11_cid_dir/$registry-$ordering: $!";
    for my $subdir ("AFM", "CFM", "CIDFont", "CMap") {
      mkdir_p ("$x11_cid_dir/$registry-$ordering/$subdir")
	|| die "can't mkdir $x11_cid_dir/$registry-$ordering/$subdir: $!";
    }
  }
}

sub write_fonts_scale {
    if ($OPT_VERBOSE) { print "writing $fonts_scale_file ...\n"; }
    open (FONTS_SCALE, ">$fonts_scale_file")
      || die "can't open file >$fonts_scale_file: $!";
    for my $xlfd (sort (keys %fonts_scale_entries)) {
	  print FONTS_SCALE "$fonts_scale_entries{$xlfd} $xlfd\n";
    }
    close (FONTS_SCALE);
}

sub config_resource {
  my ($subdir) = @_;
  
  if ($OPT_VERBOSE) { print "configure $subdir ...\n"; }
  
  opendir (SUBDIR, "$gs_resource_dir/$subdir")
    || die "can't opendir $gs_resource_dir/CIDFont: $!";

  for my $file (readdir (SUBDIR)) {
    if ( -f "$gs_resource_dir/$subdir/$file" ) {

      my %info = cidresourceinfo ("$gs_resource_dir/$subdir/$file");
      
      if ($info{'Registry'}
	  && $info{'Registry'} eq "$registry"
	  && grep (/$info{'Ordering'}/,@orderings)) {
	# it's a real CID-keyed font or a CMap
	
	symlink("$gs_resource_dir/$subdir/$file",
		"$x11_cid_dir/$info{'Registry'}-$info{'Ordering'}/$subdir/$file");
	
	if ($subdir eq "CIDFont") {
	  add_xlfd (%info);
	  if( -f "$gs_resource_dir/AFM/$file.afm" ) {
	    symlink("$gs_resource_dir/AFM/$file.afm",
		    "$x11_cid_dir/$info{'Registry'}-$info{'Ordering'}/AFM/$file.afm");
	  }
	}
	
      }
    }
  }
  closedir (SUBDIR);
}

sub add_xlfd {
  my %info = @_;
  my %entries;

  if ($info{'Ordering'} eq "Japan1") {
    %entries = (
		"iso10646-1"      , "UniJIS-UCS2-H",
		"jisx0208.1983-0" , "H",
		"jisx0208.1990-0" , "H",
		"jisx0208.1997-0" , "H",
		"adobe.japan1-0"  , "Adobe-Japan1-0",
		"adobe.japan1-1"  , "Adobe-Japan1-1",
		"adobe.japan1-2"  , "Adobe-Japan1-2",
		"adobe.japan1-3"  , "Adobe-Japan1-3",
		"adobe.japan1-4"  , "Adobe-Japan1-4"
	       );
  }
  elsif ($info{'Ordering'} eq "Japan2") {
    %entries = (
		"iso10646-1"      , "UniHojo-UCS2-H",
		"jisx0212.1990-0" , "Hojo-H",
		"adobe.japan2-0"  , "Adobe-Japan2-0"
	       );
  }
  elsif ($info{'Ordering'} eq "Korea1") {
    %entries = (
		"iso10646-1"      , "UniKS-UCS2-H",
		"ksx1001.1997-0"  , "KSC-H",
		"ksx1001.1992-0"  , "KSC-H",
		"ksc5601.1987-0"  , "KSC-H",
		"adobe.korea1-0"  , "Adobe-Korea1-0",
		"adobe.korea1-1"  , "Adobe-Korea1-1",
		"adobe.korea1-2"  , "Adobe-Korea1-2"
	       );
  }
  elsif ($info{'Ordering'} eq "CNS1") {
    %entries = (
		"iso10646-1"      , "UniCNS-UCS2-H",
		"big5-0"          , "B5-H",
		"big5.eten-0"     , "ETen-B5-H",
		"cns11643.1992-1" , "CNS1-H",
		"cns11643.1992-2" , "CNS2-H",
		"adobe.cns1-0"    , "Adobe-CNS1-0",
		"adobe.cns1-1"    , "Adobe-CNS1-1",
		"adobe.cns1-2"    , "Adobe-CNS1-2",
		"adobe.cns1-3"    , "Adobe-CNS1-3"
	       );
  }
  else {
    return;
  }

  for my $i (keys %entries) {
    my ($font, $xlfd);
    my ($weight) = t1weight($info{'Weight'});
    $font = "$info{'Registry'}-$info{'Ordering'}/$info{'CIDFontName'}--$entries{$i}.cid";
    $xlfd = "-$info{'Registry'}-$info{'FamilyName'}-$weight-r-normal--0-0-0-0-p-0-$i";
    $fonts_scale_entries{$xlfd} = $font;
  }
}

sub t1weight {
  my ($weight) = @_;

  if ($weight eq "Regular")     { return "medium"; }
  if ($weight eq "Normal")      { return "medium"; }
  if ($weight eq "Medium")      { return "medium"; }
  if ($weight eq "Book")        { return "medium"; }
  if ($weight eq "Roman")       { return "medium"; }
  if ($weight eq "Light")       { return "medium"; }
  if ($weight eq "Demi")        { return "semibold"; }
  if ($weight eq "DemiBold")    { return "semibold"; }
  if ($weight eq "Bold")        { return "bold"; }
  return "medium";
}

sub cidresourceinfo {
  my ($file) = @_;
  my %info;
  
  open (FONTFILE, $file) || die "can't open file $file: $!";
  while (<FONTFILE>) {
    chomp ($ARG);
    if ($ARG =~ /\/CMapName\s*\/([^\s]+)\s*def/) {
      $info{'CMapName'} = $1;
    }
    if ($ARG =~ /\/CIDFontName\s*\/([^\s]+)\s*def/) {
      $info{'CIDFontName'} = $1;
    }
    if ($ARG =~ /\/Registry\s*\(([^\s]+)\)\s*def/) {
      $info{'Registry'} = $1;
    }
    if ($ARG =~ /\/Ordering\s*\(([^\s]+)\)\s*def/) {
      $info{'Ordering'} = $1;
    }
    if ($ARG =~ /\/Supplement\s*([^\s]+)\s*def/) {
      $info{'Supplement'} = $1;
    }
    if ($ARG =~ /\/FullName\s*\(([^)]+)\)\s*def/) {
      $info{'FullName'} = $1;
    }
    if ($ARG =~ /\/FamilyName\s*\(([^)]+)\)\s*def/) {
      $info{'FamilyName'} = $1;
    }
    if ($ARG =~ /\/Weight\s*\(([^\s]+)\)\s*def/) {
      $info{'Weight'} = $1;
    }
  }
  close (FONTFILE);
  
  # The Wadalab fonts appear to be a bit unusual, for example they
  # neither have a /FamilyName nor a /Weight entry and their /FullName
  # looks strange. For example:
  #   /FullName (WadaMin-RegularH) def
  # 'H' doesn't belong to the Weight, only 'Regular'.
  # WadaMin-Regular is Adobe-Japan1, WadaMin-RegularH is Adobe-Japan2.
  #
  # Fix this and make the entries look like they do for most other
  # fonts:
  if ($info{'FullName'} && $info{'FullName'} =~/^Wada/) {
    if ($info{'FullName'} eq "WadaGo-Bold") {
      $info{'FullName'} = "Wada Go Bold";
      $info{'FamilyName'} = "Wada Go";
      $info{'Weight'} = "Bold";
    }
    if ($info{'FullName'} eq "WadaMaruGo-Regular") {
      $info{'FullName'} = "Wada Maru Go Regular";
      $info{'FamilyName'} = "Wada Maru Go";
      $info{'Weight'} = "Regular";
    }
    if ($info{'FullName'} eq "WadaMin-Bold") {
      $info{'FullName'} = "Wada Min Bold";
      $info{'FamilyName'} = "Wada Min";
      $info{'Weight'} = "Bold";
    }
    if ($info{'FullName'} eq "WadaMin-Regular") {
      $info{'FullName'} = "Wada Min Regular";
      $info{'FamilyName'} = "Wada Min";
      $info{'Weight'} = "Regular";
    }
    if ($info{'FullName'} eq "WadaMaruGo-RegularH") {
      $info{'FullName'} = "Wada Maru Go H Regular";
      $info{'FamilyName'} = "Wada Maru Go H";
      $info{'Weight'} = "Regular";
    }
    if ($info{'FullName'} eq "WadaMin-RegularH") {
      $info{'FullName'} = "Wada Min H Regular";
      $info{'FamilyName'} = "Wada Min H";
      $info{'Weight'} = "Regular";
    }
  }
  return %info;
}

# Returns true if the modification time of $f1 differs from
# the modification time of $f2 
sub mtime_differs {
  my($f1,$f2) = @_;
  if( -e $f1 && -e $f2) {
    local (@f1s) = stat ($f1);
    local (@f2s) = stat ($f2);
    return ($f1s[9] != $f2s[9]);
  } else {
    return 0;
  }
}

# Returns true if the modification time of $f1 differs from
# the modification time of $f2 or if one of the files is missing
sub mtime_differs_or_missing {
    my($f1,$f2) = @_;
    if (! -e $f1 || ! -e $f2 || mtime_differs($f1,$f2)) {
      return 1;
    } else {
      return 0;
    }
}  

# Returns true if $f1 is newer than $f2
sub newer {
  my($f1,$f2) = @_;
  if( -e $f1 && -e $f2) {
    local (@f1s) = stat ($f1);
    local (@f2s) = stat ($f2);
    return ($f1s[9] > $f2s[9]);
  } else {
    return 0;
  }
}

# Returns true if $f1 is newer than $f2 or if one of the files is missing
sub newer_or_missing {
    my($f1,$f2) = @_;
    if (! -e $f1 || ! -e $f2 || newer($f1,$f2)) {
      return 1;
    } else {
      return 0;
    }
}

sub search_executable {
  for my $file (@_) {
    if (-x $file) {
      return $file;
    }
  }
  return "";
}
openSUSE Build Service is sponsored by