home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2007 January, February, March & April
/
Chip-Cover-CD-2007-02.iso
/
boot
/
i386
/
root
/
usr
/
sbin
/
fonts-config
< prev
next >
Wrap
Text File
|
2006-11-29
|
74KB
|
2,335 lines
#! /usr/bin/perl -w # -*- perl -*-
#
# Copyright (c) 2000-2004 SuSE Linux AG, Nuernberg, Germany.
# All rights reserved.
#
########################################################################
# create a man-page with:
#
# pod2man --section 1 --center=" " fonts-config | gzip -9 -c > fonts-config.1.gz
# cp fonts-config.1.gz /usr/share/man/man1/fonts-config.1.gz
=head1 NAME
fonts-config - configures installed X11 fonts.
=head1 SYNOPSIS
fonts-config [B<OPTION>]...
=head1 OPTIONS
=over 4
=item B<-f>, B<--force>
Force the update of all generated files even if it appears to be
unnecessary according to the time stamps.
=item B<-q>, B<--quiet>
Work silently, unless an error occurs.
=item B<-v>, B<--verbose>
Print some progress messages to standard output.
=item B<-d>, B<--debug>
Print a lot of debugging messages to standard output.
=item B<--(no)gs-fontmap>
Generate (or don't generate) a Fontmap for Ghostscript.
Can only work if the 'ftdump' binary which is in the 'ft2demos'
packages is available.
=item B<--(no)ttcap>
Generate (or don't generate) TTCap entries. TTCap entries can be used
with the xtt module and with recent versions of the freetype module.
=item B<--(no)ooo>
Generate (or don't generate) font setup for OpenOffice
=item B<--(no)java>
Generate (or don't generate) font setup for Java 1.4.x and Java 1.5.x.
=item B<--bcbwmax> size
Maximum pixel size to use the byte code interpreter with black and
white rendering.
=item B<--version>
Display version and exit.
=item B<-h>, B<--help>
Display a short help message and exit.
=back
=head1 DESCRIPTION
Configures installed X11 fonts. Basically it does the following
things:
=over 4
=item B<call cidfont-x11-config>
cidfont-x11-config is another little perl script which configures
CID-keyed fonts for use with X11, see L<cidfont-x11-config(1)>.
=item B<creates fonts.scale and fonts.dir files>
To find the list of directories currently used for server side fonts,
B</etc/X11/xorg.conf> is parsed and merged with a hardcoded list of
directories. If the font server xfs is running, B</etc/X11/fs/config>
is also parsed and the list of directories found there is merged as
well.
For each directory from this list, the time stamps of the directory,
the B<fonts.scale> file, the B<fonts.dir> file and an extra time stamp
file B<.fonts-config-timestamp> are checked. If not all the time
stamps are equal or any of these files is missing, the B<fonts.scale>
and B<fonts.dir> files will be updated as follows:
First of all a B<fonts.scale> file is created by calling
B<mkfontscale>.
Then, the entries found in the B<fonts.scale> file are merged with
the entries from all B<fonts.scale.*> files.
B<fonts.scale.*> files may be supplied by rpm-packages or manually
added by the user to override or amend the entries created
automatically by B<mkfontscale>. Entries in a B<fonts.scale.*> file
have higher priority than entries automatically created by
B<mkfontscale>. All entries generated automatically by B<mkfontscale>
for a certain font file are discarded if any B<fonts.scale.*> file
contains an entry for the same font file.
If the B<xtt> module is configured to load in B</etc/X11/xorg.conf>,
additional entries may be created to make use of the artificial bold
and italic features of B<xtt>. The time stamp of
B</etc/X11/xorg.conf> is not checked, i.e. you have to use
B<fonts-config --force> after editing B</etc/X11/xorg.conf> to switch
between the B<xtt> and B<freetype> modules.
After the final list of entries has been written back to
B<fonts.scale>, B<mkfontdir> is called.
Finally, the time stamps of the directory, B<fonts.scale>,
B<fonts.dir>, and B<.fonts-config-timestamp> are set to the time when
B<fonts-config> started.
If any B<fonts.scale> file in the directory list needed an update and
the option B<--gs-fontmap> is set, a Ghostcript Fontmap is also
generated for all scalable fonts in the directory list and the result
is written to B</usr/share/ghostscript/*/lib/Fontmap.X11-auto>.
=item B<call fc-cache>
creates cache files for fonts to use with client side font rendering
via fontconfig/libXft, for details see L<fc-cache(1)>.
B<fonts.cache-2> cache files are generated in B</var/cache/fontconfig>
for all directories which are configured in B</etc/fonts/fonts.conf>
and all their subdirectories.
=back
Usually B<fonts-config> is called automatically via SuSEconfig
(B<SuSEconfig --module fonts>), which is usually automatically
called by YaST2. But you can also execute B<fonts-config> directly,
which is mainly useful to debug it.
=head1 FILES
=over 4
=item B</etc/sysconfig/fonts-config>
Default values for some command line options of fonts-config are read
from this file if it exists. The options currently supported in
this file are:
=over 4
=item GENERATE_TTCAP_ENTRIES
can be set to "yes" or "no" and sets the default for the option B<--(no)ttcap>.
=item GENERATE_GHOSTSCRIPT_FONTMAPS
can be set to "yes" or "no" and sets the default for the option B<--(no)gs-fontmap>.
This can only work if the 'ftdump' binary which is in the 'ft2demos'
packages is available.
=item GENERATE_OOO_FONT_SETUP
can be set to "yes" or "no" and sets the default for the option B<--(no)ooo>.
=item GENERATE_JAVA_FONT_SETUP
can be set to "yes" or "no" and sets the default for the option B<--(no)java>.
=item BYTECODE_BW_MAX_PIXEL
can be set to any integer value and sets the default for the option B<--bcbwmax>.
=back
=back
=head1 SEE ALSO
L<fc-cache(1)>, L<cidfont-x11-config(1)>, L<mkfontdir(1)>, L<mkfontscale(1)>
=head1 AUTHOR
Mike FABIAN <I<mfabian@suse.de>>, 2003.
=cut
########################################################################
use utf8;
use English;
use Getopt::Long;
use strict;
my $script_start_time = time();
my $cvs_id = '$Id: fonts-config,v 1.68 2006/10/25 13:58:26 mfabian Exp $';
my $cvs_date = '$Date: 2006/10/25 13:58:26 $';
$cvs_date =~ /^\$[[:alpha:]]+: (.*) \$$/;
my $version = $1;
sub usage {
print "Usage: fonts-config [option] ...\n";
print "-f, --force Force the update of all generated files even\n";
print " if it appears unnecessary according to the time stamps\n";
print "-q, --quiet Work silently, unless an error occurs.\n";
print "-v, --verbose Print some progress messages to standard output.\n";
print "-d, --debug Print a lot of debugging messages to standard output.\n";
print " --(no)gs-fontmap generate a Fontmap file for Ghostscript.\n";
print " --(no)ttcap generate TTCap entries for xtt and recent freetype modules.\n";
print " --(no)ooo generate font setup for OpenOffice.\n";
print " --(no)java generate font setup for Java 1.4.x and Java 1.5.x.\n";
print " --bcbwmax size maximum pixel size to use the byte code interpreter with\n";
print " black and white rendering.\n";
print " --(no)ebitmap whether to use embedded bitmaps or not.\n";
print " --ebitmaplang string the argument is a string which contains a list of colon\n";
print " separated languages, for example \"ja:ko:zh-CN\" \n";
print " which means \"use embedded bitmaps only for\n";
print " fonts supporting Japanese, Korean, or simplified Chinese.\n";
print " --version Display version and exit.\n";
print "-h, --help Display this help and exit.\n";
exit 1;
}
my $OPT_FORCE = 0;
my $OPT_QUIET = 0;
my $OPT_VERBOSE = 1;
my $OPT_DEBUG = 0;
my $OPT_TTCAP = 0;
my $OPT_GS_FONTMAP = 1;
my $OPT_OOO = 1;
my $OPT_JAVA = 1;
my $OPT_BCBWMAX = 0;
my $OPT_EBITMAP = 1;
my $OPT_EBITMAP_LANG = "ja:ko:zh-CN:zh-TW:zh-HK:zh-SG";
my $OPT_VERSION = 0;
my $OPT_HELP = 0;
my %sysconfig_options = (
"GENERATE_TTCAP_ENTRIES" , "OPT_TTCAP",
"GENERATE_GHOSTSCRIPT_FONTMAPS" , "OPT_GS_FONTMAP",
"GENERATE_OOO_FONT_SETUP" , "OPT_OOO",
"GENERATE_JAVA_FONT_SETUP" , "OPT_JAVA",
"BYTECODE_BW_MAX_PIXEL" , "OPT_BCBWMAX",
"USE_EMBEDDED_BITMAPS" , "OPT_EBITMAP",
"EMBEDDED_BITMAPS_LANGUAGES" , "OPT_EBITMAP_LANG"
);
my $sysconfig_file = "/etc/sysconfig/fonts-config";
sub get_option_defaults_from_sysconfig {
if (open (SYSCONFIG, "$sysconfig_file")) {
no strict "vars";
# print "reading defaults from $sysconfig.\n";
while (<SYSCONFIG>) {
chomp ($ARG);
if ($ARG =~ /([^#]*)#?.*/) { # strip comments
$ARG = $1;
}
eval ("\$$ARG;");
}
close (SYSCONFIG);
for my $i (keys %sysconfig_options) {
if (eval ("\$$i") =~ /yes/i) {
eval("\$$sysconfig_options{$i}=1");
}
elsif (eval ("\$$i") =~ /no/i) {
eval("\$$sysconfig_options{$i}=0");
}
elsif (eval ("\$$i") =~ /[0-9]+/) { # Type integer
eval("\$$sysconfig_options{$i}=\$$i");
}
elsif (eval ("\$$i") =~ /[-:a-zA-Z0-9]+/) { # Type string
eval("\$$sysconfig_options{$i}=\$$i");
}
else { # this case also occurs when the variable is the empty string!
eval("\$$sysconfig_options{$i}=0");
}
}
return (0);
}
else {
# print "$sysconfig doesn't exist, using builtin defaults.\n";
return (1);
}
}
get_option_defaults_from_sysconfig();
# Process command line options
my %opt;
unless (GetOptions(\%opt,
'force|f', \$OPT_FORCE,
'quiet|q', \$OPT_QUIET,
'verbose|v', \$OPT_VERBOSE,
'debug|d', \$OPT_DEBUG,
'gs-fontmap!', \$OPT_GS_FONTMAP,
'ttcap!', \$OPT_TTCAP,
'ooo!', \$OPT_OOO,
'java!', \$OPT_JAVA,
'bcbwmax=i', \$OPT_BCBWMAX,
'ebitmap!', \$OPT_EBITMAP,
'ebitmaplang=s', \$OPT_EBITMAP_LANG,
'version', \$OPT_VERSION,
'help|h', \$OPT_HELP,
)) {
&usage ();
exit 1;
}
if ($OPT_VERSION) {
print "fonts-config $version\n";
exit 0;
}
if ($OPT_HELP) {
&usage ();
exit 0;
}
my $VERBOSITY_QUIET = 0;
my $VERBOSITY_VERBOSE = 1;
my $VERBOSITY_DEBUG = 256;
my $VERBOSITY = $VERBOSITY_VERBOSE; # default
if ($OPT_DEBUG) {
$VERBOSITY = $VERBOSITY_DEBUG;
}
elsif ($OPT_VERBOSE) {
$VERBOSITY = $VERBOSITY_VERBOSE;
}
elsif ($OPT_QUIET) {
$VERBOSITY = $VERBOSITY_QUIET;
}
no strict "vars";
no warnings;
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "The following options were read from $sysconfig_file:\n";
for my $i (keys %sysconfig_options) {
if (defined eval ("\$$i")) {
printf "$i=%s\n", eval("\$$i");
}
}
print "--- end of options froom $sysconfig_file ---\n";
}
use warnings;
use strict;
# 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;
}
# external binaries:
my $fc_cache_bin = search_executable ("/usr/bin/fc-cache", "/usr/X11R6/bin/fc-cache");
my $fc_cache32_bin = search_executable ("/usr/bin/fc-cache32", "/usr/bin/fc-cache-x86");
my $fc_cache64_bin = search_executable ("/usr/bin/fc-cache64");
my $fc_match_bin = search_executable ("/usr/bin/fc-match");
my $cidfont_x11_config_bin = search_executable ("/usr/sbin/cidfont-x11-config");
my $xset_bin = search_executable ("/usr/bin/xset", "/usr/X11R6/bin/xset");
my $xfs_bin = search_executable ("/usr/bin/xfs", "/usr/X11R6/bin/xfs");
my $checkproc_bin = search_executable ("/sbin/checkproc");
my $killproc_bin = search_executable ("/sbin/killproc");
my $XFree86_bin = search_executable ("/usr/bin/Xorg", "/usr/X11R6/bin/Xorg", "/usr/X11R6/bin/XFree86");
my $mkfontscale_bin = search_executable ("/usr/bin/mkfontscale", "/usr/X11R6/bin/mkfontscale");
my $mkfontdir_bin = search_executable ("/usr/bin/mkfontdir", "/usr/X11R6/bin/mkfontdir");
my $ftdump_bin = search_executable ("/usr/bin/ftdump");
my $xtt_module_used = 0;
my $freetype_module_used = 0;
my $have_file_mmagic = 0;
eval { require File::MMagic; };
unless ($EVAL_ERROR) {
$have_file_mmagic = 1;
import File::MMagic;
}
my $command = "";
# search whether true CID-keyed fonts are available
# in /usr/share/ghostscript/Resource and if yes make them
# available to X11 as well:
if ($cidfont_x11_config_bin) {
$command = $cidfont_x11_config_bin;
if ($VERBOSITY == $VERBOSITY_VERBOSE) {
print "Configure X11 to use available CID-keyed fonts ...\n";
}
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
$command .= " --verbose ";
}
if ($OPT_FORCE) {
$command .= " --force ";
}
my_system ($command);
}
my @x11_font_dirs = x11_font_dirs();
my $gs_fontmap_needs_update = 0;
if ($VERBOSITY == $VERBOSITY_VERBOSE) {
print "Creating fonts.{scale,dir} files ";
}
for my $dir (@x11_font_dirs) {
make_fonts_scale_and_fonts_dir ($dir);
if ($VERBOSITY == $VERBOSITY_VERBOSE) {
print "."; # "progress bar"
}
}
if ($VERBOSITY == $VERBOSITY_VERBOSE) {
print "\n";
}
# The following three lines may change files in /etc/fonts, therefore
# they have to be called *before* fc-cache. If anything is
# changed in /etc/fonts after calling fc-cache, fontconfig
# will think that the cache files are out of date again.
font_dirs_setup ();
hinting_setup ();
embedded_bitmap_setup ();
my $fc_cache_exit_status = 256;
if ($fc_cache_bin) {
$command = "$fc_cache_bin";
if ($VERBOSITY == $VERBOSITY_VERBOSE) {
print "Creating cache files for fontconfig ";
}
if ($OPT_FORCE) {
$command .= " --really-force ";
}
if ($VERBOSITY >= $VERBOSITY_VERBOSE) {
$command .= " --verbose ";
}
if ($VERBOSITY == $VERBOSITY_VERBOSE) { # with "progress bar"
open (FC_CACHE, "$command |");
select (STDOUT);
$OUTPUT_AUTOFLUSH = 1;
while(<FC_CACHE>) {
print ".";
}
print "\n";
close (FC_CACHE);
}
else { # without "progress bar"
my_system($command);
}
}
$fc_cache_exit_status = $CHILD_ERROR;
if ($VERBOSITY == $VERBOSITY_DEBUG) {
print "exit status of fc-cache: $fc_cache_exit_status\n";
}
my $fc_cache32_exit_status = 256;
if ($fc_cache32_bin) {
$command = "$fc_cache32_bin";
if ($VERBOSITY == $VERBOSITY_VERBOSE) {
print "Creating 32bit cache files for fontconfig ";
}
if ($VERBOSITY >= $VERBOSITY_VERBOSE) {
$command .= " --verbose ";
}
if ($VERBOSITY == $VERBOSITY_VERBOSE) { # with "progress bar"
open (FC_CACHE, "$command |");
select (STDOUT);
$OUTPUT_AUTOFLUSH = 1;
while(<FC_CACHE>) {
print ".";
}
print "\n";
close (FC_CACHE);
}
else { # without "progress bar"
my_system($command);
}
}
$fc_cache32_exit_status = $CHILD_ERROR;
if ($VERBOSITY == $VERBOSITY_DEBUG) {
print "exit status of fc-cache: $fc_cache32_exit_status\n";
}
my $fc_cache64_exit_status = 256;
if ($fc_cache64_bin) {
$command = "$fc_cache64_bin";
if ($VERBOSITY == $VERBOSITY_VERBOSE) {
print "Creating 64bit cache files for fontconfig ";
}
if ($VERBOSITY >= $VERBOSITY_VERBOSE) {
$command .= " --verbose ";
}
if ($VERBOSITY == $VERBOSITY_VERBOSE) { # with "progress bar"
open (FC_CACHE, "$command |");
select (STDOUT);
$OUTPUT_AUTOFLUSH = 1;
while(<FC_CACHE>) {
print ".";
}
print "\n";
close (FC_CACHE);
}
else { # without "progress bar"
my_system($command);
}
}
$fc_cache64_exit_status = $CHILD_ERROR;
if ($VERBOSITY == $VERBOSITY_DEBUG) {
print "exit status of fc-cache: $fc_cache64_exit_status\n";
}
# make_gs_fontmap uses fontconfig,
# therefore it has to be called *after* fc-cache
if ($OPT_GS_FONTMAP) {
if ($OPT_FORCE || $gs_fontmap_needs_update ) {
make_gs_fontmap (@x11_font_dirs);
}
}
# generate_ooo_font_setup uses fontconfig,
# therefore it has to be called *after* fc-cache
if ($OPT_OOO) {
generate_ooo_font_setup ();
}
# generate_java_font_setup uses fontconfig,
# therefore it has to be called *after* fc-cache
if ($OPT_JAVA) {
generate_java_font_setup ();
}
# source all shell scripts from the directory /usr/lib/fonts-config/conf.d
# which start with at least one digit (sorted in POSIX sort order because this
# perl script does *not* use "use locale"):
if (opendir (DIR, "/usr/lib/fonts-config/conf.d")) {
my @entries = readdir (DIR);
for my $entry (sort (@entries)) {
if ("$entry" =~ /\./ || "$entry" =~ /\.\./
|| "$entry" !~ /^[0-9]+/
|| ! -f "/usr/lib/fonts-config/conf.d/$entry") {
next;
}
my_system ("sh /usr/lib/fonts-config/conf.d/$entry");
}
closedir DIR;
}
if ($xset_bin) {
if ($ENV{DISPLAY} && $ENV{DISPLAY} =~ /^:[0-9].*/) {
# it's a local display
$command = "$xset_bin fp rehash ";
unless ($VERBOSITY >= $VERBOSITY_DEBUG) {
$command .= " > /dev/null 2>&1 ";
}
my_system ($command);
}
}
if ($xfs_bin && my_system ("$checkproc_bin $xfs_bin") == 0) {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "Reloading config file of X Font Server ...\n";
}
my_system ("$killproc_bin $xfs_bin -USR1");
}
elsif ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "X Font Server not used.\n";
}
exit 0;
########################################################################
sub version_compare {
my ($version_string_1, $version_string_2) = @_;
# compare two version numbers consisting only of digits and dots
# returns an integer less than, equal to, or greater than zero
# if $version_string_1 is found, respectively, to be a smaller version,
# equal version, or greater version than $version_string_2.
my @v1 = split (/\./, $version_string_1);
my @v2 = split (/\./, $version_string_2);
for (my $i = 0 ; $i <= $#v1 && $i <= $#v2; $i++) {
if ($v1[$i] < $v2[$i]) {
return -1;
} elsif ($v1[$i] > $v2[$i]) {
return 1;
}
}
if ($#v1 < $#v2) {
return -1;
} elsif ($#v1 > $#v2) {
return 1;
}
return 0;
}
sub fontconfig_version {
if ($fc_cache_bin) {
open (VERSION, "$fc_cache_bin -V 2>&1 |");
binmode VERSION, ":bytes";
while (<VERSION>) {
if ($ARG =~ /fontconfig\s+version\s+([.[:digit:]]+)\s*/) {
close (VERSION);
return "$1";
}
}
close (VERSION);
}
# don't know the version
return "";
}
sub xfree86_version {
if ($XFree86_bin) {
open (VERSION, "$XFree86_bin -version 2>&1 |");
binmode VERSION, ":bytes";
while (<VERSION>) {
if ($ARG =~ /Version\s+([.[:digit:]]+)\s*/) {
close (VERSION);
return "$1";
}
}
close (VERSION);
}
# don't know the version
return "";
}
sub freetype_module_supports_ttcap {
my ($v1, $v2, $v3, $v4) = xfree86_version();
if (version_compare(xfree86_version(), "4.3.99") >= 0) {
if ($VERBOSITY == $VERBOSITY_DEBUG) {
print "freetype module supports TTCap.\n";
}
return 1;
}
else {
if ($VERBOSITY == $VERBOSITY_DEBUG) {
print "freetype module does not support TTCap.\n";
}
return 0;
}
}
sub x11_font_dirs {
my @dirs = ();
my @standard_dirs = (
"/usr/share/fonts/local",
"/usr/share/fonts/misc",
"/usr/share/fonts/75dpi",
"/usr/share/fonts/100dpi",
"/usr/share/fonts/Type1",
"/usr/share/fonts/URW",
"/usr/share/fonts/Speedo",
"/usr/share/fonts/PEX",
"/usr/share/fonts/cyrillic",
"/usr/share/fonts/latin2/misc",
"/usr/share/fonts/latin2/75dpi",
"/usr/share/fonts/latin2/100dpi",
"/usr/share/fonts/latin2/Type1",
"/usr/share/fonts/latin7/75dpi",
"/usr/share/fonts/baekmuk",
"/usr/share/fonts/japanese",
"/usr/share/fonts/kwintv",
"/usr/share/fonts/truetype",
"/usr/share/fonts/uni",
"/usr/share/fonts/CID",
"/usr/share/fonts/ucs/misc",
"/usr/share/fonts/ucs/75dpi",
"/usr/share/fonts/ucs/100dpi",
"/usr/share/fonts/hellas/misc",
"/usr/share/fonts/hellas/75dpi",
"/usr/share/fonts/hellas/100dpi",
"/usr/share/fonts/hellas/Type1",
"/usr/share/fonts/misc/sgi",
"/usr/share/fonts/xtest",
"/usr/X11R6/lib/X11/fonts/local",
"/usr/X11R6/lib/X11/fonts/misc",
"/usr/X11R6/lib/X11/fonts/75dpi",
"/usr/X11R6/lib/X11/fonts/100dpi",
"/usr/X11R6/lib/X11/fonts/Type1",
"/usr/X11R6/lib/X11/fonts/URW",
"/usr/X11R6/lib/X11/fonts/Speedo",
"/usr/X11R6/lib/X11/fonts/PEX",
"/usr/X11R6/lib/X11/fonts/cyrillic",
"/usr/X11R6/lib/X11/fonts/latin2/misc",
"/usr/X11R6/lib/X11/fonts/latin2/75dpi",
"/usr/X11R6/lib/X11/fonts/latin2/100dpi",
"/usr/X11R6/lib/X11/fonts/latin2/Type1",
"/usr/X11R6/lib/X11/fonts/latin7/75dpi",
"/usr/X11R6/lib/X11/fonts/baekmuk",
"/usr/X11R6/lib/X11/fonts/japanese",
"/usr/X11R6/lib/X11/fonts/kwintv",
"/usr/X11R6/lib/X11/fonts/truetype",
"/usr/X11R6/lib/X11/fonts/uni",
"/usr/X11R6/lib/X11/fonts/CID",
"/usr/X11R6/lib/X11/fonts/ucs/misc",
"/usr/X11R6/lib/X11/fonts/ucs/75dpi",
"/usr/X11R6/lib/X11/fonts/ucs/100dpi",
"/usr/X11R6/lib/X11/fonts/hellas/misc",
"/usr/X11R6/lib/X11/fonts/hellas/75dpi",
"/usr/X11R6/lib/X11/fonts/hellas/100dpi",
"/usr/X11R6/lib/X11/fonts/hellas/Type1",
"/usr/X11R6/lib/X11/fonts/misc/sgi",
"/usr/X11R6/lib/X11/fonts/xtest",
"/opt/kde3/share/fonts"
);
push (@dirs, @standard_dirs);
push (@dirs, xorg_config_font_dirs());
push (@dirs, xfs_font_dirs());
# Attention!:
# /usr/X11R6/lib/X11/fonts/encodings usually doesn't contain any fonts.
# Neverthelesss a valid encodings.dir file must exist in that directory
# because some applications, e.g. luit, read encodings.dir from there
# (See for example "LANG=ja_JP strace -eopen luit -c").
# The easiest way to make sure that the encodings.dir in that directory
# is correct and up to date is to add the "encodings" directory to the
# list of font directories.
# Then mkfontdir will be called on that directory as well and a correct
# encodings.dir will be generated.
if (-d "/usr/share/fonts/encodings") {
push (@dirs, ("/usr/share/fonts/encodings"));
} else {
push (@dirs, ("/usr/X11R6/lib/X11/fonts/encodings"));
}
# remove non existing directories and duplicates:
my %dirs = ();
for my $dir (@dirs) {
if (-d $dir) {
$dirs{$dir} = "";
}
}
return (keys %dirs);
}
# gets font paths configured in /etc/X11/xorg.conf
# and check wether the "xtt" and/or "freetype" modules are loaded:
sub xorg_config_font_dirs {
my @dirs = ();
my $file = "/etc/X11/xorg.conf";
if (-e $file) {
open (CONFIGFILE, $file) || die "can't open file $file: $!";
while (<CONFIGFILE>) {
chomp ($ARG);
if ($ARG =~ /([^#]*)#?.*/) { # strip comments
$ARG = $1;
}
if ($ARG =~ /\s*FontPath\s+"(.+?)(:unscaled|:scaled)?"\s*/i) {
push (@dirs, $1);
}
if ($ARG =~ /\s*Load\s+"xtt"/) {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "xtt module is used.\n";
}
$xtt_module_used = 1;
}
if ($ARG =~ /\s*Load\s+"freetype"/) {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "freetype module is used.\n";
}
$freetype_module_used = 1;
}
}
close (CONFIGFILE);
}
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "font paths found in $file:\n";
for my $dir (@dirs) {
print "$dir\n";
}
}
return @dirs;
}
# gets font paths configured for xfs if xfs exists and is running:
sub xfs_font_dirs {
my @dirs = ();
my $file = "/etc/X11/fs/config";
if ($xfs_bin && my_system ("$checkproc_bin $xfs_bin") == 0) {
if (-e $file) {
my $config_file_contents = "";
open (CONFIGFILE, $file) || die "can't open file $file: $!";
while (<CONFIGFILE>) {
$ARG =~ /([^#]*)#?.*/; # strip comments
$config_file_contents .= $1;
}
close (CONFIGFILE);
$config_file_contents =~ /catalogue[^=]*=([^=]*?)\n[^\n]*=/si;
my $catalogue = $1;
@dirs = split(/[\s,\\]+/, $catalogue);
for my $index (0 .. $#dirs) {
if ($dirs[$index] =~ /(.+?)(:unscaled|:scaled)/) {
$dirs[$index] = $1;
}
}
}
}
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "font paths found in $file:\n";
for my $dir (@dirs) {
print "$dir\n";
}
}
return @dirs;
}
sub create_symbolic_links {
my ($dir) = @_;
my $cwd;
chomp ($cwd = `pwd`);
chdir $dir ||die "Can't cd to $dir: $!\n";
# create symbolic links for PostScript fonts in pfa format
# which have no extension:
# (seems like all such fonts are gone now, I can't find
# such fonts any more on my system 2005.09.01)
if ($have_file_mmagic) {
my $mm = new File::MMagic; # use internal magic file
# $mm = File::MMagic::new('/etc/magic'); # use external magic file
my $type;
for my $file (glob ("*")) {
unless ($file =~ /\./i) {
$type = $mm->checktype_filename($file);
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "File::MMagic $file: $type\n";
}
if ($type =~ /application\/postscript/) {
# it's probably a PostScript font in pfa format
# create a symbolic link unless it has the .pfa extension already
# or is a .gsf file (File::MMagic detects .gsf files also as
# "application/postscript", but it makes no sense to link these
# to .pfa)
unless ($file =~ /\.pfa|\.gsf/i) {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
printf "symlink ($file, \"${file}.pfa\")\n";
}
symlink ($file, "${file}.pfa");
}
}
}
}
}
# create symbolic links for files which have characters in
# their name which are impossible to use in the file name in
# fonts.dir:
my @forbidden_characters = (" ", ":");
for my $file (glob ("*.*")) {
for my $forbidden_character (@forbidden_characters) {
if ($file =~ /$forbidden_character/) {
my $file_new;
($file_new = $file) =~ s/$forbidden_character/_/g;
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
printf "symlink ($file, $file_new)\n";
}
symlink ($file, $file_new);
}
}
}
chdir $cwd ||die "Can't cd to $cwd: $!\n";
}
sub make_fonts_scale_and_fonts_dir {
my ($dir) = @_;
my $timestamp = "$dir/.fonts-config-timestamp";
my $try_again = 0;
# workaround for a bug in older versions of /usr/sbin/Check which
# gzips the timestamp files:
if (-e "${timestamp}.gz") {
unlink ("${timestamp}.gz");
}
if ($OPT_FORCE ||
mtime_differs_or_missing ("$timestamp","$dir") ||
mtime_differs_or_missing ("$timestamp","$dir/fonts.scale") ||
mtime_differs_or_missing ("$timestamp","$dir/fonts.dir")) {
# Touch and delete fonts.scale and fonts.dir just to make sure
# we are starting from scratch and the directory is writeable:
my_system ("touch $dir/fonts.scale $dir/fonts.dir > /dev/null 2>&1");
if (!unlink ("$dir/fonts.scale", "$dir/fonts.dir")) {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "Cannot write in $dir. Readonly filesystem?\n";
}
return;
}
$gs_fontmap_needs_update = 1;
create_symbolic_links($dir);
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "creating $dir/fonts.{scale,dir} ...\n";
}
if ($mkfontscale_bin) {
$command = "$mkfontscale_bin $dir";
unless ($VERBOSITY >= $VERBOSITY_DEBUG) {
$command .= " > /dev/null 2>&1 ";
}
my_system ($command);
}
if (! -e "$dir/fonts.scale" ) {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "mkfontscale is not available or it failed. ";
print "-> Create an empty fonts.scale file.\n";
}
$try_again = 1;
my_system ("echo 0 > $dir/fonts.scale");
}
fix_fonts_scale ($dir);
if ($mkfontdir_bin) {
$command = "$mkfontdir_bin ";
if (-d "/usr/X11R6/lib/X11/fonts/encodings") {
$command .= " -e /usr/X11R6/lib/X11/fonts/encodings";
}
if (-d "/usr/X11R6/lib/X11/fonts/encodings/large") {
$command .= " -e /usr/X11R6/lib/X11/fonts/encodings/large";
}
if (-d "/usr/share/fonts/encodings") {
$command .= " -e /usr/share/fonts/encodings";
}
if (-d "/usr/share/fonts/encodings/large") {
$command .= " -e /usr/share/fonts/encodings/large";
}
$command .= " $dir";
my_system ($command);
}
if (! -e "$dir/fonts.dir" ) {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "mkfontdir is not available or it failed. ";
}
$try_again = 1;
if (-f "$dir/fonts.scale" ){
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "A fonts.scale file exists, copy it to fonts.dir.";
}
my_system ("cp $dir/fonts.scale $dir/fonts.dir");
}
else {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "No fonts.scale file exists either, create an empty fonts.dir.";
}
my_system ("echo 0 > $dir/fonts.dir");
}
}
# Directory done. Now update time stamps:
if ($try_again) {
# mkfontscale and/or mkfontdir failed or didn't exist. Remove the
# timestamp to make sure this script tries again next time
# when the problem with mkfontscale and/or mkfontdir is fixed:
unlink ("$timestamp");
}
else {
# fonts.cache-* files are now generated in /var/cache/fontconfig,
# remove old cache files in the individual directories
# (fc-cache does this as well when the cache files are out of date
# but it can't hurt to remove them here as well just to make sure).
for my $file (glob ("$dir/fonts.cache-*")) {
if (-e "$file") {
unlink ("$file");
}
}
if (! -e $timestamp) {
my_system ("touch $timestamp");
}
utime ($script_start_time, $script_start_time,
("$dir/fonts.dir", "$dir/fonts.scale", $timestamp, $dir));
}
}
}
sub fix_fonts_scale {
my ($dir) = @_;
my ($file, $options, $font, $xlfd);
my %fonts_scale_entries = ();
my %blacklist = ();
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "----------------------------------------------------------------------\n";
print "fix fonts.scale in $dir:\n";
}
######################################################################
# first parse the "handmade" fonts.scale.* files:
for $file (glob ("$dir/fonts.scale.*")) {
if (-e $file) {
if ($file =~ /~$|\.swp$|\.bak$|\.sav$|\.save$|\.rpmsave$|\.rpmorig|\.rpmnew$/) {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "$file is considered a backup file, ignored.\n";
}
next;
}
open (FONTS_SCALE, $file) || die "can't open file $file: $!";
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "reading $dir/$file ...\n";
}
while (<FONTS_SCALE>) {
if ($ARG =~ /^(.*?)([^:\s]+)\s+(-.+?)\s*$/) { # font name and xlfd found
$options = $1;
$font = $2;
$xlfd = $3;
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "handmade entry found: options=$options font=$font xlfd=$xlfd\n";
}
if (( $OPT_TTCAP ) && $options =~ /:([0-9]):/) {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "--ttcap option is set: convert face number to TTCap syntax: fn=$1:\n";
}
$options = "fn=$1:";
}
if ($freetype_module_used && ! $OPT_TTCAP ) {
if ($options =~ /fn=([0-9]):/) {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "freetype module used and --ttcap option is not set: convert face number to freetype syntax: :$1:\n";
}
$options = ":$1:";
} elsif ($options =~ /[a-z=]/i) {
# there's more then just a face number, better ignore it
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "xtt module not used: discard xtt only entry $ARG\n";
}
next;
}
}
unless ( $font =~ /\.cid$/) {
# For font file name entries ending with ".cid", such a file
# usually doesn't exist and it doesn't need to. The backend which
# renders CID-keyed fonts just parses this name to find the real
# font files and mapping tables
#
# For other entries, we check whether the file exists.
if (! -e "$dir/$font") {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "file $dir/$font doesn't exist, discard entry $ARG\n";
}
next;
}
}
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "adding handmade entry $ARG\n";
}
$fonts_scale_entries{$xlfd} = "${options}${font}";
# This font has "handmade" fonts.scale entries.
# Add it to the blacklist to discard any entries for this font
# which which might have been automatically created
# by mkfontscale:
$blacklist{$font} = "yes";
}
}
close (FONTS_SCALE);
}
}
######################################################################
# blacklist globs to avoid fonts known to be broken:
#
# (broken fonts may still be included in manually edited fonts.scale.*
# files. He who edits these files manually should know what he is doing ...)
my @blacklist_globs = ();
# push (@blacklist_globs, ("totally-broken*.ttf", "fubar*.ttc"));
# the Hershey-Fonts from ghostscript-fonts-other.rpm have broken outlines
# and don't work with X11, neither with the freetype module nor via libXft.
push (@blacklist_globs, ("hrger.pfa", "hrgrr.pfa", "hritr.pfa", "hrpld.pfa",
"hrpldi.pfa", "hrplt.pfa", "hrplti.pfa", "hrscc.pfa",
"hrscs.pfa",
"u003043t.gsf",
"u004006t.gsf",
# .bdf fonts currently don't work with Xft2:
"*.bdf"
));
my @blacklist_fonts_cache = ();
for my $glob (@blacklist_globs) {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "expanding blacklist glob: $dir/$glob\n";
}
for my $font (glob ("$dir/$glob")) {
if (-e $font) {
$font =~ /\/([^\/]+)$/; # basename (strip directory)
$font = $1;
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "$dir/$font matched by blacklist glob, adding $font to blacklist.\n";
}
$blacklist{$font} = "yes";
push (@blacklist_fonts_cache, ($font));
}
}
}
######################################################################
# remove broken entries from fonts.cache-1:
if (@blacklist_fonts_cache) {
my @entries = ();
$file = "$dir/fonts.cache-1";
if (-e $file) {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "removing blacklisted fonts @blacklist_fonts_cache from $file\n";
}
open (FONTS_CACHE, $file) || die "can't open file $file: $!";
while (<FONTS_CACHE>) {
$ARG =~ /^"([^"]+)" /;
if (! grep /$1/, @blacklist_fonts_cache) {
push (@entries, ($ARG));
}
}
close (FONTS_CACHE);
open (FONTS_CACHE, ">$file") || die "can't open file $file: $!";
for my $entry (@entries) {
print FONTS_CACHE "$entry";
}
close (FONTS_CACHE);
}
}
######################################################################
# Now parse the fonts.scale file automatically created by mkfontscale:
$file = "$dir/fonts.scale";
open (FONTS_SCALE, $file) || die "can't open file $file: $!";
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "reading $dir/$file ...\n";
}
while (<FONTS_SCALE>) {
if ($ARG =~ /^(.*?)([^:\s]+)\s+(-.+?)\s*$/) { # font name and xlfd found
$options = $1;
$font = $2;
$xlfd = $3;
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "mkfontscale entry found: options=$options font=$font xlfd=$xlfd\n";
}
# mkfontscale apparently doesn't yet generate the special options for
# the freetype module to use different face numbers in .ttc files.
# But this might change, therefore it is probably better to check this as well:
if ( ( $OPT_TTCAP ) && $options =~ /:([0-9]):/) {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "--ttcap option is set: convert face number to TTCap syntax: fn=$1:\n";
}
$options = "fn=$1:";
}
if ($blacklist{$font}) {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "$dir/$font is blacklisted, ignored.\n";
}
next;
}
$fonts_scale_entries{$xlfd} = "${options}${font}";
}
}
close (FONTS_SCALE);
######################################################################
# generate an oblique entry if only italic is there and vice versa:
for my $old_xlfd (keys %fonts_scale_entries) {
if ($old_xlfd =~ /(-[^-]+-[^-]+-[^-]+)(-[io]-)([^-]+-[^-]*-\d+-\d+-\d+-\d+-[pmc]-\d+-[^-]+-[^-]+)/i) {
my $new_xlfd = "";
if ("$2" eq "-i-") {
$new_xlfd = "${1}-o-${3}";
} else {
$new_xlfd = "${1}-i-${3}";
}
unless ($fonts_scale_entries{$new_xlfd}) {
$fonts_scale_entries{$new_xlfd} = $fonts_scale_entries{$old_xlfd};
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "generated o/i: $fonts_scale_entries{$new_xlfd} $new_xlfd\n";
}
}
}
}
######################################################################
# generate TTCap options for xtt:
if ($OPT_TTCAP) {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "generating TTCap options for use with xtt or recent freetype modules ...\n";
}
my ($italic, $oblique, $bold, $bold_italic, $bold_oblique);
my $artificial_italic = "ai=0.2:";
my $doublestrike = "ds=y:";
for my $medium (sort (keys %fonts_scale_entries)) {
if ($medium !~ /-medium-r-/) {
next;
}
if ($fonts_scale_entries{$medium} !~ /^(.*?)([^:]+)$/) {
next; # should not happen ...
}
$options = $1;
$font = $2;
if ( $xtt_module_used && $font !~ /\.ttf$|\.ttc$/i ) {
next; # xtt can only handle TrueType fonts.
}
elsif ( $freetype_module_used && $font !~ /\.ttf$|\.ttc$|\.otf|\.otc|\.pfa|\.pfb/i ) {
next; # the freetype module handles TrueType, OpenType, and Type1 fonts.
}
elsif ( !$freetype_module_used && !$xtt_module_used) {
# neither the xtt module nor the freetype module is used, generating TTCap
# options makes no sense.
next;
}
if ($options) {
next; # there are already some TTCap options, better don't touch this
}
($italic = $medium) =~ s/-medium-r-/-medium-i-/;
($oblique = $medium) =~ s/-medium-r-/-medium-o-/;
($bold = $medium) =~ s/-medium-r-/-bold-r-/;
($bold_italic = $medium) =~ s/-medium-r-/-bold-i-/;
($bold_oblique = $medium) =~ s/-medium-r-/-bold-o-/;
unless ($fonts_scale_entries{$italic} ||
$fonts_scale_entries{$oblique}) {
$fonts_scale_entries{$italic} = "${artificial_italic}${font}";
$fonts_scale_entries{$oblique} = "${artificial_italic}${font}";
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "generated TTCap entry: $fonts_scale_entries{$italic} $italic\n";
print "generated TTCap entry: $fonts_scale_entries{$oblique} $oblique\n";
}
}
unless ($fonts_scale_entries{$bold}) {
$fonts_scale_entries{$bold} = "${doublestrike}${font}";
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "generated TTCap entry: $fonts_scale_entries{$bold} $bold\n";
}
}
unless ($fonts_scale_entries{$bold_italic} ||
$fonts_scale_entries{$bold_oblique}) {
$fonts_scale_entries{$bold_italic} = "${doublestrike}${artificial_italic}${font}";
$fonts_scale_entries{$bold_oblique} = "${doublestrike}${artificial_italic}${font}";
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "generated TTCap entry: $fonts_scale_entries{$bold_italic} $bold_italic\n";
print "generated TTCap entry: $fonts_scale_entries{$bold_oblique} $bold_oblique\n";
}
}
}
# add bw=0.5 option when necessary:
for my $xlfd (sort (keys %fonts_scale_entries)) {
if ($fonts_scale_entries{$xlfd} !~ /^(.*?)([^:]+)$/) {
next; # should not happen ...
}
$options = $1;
$font = $2;
if ( $xtt_module_used && $font !~ /\.ttf$|\.ttc$/i ) {
next; # xtt can only handle TrueType fonts.
}
elsif ( $freetype_module_used && $font !~ /\.ttf$|\.ttc$|\.otf|\.otc|\.pfa|\.pfb/i ) {
next; # the new freetype module handles TrueType, OpenType, and Type1 fonts.
}
elsif ( !$freetype_module_used && !$xtt_module_used) {
# neither the xtt module nor the freetype module is used, generating TTCap
# options makes no sense.
next;
}
if ($options =~ /bw=/) {
next; # there is already a bw=<something> TTCap option, better don't touch this
}
if ($xlfd =~ /c-0-jisx0201.1976-0/) {
$fonts_scale_entries{$xlfd} = "${options}bw=0.5:${font}";
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "added bw=0.5 option: $fonts_scale_entries{$xlfd} $xlfd\n";
}
}
}
}
######################################################################
# weed out entries which certainly cannot work:
for my $xlfd (keys %fonts_scale_entries) {
if ($fonts_scale_entries{$xlfd} !~ /\.([[:alnum:]]+)(\.gz)?$/i) {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "file has no extension, discarding $fonts_scale_entries{$xlfd} $xlfd\n";
}
delete $fonts_scale_entries{$xlfd};
next;
}
else {
my $extension = $1 ;
# Currently only the freetype module can handle .otf fonts.
#
# If both xtt and freetype are used at the same time, xtt will only register
# for .ttf and .ttc fonts and freetype will still be able to handle
# the .otf fonts.
# But if freetype is not used, .otf fonts won't work at all and
# directories containing entries for .otf fonts in fonts.dir will be
# removed from the font path.
# This is not nice because there may be other fonts in that directory which
# could be used, for example .ttf or .ttc.
# Therefore it is better to throw away all entries for .otf fonts if
# the freetype module is not used:
if ($extension =~ /otf/i && ! $freetype_module_used) {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print ".otf won't work without freetype module, discarding $fonts_scale_entries{$xlfd} $xlfd\n";
}
delete $fonts_scale_entries{$xlfd};
}
if ($extension =~ /gsf/i) {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print ".gsf fonts won't work with X11, discarding $fonts_scale_entries{$xlfd} $xlfd\n";
}
delete $fonts_scale_entries{$xlfd};
}
}
}
######################################################################
# write final result to fonts.scale:
$file = "$dir/fonts.scale";
open (FONTS_SCALE, ">$file") || die "can't open file $file: $!";
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "writing $dir/$file ...\n";
}
printf FONTS_SCALE "%d\n", scalar(keys %fonts_scale_entries);
for my $xlfd (sort (keys %fonts_scale_entries)) {
print FONTS_SCALE "$fonts_scale_entries{$xlfd} $xlfd\n";
}
close (FONTS_SCALE);
}
######################################################################
sub get_font_name_entries {
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 = "";
my $family = "";
my $style = "";
my $face_number = 0;
while (<FONT>) {
if ($ARG =~ /face.*number.*:\s*([0-9]+)\s*/i) {
$face_number = $1;
}
if ($face_number > 0) {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "face_number=$face_number found. All faces with number > 0 ignored.\n";
}
last;
}
# 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;
}
}
close (FONT);
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "ftdump: font=$font postscript=$postscript family=$family style=$style\n";
}
return ($postscript, $family, $style);
}
sub gs_fontmap_aliases_add {
my ($aliases, $alias) = @_;
my $alias_case_normalized = $alias;
$alias_case_normalized =~ s/\b(\w)(\w*)/ uc($1) . lc($2) /eg;
$alias_case_normalized =~ s/ //g;
$alias =~ s/ //g;
$aliases->{$alias} = "";
$aliases->{$alias_case_normalized} = "";
}
sub gs_fontmap_aliases {
my ($postscript, $family, $style, $xlfd) = @_;
my $xlfd_fmly = "";
my $xlfd_wght = "";
my $xlfd_slant = "";
my %aliases = ();
if ($xlfd && $xlfd =~
/-[^-]+-([^-]+)-([^-]+)-([^-])-[^-]+-[^-]*-\d+-\d+-\d+-\d+-[pmc]-\d+-[^-]+-[^-]+/i) {
$xlfd_fmly = $1;
$xlfd_wght = $2;
$xlfd_slant = $3;
# Some aliases for applications which don't use the correct PostScript
# names but rather some combination of family, weight, and slant from the XLFD.
# Probably because there is no way to get the PostScript name without
# direct access to the font file. When X11 core fonts are used instead of
# fontconfig/libXft, the application may only see the XLFD and can only
# try to "guess" the PostScript name from the XLFD.
# (For example Qt3 does something like this ...)
if ($xlfd_fmly) {
if ($xlfd_wght !~ /bold/i && $xlfd_slant ne "i" && $xlfd_slant ne "o") {
gs_fontmap_aliases_add(\%aliases, "$xlfd_fmly");
}
if ($xlfd_wght !~ /bold/i && ($xlfd_slant eq "i" || $xlfd_slant eq "o")) {
gs_fontmap_aliases_add(\%aliases, "$xlfd_fmly-Italic");
}
if ($xlfd_wght =~ /bold/i && $xlfd_slant ne "i" && $xlfd_slant ne "o") {
gs_fontmap_aliases_add(\%aliases, "$xlfd_fmly-Bold");
}
if ($xlfd_wght =~ /bold/i && ($xlfd_slant eq "i" || $xlfd_slant eq "o")) {
gs_fontmap_aliases_add(\%aliases, "$xlfd_fmly-Bold Italic");
}
}
}
# an alias to the PostScript name would make no sense, delete it if
# it was accidentally created:
delete $aliases{$postscript};
return (sort (keys %aliases));
}
sub make_gs_fontmap {
my (@font_dirs) = @_;
if (!$ftdump_bin) {
print "Warning: Creation of a Fontmap for Ghostmap has been requested\n";
print " (either the the option --gs-fontmap has been used or the variable\n";
print" GENERATE_GHOSTSCRIPT_FONTMAPS in /etc/sysconfig/fonts-config\n";
print" has been set to \"yes\").\n";
print " But the 'ftdump' program which is needed to do this is\n";
print " apparently not installed. 'ftdump' is in the 'ft2demos'\n";
print " package. Please install this package if you want a Fontmap\n";
print " for Ghostscript to be created.\n";
}
else {
if ($VERBOSITY >= $VERBOSITY_VERBOSE) {
print "Creating Fontmap entries for Ghostscript ";
}
for my $fontmap_dir (glob ("/usr/share/ghostscript/[0-9]*/lib")) {
if (-e $fontmap_dir) {
my $file = "$fontmap_dir/Fontmap.X11-auto";
open (FONTMAP, ">$file") || die "can't open file $file: $!";
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
printf "writing $file ...\n";
}
print FONTMAP "% Fontmap for scalable fonts found in the X11 font paths\n";
print FONTMAP "%\n";
print FONTMAP "% This file is automatically generated by\n";
print FONTMAP "% \"fonts-config\" (version $version) and will be\n";
print FONTMAP "% overwritten during the next run of this script.\n";
print FONTMAP "%\n";
print FONTMAP "% Don't edit this file. If you want to create your own\n";
print FONTMAP "% manual Fontmap entries, put them elsewhere.\n";
print FONTMAP "%\n";
my %fontmap_entries = ();
for my $dir (@font_dirs) {
open (FONTS_SCALE, "$dir/fonts.scale") || die "can't open file $dir/fonts.scale: $!";
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "creating hashtable of xlfds from $dir/fonts.scale ...\n";
}
my %xlfds;
while (<FONTS_SCALE>) {
my ($options, $font, $xlfd);
if ($ARG =~ /^(.*?)([^:\s]+)\s+(-.+?)\s*$/) { # font name and xlfd found
$options = $1;
$font = $2;
$xlfd = $3;
unless ($options) { # ignore face numbers > 0 and other options
$xlfds{"$dir/$font"} = $xlfd;
}
}
}
close (FONTS_SCALE);
for my $font (glob ("$dir/*.{ttf,ttc,pfa,pfb}")) {
if (-e $font) {
my ($postscript, $family, $style) = get_font_name_entries($font);
if ($postscript) {
print FONTMAP "%----------------------------------------------------------------------\n";
print FONTMAP "% postscript=\"$postscript\" family=\"$family\" style=\"$style\"\n";
if ($xlfds{$font}) {
print FONTMAP "% xlfd=\"$xlfds{$font}\"\n";
} else {
print FONTMAP "% xlfd=\"\"\n";
}
if ($fontmap_entries{$postscript}) {
print FONTMAP "% /$postscript ($font) ; % warning: duplicate!\n";
} else {
print FONTMAP "/$postscript ($font) ;\n";
$fontmap_entries{$postscript} = "true";
}
for my $alias (gs_fontmap_aliases($postscript, $family, $style, $xlfds{$font})) {
if ($fontmap_entries{$alias}) {
print FONTMAP "% /$alias /$postscript ; % warning: duplicate!\n";
} else {
print FONTMAP "/$alias /$postscript ;\n";
$fontmap_entries{$alias} = "true";
}
}
}
}
}
if ($VERBOSITY == $VERBOSITY_VERBOSE) {
print "."; # "progress bar"
}
}
close (FONTMAP);
}
}
if ($VERBOSITY == $VERBOSITY_VERBOSE) {
print "\n";
}
}
}
########################################################################
sub generate_ooo_font_setup {
my $common_xcu_file = "/usr/lib/ooo-1.1/share/registry/data/org/openoffice/Office/Common.xcu";
my $common_xcu_template_file = "/usr/share/fonts-config/Common.xcu.template";
my $common_xcu = "";
my $common_xcu_template = "";
my $within_font_node_depth = 0;
my $ooo_truetype_font_dir = "/usr/lib/ooo-1.1/share/fonts/truetype";
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
printf "generating OpenOffice font setup\n";
}
if (! -f "$common_xcu_file") {
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
printf "Nothing to do for this version of OpenOffice.\n";
}
return;
}
if (! -f "$common_xcu_template_file") {
printf "File $common_xcu_template_file missing. This should not happen.\n";
printf "Skipping OpenOffice font setup\n";
return;
}
my @msgothic_list = ("MS Gothic",
"HGGothicB",
"HG\\-GothicB\\-Sun",
"TLGothic",
"IPAGothic",
"Sazanami Gothic",
"Kochi Gothic");
my @mspgothic_list = ("MS PGothic",
"HGPGothicB",
"HG\\-PGothicB\\-Sun",
"TLPGothic",
"IPAPGothic",
"Sazanami Gothic",
"Kochi Gothic");
my @msmincho_list = ("MS Mincho",
"HGMinchoL",
"HG\\-MinchoL\\-Sun",
"TLMincho",
"IPAMincho",
"Sazanami Mincho",
"Kochi Mincho");
my @mspmincho_list = ("MS PMincho",
"HGPMinchoL",
"HG\\-PMinchoL\\-Sun",
"TLPMincho",
"IPAPMincho",
"Sazanami Mincho",
"Kochi Mincho");
my $msgothic = "Sazanami Gothic";
my $mspgothic = "Sazanami Gothic";
my $msmincho = "Sazanami Mincho";
my $mspmincho = "Sazanami Mincho";
for my $font (@msgothic_list) {
if (`fc-list "$font"`) {
$msgothic = $font;
last;
}
}
for my $font (@mspgothic_list) {
if (`fc-list "$font"`) {
$mspgothic = $font;
last;
}
}
for my $font (@msmincho_list) {
if (`fc-list "$font"`) {
$msmincho = $font;
last;
}
}
for my $font (@mspmincho_list) {
if (`fc-list "$font"`) {
$mspmincho = $font;
last;
}
}
open (TEMPLATE, "$common_xcu_template_file") || die "can't open file $common_xcu_template_file: $!";
binmode TEMPLATE, ":utf8";
while (<TEMPLATE>) {
$ARG =~ s/_MSGOTHIC_/$msgothic/;
$ARG =~ s/_MSPGOTHIC_/$mspgothic/;
$ARG =~ s/_MSMINCHO_/$msmincho/;
$ARG =~ s/_MSPMINCHO_/$mspmincho/;
$common_xcu_template .= $ARG;
}
close (TEMPLATE);
if (-f "$common_xcu_file" ) {
open (XCU, "$common_xcu_file") || die "can't open file $common_xcu_file: $!";
binmode XCU, ":utf8";
while (<XCU>) {
if ($ARG =~ /<node oor:name="Font">/) {
$within_font_node_depth = 1;
next;
}
if ($within_font_node_depth > 0) {
if ($ARG =~ /<node.*>/) {
$within_font_node_depth++;
}
if ($ARG =~ /<\/node>/) {
$within_font_node_depth--;
}
next;
}
unless ($ARG =~ /<\/oor:component-data>/) {
$common_xcu .= $ARG;
}
}
close (XCU);
open (XCU, ">$common_xcu_file") || die "can't open file $common_xcu_file: $!";
binmode XCU, ":utf8";
print XCU $common_xcu;
print XCU $common_xcu_template;
print XCU '</oor:component-data>'; print XCU "\n";
close (XCU);
}
if ( -d "$ooo_truetype_font_dir" ) {
for my $font (`fc-list :lang=ja:outline=true file`) {
my $basename;
chomp ($font);
$font =~ s/:.*$//;
($basename = $font ) =~ s/.*\/([^\/]+)/$1/;
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
printf "symlink (\"$font\", \"$ooo_truetype_font_dir/$basename\")\n";
}
symlink ("$font", "$ooo_truetype_font_dir/$basename");
}
# remove dead links:
for my $file (glob ("$ooo_truetype_font_dir/*")) {
if (! -f "$file") {
unlink("$file");
}
}
}
}
########################################################################
sub generate_java_font_setup {
my @font_properties_ja_globs = ("/usr/lib*/jvm/java-1[._]4[._]?-sun-*/jre/lib/font.properties.ja");
my $font_properties_ja_template_file = "/usr/share/fonts-config/font.properties.ja.template";
my $font_properties_ja_template = "";
my @fontconfig_SuSE_properties_globs = "/usr/lib*/jvm/java-1.5.?-sun-*/jre/lib/fontconfig.SuSE.properties";
my $fontconfig_SuSE_properties_template_file = "/usr/share/fonts-config/fontconfig.SuSE.properties.template";
my $fontconfig_SuSE_properties_template = "";
if ($VERBOSITY >= $VERBOSITY_QUIET) {
printf "generating java font setup\n";
}
my @sans_japanese_priority = ("MS Gothic",
"HGGothicB",
"IPAGothic",
"Sazanami Gothic");
my @serif_japanese_priority = ("MS Mincho",
"HGMinchoL",
"IPAMincho",
"Sazanami Mincho");
my @sans_simplified_chinese_priority = ("FZSongTi",
"AR PL SungtiL GB");
my @serif_simplified_chinese_priority = ("FZSongTi",
"AR PL SungtiL GB");
my @sans_traditional_chinese_priority = ("FZMingTiB",
"AR PL Mingti2L Big5");
my @serif_traditional_chinese_priority = ("FZMingTiB",
"AR PL Mingti2L Big5");
my @sans_korean_priority = ("UnDotum",
"Baekmuk Gulim",
"Baekmuk Dotum");
my @serif_korean_priority = ("UnBatang",
"Baekmuk Batang");
my %sans_japanese_xlfds =
(
"MS Gothic" , "-ricoh-ms gothic-",
"HGGothicB" , "-ricoh-hggothicb-",
"IPAGothic" , "-misc-ipagothic-",
"Sazanami Gothic" , "-misc-sazanami gothic-"
);
my %serif_japanese_xlfds =
(
"MS Mincho" , "-ricoh-ms mincho-",
"HGMinchoL" , "-ricoh-hgminchol-",
"IPAMincho" , "-misc-ipamincho-",
"Sazanami Mincho" , "-misc-sazanami mincho-"
);
my %sans_simplified_chinese_xlfds =
(
"FZSongTi" , "-founder-SongTi-",
"AR PL SungtiL GB" , "-arphic-ar pl sungtil gb-"
);
my %serif_simplified_chinese_xlfds =
(
"FZSongTi" , "-founder-SongTi-",
"AR PL SungtiL GB" , "-arphic-ar pl sungtil gb-"
);
my %sans_traditional_chinese_xlfds =
(
"FZMingTiB" , "-founder-MingTiB-",
"AR PL Mingti2L Big5" , "-arphic-ar pl mingti2l big5-"
);
my %serif_traditional_chinese_xlfds =
(
"FZMingTiB" , "-founder-MingTiB-",
"AR PL Mingti2L Big5" , "-arphic-ar pl mingti2l big5-"
);
my %sans_korean_xlfds =
(
"UnDotum" , "-misc-undotum-",
"Baekmuk Gulim" , "-baekmukttf-gulim-",
"Baekmuk Dotum" , "-baekmukttf-dotum-"
);
my %serif_korean_xlfds =
(
"UnBatang" , "-misc-unbatang-",
"Baekmuk Batang" , "-baekmukttf-batang-"
);
my $sans_japanese_xlfd = "-misc-sazanami gothic-";
my $sans_japanese_file = "/usr/share/fonts/truetype/sazanami-gothic.ttf";
my $serif_japanese_xlfd = "-misc-sazanami mincho-";
my $serif_japanese_file = "/usr/share/fonts/truetype/sazanami-mincho.ttf";
my $sans_simplified_chinese_xlfd = "-arphic-ar pl sungtil gb-";
my $sans_simplified_chinese_file = "/usr/share/fonts/truetype/gbsn00lp.ttf";
my $serif_simplified_chinese_xlfd = "-arphic-ar pl sungtil gb-";
my $serif_simplified_chinese_file = "/usr/share/fonts/truetype/gbsn00lp.ttf";
my $sans_traditional_chinese_xlfd = "-arphic-ar pl mingti2l big5-";
my $sans_traditional_chinese_file = "/usr/share/fonts/truetype/bsmi00lp.ttf";
my $serif_traditional_chinese_xlfd = "-arphic-ar pl mingti2l big5-";
my $serif_traditional_chinese_file = "/usr/share/fonts/truetype/bsmi00lp.ttf";
my $sans_korean_xlfd = "-baekmukttf-dotum-";
my $sans_korean_file = "/usr/share/fonts/truetype/dotum.ttf";
my $serif_korean_xlfd = "-baekmukttf-batang-";
my $serif_korean_file = "/usr/share/fonts/truetype/batang.ttf";
for my $font (@sans_japanese_priority) {
if (`fc-list "$font"`) {
open (NAMES, "fc-list \"$font\" file |");
binmode NAMES, ":bytes";
while (<NAMES>) {
chomp $ARG;
$ARG =~ s/:.*$//;
if ($ARG =~ /\.ttf|\.ttc/ && -f "$ARG") {
$sans_japanese_file = $ARG;
$sans_japanese_xlfd = $sans_japanese_xlfds{"$font"};
}
}
close (NAMES);
last;
}
}
if ( ! -f $sans_japanese_file ) {
print "Warning: cannot find a sans serif Japanese font. Japanese in Java might not work.\n";
}
for my $font (@serif_japanese_priority) {
if (`fc-list "$font"`) {
open (NAMES, "fc-list \"$font\" file |");
binmode NAMES, ":bytes";
while (<NAMES>) {
chomp $ARG;
$ARG =~ s/:.*$//;
if ($ARG =~ /\.ttf|\.ttc/ && -f "$ARG") {
$serif_japanese_file = $ARG;
$serif_japanese_xlfd = $serif_japanese_xlfds{"$font"};
}
}
close (NAMES);
last;
}
}
if ( ! -f $serif_japanese_file ) {
print "Warning: cannot find a serif Japanese font. Japanese in Java might not work.\n";
}
for my $font (@sans_simplified_chinese_priority) {
if (`fc-list "$font"`) {
open (NAMES, "fc-list \"$font\" file |");
binmode NAMES, ":bytes";
while (<NAMES>) {
chomp $ARG;
$ARG =~ s/:.*$//;
if ($ARG =~ /\.ttf|\.ttc/ && -f "$ARG") {
$sans_simplified_chinese_file = $ARG;
$sans_simplified_chinese_xlfd = $sans_simplified_chinese_xlfds{"$font"};
}
}
close (NAMES);
last;
}
}
if ( ! -f $sans_simplified_chinese_file ) {
print "Warning: cannot find a sans serif simplified Chinese font. Simplified Chinese in Java might not work.\n";
}
for my $font (@serif_simplified_chinese_priority) {
if (`fc-list "$font"`) {
open (NAMES, "fc-list \"$font\" file |");
binmode NAMES, ":bytes";
while (<NAMES>) {
chomp $ARG;
$ARG =~ s/:.*$//;
if ($ARG =~ /\.ttf|\.ttc/ && -f "$ARG") {
$serif_simplified_chinese_file = $ARG;
$serif_simplified_chinese_xlfd = $serif_simplified_chinese_xlfds{"$font"};
}
}
close (NAMES);
last;
}
}
if ( ! -f $serif_simplified_chinese_file ) {
print "Warning: cannot find a serif simplified Chinese font. Simplified Chinese in Java might not work.\n";
}
for my $font (@sans_traditional_chinese_priority) {
if (`fc-list "$font"`) {
open (NAMES, "fc-list \"$font\" file |");
binmode NAMES, ":bytes";
while (<NAMES>) {
chomp $ARG;
$ARG =~ s/:.*$//;
if ($ARG =~ /\.ttf|\.ttc/ && -f "$ARG") {
$sans_traditional_chinese_file = $ARG;
$sans_traditional_chinese_xlfd = $sans_traditional_chinese_xlfds{"$font"};
}
}
close (NAMES);
last;
}
}
if ( ! -f $sans_traditional_chinese_file ) {
print "Warning: cannot find a sans serif traditional Chinese font. Traditional Chinese in Java might not work.\n";
}
for my $font (@serif_traditional_chinese_priority) {
if (`fc-list "$font"`) {
open (NAMES, "fc-list \"$font\" file |");
binmode NAMES, ":bytes";
while (<NAMES>) {
chomp $ARG;
$ARG =~ s/:.*$//;
if ($ARG =~ /\.ttf|\.ttc/ && -f "$ARG") {
$serif_traditional_chinese_file = $ARG;
$serif_traditional_chinese_xlfd = $serif_traditional_chinese_xlfds{"$font"};
}
}
close (NAMES);
last;
}
}
if ( ! -f $serif_traditional_chinese_file ) {
print "Warning: cannot find a serif traditional Chinese font. Traditional Chinese in Java might not work.\n";
}
for my $font (@sans_korean_priority) {
if (`fc-list "$font"`) {
open (NAMES, "fc-list \"$font\" file |");
binmode NAMES, ":bytes";
while (<NAMES>) {
chomp $ARG;
$ARG =~ s/:.*$//;
if ($ARG =~ /\.ttf|\.ttc/ && -f "$ARG") {
$sans_korean_file = $ARG;
$sans_korean_xlfd = $sans_korean_xlfds{"$font"};
}
}
close (NAMES);
last;
}
}
if ( ! -f $sans_korean_file ) {
print "Warning: cannot find a sans serif Korean font. Korean in Java might not work.\n";
}
for my $font (@serif_korean_priority) {
if (`fc-list "$font"`) {
open (NAMES, "fc-list \"$font\" file |");
binmode NAMES, ":bytes";
while (<NAMES>) {
chomp $ARG;
$ARG =~ s/:.*$//;
if ($ARG =~ /\.ttf|\.ttc/ && -f "$ARG") {
$serif_korean_file = $ARG;
$serif_korean_xlfd = $serif_korean_xlfds{"$font"};
}
}
close (NAMES);
last;
}
}
if ( ! -f $serif_korean_file ) {
print "Warning: cannot find a serif Korean font. Korean in Java might not work.\n";
}
(my $sans_japanese_xlfd_no_space = $sans_japanese_xlfd) =~ s/ /_/g;
(my $serif_japanese_xlfd_no_space = $serif_japanese_xlfd) =~ s/ /_/g;
(my $sans_simplified_chinese_xlfd_no_space = $sans_simplified_chinese_xlfd) =~ s/ /_/g;
(my $serif_simplified_chinese_xlfd_no_space = $serif_simplified_chinese_xlfd) =~ s/ /_/g;
(my $sans_traditional_chinese_xlfd_no_space = $sans_traditional_chinese_xlfd) =~ s/ /_/g;
(my $serif_traditional_chinese_xlfd_no_space = $serif_traditional_chinese_xlfd) =~ s/ /_/g;
(my $sans_korean_xlfd_no_space = $sans_korean_xlfd) =~ s/ /_/g;
(my $serif_korean_xlfd_no_space = $serif_korean_xlfd) =~ s/ /_/g;
# setup for Java 1.4 (only for Japanese at the moment):
if (-f "$font_properties_ja_template_file") {
open (TEMPLATE, "$font_properties_ja_template_file") || die "can't open file $font_properties_ja_template_file: $!";
binmode TEMPLATE, ":utf8";
while (<TEMPLATE>) {
$ARG =~ s/_SANS_JAPANESE_XLFD_NO_SPACE_/$sans_japanese_xlfd_no_space/g;
$ARG =~ s/_SANS_JAPANESE_FILE_/$sans_japanese_file/g;
$ARG =~ s/_SANS_JAPANESE_XLFD_/$sans_japanese_xlfd/g;
$ARG =~ s/_SERIF_JAPANESE_XLFD_NO_SPACE_/$serif_japanese_xlfd_no_space/g;
$ARG =~ s/_SERIF_JAPANESE_FILE_/$serif_japanese_file/g;
$ARG =~ s/_SERIF_JAPANESE_XLFD_/$serif_japanese_xlfd/g;
$font_properties_ja_template .= $ARG;
}
close (TEMPLATE);
for my $globpattern (@font_properties_ja_globs) {
for my $file (glob ("$globpattern")) {
if (-f "$file") {
if ($VERBOSITY >= $VERBOSITY_QUIET) {
printf "writing $file\n";
}
open (FONTPROP, ">$file") || die "can't open file $file: $!";
binmode FONTPROP, ":utf8";
print FONTPROP $font_properties_ja_template;
close (FONTPROP);
}
}
}
}
# setup for Java 1.5 (for Japanese, Chinese, and Korean):
# I hope it is good enough to get the font directory from the full
# path of the Japanese sans serif file.
# Probably all fonts are in the same directory:
(my $x11fontdir = $sans_japanese_file) =~ s/\/[^\/]+$//;
if (-f "$fontconfig_SuSE_properties_template_file") {
open (TEMPLATE, "$fontconfig_SuSE_properties_template_file") || die "can't open file $fontconfig_SuSE_properties_template_file: $!";
binmode TEMPLATE, ":utf8";
while (<TEMPLATE>) {
$ARG =~ s/_SANS_JAPANESE_XLFD_NO_SPACE_/$sans_japanese_xlfd_no_space/g;
$ARG =~ s/_SANS_JAPANESE_FILE_/$sans_japanese_file/g;
$ARG =~ s/_SANS_JAPANESE_XLFD_/$sans_japanese_xlfd/g;
$ARG =~ s/_SERIF_JAPANESE_XLFD_NO_SPACE_/$serif_japanese_xlfd_no_space/g;
$ARG =~ s/_SERIF_JAPANESE_FILE_/$serif_japanese_file/g;
$ARG =~ s/_SERIF_JAPANESE_XLFD_/$serif_japanese_xlfd/g;
$ARG =~ s/_SANS_SIMPLIFIED_CHINESE_XLFD_NO_SPACE_/$sans_simplified_chinese_xlfd_no_space/g;
$ARG =~ s/_SANS_SIMPLIFIED_CHINESE_FILE_/$sans_simplified_chinese_file/g;
$ARG =~ s/_SANS_SIMPLIFIED_CHINESE_XLFD_/$sans_simplified_chinese_xlfd/g;
$ARG =~ s/_SERIF_SIMPLIFIED_CHINESE_XLFD_NO_SPACE_/$serif_simplified_chinese_xlfd_no_space/g;
$ARG =~ s/_SERIF_SIMPLIFIED_CHINESE_FILE_/$serif_simplified_chinese_file/g;
$ARG =~ s/_SERIF_SIMPLIFIED_CHINESE_XLFD_/$serif_simplified_chinese_xlfd/g;
$ARG =~ s/_SANS_TRADITIONAL_CHINESE_XLFD_NO_SPACE_/$sans_traditional_chinese_xlfd_no_space/g;
$ARG =~ s/_SANS_TRADITIONAL_CHINESE_FILE_/$sans_traditional_chinese_file/g;
$ARG =~ s/_SANS_TRADITIONAL_CHINESE_XLFD_/$sans_traditional_chinese_xlfd/g;
$ARG =~ s/_SERIF_TRADITIONAL_CHINESE_XLFD_NO_SPACE_/$serif_traditional_chinese_xlfd_no_space/g;
$ARG =~ s/_SERIF_TRADITIONAL_CHINESE_FILE_/$serif_traditional_chinese_file/g;
$ARG =~ s/_SERIF_TRADITIONAL_CHINESE_XLFD_/$serif_traditional_chinese_xlfd/g;
$ARG =~ s/_SANS_KOREAN_XLFD_NO_SPACE_/$sans_korean_xlfd_no_space/g;
$ARG =~ s/_SANS_KOREAN_FILE_/$sans_korean_file/g;
$ARG =~ s/_SANS_KOREAN_XLFD_/$sans_korean_xlfd/g;
$ARG =~ s/_SERIF_KOREAN_XLFD_NO_SPACE_/$serif_korean_xlfd_no_space/g;
$ARG =~ s/_SERIF_KOREAN_FILE_/$serif_korean_file/g;
$ARG =~ s/_SERIF_KOREAN_XLFD_/$serif_korean_xlfd/g;
$ARG =~ s/_X11FONTDIR_/$x11fontdir/;
$fontconfig_SuSE_properties_template .= $ARG;
}
close (TEMPLATE);
for my $globpattern (@fontconfig_SuSE_properties_globs) {
for my $file (glob ("$globpattern")) {
if (-f "$file") {
if ($VERBOSITY >= $VERBOSITY_QUIET) {
printf "writing $file\n";
}
open (FONTPROP, ">$file") || die "can't open file $file: $!";
binmode FONTPROP, ":utf8";
print FONTPROP $fontconfig_SuSE_properties_template;
close (FONTPROP);
}
}
}
}
}
########################################################################
my @font_dirs = ();
sub font_dirs_setup_add_font_dir {
my ($dir) = @_;
while (-l "$dir") {
$dir = readlink ("$dir");
}
if (! -d "$dir") {
return;
}
if (grep (/$dir/, @font_dirs)) {
return;
}
push (@font_dirs, ("$dir"));
if (opendir (DIR, $dir)) {
my @entries = readdir (DIR);
for my $entry (@entries) {
if ("$entry" =~ /\./ || "$entry" =~ /\.\./ || ! -d "$dir/$entry") {
next;
}
font_dirs_setup_add_font_dir("$dir/$entry");
}
closedir DIR;
}
}
sub font_dirs_setup {
my $suse_font_dirs_file = "/etc/fonts/suse-font-dirs.conf";
my $suse_font_dirs_template_file = "/usr/share/fonts-config/suse-font-dirs.conf.template";
my $suse_font_dirs = "";
my $suse_font_dirs_template = "";
if (-f "$suse_font_dirs_template_file") {
open (TEMPLATE, "$suse_font_dirs_template_file") || die "can't open file $suse_font_dirs_template_file: $!";
binmode TEMPLATE, ":utf8";
while (<TEMPLATE>) {
if ($ARG =~ /<dir>(.*)<\/dir>/) {
for my $dir (glob ("$1")) {
if (-d "$dir") {
font_dirs_setup_add_font_dir ("$dir");
}
}
}
elsif ($ARG =~ /<\/fontconfig>/) {
for my $dir (@font_dirs) {
$suse_font_dirs_template .= " <dir>$dir</dir>\n";
}
$suse_font_dirs_template .= "\n</fontconfig>\n";
}
else {
$suse_font_dirs_template .= $ARG;
}
}
close (TEMPLATE);
if (open (CONF, "$suse_font_dirs_file")) {
while (<CONF>) {
$suse_font_dirs .= $ARG;
}
close (CONF);
}
if ("$suse_font_dirs_template" eq "$suse_font_dirs") {
if ($VERBOSITY >= $VERBOSITY_QUIET) {
printf "$suse_font_dirs_file unchanged\n";
}
} else {
if ($VERBOSITY >= $VERBOSITY_QUIET) {
printf "writing $suse_font_dirs_file\n";
}
open (CONF, ">$suse_font_dirs_file") || die "can't open file $suse_font_dirs_file: $!";
print CONF $suse_font_dirs_template;
close (CONF);
}
}
}
########################################################################
sub hinting_setup {
my $suse_hinting_file = "/etc/fonts/suse-hinting.conf";
my $suse_hinting_template_file = "/usr/share/fonts-config/suse-hinting.conf.template";
my $suse_hinting = "";
my $suse_hinting_template = "";
if (-f "$suse_hinting_template_file") {
open (TEMPLATE, "$suse_hinting_template_file") || die "can't open file $suse_hinting_template_file: $!";
binmode TEMPLATE, ":utf8";
while (<TEMPLATE>) {
$ARG =~ s/_BYTECODE_BW_MAX_PIXEL_/$OPT_BCBWMAX/;
$suse_hinting_template .= $ARG;
}
close (TEMPLATE);
if (open (CONF, "$suse_hinting_file")) {
while (<CONF>) {
$suse_hinting .= $ARG;
}
close (CONF);
}
if ("$suse_hinting_template" eq "$suse_hinting") {
if ($VERBOSITY >= $VERBOSITY_QUIET) {
printf "$suse_hinting_file unchanged\n";
}
} else {
if ($VERBOSITY >= $VERBOSITY_QUIET) {
printf "writing $suse_hinting_file\n";
}
open (CONF, ">$suse_hinting_file") || die "can't open file $suse_hinting_file: $!";
print CONF $suse_hinting_template;
close (CONF);
}
}
}
########################################################################
sub embedded_bitmap_setup {
my $suse_bitmaps_file = "/etc/fonts/suse-bitmaps.conf";
my $suse_bitmaps_template_file = "/usr/share/fonts-config/suse-bitmaps.conf.template";
my $suse_bitmaps = "";
my $suse_bitmaps_template = "";
if (-f "$suse_bitmaps_template_file") {
open (TEMPLATE, "$suse_bitmaps_template_file") || die "can't open file $suse_bitmaps_template_file: $!";
binmode TEMPLATE, ":utf8";
while (<TEMPLATE>) {
if ($ARG !~ /_USE_EMBEDDED_BITMAPS_PLACEHOLDER_/) {
$suse_bitmaps_template .= $ARG;
}
else {
if (! $OPT_EBITMAP) {
$suse_bitmaps_template .= " <match target=\"font\">\n";
$suse_bitmaps_template .= " <edit name=\"embeddedbitmap\" mode=\"assign\">\n";
$suse_bitmaps_template .= " <bool>false</bool>\n";
$suse_bitmaps_template .= " </edit>\n";
$suse_bitmaps_template .= " </match>\n";
} elsif ($OPT_EBITMAP && $OPT_EBITMAP_LANG =~ /0/) {
$suse_bitmaps_template .= " <match target=\"font\">\n";
$suse_bitmaps_template .= " <edit name=\"embeddedbitmap\" mode=\"assign\">\n";
$suse_bitmaps_template .= " <bool>true</bool>\n";
$suse_bitmaps_template .= " </edit>\n";
$suse_bitmaps_template .= " </match>\n";
} else {
$suse_bitmaps_template .= " <match target=\"font\">\n";
$suse_bitmaps_template .= " <edit name=\"embeddedbitmap\" mode=\"assign\">\n";
$suse_bitmaps_template .= " <bool>false</bool>\n";
$suse_bitmaps_template .= " </edit>\n";
$suse_bitmaps_template .= " </match>\n";
$suse_bitmaps_template .= " <match target=\"font\">\n";
$suse_bitmaps_template .= " <test name=\"lang\" compare=\"contains\">\n";
my @languages = split (":", "$OPT_EBITMAP_LANG");
for my $i (@languages) {
$suse_bitmaps_template .= " <string>$i</string>\n";
}
$suse_bitmaps_template .= " </test>\n";
$suse_bitmaps_template .= " <edit name=\"embeddedbitmap\" mode=\"assign\">\n";
$suse_bitmaps_template .= " <bool>true</bool>\n";
$suse_bitmaps_template .= " </edit>\n";
$suse_bitmaps_template .= " </match>\n";
}
}
}
close (TEMPLATE);
if (open (CONF, "$suse_bitmaps_file")) {
while (<CONF>) {
$suse_bitmaps .= $ARG;
}
close (CONF);
}
if ("$suse_bitmaps_template" eq "$suse_bitmaps") {
if ($VERBOSITY >= $VERBOSITY_QUIET) {
printf "$suse_bitmaps_file unchanged\n";
}
} else {
if ($VERBOSITY >= $VERBOSITY_QUIET) {
printf "writing $suse_bitmaps_file\n";
}
open (CONF, ">$suse_bitmaps_file") || die "can't open file $suse_bitmaps_file: $!";
print CONF $suse_bitmaps_template;
close (CONF);
}
}
}
########################################################################
# 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) {
my @f1s = stat ($f1);
my @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) {
my @f1s = stat ($f1);
my @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 my_system {
my ($command) = @_;
if ($VERBOSITY >= $VERBOSITY_DEBUG) {
print "executing: $command\n";
}
return system ($command);
}
sub search_executable {
for my $file (@_) {
if (-x $file) {
return $file;
}
}
return "";
}