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 >
Text File  |  2006-11-29  |  74KB  |  2,335 lines

  1. #! /usr/bin/perl -w                                       # -*- perl -*-
  2. #
  3. # Copyright (c) 2000-2004 SuSE Linux AG, Nuernberg, Germany.
  4. # All rights reserved.
  5. #
  6. ########################################################################
  7. # create a man-page with:
  8. #
  9. #     pod2man --section 1 --center=" " fonts-config | gzip -9 -c > fonts-config.1.gz
  10. #     cp fonts-config.1.gz /usr/share/man/man1/fonts-config.1.gz
  11.  
  12. =head1 NAME
  13.  
  14. fonts-config - configures installed X11 fonts.
  15.  
  16. =head1 SYNOPSIS
  17.  
  18. fonts-config [B<OPTION>]...
  19.  
  20. =head1 OPTIONS
  21.  
  22. =over 4
  23.  
  24. =item B<-f>, B<--force>
  25.  
  26. Force the update of all generated files even if it appears to be
  27. unnecessary according to the time stamps.
  28.  
  29. =item B<-q>, B<--quiet>
  30.  
  31. Work silently, unless an error occurs.
  32.  
  33. =item B<-v>, B<--verbose>
  34.  
  35. Print some progress messages to standard output.
  36.  
  37. =item B<-d>, B<--debug>
  38.  
  39. Print a lot of debugging messages to standard output.
  40.  
  41. =item B<--(no)gs-fontmap>
  42.  
  43. Generate (or don't generate)  a Fontmap for Ghostscript.
  44.  
  45. Can only work if the 'ftdump' binary which is in the 'ft2demos'
  46. packages is available.
  47.  
  48. =item B<--(no)ttcap>
  49.  
  50. Generate (or don't generate) TTCap entries.  TTCap entries can be used
  51. with the xtt module and with recent versions of the freetype module.
  52.  
  53. =item B<--(no)ooo>
  54.  
  55. Generate (or don't generate) font setup for OpenOffice
  56.  
  57. =item B<--(no)java>
  58.  
  59. Generate (or don't generate) font setup for Java 1.4.x and Java 1.5.x.
  60.  
  61. =item B<--bcbwmax> size
  62.  
  63. Maximum pixel size to use the byte code interpreter with black and
  64. white rendering.
  65.  
  66. =item B<--version>
  67.  
  68. Display version and exit.
  69.  
  70. =item B<-h>, B<--help>
  71.  
  72. Display a short help message and exit.
  73.  
  74. =back
  75.  
  76. =head1 DESCRIPTION
  77.  
  78. Configures installed X11 fonts. Basically it does the following
  79. things:
  80.  
  81. =over 4
  82.  
  83. =item B<call cidfont-x11-config>
  84.  
  85. cidfont-x11-config is another little perl script which configures
  86. CID-keyed fonts for use with X11, see L<cidfont-x11-config(1)>.
  87.  
  88. =item B<creates fonts.scale and fonts.dir files>
  89.  
  90. To find the list of directories currently used for server side fonts,
  91. B</etc/X11/xorg.conf> is parsed and merged with a hardcoded list of
  92. directories. If the font server xfs is running, B</etc/X11/fs/config>
  93. is also parsed and the list of directories found there is merged as
  94. well.
  95.  
  96. For each directory from this list, the time stamps of the directory,
  97. the B<fonts.scale> file, the B<fonts.dir> file and an extra time stamp
  98. file B<.fonts-config-timestamp> are checked.  If not all the time
  99. stamps are equal or any of these files is missing, the B<fonts.scale>
  100. and B<fonts.dir> files will be updated as follows:
  101.  
  102. First of all a B<fonts.scale> file is created by calling
  103. B<mkfontscale>.
  104.  
  105. Then, the entries found in the B<fonts.scale> file are merged with
  106. the entries from all B<fonts.scale.*> files.
  107.  
  108. B<fonts.scale.*> files may be supplied by rpm-packages or manually
  109. added by the user to override or amend the entries created
  110. automatically by B<mkfontscale>. Entries in a B<fonts.scale.*> file
  111. have higher priority than entries automatically created by
  112. B<mkfontscale>.  All entries generated automatically by B<mkfontscale>
  113. for a certain font file are discarded if any B<fonts.scale.*> file
  114. contains an entry for the same font file.
  115.  
  116. If the B<xtt> module is configured to load in B</etc/X11/xorg.conf>,
  117. additional entries may be created to make use of the artificial bold
  118. and italic features of B<xtt>. The time stamp of
  119. B</etc/X11/xorg.conf> is not checked, i.e. you have to use
  120. B<fonts-config --force> after editing B</etc/X11/xorg.conf> to switch
  121. between the B<xtt> and B<freetype> modules.
  122.  
  123. After the final list of entries has been written back to
  124. B<fonts.scale>, B<mkfontdir> is called.
  125.  
  126. Finally, the time stamps of the directory, B<fonts.scale>,
  127. B<fonts.dir>, and B<.fonts-config-timestamp> are set to the time when
  128. B<fonts-config> started.
  129.  
  130. If any B<fonts.scale> file in the directory list needed an update and
  131. the option B<--gs-fontmap> is set, a Ghostcript Fontmap is also
  132. generated for all scalable fonts in the directory list and the result
  133. is written to B</usr/share/ghostscript/*/lib/Fontmap.X11-auto>.
  134.  
  135. =item B<call fc-cache>
  136.  
  137. creates cache files for fonts to use with client side font rendering
  138. via fontconfig/libXft, for details see L<fc-cache(1)>.
  139. B<fonts.cache-2> cache files are generated in B</var/cache/fontconfig>
  140. for all directories which are configured in B</etc/fonts/fonts.conf>
  141. and all their subdirectories.
  142.  
  143. =back
  144.  
  145. Usually B<fonts-config> is called automatically via SuSEconfig
  146. (B<SuSEconfig --module fonts>), which is usually automatically
  147. called by YaST2. But you can also execute B<fonts-config> directly,
  148. which is mainly useful to debug it.
  149.  
  150. =head1 FILES
  151.  
  152. =over 4
  153.  
  154. =item B</etc/sysconfig/fonts-config>
  155.  
  156. Default values for some command line options of fonts-config are read
  157. from this file if it exists.  The options currently supported in
  158. this file are:
  159.  
  160. =over 4
  161.  
  162. =item GENERATE_TTCAP_ENTRIES
  163.  
  164. can be set to "yes" or "no" and sets the default for the option B<--(no)ttcap>.
  165.  
  166. =item GENERATE_GHOSTSCRIPT_FONTMAPS
  167.  
  168. can be set to "yes" or "no" and sets the default for the option B<--(no)gs-fontmap>.
  169.  
  170. This can only work if the 'ftdump' binary which is in the 'ft2demos'
  171. packages is available.
  172.  
  173. =item GENERATE_OOO_FONT_SETUP
  174.  
  175. can be set to "yes" or "no" and sets the default for the option B<--(no)ooo>.
  176.  
  177. =item GENERATE_JAVA_FONT_SETUP
  178.  
  179. can be set to "yes" or "no" and sets the default for the option B<--(no)java>.
  180.  
  181. =item BYTECODE_BW_MAX_PIXEL
  182.  
  183. can be set to any integer value and sets the default for the option B<--bcbwmax>.
  184.  
  185. =back
  186.  
  187. =back
  188.  
  189. =head1 SEE ALSO
  190.  
  191. L<fc-cache(1)>, L<cidfont-x11-config(1)>, L<mkfontdir(1)>, L<mkfontscale(1)>
  192.  
  193. =head1 AUTHOR
  194.  
  195. Mike FABIAN <I<mfabian@suse.de>>, 2003.
  196.  
  197. =cut
  198.  
  199. ########################################################################
  200.  
  201. use utf8;
  202. use English;
  203. use Getopt::Long;
  204. use strict;
  205.  
  206. my $script_start_time = time();
  207.  
  208. my $cvs_id = '$Id: fonts-config,v 1.68 2006/10/25 13:58:26 mfabian Exp $';
  209. my $cvs_date = '$Date: 2006/10/25 13:58:26 $';
  210. $cvs_date =~ /^\$[[:alpha:]]+: (.*) \$$/;
  211. my $version = $1;
  212.  
  213. sub usage {
  214.   print "Usage: fonts-config [option] ...\n";
  215.   print "-f, --force              Force the update of all generated files even\n";
  216.   print "                         if it appears unnecessary according to the time stamps\n";
  217.   print "-q, --quiet              Work silently, unless an error occurs.\n";
  218.   print "-v, --verbose            Print some progress messages to standard output.\n";
  219.   print "-d, --debug              Print a lot of debugging messages to standard output.\n";
  220.   print "    --(no)gs-fontmap     generate a Fontmap file for Ghostscript.\n";
  221.   print "    --(no)ttcap          generate TTCap entries for xtt and recent freetype modules.\n";
  222.   print "    --(no)ooo            generate font setup for OpenOffice.\n";
  223.   print "    --(no)java           generate font setup for Java 1.4.x and Java 1.5.x.\n";
  224.   print "    --bcbwmax  size      maximum pixel size to use the byte code interpreter with\n";
  225.   print "                         black and white rendering.\n";
  226.   print "    --(no)ebitmap        whether to use embedded bitmaps or not.\n";
  227.   print "    --ebitmaplang string the argument is a string which contains a list of colon\n";
  228.   print "                         separated languages, for example \"ja:ko:zh-CN\" \n";
  229.   print "                         which means \"use embedded bitmaps only for\n";
  230.   print "                         fonts supporting Japanese, Korean, or simplified Chinese.\n";
  231.   print "    --version            Display version and exit.\n";
  232.   print "-h, --help               Display this help and exit.\n";
  233.   exit 1;
  234. }
  235.  
  236. my $OPT_FORCE = 0;
  237. my $OPT_QUIET = 0;
  238. my $OPT_VERBOSE = 1;
  239. my $OPT_DEBUG = 0;
  240. my $OPT_TTCAP = 0;
  241. my $OPT_GS_FONTMAP = 1;
  242. my $OPT_OOO = 1;
  243. my $OPT_JAVA = 1;
  244. my $OPT_BCBWMAX = 0;
  245. my $OPT_EBITMAP = 1;
  246. my $OPT_EBITMAP_LANG = "ja:ko:zh-CN:zh-TW:zh-HK:zh-SG";
  247. my $OPT_VERSION = 0;
  248. my $OPT_HELP = 0;
  249.  
  250. my %sysconfig_options = (
  251.              "GENERATE_TTCAP_ENTRIES"         , "OPT_TTCAP",
  252.              "GENERATE_GHOSTSCRIPT_FONTMAPS"  , "OPT_GS_FONTMAP",
  253.              "GENERATE_OOO_FONT_SETUP"        , "OPT_OOO",
  254.              "GENERATE_JAVA_FONT_SETUP"       , "OPT_JAVA",
  255.              "BYTECODE_BW_MAX_PIXEL"          , "OPT_BCBWMAX",
  256.              "USE_EMBEDDED_BITMAPS"           , "OPT_EBITMAP",
  257.              "EMBEDDED_BITMAPS_LANGUAGES"     , "OPT_EBITMAP_LANG"
  258.             );
  259.  
  260. my $sysconfig_file = "/etc/sysconfig/fonts-config";
  261.  
  262. sub get_option_defaults_from_sysconfig {
  263.   if (open (SYSCONFIG, "$sysconfig_file")) {
  264.     no strict "vars";
  265.     # print "reading defaults from $sysconfig.\n";
  266.     while (<SYSCONFIG>) {
  267.       chomp ($ARG);
  268.       if ($ARG =~ /([^#]*)#?.*/) { # strip comments
  269.     $ARG = $1;
  270.       }
  271.       eval ("\$$ARG;");
  272.     }
  273.     close (SYSCONFIG);
  274.     for my $i (keys %sysconfig_options) {
  275.       if (eval ("\$$i") =~ /yes/i) {
  276.     eval("\$$sysconfig_options{$i}=1");
  277.       }
  278.       elsif (eval ("\$$i") =~ /no/i) {
  279.     eval("\$$sysconfig_options{$i}=0");
  280.       }
  281.       elsif (eval ("\$$i") =~ /[0-9]+/) { # Type integer
  282.     eval("\$$sysconfig_options{$i}=\$$i");
  283.       }
  284.       elsif (eval ("\$$i") =~ /[-:a-zA-Z0-9]+/) { # Type string
  285.     eval("\$$sysconfig_options{$i}=\$$i");
  286.       }
  287.       else { # this case also occurs when the variable is the empty string!
  288.     eval("\$$sysconfig_options{$i}=0");
  289.       }
  290.     }
  291.     return (0);
  292.   }
  293.   else {
  294.     # print "$sysconfig doesn't exist, using builtin defaults.\n";
  295.     return (1);
  296.   }
  297. }
  298.  
  299.  
  300. get_option_defaults_from_sysconfig();
  301.  
  302. # Process command line options
  303. my %opt;
  304. unless (GetOptions(\%opt,
  305.            'force|f',       \$OPT_FORCE,
  306.            'quiet|q',       \$OPT_QUIET,
  307.            'verbose|v',     \$OPT_VERBOSE,
  308.            'debug|d',       \$OPT_DEBUG,
  309.                    'gs-fontmap!',   \$OPT_GS_FONTMAP,
  310.            'ttcap!',        \$OPT_TTCAP,
  311.            'ooo!',          \$OPT_OOO,
  312.            'java!',         \$OPT_JAVA,
  313.            'bcbwmax=i',     \$OPT_BCBWMAX,
  314.            'ebitmap!',      \$OPT_EBITMAP,
  315.            'ebitmaplang=s', \$OPT_EBITMAP_LANG,
  316.            'version',       \$OPT_VERSION,
  317.            'help|h',        \$OPT_HELP,
  318.           )) {
  319.   &usage ();
  320.   exit 1;
  321. }
  322.  
  323. if ($OPT_VERSION) {
  324.   print "fonts-config $version\n";
  325.   exit 0;
  326. }
  327.  
  328. if ($OPT_HELP) {
  329.   &usage ();
  330.   exit 0;
  331. }
  332.  
  333. my $VERBOSITY_QUIET   = 0;
  334. my $VERBOSITY_VERBOSE = 1;
  335. my $VERBOSITY_DEBUG   = 256;
  336. my $VERBOSITY         = $VERBOSITY_VERBOSE; # default
  337.  
  338. if ($OPT_DEBUG) {
  339.   $VERBOSITY = $VERBOSITY_DEBUG;
  340. }
  341. elsif ($OPT_VERBOSE) {
  342.   $VERBOSITY = $VERBOSITY_VERBOSE;
  343. }
  344. elsif ($OPT_QUIET) {
  345.   $VERBOSITY = $VERBOSITY_QUIET;
  346. }
  347.  
  348. no strict "vars";
  349. no warnings;
  350. if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  351.   print "The following options were read from $sysconfig_file:\n";
  352.   for my $i (keys %sysconfig_options) {
  353.     if (defined eval ("\$$i")) {
  354.       printf "$i=%s\n", eval("\$$i");
  355.     }
  356.   }
  357.   print "--- end of options froom $sysconfig_file ---\n";
  358. }
  359. use warnings;
  360. use strict;
  361.  
  362. # check if we are started as root
  363. # only one of UID and USER must be set correctly
  364.  
  365. if ($UID != 0 && $ENV{USER} !~ /root/) {
  366.     print "*** Error: You must be root to start $0\n";
  367.     usage();
  368.     exit 1;
  369. }
  370.  
  371. # external binaries:
  372. my $fc_cache_bin = search_executable ("/usr/bin/fc-cache", "/usr/X11R6/bin/fc-cache");
  373. my $fc_cache32_bin = search_executable ("/usr/bin/fc-cache32", "/usr/bin/fc-cache-x86");
  374. my $fc_cache64_bin = search_executable ("/usr/bin/fc-cache64");
  375. my $fc_match_bin = search_executable ("/usr/bin/fc-match");
  376. my $cidfont_x11_config_bin = search_executable ("/usr/sbin/cidfont-x11-config");
  377. my $xset_bin = search_executable ("/usr/bin/xset", "/usr/X11R6/bin/xset");
  378. my $xfs_bin = search_executable ("/usr/bin/xfs", "/usr/X11R6/bin/xfs");
  379. my $checkproc_bin = search_executable ("/sbin/checkproc");
  380. my $killproc_bin = search_executable ("/sbin/killproc");
  381. my $XFree86_bin = search_executable ("/usr/bin/Xorg", "/usr/X11R6/bin/Xorg", "/usr/X11R6/bin/XFree86");
  382. my $mkfontscale_bin = search_executable ("/usr/bin/mkfontscale", "/usr/X11R6/bin/mkfontscale");
  383. my $mkfontdir_bin = search_executable ("/usr/bin/mkfontdir", "/usr/X11R6/bin/mkfontdir");
  384. my $ftdump_bin = search_executable ("/usr/bin/ftdump");
  385.  
  386. my $xtt_module_used = 0;
  387. my $freetype_module_used = 0;
  388.  
  389. my $have_file_mmagic = 0;
  390. eval { require File::MMagic; };
  391. unless ($EVAL_ERROR) {
  392.   $have_file_mmagic = 1;
  393.   import File::MMagic;
  394. }
  395.  
  396. my $command = "";
  397.  
  398. # search whether true CID-keyed fonts are available
  399. # in /usr/share/ghostscript/Resource and if yes make them
  400. # available to X11 as well:
  401. if ($cidfont_x11_config_bin) {
  402.   $command = $cidfont_x11_config_bin;
  403.   if ($VERBOSITY == $VERBOSITY_VERBOSE) {
  404.     print "Configure X11 to use available CID-keyed fonts ...\n";
  405.   }
  406.   if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  407.     $command .= " --verbose ";
  408.   }
  409.   if ($OPT_FORCE)   {
  410.     $command .= " --force ";
  411.   }
  412.   my_system ($command);
  413. }
  414.  
  415. my @x11_font_dirs = x11_font_dirs();
  416. my $gs_fontmap_needs_update = 0;
  417.  
  418. if ($VERBOSITY == $VERBOSITY_VERBOSE) {
  419.   print "Creating fonts.{scale,dir} files ";
  420. }
  421. for my $dir (@x11_font_dirs) {
  422.   make_fonts_scale_and_fonts_dir ($dir);
  423.   if ($VERBOSITY == $VERBOSITY_VERBOSE) {
  424.     print "."; # "progress bar"
  425.   }
  426. }
  427. if ($VERBOSITY == $VERBOSITY_VERBOSE) {
  428.   print "\n";
  429. }
  430.  
  431. # The following three lines may change files in /etc/fonts, therefore
  432. # they have to be called *before* fc-cache. If anything is
  433. # changed in /etc/fonts after calling fc-cache, fontconfig
  434. # will think that the cache files are out of date again.
  435. font_dirs_setup ();
  436. hinting_setup ();
  437. embedded_bitmap_setup ();
  438.  
  439. my $fc_cache_exit_status = 256;
  440.  
  441. if ($fc_cache_bin) {
  442.   $command = "$fc_cache_bin";
  443.   if ($VERBOSITY == $VERBOSITY_VERBOSE) {
  444.     print "Creating cache files for fontconfig ";
  445.   }
  446.   if ($OPT_FORCE)   {
  447.     $command .= " --really-force ";
  448.   }
  449.   if ($VERBOSITY >= $VERBOSITY_VERBOSE) {
  450.     $command .= " --verbose ";
  451.   }
  452.   if ($VERBOSITY == $VERBOSITY_VERBOSE) { # with "progress bar"
  453.     open (FC_CACHE, "$command |");
  454.     select (STDOUT);
  455.     $OUTPUT_AUTOFLUSH = 1;
  456.     while(<FC_CACHE>) {
  457.       print ".";
  458.     }
  459.     print "\n";
  460.     close (FC_CACHE);
  461.   }
  462.   else { # without "progress bar"
  463.     my_system($command);
  464.   }
  465. }
  466. $fc_cache_exit_status = $CHILD_ERROR;
  467. if ($VERBOSITY == $VERBOSITY_DEBUG) {
  468.   print "exit status of fc-cache: $fc_cache_exit_status\n";
  469. }
  470.  
  471. my $fc_cache32_exit_status = 256;
  472.  
  473. if ($fc_cache32_bin) {
  474.   $command = "$fc_cache32_bin";
  475.   if ($VERBOSITY == $VERBOSITY_VERBOSE) {
  476.     print "Creating 32bit cache files for fontconfig ";
  477.   }
  478.   if ($VERBOSITY >= $VERBOSITY_VERBOSE) {
  479.     $command .= " --verbose ";
  480.   }
  481.   if ($VERBOSITY == $VERBOSITY_VERBOSE) { # with "progress bar"
  482.     open (FC_CACHE, "$command |");
  483.     select (STDOUT);
  484.     $OUTPUT_AUTOFLUSH = 1;
  485.     while(<FC_CACHE>) {
  486.       print ".";
  487.     }
  488.     print "\n";
  489.     close (FC_CACHE);
  490.   }
  491.   else { # without "progress bar"
  492.     my_system($command);
  493.   }
  494. }
  495. $fc_cache32_exit_status = $CHILD_ERROR;
  496. if ($VERBOSITY == $VERBOSITY_DEBUG) {
  497.   print "exit status of fc-cache: $fc_cache32_exit_status\n";
  498. }
  499.  
  500. my $fc_cache64_exit_status = 256;
  501.  
  502. if ($fc_cache64_bin) {
  503.   $command = "$fc_cache64_bin";
  504.   if ($VERBOSITY == $VERBOSITY_VERBOSE) {
  505.     print "Creating 64bit cache files for fontconfig ";
  506.   }
  507.   if ($VERBOSITY >= $VERBOSITY_VERBOSE) {
  508.     $command .= " --verbose ";
  509.   }
  510.   if ($VERBOSITY == $VERBOSITY_VERBOSE) { # with "progress bar"
  511.     open (FC_CACHE, "$command |");
  512.     select (STDOUT);
  513.     $OUTPUT_AUTOFLUSH = 1;
  514.     while(<FC_CACHE>) {
  515.       print ".";
  516.     }
  517.     print "\n";
  518.     close (FC_CACHE);
  519.   }
  520.   else { # without "progress bar"
  521.     my_system($command);
  522.   }
  523. }
  524. $fc_cache64_exit_status = $CHILD_ERROR;
  525. if ($VERBOSITY == $VERBOSITY_DEBUG) {
  526.   print "exit status of fc-cache: $fc_cache64_exit_status\n";
  527. }
  528.  
  529. # make_gs_fontmap uses fontconfig,
  530. # therefore it has to be called *after* fc-cache
  531. if ($OPT_GS_FONTMAP) {
  532.   if ($OPT_FORCE || $gs_fontmap_needs_update ) {
  533.     make_gs_fontmap (@x11_font_dirs);
  534.   }
  535. }
  536.  
  537. # generate_ooo_font_setup uses fontconfig,
  538. # therefore it has to be called *after* fc-cache
  539. if ($OPT_OOO) {
  540.   generate_ooo_font_setup ();
  541. }
  542.  
  543. # generate_java_font_setup uses fontconfig,
  544. # therefore it has to be called *after* fc-cache
  545. if ($OPT_JAVA) {
  546.   generate_java_font_setup ();
  547. }
  548.  
  549. # source all shell scripts from the directory /usr/lib/fonts-config/conf.d
  550. # which start with at least one digit (sorted in POSIX sort order because this
  551. # perl script does *not* use "use locale"):
  552. if (opendir (DIR, "/usr/lib/fonts-config/conf.d")) {
  553.   my @entries = readdir (DIR);
  554.   for my $entry (sort (@entries)) {
  555.       if ("$entry" =~ /\./ || "$entry" =~ /\.\./
  556.       || "$entry" !~ /^[0-9]+/
  557.       || ! -f "/usr/lib/fonts-config/conf.d/$entry") {
  558.     next;
  559.       }
  560.       my_system ("sh /usr/lib/fonts-config/conf.d/$entry");
  561.   }
  562.   closedir DIR;
  563. }
  564.  
  565. if ($xset_bin) {
  566.   if ($ENV{DISPLAY} && $ENV{DISPLAY} =~ /^:[0-9].*/) {
  567.     # it's a local display
  568.     $command = "$xset_bin fp rehash ";
  569.     unless ($VERBOSITY >= $VERBOSITY_DEBUG) {
  570.       $command .= " > /dev/null 2>&1 ";
  571.     }
  572.     my_system ($command);
  573.   }
  574. }
  575.  
  576. if ($xfs_bin && my_system ("$checkproc_bin $xfs_bin") == 0) {
  577.   if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  578.     print "Reloading config file of X Font Server ...\n";
  579.   }
  580.   my_system ("$killproc_bin $xfs_bin -USR1");
  581. }
  582. elsif ($VERBOSITY >= $VERBOSITY_DEBUG) {
  583.   print "X Font Server not used.\n";
  584. }
  585.  
  586. exit 0;
  587.  
  588. ########################################################################
  589.  
  590. sub version_compare {
  591.   my ($version_string_1, $version_string_2) = @_;
  592.   # compare two version numbers consisting only of digits and dots
  593.   # returns an integer less than, equal to, or greater than zero
  594.   # if $version_string_1 is found, respectively, to be a smaller version,
  595.   # equal version, or greater version than $version_string_2.
  596.   my @v1 = split (/\./, $version_string_1);
  597.   my @v2 = split (/\./, $version_string_2);
  598.   for (my $i = 0 ; $i <= $#v1 && $i <= $#v2; $i++) {
  599.     if ($v1[$i] < $v2[$i]) {
  600.       return -1;
  601.     } elsif ($v1[$i] > $v2[$i]) {
  602.       return 1;
  603.     }
  604.   }
  605.   if ($#v1 < $#v2) {
  606.     return -1;
  607.   } elsif ($#v1 > $#v2) {
  608.     return 1;
  609.   }
  610.   return 0;
  611. }
  612.  
  613. sub fontconfig_version {
  614.   if ($fc_cache_bin) {
  615.     open (VERSION, "$fc_cache_bin -V 2>&1 |");
  616.     binmode VERSION, ":bytes";
  617.     while (<VERSION>) {
  618.       if ($ARG =~ /fontconfig\s+version\s+([.[:digit:]]+)\s*/) {
  619.     close (VERSION);
  620.     return "$1";
  621.       }
  622.     }
  623.     close (VERSION);
  624.   }
  625.   # don't know the version
  626.   return "";
  627. }
  628.  
  629. sub xfree86_version {
  630.   if ($XFree86_bin) {
  631.     open (VERSION, "$XFree86_bin -version 2>&1 |");
  632.     binmode VERSION, ":bytes";
  633.     while (<VERSION>) {
  634.       if ($ARG =~ /Version\s+([.[:digit:]]+)\s*/) {
  635.     close (VERSION);
  636.     return "$1";
  637.       }
  638.     }
  639.     close (VERSION);
  640.   }
  641.   # don't know the version
  642.   return "";
  643. }
  644.  
  645. sub freetype_module_supports_ttcap {
  646.   my ($v1, $v2, $v3, $v4) = xfree86_version();
  647.   if (version_compare(xfree86_version(), "4.3.99") >= 0) {
  648.     if ($VERBOSITY == $VERBOSITY_DEBUG) {
  649.       print "freetype module supports TTCap.\n";
  650.     }
  651.     return 1;
  652.   }
  653.   else {
  654.     if ($VERBOSITY == $VERBOSITY_DEBUG) {
  655.       print "freetype module does not support TTCap.\n";
  656.     }
  657.     return 0;
  658.   }
  659. }
  660.  
  661. sub x11_font_dirs {
  662.   my @dirs = ();
  663.   my @standard_dirs = (
  664.                "/usr/share/fonts/local",
  665.                "/usr/share/fonts/misc",
  666.                "/usr/share/fonts/75dpi",
  667.                "/usr/share/fonts/100dpi",
  668.                "/usr/share/fonts/Type1",
  669.                "/usr/share/fonts/URW",
  670.                "/usr/share/fonts/Speedo",
  671.                "/usr/share/fonts/PEX",
  672.                "/usr/share/fonts/cyrillic",
  673.                "/usr/share/fonts/latin2/misc",
  674.                "/usr/share/fonts/latin2/75dpi",
  675.                "/usr/share/fonts/latin2/100dpi",
  676.                "/usr/share/fonts/latin2/Type1",
  677.                "/usr/share/fonts/latin7/75dpi",
  678.                "/usr/share/fonts/baekmuk",
  679.                "/usr/share/fonts/japanese",
  680.                "/usr/share/fonts/kwintv",
  681.                "/usr/share/fonts/truetype",
  682.                "/usr/share/fonts/uni",
  683.                "/usr/share/fonts/CID",
  684.                "/usr/share/fonts/ucs/misc",
  685.                "/usr/share/fonts/ucs/75dpi",
  686.                "/usr/share/fonts/ucs/100dpi",
  687.                "/usr/share/fonts/hellas/misc",
  688.                "/usr/share/fonts/hellas/75dpi",
  689.                "/usr/share/fonts/hellas/100dpi",
  690.                "/usr/share/fonts/hellas/Type1",
  691.                "/usr/share/fonts/misc/sgi",
  692.                "/usr/share/fonts/xtest",
  693.                "/usr/X11R6/lib/X11/fonts/local",
  694.                "/usr/X11R6/lib/X11/fonts/misc",
  695.                "/usr/X11R6/lib/X11/fonts/75dpi",
  696.                "/usr/X11R6/lib/X11/fonts/100dpi",
  697.                "/usr/X11R6/lib/X11/fonts/Type1",
  698.                "/usr/X11R6/lib/X11/fonts/URW",
  699.                "/usr/X11R6/lib/X11/fonts/Speedo",
  700.                "/usr/X11R6/lib/X11/fonts/PEX",
  701.                "/usr/X11R6/lib/X11/fonts/cyrillic",
  702.                "/usr/X11R6/lib/X11/fonts/latin2/misc",
  703.                "/usr/X11R6/lib/X11/fonts/latin2/75dpi",
  704.                "/usr/X11R6/lib/X11/fonts/latin2/100dpi",
  705.                "/usr/X11R6/lib/X11/fonts/latin2/Type1",
  706.                "/usr/X11R6/lib/X11/fonts/latin7/75dpi",
  707.                "/usr/X11R6/lib/X11/fonts/baekmuk",
  708.                "/usr/X11R6/lib/X11/fonts/japanese",
  709.                "/usr/X11R6/lib/X11/fonts/kwintv",
  710.                "/usr/X11R6/lib/X11/fonts/truetype",
  711.                "/usr/X11R6/lib/X11/fonts/uni",
  712.                "/usr/X11R6/lib/X11/fonts/CID",
  713.                "/usr/X11R6/lib/X11/fonts/ucs/misc",
  714.                "/usr/X11R6/lib/X11/fonts/ucs/75dpi",
  715.                "/usr/X11R6/lib/X11/fonts/ucs/100dpi",
  716.                "/usr/X11R6/lib/X11/fonts/hellas/misc",
  717.                "/usr/X11R6/lib/X11/fonts/hellas/75dpi",
  718.                "/usr/X11R6/lib/X11/fonts/hellas/100dpi",
  719.                "/usr/X11R6/lib/X11/fonts/hellas/Type1",
  720.                "/usr/X11R6/lib/X11/fonts/misc/sgi",
  721.                "/usr/X11R6/lib/X11/fonts/xtest",
  722.                "/opt/kde3/share/fonts"
  723.               );
  724.  
  725.   push (@dirs, @standard_dirs);
  726.   push (@dirs, xorg_config_font_dirs());
  727.   push (@dirs, xfs_font_dirs());
  728.  
  729.   # Attention!:
  730.   # /usr/X11R6/lib/X11/fonts/encodings usually doesn't contain any fonts.
  731.   # Neverthelesss a valid encodings.dir file must exist in that directory
  732.   # because some applications, e.g. luit, read encodings.dir from there
  733.   # (See for example "LANG=ja_JP strace -eopen luit -c").
  734.   # The easiest way to make sure that the encodings.dir in that directory
  735.   # is correct and up to date is to add the "encodings" directory to the
  736.   # list of font directories.
  737.   # Then mkfontdir will be called on that directory as well and a correct
  738.   # encodings.dir will be generated.
  739.   if (-d "/usr/share/fonts/encodings") {
  740.       push (@dirs, ("/usr/share/fonts/encodings"));
  741.   } else {
  742.       push (@dirs, ("/usr/X11R6/lib/X11/fonts/encodings"));
  743.   }
  744.   
  745.   # remove non existing directories and duplicates:
  746.   my %dirs = ();
  747.   for my $dir (@dirs) {
  748.     if (-d $dir) {
  749.       $dirs{$dir} = "";
  750.     }
  751.   }
  752.   return (keys %dirs);
  753. }
  754.  
  755. # gets font paths configured in /etc/X11/xorg.conf
  756. # and check wether the "xtt" and/or "freetype" modules are loaded:
  757. sub xorg_config_font_dirs {
  758.   my @dirs = ();
  759.   my $file = "/etc/X11/xorg.conf";
  760.   if (-e $file) {
  761.     open (CONFIGFILE, $file) || die "can't open file $file: $!";
  762.     while (<CONFIGFILE>) {
  763.       chomp ($ARG);
  764.       if ($ARG =~ /([^#]*)#?.*/) { # strip comments
  765.     $ARG = $1;
  766.       }
  767.       if ($ARG =~ /\s*FontPath\s+"(.+?)(:unscaled|:scaled)?"\s*/i) {
  768.     push (@dirs, $1);
  769.       }
  770.       if ($ARG =~ /\s*Load\s+"xtt"/) {
  771.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  772.       print "xtt module is used.\n";
  773.     }
  774.     $xtt_module_used = 1;
  775.       }
  776.       if ($ARG =~ /\s*Load\s+"freetype"/) {
  777.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  778.       print "freetype module is used.\n";
  779.     }
  780.     $freetype_module_used = 1;
  781.       }
  782.     }
  783.     close (CONFIGFILE);
  784.   }
  785.   if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  786.     print "font paths found in $file:\n";
  787.     for my $dir (@dirs) {
  788.       print "$dir\n";
  789.     }
  790.   }
  791.   return @dirs;
  792. }
  793.  
  794. # gets font paths configured for xfs if xfs exists and is running:
  795. sub xfs_font_dirs {
  796.   my @dirs = ();
  797.   my $file = "/etc/X11/fs/config";
  798.   if ($xfs_bin && my_system ("$checkproc_bin $xfs_bin") == 0) {
  799.     if (-e $file) {
  800.       my $config_file_contents = "";
  801.       open (CONFIGFILE, $file) || die "can't open file $file: $!";
  802.       while (<CONFIGFILE>) {
  803.     $ARG =~ /([^#]*)#?.*/; # strip comments
  804.     $config_file_contents .= $1;
  805.       }
  806.       close (CONFIGFILE);
  807.       $config_file_contents =~ /catalogue[^=]*=([^=]*?)\n[^\n]*=/si;
  808.       my $catalogue = $1;
  809.       @dirs = split(/[\s,\\]+/, $catalogue);
  810.       for my $index (0 .. $#dirs) {
  811.     if ($dirs[$index] =~ /(.+?)(:unscaled|:scaled)/) {
  812.       $dirs[$index] = $1;
  813.     }
  814.       }
  815.     }
  816.   }
  817.   if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  818.     print "font paths found in $file:\n";
  819.     for my $dir (@dirs) {
  820.       print "$dir\n";
  821.     }
  822.   }
  823.   return @dirs;
  824. }
  825.  
  826. sub create_symbolic_links {
  827.   my ($dir) = @_;
  828.   
  829.   my $cwd;
  830.   chomp ($cwd = `pwd`);
  831.   chdir $dir ||die "Can't cd to $dir: $!\n";
  832.   
  833.   # create symbolic links for PostScript fonts in pfa format
  834.   # which have no extension:
  835.   # (seems like all such fonts are gone now, I can't find
  836.   # such fonts any more on my system 2005.09.01)
  837.   if ($have_file_mmagic) {
  838.     my $mm = new File::MMagic; # use internal magic file
  839.     # $mm = File::MMagic::new('/etc/magic'); # use external magic file
  840.     my $type;
  841.     for my $file (glob ("*")) {
  842.       unless ($file =~ /\./i) {
  843.     $type = $mm->checktype_filename($file);
  844.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  845.       print "File::MMagic $file: $type\n";
  846.     }
  847.     if ($type =~ /application\/postscript/) {
  848.       # it's probably a PostScript font in pfa format
  849.       # create a symbolic link unless it has the .pfa extension already
  850.       # or is a .gsf file (File::MMagic detects .gsf files also as
  851.       # "application/postscript", but it makes no sense to link these
  852.       # to .pfa)
  853.       unless ($file =~ /\.pfa|\.gsf/i) {
  854.         if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  855.           printf "symlink ($file, \"${file}.pfa\")\n";
  856.         }
  857.         symlink ($file, "${file}.pfa");
  858.       }
  859.     }
  860.       }
  861.     }
  862.   }
  863.   
  864.   # create symbolic links for files which have characters in
  865.   # their name which are impossible to use in the file name in
  866.   # fonts.dir:
  867.  
  868.   my @forbidden_characters = (" ", ":");
  869.   for my $file (glob ("*.*")) {
  870.     for my $forbidden_character (@forbidden_characters) {
  871.       if ($file =~ /$forbidden_character/) {
  872.     my $file_new;
  873.     ($file_new = $file) =~ s/$forbidden_character/_/g;
  874.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  875.       printf "symlink ($file, $file_new)\n";
  876.     }
  877.     symlink ($file, $file_new);
  878.       }
  879.     }
  880.   }
  881.  
  882.   chdir $cwd ||die "Can't cd to $cwd: $!\n";
  883. }
  884.  
  885. sub make_fonts_scale_and_fonts_dir {
  886.   my ($dir) = @_;
  887.   my $timestamp = "$dir/.fonts-config-timestamp";
  888.   my $try_again = 0;
  889.  
  890.   # workaround for a bug in older versions of /usr/sbin/Check which
  891.   # gzips the timestamp files:
  892.   if (-e "${timestamp}.gz") {
  893.     unlink ("${timestamp}.gz");
  894.   }
  895.  
  896.   if ($OPT_FORCE ||
  897.       mtime_differs_or_missing ("$timestamp","$dir") ||
  898.       mtime_differs_or_missing ("$timestamp","$dir/fonts.scale") ||
  899.       mtime_differs_or_missing ("$timestamp","$dir/fonts.dir")) {
  900.  
  901.     # Touch and delete fonts.scale and fonts.dir just to make sure
  902.     # we are starting from scratch and the directory is writeable:
  903.     my_system ("touch $dir/fonts.scale $dir/fonts.dir > /dev/null 2>&1");
  904.     if (!unlink ("$dir/fonts.scale", "$dir/fonts.dir")) {
  905.       if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  906.     print "Cannot write in $dir. Readonly filesystem?\n";
  907.       }
  908.       return;
  909.     }
  910.  
  911.     $gs_fontmap_needs_update = 1;
  912.  
  913.     create_symbolic_links($dir);
  914.     
  915.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  916.       print "creating $dir/fonts.{scale,dir} ...\n";
  917.     }
  918.     if ($mkfontscale_bin) {
  919.       $command = "$mkfontscale_bin $dir";
  920.       unless ($VERBOSITY >= $VERBOSITY_DEBUG) {
  921.     $command .= " > /dev/null 2>&1 ";
  922.       }
  923.       my_system ($command);
  924.     }
  925.  
  926.     if (! -e "$dir/fonts.scale" ) {
  927.       if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  928.     print "mkfontscale is not available or it failed. ";
  929.     print "-> Create an empty fonts.scale file.\n";
  930.       }
  931.       $try_again = 1;
  932.       my_system ("echo 0 > $dir/fonts.scale");
  933.     }
  934.     
  935.     fix_fonts_scale ($dir);
  936.     
  937.     if ($mkfontdir_bin) {
  938.       $command = "$mkfontdir_bin ";
  939.       if (-d "/usr/X11R6/lib/X11/fonts/encodings") {
  940.     $command .= " -e /usr/X11R6/lib/X11/fonts/encodings";
  941.       }
  942.       if (-d "/usr/X11R6/lib/X11/fonts/encodings/large") {
  943.     $command .= " -e /usr/X11R6/lib/X11/fonts/encodings/large";
  944.       }
  945.       if (-d "/usr/share/fonts/encodings") {
  946.     $command .= " -e /usr/share/fonts/encodings";
  947.       }
  948.       if (-d "/usr/share/fonts/encodings/large") {
  949.     $command .= " -e /usr/share/fonts/encodings/large";
  950.       }
  951.       $command .= " $dir";
  952.       my_system ($command);
  953.     }
  954.  
  955.     if (! -e "$dir/fonts.dir" ) {
  956.       if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  957.     print "mkfontdir is not available or it failed. ";
  958.       }
  959.       $try_again = 1;
  960.       if (-f "$dir/fonts.scale" ){
  961.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  962.       print "A fonts.scale file exists, copy it to fonts.dir.";
  963.     }
  964.     my_system ("cp $dir/fonts.scale $dir/fonts.dir");
  965.       }
  966.       else {
  967.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  968.       print "No fonts.scale file exists either, create an empty fonts.dir.";
  969.     }
  970.     my_system ("echo 0 > $dir/fonts.dir");
  971.       }
  972.     }
  973.  
  974.     # Directory done. Now update time stamps:
  975.     if ($try_again) {
  976.       # mkfontscale and/or mkfontdir failed or didn't exist. Remove the
  977.       # timestamp to make sure this script tries again next time
  978.       # when the problem with mkfontscale and/or mkfontdir is fixed:
  979.       unlink ("$timestamp");
  980.     }
  981.     else {
  982.       # fonts.cache-* files are now generated in /var/cache/fontconfig,
  983.       # remove old cache files in the individual directories
  984.       # (fc-cache does this as well when the cache files are out of date
  985.       # but it can't hurt to remove them here as well just to make sure).
  986.       for my $file (glob ("$dir/fonts.cache-*")) {
  987.     if (-e "$file") {
  988.       unlink ("$file");
  989.     }
  990.       }
  991.       if (! -e $timestamp) {
  992.     my_system ("touch $timestamp");
  993.       }
  994.       utime ($script_start_time, $script_start_time,
  995.          ("$dir/fonts.dir", "$dir/fonts.scale", $timestamp, $dir));
  996.     }
  997.   }
  998. }
  999.  
  1000. sub fix_fonts_scale {
  1001.   my ($dir) = @_;
  1002.   my ($file, $options, $font, $xlfd);
  1003.   my %fonts_scale_entries = ();
  1004.   my %blacklist = ();
  1005.  
  1006.   if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1007.     print "----------------------------------------------------------------------\n";
  1008.     print "fix fonts.scale in $dir:\n";
  1009.   }
  1010.  
  1011.   ######################################################################
  1012.   # first parse the "handmade" fonts.scale.* files:
  1013.   for $file (glob ("$dir/fonts.scale.*")) {
  1014.     if (-e $file) {
  1015.       if ($file =~ /~$|\.swp$|\.bak$|\.sav$|\.save$|\.rpmsave$|\.rpmorig|\.rpmnew$/) {
  1016.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1017.       print "$file is considered a backup file, ignored.\n";
  1018.     }
  1019.     next;
  1020.       }
  1021.       open (FONTS_SCALE, $file) || die "can't open file $file: $!";
  1022.       if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1023.     print "reading $dir/$file ...\n";
  1024.       }
  1025.       while (<FONTS_SCALE>) {
  1026.     if ($ARG =~ /^(.*?)([^:\s]+)\s+(-.+?)\s*$/) { # font name and xlfd found
  1027.       $options = $1;
  1028.       $font = $2;
  1029.       $xlfd = $3;
  1030.       if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1031.         print "handmade entry found: options=$options font=$font xlfd=$xlfd\n";
  1032.       }
  1033.       if (( $OPT_TTCAP ) && $options =~ /:([0-9]):/) {
  1034.         if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1035.           print "--ttcap option is set: convert face number to TTCap syntax: fn=$1:\n";
  1036.         }
  1037.         $options = "fn=$1:";
  1038.       }
  1039.       if ($freetype_module_used && ! $OPT_TTCAP ) {
  1040.         if ($options =~ /fn=([0-9]):/) {
  1041.           if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1042.         print "freetype module used and --ttcap option is not set: convert face number to freetype syntax: :$1:\n";
  1043.           }
  1044.           $options = ":$1:";
  1045.         } elsif ($options =~ /[a-z=]/i) {
  1046.           # there's more then just a face number, better ignore it 
  1047.           if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1048.         print "xtt module not used: discard xtt only entry $ARG\n";
  1049.           }
  1050.           next;
  1051.         }
  1052.       }
  1053.       unless ( $font =~ /\.cid$/) {
  1054.         # For font file name entries ending with ".cid", such a file
  1055.         # usually doesn't exist and it doesn't need to. The backend which
  1056.         # renders CID-keyed fonts just parses this name to find the real
  1057.         # font files and mapping tables
  1058.         #
  1059.         # For other entries, we check whether the file exists.
  1060.         if (! -e "$dir/$font") {
  1061.           if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1062.         print "file $dir/$font doesn't exist, discard entry $ARG\n";
  1063.           }
  1064.           next;
  1065.         }
  1066.       }
  1067.       if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1068.         print "adding handmade entry $ARG\n";
  1069.       }
  1070.       $fonts_scale_entries{$xlfd} = "${options}${font}";
  1071.       # This font has "handmade" fonts.scale entries.
  1072.       # Add it to the blacklist to discard any entries for this font
  1073.       # which which might have been automatically created
  1074.       # by mkfontscale:
  1075.       $blacklist{$font} = "yes";
  1076.     }
  1077.       }
  1078.       close (FONTS_SCALE);
  1079.     }
  1080.   }
  1081.  
  1082.   ######################################################################
  1083.   # blacklist globs to avoid fonts known to be broken:
  1084.   #
  1085.   # (broken fonts may still be included in manually edited fonts.scale.*
  1086.   # files. He who edits these files manually should know what he is doing ...)
  1087.  
  1088.   my @blacklist_globs = ();
  1089.   
  1090.   # push (@blacklist_globs, ("totally-broken*.ttf", "fubar*.ttc"));
  1091.   
  1092.   # the Hershey-Fonts from ghostscript-fonts-other.rpm have broken outlines
  1093.   # and don't work with X11, neither with the freetype module nor via libXft.
  1094.   push (@blacklist_globs, ("hrger.pfa", "hrgrr.pfa", "hritr.pfa", "hrpld.pfa",
  1095.                "hrpldi.pfa", "hrplt.pfa", "hrplti.pfa", "hrscc.pfa",
  1096.                "hrscs.pfa",
  1097.                "u003043t.gsf",
  1098.                "u004006t.gsf",
  1099.                # .bdf fonts currently don't work with Xft2:
  1100.                "*.bdf" 
  1101.               ));
  1102.  
  1103.   my @blacklist_fonts_cache = ();
  1104.   
  1105.   for my $glob (@blacklist_globs) {
  1106.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1107.       print "expanding blacklist glob: $dir/$glob\n";
  1108.     }
  1109.     for my $font (glob ("$dir/$glob")) {
  1110.       if (-e $font) {
  1111.     $font =~ /\/([^\/]+)$/; # basename (strip directory)
  1112.     $font = $1;
  1113.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1114.       print "$dir/$font matched by blacklist glob, adding $font to blacklist.\n";
  1115.     }
  1116.     $blacklist{$font} = "yes";
  1117.     push (@blacklist_fonts_cache, ($font));
  1118.       }
  1119.     }
  1120.   }
  1121.  
  1122.   ######################################################################
  1123.   # remove broken entries from fonts.cache-1:
  1124.   if (@blacklist_fonts_cache) {
  1125.     my @entries = ();
  1126.     $file = "$dir/fonts.cache-1";
  1127.     if (-e $file) {
  1128.       if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1129.     print "removing blacklisted fonts @blacklist_fonts_cache from $file\n";
  1130.       }
  1131.       open (FONTS_CACHE, $file) || die "can't open file $file: $!";
  1132.       while (<FONTS_CACHE>) {
  1133.     $ARG =~ /^"([^"]+)" /;
  1134.     if (! grep /$1/, @blacklist_fonts_cache) {
  1135.       push (@entries, ($ARG));
  1136.     }
  1137.       }
  1138.       close (FONTS_CACHE);
  1139.       open (FONTS_CACHE, ">$file") || die "can't open file $file: $!";
  1140.       for my $entry (@entries) {
  1141.     print FONTS_CACHE "$entry";
  1142.       }
  1143.       close (FONTS_CACHE);
  1144.     }
  1145.   }
  1146.   
  1147.   ######################################################################
  1148.   # Now parse the fonts.scale file automatically created by mkfontscale:
  1149.   $file = "$dir/fonts.scale";
  1150.   open (FONTS_SCALE, $file) || die "can't open file $file: $!";
  1151.   if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1152.     print "reading $dir/$file ...\n";
  1153.   }
  1154.   while (<FONTS_SCALE>) {
  1155.     if ($ARG =~ /^(.*?)([^:\s]+)\s+(-.+?)\s*$/) { # font name and xlfd found
  1156.       $options = $1;
  1157.       $font = $2;
  1158.       $xlfd = $3;
  1159.       if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1160.       print "mkfontscale entry found: options=$options font=$font xlfd=$xlfd\n";
  1161.       }
  1162.       # mkfontscale apparently doesn't yet generate the special options for
  1163.       # the freetype module to use different face numbers in .ttc files.
  1164.       # But this might change, therefore it is probably better to check this as well:
  1165.       if ( ( $OPT_TTCAP ) && $options =~ /:([0-9]):/) {
  1166.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1167.       print "--ttcap option is set: convert face number to TTCap syntax: fn=$1:\n";
  1168.     }
  1169.     $options = "fn=$1:";
  1170.       }
  1171.       if ($blacklist{$font}) {
  1172.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1173.       print "$dir/$font is blacklisted, ignored.\n";
  1174.     }
  1175.     next;
  1176.       }
  1177.       $fonts_scale_entries{$xlfd} = "${options}${font}";
  1178.     }
  1179.   }
  1180.   close (FONTS_SCALE);
  1181.  
  1182.   ######################################################################
  1183.   # generate an oblique entry if only italic is there and vice versa:
  1184.  
  1185.   for my $old_xlfd (keys %fonts_scale_entries) {
  1186.     if ($old_xlfd =~ /(-[^-]+-[^-]+-[^-]+)(-[io]-)([^-]+-[^-]*-\d+-\d+-\d+-\d+-[pmc]-\d+-[^-]+-[^-]+)/i) {
  1187.       my $new_xlfd = "";
  1188.       if ("$2" eq "-i-") {
  1189.      $new_xlfd = "${1}-o-${3}";
  1190.       } else {
  1191.      $new_xlfd = "${1}-i-${3}";
  1192.       }
  1193.       unless ($fonts_scale_entries{$new_xlfd}) {
  1194.     $fonts_scale_entries{$new_xlfd} = $fonts_scale_entries{$old_xlfd};
  1195.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1196.       print "generated o/i: $fonts_scale_entries{$new_xlfd} $new_xlfd\n";
  1197.     }
  1198.       }
  1199.     }
  1200.   }
  1201.   
  1202.   ######################################################################
  1203.   # generate TTCap options for xtt:
  1204.   if ($OPT_TTCAP) {
  1205.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1206.       print "generating TTCap options for use with xtt or recent freetype modules ...\n";
  1207.     }
  1208.     my ($italic, $oblique, $bold, $bold_italic, $bold_oblique);
  1209.     my $artificial_italic = "ai=0.2:";
  1210.     my $doublestrike = "ds=y:";
  1211.     for my $medium (sort (keys %fonts_scale_entries)) {
  1212.       if ($medium !~ /-medium-r-/) {
  1213.     next;
  1214.       }
  1215.       if ($fonts_scale_entries{$medium} !~ /^(.*?)([^:]+)$/) {
  1216.     next; # should not happen ...
  1217.       }
  1218.       $options = $1;
  1219.       $font = $2;
  1220.       if ( $xtt_module_used && $font !~ /\.ttf$|\.ttc$/i ) {
  1221.     next; # xtt can only handle TrueType fonts.
  1222.       }
  1223.       elsif ( $freetype_module_used && $font !~ /\.ttf$|\.ttc$|\.otf|\.otc|\.pfa|\.pfb/i ) {
  1224.     next; # the freetype module handles TrueType, OpenType, and Type1 fonts.
  1225.       }
  1226.       elsif ( !$freetype_module_used && !$xtt_module_used) {
  1227.     # neither the xtt module nor the freetype module is used, generating TTCap
  1228.     # options makes no sense.
  1229.     next;
  1230.       }
  1231.       if ($options) {
  1232.     next; # there are already some TTCap options, better don't touch this
  1233.       }
  1234.       ($italic       = $medium) =~ s/-medium-r-/-medium-i-/;
  1235.       ($oblique      = $medium) =~ s/-medium-r-/-medium-o-/;
  1236.       ($bold         = $medium) =~ s/-medium-r-/-bold-r-/;
  1237.       ($bold_italic  = $medium) =~ s/-medium-r-/-bold-i-/;
  1238.       ($bold_oblique = $medium) =~ s/-medium-r-/-bold-o-/;
  1239.       unless ($fonts_scale_entries{$italic} ||
  1240.           $fonts_scale_entries{$oblique}) {
  1241.     $fonts_scale_entries{$italic}  = "${artificial_italic}${font}";
  1242.     $fonts_scale_entries{$oblique} = "${artificial_italic}${font}";
  1243.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1244.       print "generated TTCap entry: $fonts_scale_entries{$italic} $italic\n";
  1245.       print "generated TTCap entry: $fonts_scale_entries{$oblique} $oblique\n";
  1246.     }
  1247.       }
  1248.       unless ($fonts_scale_entries{$bold}) {
  1249.     $fonts_scale_entries{$bold}  = "${doublestrike}${font}";
  1250.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1251.       print "generated TTCap entry: $fonts_scale_entries{$bold} $bold\n";
  1252.     }
  1253.       }
  1254.       unless ($fonts_scale_entries{$bold_italic} ||
  1255.           $fonts_scale_entries{$bold_oblique}) {
  1256.     $fonts_scale_entries{$bold_italic}  = "${doublestrike}${artificial_italic}${font}";
  1257.     $fonts_scale_entries{$bold_oblique} = "${doublestrike}${artificial_italic}${font}";
  1258.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1259.       print "generated TTCap entry: $fonts_scale_entries{$bold_italic} $bold_italic\n";
  1260.       print "generated TTCap entry: $fonts_scale_entries{$bold_oblique} $bold_oblique\n";
  1261.     }
  1262.       }
  1263.     }
  1264.     # add bw=0.5 option when necessary:
  1265.     for my $xlfd (sort (keys %fonts_scale_entries)) {
  1266.       if ($fonts_scale_entries{$xlfd} !~ /^(.*?)([^:]+)$/) {
  1267.     next; # should not happen ...
  1268.       }
  1269.       $options = $1;
  1270.       $font = $2;
  1271.       if ( $xtt_module_used && $font !~ /\.ttf$|\.ttc$/i ) {
  1272.     next; # xtt can only handle TrueType fonts.
  1273.       }
  1274.       elsif ( $freetype_module_used && $font !~ /\.ttf$|\.ttc$|\.otf|\.otc|\.pfa|\.pfb/i ) {
  1275.     next; # the new freetype module handles TrueType, OpenType, and Type1 fonts.
  1276.       }
  1277.       elsif ( !$freetype_module_used && !$xtt_module_used) {
  1278.     # neither the xtt module nor the freetype module is used, generating TTCap
  1279.     # options makes no sense.
  1280.     next;
  1281.       }
  1282.       if ($options =~ /bw=/) {
  1283.     next; # there is already a bw=<something> TTCap option, better don't touch this
  1284.       }
  1285.       if ($xlfd =~ /c-0-jisx0201.1976-0/) {
  1286.     $fonts_scale_entries{$xlfd} = "${options}bw=0.5:${font}";
  1287.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1288.       print "added bw=0.5 option: $fonts_scale_entries{$xlfd} $xlfd\n";
  1289.     }
  1290.       }
  1291.     }
  1292.   }
  1293.   ######################################################################
  1294.   # weed out entries which certainly cannot work:
  1295.  
  1296.   for my $xlfd (keys %fonts_scale_entries) {
  1297.     if ($fonts_scale_entries{$xlfd} !~ /\.([[:alnum:]]+)(\.gz)?$/i) {
  1298.       if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1299.     print "file has no extension, discarding $fonts_scale_entries{$xlfd} $xlfd\n";
  1300.       }
  1301.       delete $fonts_scale_entries{$xlfd};
  1302.       next;
  1303.     }
  1304.     else {
  1305.       my $extension = $1 ;
  1306.  
  1307.       # Currently only the freetype module can handle .otf fonts.
  1308.       #
  1309.       # If both xtt and freetype are used at the same time, xtt will only register
  1310.       # for .ttf and .ttc fonts and freetype will still be able to handle
  1311.       # the .otf fonts.
  1312.       # But if freetype is not used, .otf fonts won't work at all and
  1313.       # directories containing entries for .otf fonts in fonts.dir will be
  1314.       # removed from the font path.
  1315.       # This is not nice because there may be other fonts in that directory which
  1316.       # could be used, for example .ttf or .ttc.
  1317.       # Therefore it is better to throw away all entries for .otf fonts if
  1318.       # the freetype module is not used:
  1319.       if ($extension =~ /otf/i && ! $freetype_module_used) {
  1320.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1321.       print ".otf won't work without freetype module, discarding $fonts_scale_entries{$xlfd} $xlfd\n";
  1322.     }
  1323.     delete $fonts_scale_entries{$xlfd};
  1324.       }
  1325.       if ($extension =~ /gsf/i) {
  1326.      if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1327.        print ".gsf fonts won't work with X11, discarding $fonts_scale_entries{$xlfd} $xlfd\n";
  1328.      }
  1329.      delete $fonts_scale_entries{$xlfd};
  1330.       }
  1331.     }
  1332.   }
  1333.  
  1334.   ######################################################################
  1335.   # write final result to fonts.scale:
  1336.   
  1337.   $file = "$dir/fonts.scale";
  1338.   open (FONTS_SCALE, ">$file") || die "can't open file $file: $!";
  1339.   if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1340.     print "writing $dir/$file ...\n";
  1341.   }
  1342.   printf FONTS_SCALE "%d\n", scalar(keys %fonts_scale_entries);
  1343.   for my $xlfd (sort (keys %fonts_scale_entries)) {  
  1344.     print FONTS_SCALE "$fonts_scale_entries{$xlfd} $xlfd\n";
  1345.   }
  1346.   close (FONTS_SCALE);
  1347.  
  1348. }
  1349.  
  1350. ######################################################################
  1351.  
  1352. sub get_font_name_entries {
  1353.   my ($font) = @_;
  1354.  
  1355.   # quote " in font names:
  1356.   $font =~ s/\"/\\\"/g;
  1357.   open (FONT, "ftdump \"$font\" 2>/dev/null |");
  1358.   # Apparently there are some fonts which have non-ASCII PostScript names.
  1359.   # If we are running in a UTF-8 locale, Perl will complain
  1360.   #    "Malformed UTF-8 character"
  1361.   # when reading the ftdump output of such a font.
  1362.   # Avoid that error by using the layer ":bytes" for this file handle.
  1363.   binmode FONT, ":bytes";
  1364.  
  1365.   my $postscript = "";
  1366.   my $family = "";
  1367.   my $style = "";
  1368.   my $face_number = 0;
  1369.  
  1370.   while (<FONT>) {
  1371.     if ($ARG =~ /face.*number.*:\s*([0-9]+)\s*/i) {
  1372.       $face_number = $1;
  1373.     }
  1374.     if ($face_number > 0) {
  1375.       if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1376.     print "face_number=$face_number found. All faces with number > 0 ignored.\n";
  1377.       }
  1378.       last;
  1379.     }
  1380.     # the following regexp should work with ftdump from either Freetype-1 or Freetype-2
  1381.     if ($ARG =~ /postscript.*:\s+([[:alnum:]\-]+?)\s*$/i) {
  1382.       $postscript = $1;
  1383.       if ($postscript eq "UNAVAILABLE") {
  1384.     $postscript = "";
  1385.       }
  1386.     }
  1387.     if ($ARG =~ /family.*:\s+([[:alnum:]].*[[:alnum:]])\s*$/i) {
  1388.       $family = $1;
  1389.     }
  1390.     if ($ARG =~ /style.*:\s+([[:alnum:]].*[[:alnum:]])\s*$/i) {
  1391.       $style = $1;
  1392.     }
  1393.   }
  1394.   close (FONT);
  1395.   if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1396.     print "ftdump: font=$font postscript=$postscript family=$family style=$style\n";
  1397.   }
  1398.   return ($postscript, $family, $style);
  1399. }
  1400.  
  1401. sub gs_fontmap_aliases_add {
  1402.   my ($aliases, $alias) = @_;
  1403.   my $alias_case_normalized = $alias;
  1404.   $alias_case_normalized =~ s/\b(\w)(\w*)/ uc($1) . lc($2) /eg;
  1405.   $alias_case_normalized =~ s/ //g;
  1406.   $alias =~ s/ //g;
  1407.   $aliases->{$alias} = "";
  1408.   $aliases->{$alias_case_normalized} = "";
  1409. }
  1410.  
  1411. sub gs_fontmap_aliases {
  1412.   my ($postscript, $family, $style, $xlfd) = @_;
  1413.   my $xlfd_fmly = "";
  1414.   my $xlfd_wght = "";
  1415.   my $xlfd_slant = "";
  1416.   my %aliases = ();
  1417.  
  1418.   if ($xlfd && $xlfd =~
  1419.       /-[^-]+-([^-]+)-([^-]+)-([^-])-[^-]+-[^-]*-\d+-\d+-\d+-\d+-[pmc]-\d+-[^-]+-[^-]+/i) {
  1420.     $xlfd_fmly = $1;
  1421.     $xlfd_wght = $2;
  1422.     $xlfd_slant = $3;
  1423.     # Some aliases for applications which don't use the correct PostScript
  1424.     # names but rather some combination of family, weight, and slant from the XLFD.
  1425.     # Probably because there is no way to get the PostScript name without
  1426.     # direct access to the font file. When X11 core fonts are used instead of
  1427.     # fontconfig/libXft, the application may only see the XLFD and can only
  1428.     # try to "guess" the PostScript name from the XLFD.
  1429.     # (For example Qt3 does something like this ...)
  1430.     if ($xlfd_fmly) {
  1431.       if ($xlfd_wght !~ /bold/i && $xlfd_slant ne "i" && $xlfd_slant ne "o") {
  1432.     gs_fontmap_aliases_add(\%aliases, "$xlfd_fmly");
  1433.       }
  1434.       if ($xlfd_wght !~ /bold/i && ($xlfd_slant eq "i" || $xlfd_slant eq "o")) {
  1435.     gs_fontmap_aliases_add(\%aliases, "$xlfd_fmly-Italic");
  1436.       }
  1437.       if ($xlfd_wght =~ /bold/i && $xlfd_slant ne "i" && $xlfd_slant ne "o") {
  1438.     gs_fontmap_aliases_add(\%aliases, "$xlfd_fmly-Bold");
  1439.       }
  1440.       if ($xlfd_wght =~ /bold/i && ($xlfd_slant eq "i" || $xlfd_slant eq "o")) {
  1441.     gs_fontmap_aliases_add(\%aliases, "$xlfd_fmly-Bold Italic");
  1442.       }
  1443.     }
  1444.   }
  1445.   # an alias to the PostScript name would make no sense, delete it if
  1446.   # it was accidentally created:
  1447.   delete $aliases{$postscript};
  1448.   return (sort (keys %aliases));
  1449. }
  1450.  
  1451. sub make_gs_fontmap {
  1452.   my (@font_dirs) = @_;
  1453.  
  1454.   if (!$ftdump_bin) {
  1455.     print "Warning: Creation of a Fontmap for Ghostmap has been requested\n";
  1456.     print "         (either the the option --gs-fontmap has been used or the variable\n";
  1457.     print"           GENERATE_GHOSTSCRIPT_FONTMAPS in /etc/sysconfig/fonts-config\n";
  1458.     print"           has been set to \"yes\").\n";
  1459.     print "         But the 'ftdump' program which is needed to do this is\n";
  1460.     print "         apparently not installed. 'ftdump' is in the 'ft2demos'\n";
  1461.     print "         package. Please install this package if you want a Fontmap\n";
  1462.     print "         for Ghostscript to be created.\n";
  1463.   }
  1464.   else {
  1465.     if ($VERBOSITY >= $VERBOSITY_VERBOSE) {
  1466.       print "Creating Fontmap entries for Ghostscript ";
  1467.     }
  1468.     for my $fontmap_dir (glob ("/usr/share/ghostscript/[0-9]*/lib")) {
  1469.       if (-e $fontmap_dir) {
  1470.     my $file = "$fontmap_dir/Fontmap.X11-auto";
  1471.     open (FONTMAP, ">$file") || die "can't open file $file: $!";
  1472.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1473.       printf "writing $file ...\n";
  1474.     }
  1475.       
  1476.     print FONTMAP "% Fontmap for scalable fonts found in the X11 font paths\n";
  1477.     print FONTMAP "%\n";
  1478.     print FONTMAP "% This file is automatically generated by\n";
  1479.     print FONTMAP "% \"fonts-config\" (version $version) and will be\n";
  1480.     print FONTMAP "% overwritten during the next run of this script.\n";
  1481.     print FONTMAP "%\n";
  1482.     print FONTMAP "% Don't edit this file. If you want to create your own\n";
  1483.     print FONTMAP "% manual Fontmap entries, put them elsewhere.\n";
  1484.     print FONTMAP "%\n";
  1485.  
  1486.     my %fontmap_entries = ();
  1487.     for my $dir (@font_dirs) {
  1488.     
  1489.       open (FONTS_SCALE, "$dir/fonts.scale") || die "can't open file $dir/fonts.scale: $!";
  1490.       if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1491.         print "creating hashtable of xlfds from $dir/fonts.scale ...\n";
  1492.       }
  1493.       my %xlfds;
  1494.       while (<FONTS_SCALE>) {
  1495.         my ($options, $font, $xlfd);
  1496.         if ($ARG =~ /^(.*?)([^:\s]+)\s+(-.+?)\s*$/) { # font name and xlfd found
  1497.           $options = $1;
  1498.           $font = $2;
  1499.           $xlfd = $3;
  1500.           unless ($options) { # ignore face numbers > 0 and other options
  1501.         $xlfds{"$dir/$font"} = $xlfd;
  1502.           }
  1503.         }
  1504.       }
  1505.       close (FONTS_SCALE);
  1506.  
  1507.       for my $font (glob ("$dir/*.{ttf,ttc,pfa,pfb}")) {
  1508.         if (-e $font) {
  1509.           my ($postscript, $family, $style) = get_font_name_entries($font);
  1510.           if ($postscript) {
  1511.         print FONTMAP "%----------------------------------------------------------------------\n";
  1512.         print FONTMAP "% postscript=\"$postscript\" family=\"$family\" style=\"$style\"\n";
  1513.         if ($xlfds{$font}) {
  1514.           print FONTMAP "% xlfd=\"$xlfds{$font}\"\n";
  1515.         } else {
  1516.           print FONTMAP "% xlfd=\"\"\n";
  1517.         }
  1518.         if ($fontmap_entries{$postscript}) {
  1519.           print FONTMAP "% /$postscript ($font) ; % warning: duplicate!\n";
  1520.         } else {
  1521.           print FONTMAP "/$postscript ($font) ;\n";
  1522.           $fontmap_entries{$postscript} = "true";
  1523.         }
  1524.         for my $alias (gs_fontmap_aliases($postscript, $family, $style, $xlfds{$font})) {
  1525.           if ($fontmap_entries{$alias}) {
  1526.             print FONTMAP "% /$alias /$postscript ; % warning: duplicate!\n";
  1527.           } else {
  1528.             print FONTMAP "/$alias /$postscript ;\n";
  1529.             $fontmap_entries{$alias} = "true";
  1530.           }
  1531.         }
  1532.           }
  1533.         }
  1534.       }
  1535.       if ($VERBOSITY == $VERBOSITY_VERBOSE) {
  1536.         print ".";        # "progress bar"
  1537.       }
  1538.     }
  1539.     close (FONTMAP);
  1540.       }
  1541.     }
  1542.     if ($VERBOSITY == $VERBOSITY_VERBOSE) {
  1543.       print "\n";
  1544.     }
  1545.   }
  1546. }
  1547.  
  1548. ########################################################################
  1549. sub generate_ooo_font_setup {
  1550.   my $common_xcu_file = "/usr/lib/ooo-1.1/share/registry/data/org/openoffice/Office/Common.xcu";
  1551.   my $common_xcu_template_file = "/usr/share/fonts-config/Common.xcu.template";
  1552.   my $common_xcu = "";
  1553.   my $common_xcu_template = "";
  1554.   my $within_font_node_depth = 0;
  1555.   my $ooo_truetype_font_dir = "/usr/lib/ooo-1.1/share/fonts/truetype";
  1556.   
  1557.   if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1558.     printf "generating OpenOffice font setup\n";
  1559.   }
  1560.  
  1561.   if (! -f "$common_xcu_file") {
  1562.     if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1563.       printf "Nothing to do for this version of OpenOffice.\n";
  1564.     }
  1565.     return;
  1566.   }
  1567.   
  1568.   if (! -f "$common_xcu_template_file") {
  1569.     printf "File $common_xcu_template_file missing. This should not happen.\n";
  1570.     printf "Skipping OpenOffice font setup\n";
  1571.     return;
  1572.   }
  1573.  
  1574.   my @msgothic_list = ("MS Gothic",
  1575.                "HGGothicB",
  1576.                "HG\\-GothicB\\-Sun",
  1577.                "TLGothic",
  1578.                "IPAGothic",
  1579.                "Sazanami Gothic",
  1580.                "Kochi Gothic");
  1581.  
  1582.   my @mspgothic_list = ("MS PGothic",
  1583.                "HGPGothicB",
  1584.                "HG\\-PGothicB\\-Sun",
  1585.                "TLPGothic",
  1586.                "IPAPGothic",
  1587.                "Sazanami Gothic",
  1588.                "Kochi Gothic");
  1589.  
  1590.   my @msmincho_list = ("MS Mincho",
  1591.                "HGMinchoL",
  1592.                "HG\\-MinchoL\\-Sun",
  1593.                "TLMincho",
  1594.                "IPAMincho",
  1595.                "Sazanami Mincho",
  1596.                "Kochi Mincho");
  1597.  
  1598.   my @mspmincho_list = ("MS PMincho",
  1599.             "HGPMinchoL",
  1600.             "HG\\-PMinchoL\\-Sun",
  1601.             "TLPMincho",
  1602.             "IPAPMincho",
  1603.             "Sazanami Mincho",
  1604.             "Kochi Mincho");
  1605.  
  1606.   my $msgothic = "Sazanami Gothic";
  1607.   my $mspgothic = "Sazanami Gothic";
  1608.   my $msmincho = "Sazanami Mincho";
  1609.   my $mspmincho = "Sazanami Mincho";
  1610.  
  1611.   for my $font (@msgothic_list) {
  1612.     if (`fc-list "$font"`) {
  1613.       $msgothic = $font;
  1614.       last;
  1615.     }
  1616.   }
  1617.  
  1618.   for my $font (@mspgothic_list) {
  1619.     if (`fc-list "$font"`) {
  1620.       $mspgothic = $font;
  1621.       last;
  1622.     }
  1623.   }
  1624.   for my $font (@msmincho_list) {
  1625.     if (`fc-list "$font"`) {
  1626.       $msmincho = $font;
  1627.       last;
  1628.     }
  1629.   }
  1630.   for my $font (@mspmincho_list) {
  1631.     if (`fc-list "$font"`) {
  1632.       $mspmincho = $font;
  1633.       last;
  1634.     }
  1635.   }
  1636.  
  1637.   open (TEMPLATE, "$common_xcu_template_file") || die "can't open file $common_xcu_template_file: $!";
  1638.   binmode TEMPLATE, ":utf8";
  1639.   while (<TEMPLATE>) {
  1640.     $ARG =~ s/_MSGOTHIC_/$msgothic/;
  1641.     $ARG =~ s/_MSPGOTHIC_/$mspgothic/;
  1642.     $ARG =~ s/_MSMINCHO_/$msmincho/;
  1643.     $ARG =~ s/_MSPMINCHO_/$mspmincho/;
  1644.     $common_xcu_template .= $ARG;
  1645.   }
  1646.   close (TEMPLATE);
  1647.  
  1648.   if (-f "$common_xcu_file" ) {
  1649.     open (XCU, "$common_xcu_file") || die "can't open file $common_xcu_file: $!";
  1650.     binmode XCU, ":utf8";
  1651.     while (<XCU>) {
  1652.       if ($ARG =~ /<node oor:name="Font">/) {
  1653.     $within_font_node_depth = 1;
  1654.     next;
  1655.       }
  1656.       if ($within_font_node_depth > 0) {
  1657.     if ($ARG =~ /<node.*>/) {
  1658.       $within_font_node_depth++;
  1659.     }
  1660.     if ($ARG =~ /<\/node>/) {
  1661.       $within_font_node_depth--;
  1662.     }
  1663.     next;
  1664.       }
  1665.       unless ($ARG =~ /<\/oor:component-data>/) {
  1666.     $common_xcu .= $ARG;
  1667.       }
  1668.     }
  1669.     close (XCU);
  1670.     open (XCU, ">$common_xcu_file") || die "can't open file $common_xcu_file: $!";
  1671.     binmode XCU, ":utf8";
  1672.     print XCU $common_xcu;
  1673.     print XCU $common_xcu_template;
  1674.     print XCU '</oor:component-data>'; print XCU "\n";
  1675.     close (XCU);
  1676.   }
  1677.  
  1678.   if ( -d "$ooo_truetype_font_dir" ) {
  1679.     for my $font (`fc-list :lang=ja:outline=true file`) {
  1680.       my $basename;
  1681.       chomp ($font);
  1682.       $font =~ s/:.*$//;
  1683.       ($basename = $font ) =~ s/.*\/([^\/]+)/$1/;
  1684.       if ($VERBOSITY >= $VERBOSITY_DEBUG) {
  1685.     printf "symlink (\"$font\", \"$ooo_truetype_font_dir/$basename\")\n";
  1686.       }
  1687.       symlink ("$font", "$ooo_truetype_font_dir/$basename");
  1688.     }
  1689.  
  1690.     # remove dead links:
  1691.     for my $file (glob ("$ooo_truetype_font_dir/*")) {
  1692.       if (! -f "$file") {
  1693.     unlink("$file");
  1694.       }
  1695.     }
  1696.   }
  1697.  
  1698. }
  1699.  
  1700. ########################################################################
  1701. sub generate_java_font_setup {
  1702.  
  1703.   my @font_properties_ja_globs = ("/usr/lib*/jvm/java-1[._]4[._]?-sun-*/jre/lib/font.properties.ja");
  1704.   my $font_properties_ja_template_file = "/usr/share/fonts-config/font.properties.ja.template";
  1705.   my $font_properties_ja_template = "";
  1706.   my @fontconfig_SuSE_properties_globs = "/usr/lib*/jvm/java-1.5.?-sun-*/jre/lib/fontconfig.SuSE.properties";
  1707.   my $fontconfig_SuSE_properties_template_file = "/usr/share/fonts-config/fontconfig.SuSE.properties.template";
  1708.   my $fontconfig_SuSE_properties_template = "";
  1709.   
  1710.   if ($VERBOSITY >= $VERBOSITY_QUIET) {
  1711.     printf "generating java font setup\n";
  1712.   }
  1713.  
  1714.   my @sans_japanese_priority = ("MS Gothic",
  1715.                 "HGGothicB",
  1716.                 "IPAGothic",
  1717.                 "Sazanami Gothic");
  1718.   
  1719.   my @serif_japanese_priority = ("MS Mincho",
  1720.                  "HGMinchoL",
  1721.                  "IPAMincho",
  1722.                  "Sazanami Mincho");
  1723.   
  1724.   my @sans_simplified_chinese_priority = ("FZSongTi",
  1725.                       "AR PL SungtiL GB");
  1726.   
  1727.   my @serif_simplified_chinese_priority = ("FZSongTi",
  1728.                        "AR PL SungtiL GB");
  1729.  
  1730.   my @sans_traditional_chinese_priority = ("FZMingTiB",
  1731.                        "AR PL Mingti2L Big5");
  1732.   
  1733.   my @serif_traditional_chinese_priority = ("FZMingTiB",
  1734.                         "AR PL Mingti2L Big5");
  1735.   
  1736.   my @sans_korean_priority = ("UnDotum",
  1737.                   "Baekmuk Gulim",
  1738.                   "Baekmuk Dotum");
  1739.   
  1740.   my @serif_korean_priority = ("UnBatang",
  1741.                    "Baekmuk Batang");
  1742.   
  1743.   my %sans_japanese_xlfds =
  1744.     (
  1745.      "MS Gothic"           , "-ricoh-ms gothic-",
  1746.      "HGGothicB"           , "-ricoh-hggothicb-",
  1747.      "IPAGothic"           , "-misc-ipagothic-",
  1748.      "Sazanami Gothic"     , "-misc-sazanami gothic-"
  1749.     );
  1750.   
  1751.   my %serif_japanese_xlfds =
  1752.     (
  1753.      "MS Mincho"           , "-ricoh-ms mincho-",
  1754.      "HGMinchoL"           , "-ricoh-hgminchol-",
  1755.      "IPAMincho"           , "-misc-ipamincho-",
  1756.      "Sazanami Mincho"     , "-misc-sazanami mincho-"
  1757.     );
  1758.  
  1759.   my %sans_simplified_chinese_xlfds =
  1760.     (
  1761.      "FZSongTi"            , "-founder-SongTi-",
  1762.      "AR PL SungtiL GB"    , "-arphic-ar pl sungtil gb-"
  1763.     );
  1764.  
  1765.   my %serif_simplified_chinese_xlfds =
  1766.     (
  1767.      "FZSongTi"            , "-founder-SongTi-",
  1768.      "AR PL SungtiL GB"    , "-arphic-ar pl sungtil gb-"
  1769.     );
  1770.  
  1771.   my %sans_traditional_chinese_xlfds =
  1772.     (
  1773.      "FZMingTiB"            , "-founder-MingTiB-",
  1774.      "AR PL Mingti2L Big5"  , "-arphic-ar pl mingti2l big5-"
  1775.     );
  1776.  
  1777.   my %serif_traditional_chinese_xlfds =
  1778.     (
  1779.      "FZMingTiB"            , "-founder-MingTiB-",
  1780.      "AR PL Mingti2L Big5"  , "-arphic-ar pl mingti2l big5-"
  1781.     );
  1782.  
  1783.   my %sans_korean_xlfds =
  1784.     (
  1785.      "UnDotum"              , "-misc-undotum-",
  1786.      "Baekmuk Gulim"        , "-baekmukttf-gulim-",
  1787.      "Baekmuk Dotum"        , "-baekmukttf-dotum-"
  1788.     );
  1789.  
  1790.   my %serif_korean_xlfds =
  1791.     (
  1792.      "UnBatang"             , "-misc-unbatang-",
  1793.      "Baekmuk Batang"       , "-baekmukttf-batang-"
  1794.     );
  1795.  
  1796.   my $sans_japanese_xlfd = "-misc-sazanami gothic-";
  1797.   my $sans_japanese_file = "/usr/share/fonts/truetype/sazanami-gothic.ttf";
  1798.  
  1799.   my $serif_japanese_xlfd = "-misc-sazanami mincho-";
  1800.   my $serif_japanese_file = "/usr/share/fonts/truetype/sazanami-mincho.ttf";
  1801.  
  1802.   my $sans_simplified_chinese_xlfd = "-arphic-ar pl sungtil gb-";
  1803.   my $sans_simplified_chinese_file = "/usr/share/fonts/truetype/gbsn00lp.ttf";
  1804.  
  1805.   my $serif_simplified_chinese_xlfd = "-arphic-ar pl sungtil gb-";
  1806.   my $serif_simplified_chinese_file = "/usr/share/fonts/truetype/gbsn00lp.ttf";
  1807.  
  1808.   my $sans_traditional_chinese_xlfd = "-arphic-ar pl mingti2l big5-";
  1809.   my $sans_traditional_chinese_file = "/usr/share/fonts/truetype/bsmi00lp.ttf";
  1810.  
  1811.   my $serif_traditional_chinese_xlfd = "-arphic-ar pl mingti2l big5-";
  1812.   my $serif_traditional_chinese_file = "/usr/share/fonts/truetype/bsmi00lp.ttf";
  1813.  
  1814.   my $sans_korean_xlfd = "-baekmukttf-dotum-";
  1815.   my $sans_korean_file = "/usr/share/fonts/truetype/dotum.ttf";
  1816.  
  1817.   my $serif_korean_xlfd = "-baekmukttf-batang-";
  1818.   my $serif_korean_file = "/usr/share/fonts/truetype/batang.ttf";
  1819.   
  1820.   for my $font (@sans_japanese_priority) {
  1821.     if (`fc-list "$font"`) {
  1822.       open (NAMES, "fc-list \"$font\" file |");
  1823.       binmode NAMES, ":bytes";
  1824.       while (<NAMES>) {
  1825.     chomp $ARG;
  1826.     $ARG =~ s/:.*$//;
  1827.     if ($ARG =~ /\.ttf|\.ttc/ && -f "$ARG") {
  1828.       $sans_japanese_file = $ARG;
  1829.       $sans_japanese_xlfd = $sans_japanese_xlfds{"$font"};
  1830.     }
  1831.       }
  1832.       close (NAMES);
  1833.       last;
  1834.     }
  1835.   }
  1836.   
  1837.   if ( ! -f $sans_japanese_file ) {
  1838.     print "Warning: cannot find a sans serif Japanese font. Japanese in Java might not work.\n";
  1839.   }
  1840.   
  1841.   for my $font (@serif_japanese_priority) {
  1842.     if (`fc-list "$font"`) {
  1843.       open (NAMES, "fc-list \"$font\" file |");
  1844.       binmode NAMES, ":bytes";
  1845.       while (<NAMES>) {
  1846.     chomp $ARG;
  1847.     $ARG =~ s/:.*$//;
  1848.     if ($ARG =~ /\.ttf|\.ttc/ && -f "$ARG") {
  1849.       $serif_japanese_file = $ARG;
  1850.       $serif_japanese_xlfd = $serif_japanese_xlfds{"$font"};
  1851.     }
  1852.       }
  1853.       close (NAMES);
  1854.       last;
  1855.     }
  1856.   }
  1857.   
  1858.   if ( ! -f $serif_japanese_file ) {
  1859.     print "Warning: cannot find a serif Japanese font. Japanese in Java might not work.\n";
  1860.   }
  1861.  
  1862.   for my $font (@sans_simplified_chinese_priority) {
  1863.     if (`fc-list "$font"`) {
  1864.       open (NAMES, "fc-list \"$font\" file |");
  1865.       binmode NAMES, ":bytes";
  1866.       while (<NAMES>) {
  1867.     chomp $ARG;
  1868.     $ARG =~ s/:.*$//;
  1869.     if ($ARG =~ /\.ttf|\.ttc/ && -f "$ARG") {
  1870.       $sans_simplified_chinese_file = $ARG;
  1871.       $sans_simplified_chinese_xlfd = $sans_simplified_chinese_xlfds{"$font"};
  1872.     }
  1873.       }
  1874.       close (NAMES);
  1875.       last;
  1876.     }
  1877.   }
  1878.   
  1879.   if ( ! -f $sans_simplified_chinese_file ) {
  1880.     print "Warning: cannot find a sans serif simplified Chinese font. Simplified Chinese in Java might not work.\n";
  1881.   }
  1882.   
  1883.   for my $font (@serif_simplified_chinese_priority) {
  1884.     if (`fc-list "$font"`) {
  1885.       open (NAMES, "fc-list \"$font\" file |");
  1886.       binmode NAMES, ":bytes";
  1887.       while (<NAMES>) {
  1888.     chomp $ARG;
  1889.     $ARG =~ s/:.*$//;
  1890.     if ($ARG =~ /\.ttf|\.ttc/ && -f "$ARG") {
  1891.       $serif_simplified_chinese_file = $ARG;
  1892.       $serif_simplified_chinese_xlfd = $serif_simplified_chinese_xlfds{"$font"};
  1893.     }
  1894.       }
  1895.       close (NAMES);
  1896.       last;
  1897.     }
  1898.   }
  1899.   
  1900.   if ( ! -f $serif_simplified_chinese_file ) {
  1901.     print "Warning: cannot find a serif simplified Chinese font. Simplified Chinese in Java might not work.\n";
  1902.   }
  1903.  
  1904.   for my $font (@sans_traditional_chinese_priority) {
  1905.     if (`fc-list "$font"`) {
  1906.       open (NAMES, "fc-list \"$font\" file |");
  1907.       binmode NAMES, ":bytes";
  1908.       while (<NAMES>) {
  1909.     chomp $ARG;
  1910.     $ARG =~ s/:.*$//;
  1911.     if ($ARG =~ /\.ttf|\.ttc/ && -f "$ARG") {
  1912.       $sans_traditional_chinese_file = $ARG;
  1913.       $sans_traditional_chinese_xlfd = $sans_traditional_chinese_xlfds{"$font"};
  1914.     }
  1915.       }
  1916.       close (NAMES);
  1917.       last;
  1918.     }
  1919.   }
  1920.   
  1921.   if ( ! -f $sans_traditional_chinese_file ) {
  1922.     print "Warning: cannot find a sans serif traditional Chinese font. Traditional Chinese in Java might not work.\n";
  1923.   }
  1924.   
  1925.   for my $font (@serif_traditional_chinese_priority) {
  1926.     if (`fc-list "$font"`) {
  1927.       open (NAMES, "fc-list \"$font\" file |");
  1928.       binmode NAMES, ":bytes";
  1929.       while (<NAMES>) {
  1930.     chomp $ARG;
  1931.     $ARG =~ s/:.*$//;
  1932.     if ($ARG =~ /\.ttf|\.ttc/ && -f "$ARG") {
  1933.       $serif_traditional_chinese_file = $ARG;
  1934.       $serif_traditional_chinese_xlfd = $serif_traditional_chinese_xlfds{"$font"};
  1935.     }
  1936.       }
  1937.       close (NAMES);
  1938.       last;
  1939.     }
  1940.   }
  1941.   
  1942.   if ( ! -f $serif_traditional_chinese_file ) {
  1943.     print "Warning: cannot find a serif traditional Chinese font. Traditional Chinese in Java might not work.\n";
  1944.   }
  1945.   
  1946.   for my $font (@sans_korean_priority) {
  1947.     if (`fc-list "$font"`) {
  1948.       open (NAMES, "fc-list \"$font\" file |");
  1949.       binmode NAMES, ":bytes";
  1950.       while (<NAMES>) {
  1951.     chomp $ARG;
  1952.     $ARG =~ s/:.*$//;
  1953.     if ($ARG =~ /\.ttf|\.ttc/ && -f "$ARG") {
  1954.       $sans_korean_file = $ARG;
  1955.       $sans_korean_xlfd = $sans_korean_xlfds{"$font"};
  1956.     }
  1957.       }
  1958.       close (NAMES);
  1959.       last;
  1960.     }
  1961.   }
  1962.   
  1963.   if ( ! -f $sans_korean_file ) {
  1964.     print "Warning: cannot find a sans serif Korean font. Korean in Java might not work.\n";
  1965.   }
  1966.   
  1967.   for my $font (@serif_korean_priority) {
  1968.     if (`fc-list "$font"`) {
  1969.       open (NAMES, "fc-list \"$font\" file |");
  1970.       binmode NAMES, ":bytes";
  1971.       while (<NAMES>) {
  1972.     chomp $ARG;
  1973.     $ARG =~ s/:.*$//;
  1974.     if ($ARG =~ /\.ttf|\.ttc/ && -f "$ARG") {
  1975.       $serif_korean_file = $ARG;
  1976.       $serif_korean_xlfd = $serif_korean_xlfds{"$font"};
  1977.     }
  1978.       }
  1979.       close (NAMES);
  1980.       last;
  1981.     }
  1982.   }
  1983.   
  1984.   if ( ! -f $serif_korean_file ) {
  1985.     print "Warning: cannot find a serif Korean font. Korean in Java might not work.\n";
  1986.   }
  1987.   
  1988.   (my $sans_japanese_xlfd_no_space = $sans_japanese_xlfd) =~ s/ /_/g;
  1989.   (my $serif_japanese_xlfd_no_space = $serif_japanese_xlfd) =~ s/ /_/g;
  1990.   
  1991.   (my $sans_simplified_chinese_xlfd_no_space = $sans_simplified_chinese_xlfd) =~ s/ /_/g;
  1992.   (my $serif_simplified_chinese_xlfd_no_space = $serif_simplified_chinese_xlfd) =~ s/ /_/g;
  1993.   
  1994.   (my $sans_traditional_chinese_xlfd_no_space = $sans_traditional_chinese_xlfd) =~ s/ /_/g;
  1995.   (my $serif_traditional_chinese_xlfd_no_space = $serif_traditional_chinese_xlfd) =~ s/ /_/g;
  1996.  
  1997.   (my $sans_korean_xlfd_no_space = $sans_korean_xlfd) =~ s/ /_/g;
  1998.   (my $serif_korean_xlfd_no_space = $serif_korean_xlfd) =~ s/ /_/g;
  1999.  
  2000.   # setup for Java 1.4 (only for Japanese at the moment):
  2001.   if (-f "$font_properties_ja_template_file") {
  2002.     open (TEMPLATE, "$font_properties_ja_template_file") || die "can't open file $font_properties_ja_template_file: $!";
  2003.     binmode TEMPLATE, ":utf8";
  2004.     while (<TEMPLATE>) {
  2005.       $ARG =~ s/_SANS_JAPANESE_XLFD_NO_SPACE_/$sans_japanese_xlfd_no_space/g;
  2006.       $ARG =~ s/_SANS_JAPANESE_FILE_/$sans_japanese_file/g;
  2007.       $ARG =~ s/_SANS_JAPANESE_XLFD_/$sans_japanese_xlfd/g;
  2008.       $ARG =~ s/_SERIF_JAPANESE_XLFD_NO_SPACE_/$serif_japanese_xlfd_no_space/g;
  2009.       $ARG =~ s/_SERIF_JAPANESE_FILE_/$serif_japanese_file/g;
  2010.       $ARG =~ s/_SERIF_JAPANESE_XLFD_/$serif_japanese_xlfd/g;
  2011.       $font_properties_ja_template .= $ARG;
  2012.     }
  2013.     close (TEMPLATE);
  2014.     for my $globpattern (@font_properties_ja_globs) {
  2015.       for my $file (glob ("$globpattern")) {
  2016.     if (-f "$file") {
  2017.       if ($VERBOSITY >= $VERBOSITY_QUIET) {
  2018.         printf "writing $file\n";
  2019.       }
  2020.       open (FONTPROP, ">$file") || die "can't open file $file: $!";
  2021.       binmode FONTPROP, ":utf8";
  2022.       print FONTPROP $font_properties_ja_template;
  2023.       close (FONTPROP);
  2024.     }
  2025.       }
  2026.     }
  2027.   }
  2028.  
  2029.   # setup for Java 1.5 (for Japanese, Chinese, and Korean):
  2030.  
  2031.   # I hope it is good enough to get the font directory from the full
  2032.   # path of the Japanese sans serif file.
  2033.   # Probably all fonts are in the same directory:
  2034.   (my $x11fontdir = $sans_japanese_file) =~ s/\/[^\/]+$//;
  2035.   
  2036.   if (-f "$fontconfig_SuSE_properties_template_file") {
  2037.     open (TEMPLATE, "$fontconfig_SuSE_properties_template_file") || die "can't open file $fontconfig_SuSE_properties_template_file: $!";
  2038.     binmode TEMPLATE, ":utf8";
  2039.     while (<TEMPLATE>) {
  2040.       $ARG =~ s/_SANS_JAPANESE_XLFD_NO_SPACE_/$sans_japanese_xlfd_no_space/g;
  2041.       $ARG =~ s/_SANS_JAPANESE_FILE_/$sans_japanese_file/g;
  2042.       $ARG =~ s/_SANS_JAPANESE_XLFD_/$sans_japanese_xlfd/g;
  2043.       $ARG =~ s/_SERIF_JAPANESE_XLFD_NO_SPACE_/$serif_japanese_xlfd_no_space/g;
  2044.       $ARG =~ s/_SERIF_JAPANESE_FILE_/$serif_japanese_file/g;
  2045.       $ARG =~ s/_SERIF_JAPANESE_XLFD_/$serif_japanese_xlfd/g;
  2046.  
  2047.       $ARG =~ s/_SANS_SIMPLIFIED_CHINESE_XLFD_NO_SPACE_/$sans_simplified_chinese_xlfd_no_space/g;
  2048.       $ARG =~ s/_SANS_SIMPLIFIED_CHINESE_FILE_/$sans_simplified_chinese_file/g;
  2049.       $ARG =~ s/_SANS_SIMPLIFIED_CHINESE_XLFD_/$sans_simplified_chinese_xlfd/g;
  2050.       $ARG =~ s/_SERIF_SIMPLIFIED_CHINESE_XLFD_NO_SPACE_/$serif_simplified_chinese_xlfd_no_space/g;
  2051.       $ARG =~ s/_SERIF_SIMPLIFIED_CHINESE_FILE_/$serif_simplified_chinese_file/g;
  2052.       $ARG =~ s/_SERIF_SIMPLIFIED_CHINESE_XLFD_/$serif_simplified_chinese_xlfd/g;
  2053.  
  2054.       $ARG =~ s/_SANS_TRADITIONAL_CHINESE_XLFD_NO_SPACE_/$sans_traditional_chinese_xlfd_no_space/g;
  2055.       $ARG =~ s/_SANS_TRADITIONAL_CHINESE_FILE_/$sans_traditional_chinese_file/g;
  2056.       $ARG =~ s/_SANS_TRADITIONAL_CHINESE_XLFD_/$sans_traditional_chinese_xlfd/g;
  2057.       $ARG =~ s/_SERIF_TRADITIONAL_CHINESE_XLFD_NO_SPACE_/$serif_traditional_chinese_xlfd_no_space/g;
  2058.       $ARG =~ s/_SERIF_TRADITIONAL_CHINESE_FILE_/$serif_traditional_chinese_file/g;
  2059.       $ARG =~ s/_SERIF_TRADITIONAL_CHINESE_XLFD_/$serif_traditional_chinese_xlfd/g;
  2060.  
  2061.       $ARG =~ s/_SANS_KOREAN_XLFD_NO_SPACE_/$sans_korean_xlfd_no_space/g;
  2062.       $ARG =~ s/_SANS_KOREAN_FILE_/$sans_korean_file/g;
  2063.       $ARG =~ s/_SANS_KOREAN_XLFD_/$sans_korean_xlfd/g;
  2064.       $ARG =~ s/_SERIF_KOREAN_XLFD_NO_SPACE_/$serif_korean_xlfd_no_space/g;
  2065.       $ARG =~ s/_SERIF_KOREAN_FILE_/$serif_korean_file/g;
  2066.       $ARG =~ s/_SERIF_KOREAN_XLFD_/$serif_korean_xlfd/g;
  2067.  
  2068.       $ARG =~ s/_X11FONTDIR_/$x11fontdir/;
  2069.       $fontconfig_SuSE_properties_template .= $ARG;
  2070.     }
  2071.     close (TEMPLATE);
  2072.     for my $globpattern (@fontconfig_SuSE_properties_globs) {
  2073.       for my $file (glob ("$globpattern")) {
  2074.     if (-f "$file") {
  2075.       if ($VERBOSITY >= $VERBOSITY_QUIET) {
  2076.         printf "writing $file\n";
  2077.       }
  2078.       open (FONTPROP, ">$file") || die "can't open file $file: $!";
  2079.       binmode FONTPROP, ":utf8";
  2080.       print FONTPROP $fontconfig_SuSE_properties_template;
  2081.       close (FONTPROP);
  2082.     }
  2083.       }
  2084.     }
  2085.   }
  2086.  
  2087. }
  2088.  
  2089. ########################################################################
  2090.  
  2091. my @font_dirs = ();
  2092.  
  2093. sub font_dirs_setup_add_font_dir {
  2094.   my ($dir) = @_;
  2095.  
  2096.   while (-l "$dir") {
  2097.     $dir = readlink ("$dir");
  2098.   }
  2099.   if (! -d "$dir") {
  2100.     return;
  2101.   }
  2102.   if (grep (/$dir/, @font_dirs)) {
  2103.     return;
  2104.   }
  2105.   push (@font_dirs, ("$dir"));
  2106.   if (opendir (DIR, $dir)) {
  2107.     my @entries = readdir (DIR);
  2108.     for my $entry (@entries) {
  2109.       if ("$entry" =~ /\./ || "$entry" =~ /\.\./ || ! -d "$dir/$entry") {
  2110.     next;
  2111.       }
  2112.       font_dirs_setup_add_font_dir("$dir/$entry");
  2113.     }
  2114.     closedir DIR;
  2115.   }
  2116. }
  2117.  
  2118. sub font_dirs_setup {
  2119.   my $suse_font_dirs_file = "/etc/fonts/suse-font-dirs.conf";
  2120.   my $suse_font_dirs_template_file = "/usr/share/fonts-config/suse-font-dirs.conf.template";
  2121.   my $suse_font_dirs = "";
  2122.   my $suse_font_dirs_template = "";
  2123.  
  2124.   if (-f "$suse_font_dirs_template_file") {
  2125.     open (TEMPLATE, "$suse_font_dirs_template_file") || die "can't open file $suse_font_dirs_template_file: $!";
  2126.     binmode TEMPLATE, ":utf8";
  2127.     while (<TEMPLATE>) {
  2128.       if ($ARG =~ /<dir>(.*)<\/dir>/) {
  2129.     for my $dir (glob ("$1")) {
  2130.       if (-d "$dir") {
  2131.         font_dirs_setup_add_font_dir ("$dir");
  2132.       }
  2133.     }
  2134.       }
  2135.       elsif ($ARG =~ /<\/fontconfig>/) {
  2136.     for my $dir (@font_dirs) {
  2137.       $suse_font_dirs_template .= "    <dir>$dir</dir>\n";
  2138.     }
  2139.     $suse_font_dirs_template .= "\n</fontconfig>\n";
  2140.       }
  2141.       else {
  2142.     $suse_font_dirs_template .= $ARG;
  2143.       }
  2144.     }
  2145.     close (TEMPLATE);
  2146.     if (open (CONF, "$suse_font_dirs_file")) {
  2147.       while (<CONF>) {
  2148.     $suse_font_dirs .= $ARG;
  2149.       }
  2150.       close (CONF);
  2151.     }
  2152.     if ("$suse_font_dirs_template" eq "$suse_font_dirs") {
  2153.       if ($VERBOSITY >= $VERBOSITY_QUIET) {
  2154.     printf "$suse_font_dirs_file unchanged\n";
  2155.       }
  2156.     } else {
  2157.       if ($VERBOSITY >= $VERBOSITY_QUIET) {
  2158.     printf "writing $suse_font_dirs_file\n";
  2159.       }
  2160.       open (CONF, ">$suse_font_dirs_file") || die "can't open file $suse_font_dirs_file: $!";
  2161.       print CONF $suse_font_dirs_template;
  2162.       close (CONF);
  2163.     }
  2164.   }
  2165. }
  2166. ########################################################################
  2167. sub hinting_setup {
  2168.   my $suse_hinting_file = "/etc/fonts/suse-hinting.conf";
  2169.   my $suse_hinting_template_file = "/usr/share/fonts-config/suse-hinting.conf.template";
  2170.   my $suse_hinting = "";
  2171.   my $suse_hinting_template = "";
  2172.  
  2173.   if (-f "$suse_hinting_template_file") {
  2174.     open (TEMPLATE, "$suse_hinting_template_file") || die "can't open file $suse_hinting_template_file: $!";
  2175.     binmode TEMPLATE, ":utf8";
  2176.     while (<TEMPLATE>) {
  2177.       $ARG =~ s/_BYTECODE_BW_MAX_PIXEL_/$OPT_BCBWMAX/;
  2178.       $suse_hinting_template .= $ARG;
  2179.     }
  2180.     close (TEMPLATE);
  2181.     if (open (CONF, "$suse_hinting_file")) {
  2182.       while (<CONF>) {
  2183.     $suse_hinting .= $ARG;
  2184.       }
  2185.       close (CONF);
  2186.     }
  2187.     if ("$suse_hinting_template" eq "$suse_hinting") {
  2188.       if ($VERBOSITY >= $VERBOSITY_QUIET) {
  2189.     printf "$suse_hinting_file unchanged\n";
  2190.       }
  2191.     } else {
  2192.       if ($VERBOSITY >= $VERBOSITY_QUIET) {
  2193.     printf "writing $suse_hinting_file\n";
  2194.       }
  2195.       open (CONF, ">$suse_hinting_file") || die "can't open file $suse_hinting_file: $!";
  2196.       print CONF $suse_hinting_template;
  2197.       close (CONF);
  2198.     }
  2199.   }
  2200. }
  2201.  
  2202. ########################################################################
  2203. sub embedded_bitmap_setup {
  2204.   my $suse_bitmaps_file = "/etc/fonts/suse-bitmaps.conf";
  2205.   my $suse_bitmaps_template_file = "/usr/share/fonts-config/suse-bitmaps.conf.template";
  2206.   my $suse_bitmaps = "";
  2207.   my $suse_bitmaps_template = "";
  2208.  
  2209.   if (-f "$suse_bitmaps_template_file") {
  2210.     open (TEMPLATE, "$suse_bitmaps_template_file") || die "can't open file $suse_bitmaps_template_file: $!";
  2211.     binmode TEMPLATE, ":utf8";
  2212.     while (<TEMPLATE>) {
  2213.       if ($ARG !~ /_USE_EMBEDDED_BITMAPS_PLACEHOLDER_/) {
  2214.     $suse_bitmaps_template .= $ARG;
  2215.       }
  2216.       else {
  2217.     if (! $OPT_EBITMAP) {
  2218.       $suse_bitmaps_template .= "    <match target=\"font\">\n";
  2219.       $suse_bitmaps_template .= "        <edit name=\"embeddedbitmap\" mode=\"assign\">\n";
  2220.       $suse_bitmaps_template .= "            <bool>false</bool>\n";
  2221.       $suse_bitmaps_template .= "        </edit>\n";
  2222.       $suse_bitmaps_template .= "    </match>\n";
  2223.     } elsif ($OPT_EBITMAP && $OPT_EBITMAP_LANG =~ /0/) {
  2224.       $suse_bitmaps_template .= "    <match target=\"font\">\n";
  2225.       $suse_bitmaps_template .= "        <edit name=\"embeddedbitmap\" mode=\"assign\">\n";
  2226.       $suse_bitmaps_template .= "            <bool>true</bool>\n";
  2227.       $suse_bitmaps_template .= "        </edit>\n";
  2228.       $suse_bitmaps_template .= "    </match>\n";
  2229.     } else {
  2230.       $suse_bitmaps_template .= "    <match target=\"font\">\n";
  2231.       $suse_bitmaps_template .= "        <edit name=\"embeddedbitmap\" mode=\"assign\">\n";
  2232.       $suse_bitmaps_template .= "            <bool>false</bool>\n";
  2233.       $suse_bitmaps_template .= "        </edit>\n";
  2234.       $suse_bitmaps_template .= "    </match>\n";
  2235.       $suse_bitmaps_template .= "    <match target=\"font\">\n";
  2236.       $suse_bitmaps_template .= "        <test name=\"lang\" compare=\"contains\">\n";
  2237.       my @languages = split (":", "$OPT_EBITMAP_LANG");
  2238.       for my $i (@languages) {
  2239.         $suse_bitmaps_template .= "            <string>$i</string>\n";
  2240.       }
  2241.       $suse_bitmaps_template .= "        </test>\n";
  2242.       $suse_bitmaps_template .= "        <edit name=\"embeddedbitmap\" mode=\"assign\">\n";
  2243.       $suse_bitmaps_template .= "            <bool>true</bool>\n";
  2244.       $suse_bitmaps_template .= "        </edit>\n";
  2245.       $suse_bitmaps_template .= "    </match>\n";
  2246.     }
  2247.       }
  2248.     }
  2249.     close (TEMPLATE);
  2250.     if (open (CONF, "$suse_bitmaps_file")) {
  2251.       while (<CONF>) {
  2252.     $suse_bitmaps .= $ARG;
  2253.       }
  2254.       close (CONF);
  2255.     }
  2256.     if ("$suse_bitmaps_template" eq "$suse_bitmaps") {
  2257.       if ($VERBOSITY >= $VERBOSITY_QUIET) {
  2258.     printf "$suse_bitmaps_file unchanged\n";
  2259.       }
  2260.     } else {
  2261.       if ($VERBOSITY >= $VERBOSITY_QUIET) {
  2262.     printf "writing $suse_bitmaps_file\n";
  2263.       }
  2264.       open (CONF, ">$suse_bitmaps_file") || die "can't open file $suse_bitmaps_file: $!";
  2265.       print CONF $suse_bitmaps_template;
  2266.       close (CONF);
  2267.     }
  2268.   }
  2269. }
  2270.  
  2271. ########################################################################
  2272.  
  2273. # Returns true if the modification time of $f1 differs from
  2274. # the modification time of $f2 
  2275. sub mtime_differs {
  2276.   my ($f1,$f2) = @_;
  2277.   if ( -e $f1 && -e $f2) {
  2278.     my @f1s = stat ($f1);
  2279.     my @f2s = stat ($f2);
  2280.     return ($f1s[9] != $f2s[9]);
  2281.   } else {
  2282.     return 0;
  2283.   }
  2284. }
  2285.  
  2286. # Returns true if the modification time of $f1 differs from
  2287. # the modification time of $f2 or if one of the files is missing
  2288. sub mtime_differs_or_missing {
  2289.     my ($f1,$f2) = @_;
  2290.     if (! -e $f1 || ! -e $f2 || mtime_differs ($f1,$f2)) {
  2291.       return 1;
  2292.     } else {
  2293.       return 0;
  2294.     }
  2295. }  
  2296.  
  2297. # Returns true if $f1 is newer than $f2
  2298. sub newer {
  2299.   my ($f1,$f2) = @_;
  2300.   if ( -e $f1 && -e $f2) {
  2301.     my @f1s = stat ($f1);
  2302.     my @f2s = stat ($f2);
  2303.     return ($f1s[9] > $f2s[9]);
  2304.   } else {
  2305.     return 0;
  2306.   }
  2307. }
  2308.  
  2309. # Returns true if $f1 is newer than $f2 or if one of the files is missing
  2310. sub newer_or_missing {
  2311.     my ($f1,$f2) = @_;
  2312.     if (! -e $f1 || ! -e $f2 || newer ($f1,$f2)) {
  2313.       return 1;
  2314.     } else {
  2315.       return 0;
  2316.     }
  2317. }
  2318.  
  2319. sub my_system {
  2320.   my ($command) = @_;
  2321.   if ($VERBOSITY >= $VERBOSITY_DEBUG)  {
  2322.     print "executing: $command\n";
  2323.   }
  2324.   return system ($command);
  2325. }
  2326.  
  2327. sub search_executable {
  2328.   for my $file (@_) {
  2329.     if (-x $file) {
  2330.       return $file;
  2331.     }
  2332.   }
  2333.   return "";
  2334. }
  2335.