#!/usr/bin/perl -w # # Copyright (c) 2002 SuSE Linux AG, Nuernberg, Germany. All rights reserved. # # Author: Mike Fabian , 2002 # 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; } if (system ("rpm -q freetype-tools >/dev/null 2>&1") != 0) { print "freetype-tools package missing, exiting.\n"; exit 1; } sub usage { print "Usage: cjk-latex-config [--verbose|v] [--force|f] [--type1|t]\n"; exit 1; } # Process command line options my %opt; unless (GetOptions(\%opt, 'verbose|v', \$OPT_VERBOSE, 'force|f', \$OPT_FORCE, 'type1|t', \$OPT_TYPE1, )) { &usage(); exit 1; } # to make sure ttf2tfm finds the .sdf files: system("texhash"); $tfm_created = 0; $type1_created = 0; system("mkdir -p /usr/share/texmf/fonts/truetype/"); open (TTFONTS_MAP, "/etc/ttf2pk/ttfonts.map"); while () { chomp($ARG); if ($ARG =~ /\@[a-zA-Z0-9\/]+\@/) { if($OPT_VERBOSE) { print "----------------------------------------------------------------------\n"; print "$ARG\n"; } @fields = split(/\s+/, $ARG); $tt_dir = "/usr/X11R6/lib/X11/fonts/truetype/"; $tt_basename = $fields[1]; if ($fields[0] =~ /([^\s]+)\@[a-zA-Z0-9\/]+\@/) { $latex_font_name = $1; } else { print "can't find latex font name.\n"; exit 1 } if ($fields[0] =~ /\@([a-zA-Z0-9\/]+)\@/) { $sfd_name = $1; $sfd_name =~ /.*\/([a-zA-Z0-9]+)/; $sfd_basename = $1; } else { print "can't find sfd_name.\n"; exit 1 } if ($ARG =~ /Pid=([0-9]+)/) { $pid = "$1"; } else { $pid = "3"; } if ($ARG =~ /Eid=([0-9]+)/) { $eid = "$1"; } else { $eid = "1"; } if ($ARG =~ /Slant=([0-9.]+)/) { $slant = $1; $slant_opt = "-s $1"; } else { $slant = 0; $slant_opt = "-s 0"; } if ($ARG =~ /Rotate=(Yes)/) { $rotate = 1; $rotate_opt = "-x"; } else { $rotate = 0; $rotate_opt = ""; } if (-e "$tt_dir/$tt_basename") { symlink("$tt_dir/$tt_basename", "/usr/share/texmf/fonts/truetype/$tt_basename"); $tfm_dir = "/usr/share/texmf/fonts/tfm/cjk-latex/"; $type1_dir = "/usr/share/texmf/fonts/type1/cjk-latex/"; if (0 != create_or_update_tfm ()) { print "creating .tfm failed.\n"; } if ($OPT_TYPE1 && $slant == 0 && $rotate == 0) { if (0 != create_or_update_type1 ()) { print "creating type1 font failed.\n"; } } } } } if ($type1_created) { $command = "cjk-latex-t1mapgen $type1_dir"; if (0 != system ($command)) { print "$command failed.\n"; exit 1; } } if ($tfm_created || $type1_created) { system("texhash"); } exit 0; ###################################################################### sub create_or_update_tfm { if ($OPT_FORCE || mtime_differs_or_missing ("$tt_dir/$tt_basename", "$tfm_dir/$sfd_basename/$latex_font_name/")) { if (0 != system ("mkdir -p $tfm_dir/$sfd_basename/$latex_font_name/")) { print "mkdir -p $tfm_dir/$sfd_basename/$latex_font_name/ failed.\n"; exit 1; } if (! chdir ("$tfm_dir/$sfd_basename/$latex_font_name/")) { print "can't chdir to $tfm_dir/$sfd_basename/$latex_font_name/\n"; exit 1; } $command = "ttf2tfm $tt_dir/$tt_basename "; unless ($OPT_VERBOSE) { $command .= " -q"; } $command .= " -P $pid -E $eid $rotate_opt $slant_opt $latex_font_name\@$sfd_name\@"; if ($OPT_VERBOSE) { print "$command\n"; } else { $command .= " > /dev/null 2>&1"; print "$latex_font_name\@$sfd_name\@: calling ttf2tfm ...\n"; } if (0 != system($command)) { print "$command failed.\n"; return 1; } # success, mark this by giving the created directory the same time stamp # as the TT-font: system("touch -r $tt_dir/$tt_basename $tfm_dir/$sfd_basename/$latex_font_name/"); $tfm_created = 1; return 0; } } ###################################################################### sub create_or_update_type1 { if ($OPT_FORCE || mtime_differs_or_missing ("$tt_dir/$tt_basename", "$type1_dir/$sfd_basename/$latex_font_name/")) { if (0 != system ("mkdir -p $type1_dir/$sfd_basename/$latex_font_name/")) { print "mkdir -p $type1_dir/$sfd_basename/$latex_font_name/ failed.\n"; exit 1; } if (! chdir ("$type1_dir/$sfd_basename/$latex_font_name/")) { print "can't chdir to $type1_dir/$sfd_basename/$latex_font_name/\n"; exit 1; } if (grep(/$tt_basename/,("wadalab-gothic.ttf","watanabe-mincho.ttf"))) { print "$tt_basename does not work with ttf2pt1, skipping ...\n"; return 0; } # disable smoothing of outlines for broken fonts # (for details see 'man ttf2pt1'): my $smoothing_opt = " "; if (grep(/$tt_basename/,("kochi-gothic.ttf"))) { print "$tt_basename broken, disabling smoothing of outlines.\n"; $smoothing_opt = " -O s "; } $sfd_file = "/usr/share/texmf/ttf2tfm/$sfd_basename.sfd"; $map_file = `mktemp /tmp/cjk-latex-config-map.XXXXXX`; chomp $map_file; if ($map_file eq "") { print "mktemp /tmp/cjk-latex-config-map.XXXXXX failed.\n"; } @planes = sfd2map($sfd_file,$map_file); if ($#planes == -1) { print "sfd2map($sfd_file,$map_file) failed.\n"; return 1; } for my $plane (@planes) { if ($OPT_VERBOSE) { $command = "ttf2pt1 -W 99 "; } else { $command = "ttf2pt1 -W 0 "; } $command .= $smoothing_opt; $command .= " -p ft -b -G a -m h=5000 "; $command .= " -L $map_file+pid=$pid,eid=$eid,$plane "; $command .= " $tt_dir/$tt_basename $latex_font_name$plane"; if ($OPT_VERBOSE) { print "$command\n"; } else { $command .= " > /dev/null 2>&1"; print "$latex_font_name\@$sfd_name\@, plane=$plane: calling ttf2pt1 ...\n"; } if (0 != system($command)) { print "$command failed.\n"; return 1; } } unlink $map_file; # success, mark this by giving the created directory the same time stamp # as the TT-font: system("touch -r $tt_dir/$tt_basename $type1_dir/$sfd_basename/$latex_font_name/"); $type1_created = 1; return 0; } } ###################################################################### sub sfd2map { my($sfd_file,$map_file) = @_; if (! open (SFD, "<$sfd_file")) { print "cannot open $sfd_file\n"; return (); } if (! open (MAP, ">$map_file")) { print "cannot open $map_file\n"; close (SFD); return (); } my(@planes) = (); while () { if ( ! ($ARG =~ /^[[:space:]]*\#/)) { # skip comment lines # handle plane numbers: if ( $ARG =~ /^([[:xdigit:]]{2})[[:space:]]*/ ) { $ARG =~ s/^([[:xdigit:]]{2})[[:space:]]*/ /; print MAP "plane $1\n"; print MAP "at 0x00\n"; $planes[$#planes + 1] = $1; } # remove continuation chars '\': $ARG =~ s/\\$//; $ARG =~ s/(0x[[:xdigit:]]{1,4})/$1,/g; # handle ranges like 0xF800_0xF8FF $ARG =~ s/(0x[[:xdigit:]]{1,4}),_/$1-/g; } print MAP $ARG; } close (MAP); close (SFD); return @planes; } # 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; } }