File ghostscript-cjk-config of Package ghostscript-cjk
#! /usr/bin/perl -w # -*- mode: perl coding: utf-8 -*-
#
# Tue Mar 15 12:05:45 2005 Mike FABIAN <mfabian@suse.de>
#
########################################################################
# create a man-page with:
#
# pod2man --section 1 --center=" " ghostscript-cjk-config | gzip -9 -c > ghostscript-cjk-config.1.gz
# cp ghostscript-cjk-config.1.gz /usr/share/man/man1/ghostscript-cjk-config.1.gz
=head1 NAME
ghostscript-cjk-config - setup the available fonts for use with ghostscript-cjk
=head1 SYNOPSIS
ghostscript-cjk-config [B<OPTION>]...
=head1 OPTIONS
=over 4
=item B<-h>, B<--help>
Display a short help message and exit.
=back
=head1 DESCRIPTION
setup the available fonts for use with ghostscript-cjk
=head1 AUTHOR
Mike FABIAN <I<mfabian@suse.de>>, 2005.
=cut
######################################################################
use strict;
use utf8;
use English;
use Getopt::Long;
######################################################################
# global variables:
my $script_start_time = time();
my $cvs_id = '$Id: ghostscript-cjk-config,v 1.8 2005/03/17 11:29:45 mfabian Exp $';
my $cvs_date = '$Date: 2005/03/17 11:29:45 $';
$cvs_date =~ /^\$[[:alpha:]]+: (.*) \$$/;
my $version = $1;
my $original_wd;
chomp ($original_wd = `pwd`);
# external binaries:
my $fc_list_bin = search_executable ("/usr/bin/fc-list", "/usr/X11R6/bin/fc-list");
my $ftdump_bin = search_executable ("/usr/bin/ftdump");
# directories:
my $xfontdir = "/usr/X11R6/lib/X11/fonts/truetype";
my $gsresourcedir = "/usr/share/ghostscript/Resource";
# only for Ghostscript 8.x
my $autogen_tag = "autogenerated by ghostscript-cjk-config";
my $cidfmap_header = ""
. "%!\n"
. "% The map is a set of records, which must use one of the two formats :\n"
. "%\n"
. "% 1. A substitution of a CIF font with another CID font :\n"
. "%\n"
. "% /substituted /original ;\n"
. "%\n"
. "% Where 'substituted' is a name being used in a document,\n"
. "% 'original' is a name of an available resource.\n"
. "%\n"
. "% 2. A substutution of a CIF font with a True Type font :\n"
. "%\n"
. "% /substituted << /FileType /TrueType /Path (path) /SubfontID 1 /CSI [(ordering) supplement] >> ;\n"
. "%\n"
. "% Where 'substituted' is a name being used in a document,\n"
. "% 'path' is a path to a True Type font file,\n"
. "% 'ordering' is a value of Ordering required for CIDSystemInfo dictionary,\n"
. "% 'supplement' is a value of Supplement required for CIDSystemInfo dictionary.\n"
. "%\n"
. "% Examples :\n"
. "% \n"
. "% /ShinGo-Bold /HeiseiKakuGo-W5 ;\n"
. "% /Ryumin-Medium << /FileType /TrueType /Path (/usr/X11R6/lib/X11/fonts/truetype/sazanami-mincho.ttf) /SubfontID 0 /CSI [(Japan1) 2] >> ;\n"
. "%\n"
. "% When there are two entries for the same substitution, the first one\n"
. "% will win.\n"
. "% Therefore, if you want to add manually tuned substitutions,\n"
. "% add them above all autogenerated entries.\n"
. "% Each autogenerated entry is marked by a comment:\n"
. "% '% $autogen_tag'\n"
. "%\n";
my %cidfmap_auto = ();
# only for Ghostscript 7.x
my %install_scripts = (
"alias-aj1.sh" , "Adobe-Japan1",
"alias-aj2.sh" , "Adobe-Japan2",
"alias-ak1.sh" , "Adobe-Korea1",
"alias-ac1.sh" , "Adobe-CNS1",
"alias-ag1.sh" , "Adobe-GB1"
);
# wrapper files to fake bold and italic:
# (only for Ghostscript 7.x)
my $fake_tag = "faked by ghostscript-cjk-config";
my $fake_bold_wrapper_template = ""
. "%!PS-Adobe-3.0 Resource-CIDFont\n"
. "%%BeginResource: CIDFont (__Font-Faked__)\n"
. "%% $fake_tag\n"
. "/__Font-Faked__\n"
. "/__Font-Original__ /CIDFont findresource\n"
. "16 dict begin\n"
. " /basecidfont exch def\n"
. " /basefont-H /.basefont-H /Identity-H [ basecidfont ] composefont def\n"
. " /basefont-V /.basefont-V /Identity-V [ basecidfont ] composefont def\n"
. " /CIDFontName dup basecidfont exch get def\n"
. " /CIDFontType 1 def\n"
. " /CIDSystemInfo dup basecidfont exch get def\n"
. " /FontInfo dup basecidfont exch get def\n"
. " /FontMatrix [ 1 0 0 1 0 0 ] def\n"
. " /FontBBox [\n"
. " basecidfont /FontBBox get cvx exec\n"
. " 4 2 roll basecidfont /FontMatrix get transform\n"
. " 4 2 roll basecidfont /FontMatrix get transform\n"
. " ] def\n"
. " /cid 2 string def\n"
. " /BuildGlyph {\n"
. " gsave\n"
. " exch begin\n"
. " dup 256 idiv cid exch 0 exch put\n"
. " 256 mod cid exch 1 exch put\n"
. " rootfont /WMode known { rootfont /WMode get 1 eq } { false } ifelse\n"
. " { basefont-V } { basefont-H } ifelse setfont\n"
. " .03 setlinewidth 1 setlinejoin\n"
. " newpath\n"
. " 0 0 moveto cid false charpath stroke\n"
. " 0 0 moveto cid show\n"
. " currentpoint setcharwidth\n"
. " end\n"
. " grestore\n"
. " } bind def\n"
. " currentdict\n"
. "end\n"
. "/CIDFont defineresource pop\n"
. "%%EndResource\n"
. "%%EOF\n";
my $fake_italic_wrapper_template = ""
. "%!PS-Adobe-3.0 Resource-CIDFont\n"
. "%%BeginResource: CIDFont (__Font-Faked__)\n"
. "%% $fake_tag\n"
. "/__Font-Faked__\n"
. "/__Font-Original__ /CIDFont findresource\n"
. "dup length dict begin { 1 index /FontMatrix eq { [1 0 .3 1 0 0] matrix concatmatrix def } { def } ifelse } forall currentdict end\n"
. "/CIDFont defineresource pop\n"
. "%%EndResource\n"
. "%%EOF\n";
my $fake_bolditalic_wrapper_template = ""
. "%!PS-Adobe-3.0 Resource-CIDFont\n"
. "%%BeginResource: CIDFont (__Font-Faked__)\n"
. "%% $fake_tag\n"
. "/__Font-Faked__\n"
. "/__Font-Original__ /CIDFont findresource\n"
. "16 dict begin\n"
. " /basecidfont exch def\n"
. " /basefont-H /.basefont-H /Identity-H [ basecidfont ] composefont def\n"
. " /basefont-V /.basefont-V /Identity-V [ basecidfont ] composefont def\n"
. " /CIDFontName dup basecidfont exch get def\n"
. " /CIDFontType 1 def\n"
. " /CIDSystemInfo dup basecidfont exch get def\n"
. " /FontInfo dup basecidfont exch get def\n"
. " /FontMatrix [ 1 0 0 1 0 0 ] def\n"
. " /FontBBox [\n"
. " basecidfont /FontBBox get cvx exec\n"
. " 4 2 roll basecidfont /FontMatrix get transform\n"
. " 4 2 roll basecidfont /FontMatrix get transform\n"
. " ] def\n"
. " /cid 2 string def\n"
. " /BuildGlyph {\n"
. " gsave\n"
. " exch begin\n"
. " dup 256 idiv cid exch 0 exch put\n"
. " 256 mod cid exch 1 exch put\n"
. " rootfont /WMode known { rootfont /WMode get 1 eq } { false } ifelse\n"
. " { basefont-V } { basefont-H } ifelse setfont\n"
. " .03 setlinewidth 1 setlinejoin\n"
. " newpath\n"
. " 0 0 moveto cid false charpath stroke\n"
. " 0 0 moveto cid show\n"
. " currentpoint setcharwidth\n"
. " end\n"
. " grestore\n"
. " } bind def\n"
. " currentdict\n"
. "end\n"
. "dup length dict begin { 1 index /FontMatrix eq { [1 0 .3 1 0 0] matrix concatmatrix def } { def } ifelse } forall currentdict end\n"
. "/CIDFont defineresource pop\n"
. "%%EndResource\n"
. "%%EOF\n";
my $cmap_wrapper_template = ""
. "%!PS-Adobe-3.0 Resource-Font\n"
. "%%Creator: $fake_tag\n"
. "%%DocumentNeededResources: __CMap__ (CMap)\n"
. "%%IncludeResource: __CMap__ (CMap)\n"
. "%%BeginResource: Font (__Font__-__CMap__)\n"
. "(__Font__-__CMap__)\n"
. "(__CMap__) /CMap findresource\n"
. "[(__Font__) /CIDFont findresource]\n"
. "composefont pop\n"
. "%%EndResource\n"
. "%%EOF\n";
my @cmaps = ("78-EUC-H",
"78-EUC-V",
"78-H",
"78-RKSJ-H",
"78-RKSJ-V",
"78-V",
"78ms-RKSJ-H",
"78ms-RKSJ-V",
"83pv-RKSJ-H",
"90ms-RKSJ-H",
"90ms-RKSJ-UCS2",
"90ms-RKSJ-V",
"90msp-RKSJ-H",
"90msp-RKSJ-V",
"90pv-RKSJ-H",
"90pv-RKSJ-UCS2",
"90pv-RKSJ-UCS2C",
"90pv-RKSJ-V",
"Add-H",
"Add-RKSJ-H",
"Add-RKSJ-V",
"Add-V",
"Adobe-CNS1-0",
"Adobe-CNS1-1",
"Adobe-CNS1-2",
"Adobe-CNS1-3",
"Adobe-CNS1-4",
"Adobe-CNS1-B5pc",
"Adobe-CNS1-ETen-B5",
"Adobe-CNS1-H-CID",
"Adobe-CNS1-H-Host",
"Adobe-CNS1-H-Mac",
"Adobe-CNS1-UCS2",
"Adobe-GB1-0",
"Adobe-GB1-1",
"Adobe-GB1-2",
"Adobe-GB1-3",
"Adobe-GB1-4",
"Adobe-GB1-GBK-EUC",
"Adobe-GB1-GBpc-EUC",
"Adobe-GB1-H-CID",
"Adobe-GB1-H-Host",
"Adobe-GB1-H-Mac",
"Adobe-GB1-UCS2",
"Adobe-Japan1-0",
"Adobe-Japan1-1",
"Adobe-Japan1-2",
"Adobe-Japan1-3",
"Adobe-Japan1-4",
"Adobe-Japan1-90ms-RKSJ",
"Adobe-Japan1-90pv-RKSJ",
"Adobe-Japan1-H-CID",
"Adobe-Japan1-H-Host",
"Adobe-Japan1-H-Mac",
"Adobe-Japan1-PS-H",
"Adobe-Japan1-PS-V",
"Adobe-Japan1-UCS2",
"Adobe-Japan2-0",
"Adobe-Korea1-0",
"Adobe-Korea1-1",
"Adobe-Korea1-2",
"Adobe-Korea1-H-CID",
"Adobe-Korea1-H-Host",
"Adobe-Korea1-H-Mac",
"Adobe-Korea1-KSCms-UHC",
"Adobe-Korea1-KSCpc-EUC",
"Adobe-Korea1-UCS2",
"B5-H",
"B5-V",
"B5pc-H",
"B5pc-UCS2",
"B5pc-UCS2C",
"B5pc-V",
"CNS-EUC-H",
"CNS-EUC-V",
"CNS01-RKSJ-H",
"CNS02-RKSJ-H",
"CNS03-RKSJ-H",
"CNS04-RKSJ-H",
"CNS05-RKSJ-H",
"CNS06-RKSJ-H",
"CNS07-RKSJ-H",
"CNS1-H",
"CNS1-V",
"CNS15-RKSJ-H",
"CNS2-H",
"CNS2-V",
"ETHK-B5-H",
"ETHK-B5-V",
"ETen-B5-H",
"ETen-B5-UCS2",
"ETen-B5-V",
"ETenms-B5-H",
"ETenms-B5-V",
"EUC-H",
"EUC-V",
"Ext-H",
"Ext-RKSJ-H",
"Ext-RKSJ-V",
"Ext-V",
"GB-EUC-H",
"GB-EUC-V",
"GB-H",
"GB-RKSJ-H",
"GB-V",
"GBK-EUC-H",
"GBK-EUC-UCS2",
"GBK-EUC-V",
"GBK2K-H",
"GBK2K-V",
"GBKp-EUC-H",
"GBKp-EUC-V",
"GBT-EUC-H",
"GBT-EUC-V",
"GBT-H",
"GBT-RKSJ-H",
"GBT-V",
"GBTpc-EUC-H",
"GBTpc-EUC-V",
"GBpc-EUC-H",
"GBpc-EUC-UCS2",
"GBpc-EUC-UCS2C",
"GBpc-EUC-V",
"H",
"HK-RKSJ-H",
"HKdla-B5-H",
"HKdla-B5-V",
"HKdlb-B5-H",
"HKdlb-B5-V",
"HKgccs-B5-H",
"HKgccs-B5-V",
"HKm314-B5-H",
"HKm314-B5-V",
"HKm471-B5-H",
"HKm471-B5-V",
"HKscs-B5-H",
"HKscs-B5-V",
"Hankaku",
"Hiragana",
"Hojo-EUC-H",
"Hojo-EUC-V",
"Hojo-H",
"Hojo-RKSJ-H",
"Hojo-V",
"Identity-H",
"Identity-V",
"KSC-EUC-H",
"KSC-EUC-V",
"KSC-H",
"KSC-Johab-H",
"KSC-Johab-V",
"KSC-RKSJ-H",
"KSC-V",
"KSC2-RKSJ-H",
"KSCms-UHC-H",
"KSCms-UHC-HW-H",
"KSCms-UHC-HW-V",
"KSCms-UHC-UCS2",
"KSCms-UHC-V",
"KSCpc-EUC-H",
"KSCpc-EUC-UCS2",
"KSCpc-EUC-UCS2C",
"KSCpc-EUC-V",
"Katakana",
"NWP-H",
"NWP-V",
"RKSJ-H",
"RKSJ-V",
"Roman",
"TCVN-RKSJ-H",
"UCS2-90ms-RKSJ",
"UCS2-90pv-RKSJ",
"UCS2-B5pc",
"UCS2-ETen-B5",
"UCS2-GBK-EUC",
"UCS2-GBpc-EUC",
"UCS2-KSCms-UHC",
"UCS2-KSCpc-EUC",
"UniCNS-UCS2-H",
"UniCNS-UCS2-V",
"UniCNS-UTF16-H",
"UniCNS-UTF16-V",
"UniCNS-UTF32-H",
"UniCNS-UTF32-V",
"UniCNS-UTF8-H",
"UniCNS-UTF8-V",
"UniGB-UCS2-H",
"UniGB-UCS2-V",
"UniGB-UTF8-H",
"UniGB-UTF8-V",
"UniHojo-UCS2-H",
"UniHojo-UCS2-V",
"UniHojo-UTF16-H",
"UniHojo-UTF16-V",
"UniHojo-UTF32-H",
"UniHojo-UTF32-V",
"UniHojo-UTF8-H",
"UniHojo-UTF8-V",
"UniJIS-UCS2-H",
"UniJIS-UCS2-HW-H",
"UniJIS-UCS2-HW-V",
"UniJIS-UCS2-V",
"UniJIS-UTF8-H",
"UniJIS-UTF8-V",
"UniJISPro-UCS2-HW-V",
"UniJISPro-UCS2-V",
"UniJISPro-UTF8-V",
"UniKS-UCS2-H",
"UniKS-UCS2-V",
"UniKS-UTF16-H",
"UniKS-UTF16-V",
"UniKS-UTF32-H",
"UniKS-UTF32-V",
"UniKS-UTF8-H",
"UniKS-UTF8-V",
"V",
"WP-Symbol");
# command line options:
my $OPT_VERBOSITY;
my $OPT_VERSION;
my $OPT_HELP;
my $OPT_FORCE;
my $OPT_REMOVE_FAKES;
######################################################################
sub install_ps_name {
# only for Ghostscript 7.x
#
# installs the first existing font from the list using the supplied
# PostScript-name.
#
my ($install_script, $postscript_name, @font_list) = @_;
if ( -x "$gsresourcedir/$install_script" ) {
for my $font (@font_list) {
my $font_full_path;
if ($font !~ /\//) {
$font_full_path = "$xfontdir/$font";
}
else {
$font_full_path = $font;
}
if ( -f "$font_full_path" ) {
if ( -f "$gsresourcedir/CIDFont/$postscript_name" ) {
open (FONT, "$gsresourcedir/CIDFont/$postscript_name")
|| die "can't open file $gsresourcedir/CIDFont/$postscript_name: $!";
while (<FONT>) {
if ($ARG =~ /$font_full_path/) {
my $registry_ordering = $install_scripts{$install_script};
if ( -f "$gsresourcedir/Font/$postscript_name-$registry_ordering-0") {
# this font is already installed, save some time and don't
# do it again
close (FONT);
return;
}
}
}
close (FONT);
}
chdir "$gsresourcedir";
print "+${postscript_name}=${font_full_path}\n";
my_system (" ./$install_script uninstall $postscript_name > /dev/null");
my_system (" ./$install_script install $postscript_name=$font_full_path > /dev/null");
return;
}
}
}
}
######################################################################
sub install {
# only for Ghostscript 7.x
my ($install_script, @font_list) = @_;
for my $font (@font_list) {
my $font_full_path;
if ($font !~ /\//) {
$font_full_path = "$xfontdir/$font";
}
else {
$font_full_path = $font;
}
if ( -f "$font_full_path" && $ftdump_bin ) {
my $postscript_name = get_ps_name_from_file_name ("$font_full_path");
if ($postscript_name ne "") {
install_ps_name ($install_script, $postscript_name, $font_full_path);
}
}
}
}
######################################################################
sub get_ps_name_from_file_name {
my ($font) = @_;
# quote " in font names:
$font =~ s/\"/\\\"/g;
open (FONT, "ftdump \"$font\" 2>/dev/null |");
# Apparently there are some fonts which have non-ASCII PostScript names.
# If we are running in a UTF-8 locale, Perl will complain
# "Malformed UTF-8 character"
# when reading the ftdump output of such a font.
# Avoid that error by using the layer ":bytes" for this file handle.
binmode FONT, ":bytes";
my $postscript = "";
while (<FONT>) {
# the following regexp should work with ftdump from
# either Freetype-1 or Freetype-2
if ($ARG =~ /postscript.*:\s+([[:alnum:]\-.]+?)\s*$/i) {
$postscript = $1;
if ($postscript eq "UNAVAILABLE") {
$postscript = "";
}
last;
}
}
close (FONT);
return ($postscript);
}
######################################################################
sub add_cidfmap_auto_entry {
my ($postscript, $font_file, $face_number, $ordering, $supplement) = @_;
my $entry = "/$postscript << /FileType /TrueType /Path ($font_file) /SubfontID $face_number /CSI [($ordering) $supplement] >> ; % $autogen_tag \n";
if ($OPT_VERBOSITY >= 1) {
print "entry: $entry";
}
$cidfmap_auto{$entry} = 1;
}
######################################################################
sub add_cidfmap_auto_entry_for_postscript_name {
my ($postscript, $ordering, $supplement, @family_names) = @_;
for my $family_name (@family_names) {
if ($OPT_VERBOSITY >= 1) {
print "searching for family name \"$family_name\" ...\n";
}
open (FONT_LIST, "fc-list \"$family_name\" file index|");
binmode FONT_LIST, ":bytes";
while (<FONT_LIST>) {
my $font_file = "";
my $face_number = -1;
$ARG =~ /(.*):[[:space:]]*:index=([0-9]+)[[:space:]]*$/;
$font_file = $1;
$face_number = $2;
if ($OPT_VERBOSITY >=1) {
print "fc-list output: $ARG";
print " -> font_file=$font_file, face_number=$face_number\n";
}
# resolve symlink:
while (-l $font_file) {
$font_file = readlink ($font_file);
}
if (-r $font_file &&
$font_file =~ /\.ttf$|\.ttc$|\.otf/i && $face_number >= 0) {
add_cidfmap_auto_entry($postscript,
$font_file,
$face_number,
$ordering, $supplement);
if ($OPT_VERBOSITY >= 1) {
print "\"$postscript\" entry for \"$family_name\" created sucessfully\n";
}
return;
}
}
close (FONT_LIST);
}
}
######################################################################
sub add_all_cidfmap_auto_entries_from_file_name {
# generate config entries for using the "real" PostScript name
# for all faces found in the file $font_file
my ($font_file, $ordering, $supplement) = @_;
# resolve symlink:
while (-l $font_file) {
$font_file = readlink ($font_file);
}
if (-r $font_file ) {
# quote " in font names:
my $font_file_quoted;
($font_file_quoted = $font_file) =~ s/\"/\\\"/g;
open (FONT, "ftdump \"$font_file_quoted\" 2>/dev/null |");
# Apparently there are some fonts which have non-ASCII PostScript names.
# If we are running in a UTF-8 locale, Perl will complain
# "Malformed UTF-8 character"
# when reading the ftdump output of such a font.
# Avoid that error by using the layer ":bytes" for this file handle.
binmode FONT, ":bytes";
my $postscript = "";
my $family = "";
my $style = "";
my $face_number = -1;
while (<FONT>) {
if ($ARG =~ /face.*number.*:\s*([0-9]+)\s*/i) {
$face_number = $1;
$postscript = "";
$family = "";
$style = "";
}
# the following regexp should work with ftdump from
# either Freetype-1 or Freetype-2
if ($ARG =~ /postscript.*:\s+([[:alnum:]\-]+?)\s*$/i) {
$postscript = $1;
if ($postscript eq "UNAVAILABLE") {
$postscript = "";
}
}
if ($ARG =~ /family.*:\s+([[:alnum:]].*[[:alnum:]])\s*$/i) {
$family = $1;
}
if ($ARG =~ /style.*:\s+([[:alnum:]].*[[:alnum:]])\s*$/i) {
$style = $1;
}
if ($face_number >= 0 && $postscript ne "" && $family ne "" && $style ne "") {
add_cidfmap_auto_entry($postscript,
$font_file,
$face_number,
$ordering, $supplement);
$face_number = -1;
}
}
close (FONT);
}
}
######################################################################
sub update_cidfmap {
for my $cidfmap_dir (glob ("/etc/ghostscript/[0-9]*")) {
if (-e $cidfmap_dir) {
my $file = "$cidfmap_dir/cidfmap";
my $cidfmap_user = "";
if (-r $file) {
open (CIDFMAP, "<$file") || die "can't open file $file: $!";
if ($OPT_VERBOSITY >= 1) {
printf "reading user data from $file ...\n";
}
while (<CIDFMAP>) {
# skip autogenerated data
if ($ARG =~ /$autogen_tag/) {
next;
}
# skip empty lines
if ($ARG =~ /^[[:space:]]*$/) {
next;
}
if ($ARG =~ /([^%]*)%?.*/) { # strip comments
$ARG = $1;
}
$cidfmap_user .= $ARG;
}
close (CIDFMAP);
}
open (CIDFMAP, ">$file") || die "can't open file $file: $!";
print CIDFMAP $cidfmap_header;
print CIDFMAP "\n\n% manually edited entries:\n";
print CIDFMAP $cidfmap_user;
print CIDFMAP "\n\n% autogenerated entries:\n";
for my $entry (sort (keys %cidfmap_auto)) {
print CIDFMAP $entry;
}
close (CIDFMAP);
}
}
}
######################################################################
sub generate_fake_bold_and_italic_fonts {
# this doesn't work anymore with Ghotscript 8.x
return;
chdir "$gsresourcedir/CIDFont" ||die "Can't cd to $gsresourcedir/CIDFont: $!\n";
for my $font (glob ("*")) {
my $font_bold = $font;
my $font_italic = $font;
my $font_bolditalic = $font;
if ($font_bold !~ /Bold/i && $font_bold !~ /Italic/i) {
for my $style (("Light", "Medium", "Regular")) {
if ($font_bold =~ /${style}/i) {
$font_bold =~ s/${style}/Bold/i;
last;
}
}
if ($font_bold !~ /Bold/i) {
$font_bold = $font_bold . "-Bold";
}
}
if ($font_italic !~ /Bold/i && $font_italic !~ /Italic/i) {
for my $style (("Light", "Medium", "Regular")) {
if ($font_italic =~ /${style}/i) {
$font_italic =~ s/${style}/Italic/i;
last;
}
}
if ($font_italic !~ /Italic/i) {
$font_italic = $font_italic . "-Italic";
}
}
if ($font_bolditalic !~ /Bold/i && $font_bolditalic !~ /Italic/i) {
for my $style (("Light", "Medium", "Regular")) {
if ($font_bolditalic =~ /${style}/i) {
$font_bolditalic =~ s/${style}/BoldItalic/i;
last;
}
}
if ($font_bolditalic !~ /BoldItalic/i) {
$font_bolditalic = $font_bolditalic . "-BoldItalic";
}
}
if ("$font_bold" ne "$font") {
generate_fake ("$font", "$font_bold", "$fake_bold_wrapper_template");
}
if ("$font_italic" ne "$font") {
generate_fake ("$font", "$font_italic", "$fake_italic_wrapper_template");
}
if ("$font_bolditalic" ne "$font") {
generate_fake ("$font", "$font_bolditalic", "$fake_bolditalic_wrapper_template");
}
}
}
######################################################################
sub generate_fake {
my ($font_original, $font_faked, $wrapper) = @_;
# this doesn't work anymore with Ghostscript 8.x
return;
$wrapper =~ s/__Font-Original__/$font_original/g;
$wrapper =~ s/__Font-Faked__/$font_faked/g;
if ( ! -f "$gsresourcedir/CIDFont/$font_faked" ) {
open (WRAPPER, "> $gsresourcedir/CIDFont/$font_faked")
|| die "cannot open $gsresourcedir/CIDFont/$font_faked for writing: $!";
printf WRAPPER "%s", $wrapper;
close (WRAPPER);
}
# find out which wrappers for which CMaps exist for the original font
# and generate wrappers for the same CMaps for the faked font as well:
chdir "$gsresourcedir/Font" ||die "Can't cd to $gsresourcedir/Font: $!\n";
for my $font (glob ("$font_original-*")) {
my $cmap;
($cmap = $font) =~ s/$font_original-(.*)/$1/;
# $cmap might contain more than just the CMap here
# as there may be other fonts whose name starts just like $font_original
# but is longer.
# Check if we have found a really existing CMap:
if (grep (/$cmap/, @cmaps)) {
# now generate a wrapper file if it doesn't exist yet:
if ( ! -f "$gsresourcedir/Font/$font_faked-$cmap" ) {
if ($OPT_VERBOSITY >= 1) {
printf "creating $gsresourcedir/Font/$font_faked-$cmap\n";
}
open (WRAPPER, "> $gsresourcedir/Font/$font_faked-$cmap")
|| die "cannot open $gsresourcedir/Font/$font_faked-$cmap for writing: $!";
my $cmap_wrapper = $cmap_wrapper_template;
$cmap_wrapper =~ s/__CMap__/$cmap/g;
$cmap_wrapper =~ s/__Font__/$font_faked/g;
printf WRAPPER "%s", $cmap_wrapper;
close (WRAPPER);
}
}
}
}
######################################################################
sub clean_up {
# only for Ghostscript 7.x
for my $font (glob ("$gsresourcedir/CIDFont/*")) {
my $postscript_name;
($postscript_name = $font) =~ s/.*\/([^\/]+)/$1/;
if ( -f "$font") {
open (FONT, "$font") || die "can't open file $font: $!";
while (<FONT>) {
if ($ARG =~ /\((.+)\)[[:space:]]+\.openttcidfont/) {
my $ttfont = $1;
if ( ! -f "$ttfont" ) {
print "deleting $postscript_name\n";
my_system ("rm -f \"$gsresourcedir\"/{CIDFont,Font}/\"$postscript_name\"");
my_system ("rm -f \"$gsresourcedir\"/{CIDFont,Font}/\"$postscript_name-Bold\"");
my_system ("rm -f \"$gsresourcedir\"/{CIDFont,Font}/\"$postscript_name-BoldItalic\"");
my_system ("rm -f \"$gsresourcedir\"/{CIDFont,Font}/\"$postscript_name-Italic\"");
}
}
}
close (FONT);
}
}
}
######################################################################
sub list_font_files {
my ($language) = @_;
my %font_files = ();
open (FONT_LIST, "fc-list :lang=$language:outline=true file |");
binmode FONT_LIST, ":bytes";
while (<FONT_LIST>) {
$ARG =~ s/(.*):[[:space:]]*$/$1/;
if ($ARG =~ /\.ttf$|\.ttc$|\.otf/i) {
if (-l $ARG ) {
# resolve symlink:
$font_files{readlink ($ARG)} = 1;
}
else {
$font_files{$ARG} = 1;
}
}
}
close (FONT_LIST);
return (sort (keys %font_files));
}
######################################################################
sub remove_fakes {
# remove wrappers for fake bold and italic
my $cwd;
for my $dir (("$gsresourcedir/CIDFont", "$gsresourcedir/Font")) {
chdir "$dir" || die "Can't cd to $dir: $!\n";
for my $file (glob ("*")) {
if (! my_system ("grep -q \"$fake_tag\" $file")) {
if ($OPT_VERBOSITY >= 1) {
print "$file is faked, remove it\n";
}
unlink($file);
}
}
}
chdir $original_wd || die "Can't cd to $original_wd: $!\n";
}
######################################################################
sub remove_old_gs_cjk_wrappers {
# the wrapper files created by the gs-cjk project do not work
# anymore with Ghostscript 8.x, so they should be removed.
my $cwd;
for my $dir (("$gsresourcedir/CIDFont", "$gsresourcedir/Font")) {
chdir "$dir" || die "Can't cd to $dir: $!\n";
for my $file (glob ("*")) {
if (! my_system ("grep -q \"Creator: aliascid.ps\" $file")) {
if ($OPT_VERBOSITY >= 1) {
print "$file created by gs-cjk won't work anymore with Ghostscript 8.x. Remove it.\n";
}
unlink($file);
}
}
}
chdir $original_wd || die "Can't cd to $original_wd: $!\n";
}
######################################################################
sub search_executable {
for my $file (@_) {
if (-x $file) {
return $file;
}
}
return "";
}
######################################################################
sub my_system {
my ($command) = @_;
if ($OPT_VERBOSITY >= 1) {
print "executing: $command\n";
}
return system ($command);
}
######################################################################
sub usage {
print "Usage: ghostscript-cjk-config [option] ...\n";
print "-v, --verbosity number print some progress messages to standard output.\n";
print " --version display version and exit.\n";
print "-h, --help display this help and exit.\n";
print " --force force update of all generated files.\n";
print "-r, --remove-fakes remove generated wrappers to fake bold and italic.\n";
exit 1;
}
######################################################################
# main:
# Process command line options
my %opt;
unless (GetOptions(\%opt,
'verbosity=i', \$OPT_VERBOSITY,
'version', \$OPT_VERSION,
'help|h', \$OPT_HELP,
'force', \$OPT_FORCE,
'remove-fakes|r', \$OPT_REMOVE_FAKES,
)) {
&usage ();
exit 1;
}
if (!defined $OPT_VERBOSITY) { $OPT_VERBOSITY = 0; }
if (!defined $OPT_VERSION) { $OPT_VERSION = 0; }
if (!defined $OPT_HELP) { $OPT_HELP = 0; }
if (!defined $OPT_FORCE) { $OPT_FORCE = 0; }
if (!defined $OPT_REMOVE_FAKES) { $OPT_REMOVE_FAKES = 1; }
if ($OPT_VERSION) {
print "ghostscript-cjk-config $version\n";
exit 0;
}
if ($OPT_HELP) {
&usage ();
exit 0;
}
# check if we are started as root
# only one of UID and USER must be set correctly
if ($UID != 0 && $ENV{USER} !~ /root/) {
print "*** Error: You must be root to start $0\n";
usage();
exit 1;
}
# remove files which cannot work anymore with Ghostscript 8.x
# so that no useless junk remains after an update:
remove_old_gs_cjk_wrappers();
remove_fakes();
# generate config entries for all fonts using their "real" PostScript name:
if ($ftdump_bin && $fc_list_bin) {
for my $file (list_font_files ("ja")) {
add_all_cidfmap_auto_entries_from_file_name ("$file", "Japan1", "2");
}
for my $file (list_font_files ("ko")) {
add_all_cidfmap_auto_entries_from_file_name ("$file", "Korea1", "2");
}
for my $file (list_font_files ("zh-tw")) {
add_all_cidfmap_auto_entries_from_file_name ("$file", "CNS1", "2");
}
for my $file (list_font_files ("zh-cn")) {
add_all_cidfmap_auto_entries_from_file_name ("$file", "GB1", "2");
}
}
# generate config entries for standard PostScript names:
add_cidfmap_auto_entry_for_postscript_name ("Ryumin-Light", "Japan1", "2",
# "HG\\-MinchoL\\-Sun", # does not work yet
"MS Mincho",
"MS PMincho",
"HGMinchoL",
"HGPMinchoL",
"TLMincho",
"IPAMincho",
"IPAPMincho",
"Sazanami Mincho",
"Kochi Mincho");
add_cidfmap_auto_entry_for_postscript_name ("Adobe-Japan1", "Japan1", "2",
# "HG\\-MinchoL\\-Sun", # does not work yet
"MS Mincho",
"MS PMincho",
"HGMinchoL",
"HGPMinchoL",
"TLMincho",
"IPAMincho",
"IPAPMincho",
"Sazanami Mincho",
"Kochi Mincho");
add_cidfmap_auto_entry_for_postscript_name ("GothicBBB-Medium", "Japan1", "2",
# "HG\\-GothicB\\-Sun", # does not work yet
"MS Gothic",
"MS PGothic",
"MS UI Gothic",
"HGGothicB",
"HGPGothicB",
"TLGothic",
"IPAGothic",
"IPAPGothic",
"IPAUIGothic",
"Sazanami Gothic",
"Kochi Gothic");
add_cidfmap_auto_entry_for_postscript_name ("Adobe-Korea1", "Korea1", "2",
"Baekmuk Gulim",
"Baekmuk Dotum");
add_cidfmap_auto_entry_for_postscript_name ("GB-Song-Medium", "GB1", "2",
"FZSongTi",
"AR PL SungtiL GB",
"HanyiSong");
add_cidfmap_auto_entry_for_postscript_name ("Adobe-GB1", "GB1", "2",
"FZSongTi",
"AR PL SungtiL GB",
"HanyiSong");
add_cidfmap_auto_entry_for_postscript_name ("GB-Kai-Medium", "GB1", "2",
"FZKaiTi",
"AR PL KaitiM GB");
add_cidfmap_auto_entry_for_postscript_name ("GB-FangSong-Medium", "GB1", "2",
"FZFangSong");
add_cidfmap_auto_entry_for_postscript_name ("GB-Hei-Medium", "GB1", "2",
"FZHeiTi");
add_cidfmap_auto_entry_for_postscript_name ("B5-Song-Medium", "CNS1", "2",
"FZMingTiB",
"FZMingTi",
"AR PL Mingti2L Big5");
add_cidfmap_auto_entry_for_postscript_name ("Adobe-CNS1", "CNS1", "2",
"FZMingTiB",
"FZMingTi",
"AR PL Mingti2L Big5");
add_cidfmap_auto_entry_for_postscript_name ("B5-Kai-Medium", "CNS1", "2",
"FZKaiTiB",
"AR PL KaitiM Big5");
update_cidfmap ();
chdir $original_wd ||die "Can't cd to $original_wd: $!\n";
exit 0;