]> git.lyx.org Git - lyx.git/blob - development/autotests/useSystemFonts.pl
Cmake tests: Simplify test logic for exporting to formats lyx[0-9][0-9]x
[lyx.git] / development / autotests / useSystemFonts.pl
1 #! /usr/bin/env perl
2 # -*- mode: perl; -*-
3 #
4 # file useSystemFonts.pl
5 # 1.) Copies lyx-files to another location
6 # 2.) While copying,
7 #   2a.) searches for relative references to files and
8 #        replaces them with absolute ones
9 #   2b.) In order to be able to compile with luatex or xetex
10 #        changes default fonts to use non-tex-fonts instead
11 #
12 # Syntax: perl useSystemFonts.pl sourceFile destFile format
13 # Each param represents a path to a file
14 # sourceFile: full path to a lyx file
15 # destFile: destination path
16 #   Each subdocument will be copied into a subdirectory of dirname(destFile)
17 # format: any string of the form '[a-zA-Z0-9]+', e.g. pdf5
18 #
19 # This file is free software; you can redistribute it and/or
20 # modify it under the terms of the GNU General Public
21 # License as published by the Free Software Foundation; either
22 # version 2 of the License, or (at your option) any later version.
23 #
24 # This software is distributed in the hope that it will be useful,
25 # but WITHOUT ANY WARRANTY; without even the implied warranty of
26 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
27 # General Public License for more details.
28 #
29 # You should have received a copy of the GNU General Public
30 # License along with this software; if not, write to the Free Software
31 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
32 #
33 # Copyright (c) 2013 Kornel Benko <kornel@lyx.org>
34 #           (c) 2013 Scott Kostyshak <skotysh@lyx.org>
35
36 use strict;
37
38 BEGIN {
39   use File::Spec;
40   my $p = File::Spec->rel2abs( __FILE__ );
41   $p =~ s/[\/\\]?[^\/\\]+$//;
42   unshift(@INC, "$p");
43 }
44 use File::Basename;
45 use File::Path;
46 use File::Copy "cp";
47 use File::Temp qw/ :POSIX /;
48 use lyxStatus;
49
50 # Prototypes
51 sub printCopiedDocuments($);
52 sub interpretedCopy($$$$);
53 sub copyFoundSubdocuments($);
54 sub copyJob($$);
55 sub isrelativeFix($$$);
56 sub isrelative($$$);
57 sub createTemporaryFileName($$);
58 sub copyJobPending($$);
59 sub addNewJob($$$$$);
60 sub addFileCopyJob($$$$);
61 sub getNewNameOf($$);
62 sub getlangs($$);
63 sub simplifylangs($);
64 sub getLangEntry();
65
66 # convert lyx file to be compilable with xetex
67
68 my ($source, $dest, $format, $fontT, $languageFile, $rest) = @ARGV;
69 my %encodings = ();      # Encoding with TeX fonts, depending on language tag
70
71 diestack("Too many arguments") if (defined($rest));
72 diestack("Sourcefilename not defined") if (! defined($source));
73 diestack("Destfilename not defined") if (! defined($dest));
74 diestack("Format (e.g. pdf4) not defined") if (! defined($format));
75 diestack("Font type (e.g. texF) not defined") if (! defined($fontT));
76
77 $source = File::Spec->rel2abs($source);
78 $dest = File::Spec->rel2abs($dest);
79
80 my %font = ();
81 my $lang = "main";
82 if ($source =~ /\/([a-z][a-z](_[A-Z][A-Z])?)[\/_]/) {
83   $lang = $1;
84 }
85
86 my $inputEncoding = undef;
87 if ($fontT eq "systemF") {
88   if ($lang =~ /^(ru|uk|sk|el)$/) {
89     $font{roman} = "DejaVu Serif";
90     $font{sans} = "DejaVu Sans";
91     $font{typewriter} = "DejaVu Sans Mono";
92   }
93   elsif ($lang =~ /^(he|el|main)$/) {
94     $font{roman} = "FreeSans";
95     $font{sans} = "FreeSans";
96     $font{typewriter} = "FreeSans";
97   }
98   elsif ($lang eq "fa") {
99     $font{roman} = "FreeFarsi";
100     $font{sans} = "FreeFarsi";
101     $font{typewriter} = "FreeFarsi Monospace";
102   }
103   elsif ($lang eq "zh_CN") {
104     $font{roman} = "WenQuanYi Micro Hei";
105     $font{sans} = "WenQuanYi Micro Hei";
106     $font{typewriter} = "WenQuanYi Micro Hei";
107   }
108   elsif ($lang eq "ko" ) {
109     $font{roman} = "NanumGothic"; # NanumMyeongjo, NanumGothic Eco, NanumGothicCoding
110     $font{sans} = "NanumGothic";
111     $font{typewriter} = "NanumGothic";
112   }
113   elsif ($lang eq "ar" ) {
114     # available in 'fonts-sil-scheherazade' package
115     $font{roman} = "Scheherazade";
116     $font{sans} = "Scheherazade";
117     $font{typewriter} = "Scheherazade";
118   }
119   else {
120     # default system fonts
121     $font{roman} = "FreeSerif";
122     $font{sans} = "FreeSans";
123     $font{typewriter} = "FreeMono";
124   }
125 }
126 elsif (0) { # set to '1' to enable setting of inputencoding
127   # use tex font here
128   my %encoding = ();
129   if (defined($languageFile)) {
130     # The 2 lines below does not seem to have any effect
131     #&getlangs($languageFile, \%encoding);
132     #&simplifylangs(\%encoding);
133   }
134   if ($format =~ /^(pdf4)$/) { # xelatex
135     # set input encoding to 'ascii' always
136     $inputEncoding = {
137       "search" => '.*', # this will be substituted from '\inputencoding'-line
138       "out" => "ascii",
139     };
140   }
141   elsif ($format =~ /^(dvi3|pdf5)$/) { # (dvi)?lualatex
142     # when to set input encoding to 'ascii'?
143     if (defined($encoding{$lang})) {
144       $inputEncoding = {
145         "search" => '.*', # this will be substituted from '\inputencoding'-line
146         "out" => $encoding{$lang},
147       };
148     }
149   }
150 }
151
152 my $sourcedir = dirname($source);
153 my $destdir = dirname($dest);
154 if (! -d $destdir) {
155   diestack("could not make dir \"$destdir\"") if (! mkdir $destdir);
156 }
157
158 my $destdirOfSubdocuments;
159 {
160   my ($name, $pat, $suffix) = fileparse($source, qr/\.[^.]*/);
161   my $ext = $format . "_$lang";
162   $destdirOfSubdocuments = "$destdir/tmp_$ext" . "_$name"; # Global var, something TODO here
163 }
164
165 if(-d $destdirOfSubdocuments) {
166   rmtree($destdirOfSubdocuments);
167 }
168 mkdir($destdirOfSubdocuments);  #  for possibly included files
169
170 my %IncludedFiles = ();
171 my %type2hash = (
172   "copy_only" => "copyonly",
173   "interpret" => "interpret");
174
175 addNewJob($source, $dest, "interpret", {}, \%IncludedFiles);
176
177 copyFoundSubdocuments(\%IncludedFiles);
178
179 #printCopiedDocuments(\%IncludedFiles);
180
181 exit(0);
182 ###########################################################
183
184 sub printCopiedDocuments($)
185 {
186   my ($rFiles) = @_;
187   for my $k (keys %{$rFiles}) {
188     my $rJob = $rFiles->{$k};
189     for my $j ( values %type2hash) {
190       if (defined($rJob->{$j})) {
191         print "$j: $k->$rJob->{$j}, " . $rJob->{$j . "copied"} . "\n";
192       }
193     }
194   }
195 }
196
197 sub interpretedCopy($$$$)
198 {
199   my ($source, $dest, $destdirOfSubdocuments, $rFiles) = @_;
200   my $sourcedir = dirname($source);
201   my $res = 0;
202
203   diestack("could not read \"$source\"") if (!open(FI, $source));
204   diestack("could not write \"$dest\"") if (! open(FO, '>', $dest));
205
206   initLyxStack(\%font, $fontT, $inputEncoding);
207
208   while (my $l = <FI>) {
209     chomp($l);
210     my $rStatus = checkLyxLine($l);
211     if ($rStatus->{found}) {
212       my $rF = $rStatus->{result};
213       if ($rStatus->{"filetype"} eq "replace_only") {
214         # e.g. if no files involved (font chage etc)
215         $l = join('', @{$rF});
216       }
217       else {
218         my $filelist = $rStatus->{filelist};
219         my $fidx = $rStatus->{fileidx};
220         my $separator = $rStatus->{"separator"};
221         my $foundrelative = 0;
222         for my $f (@{$filelist}) {
223           my @isrel = isrelative($f,
224                                   $sourcedir,
225                                   $rStatus->{ext});
226           if ($isrel[0]) {
227             $foundrelative = 1;
228             my $ext = $isrel[1];
229             if ($rStatus->{"filetype"} eq "prefix_only") {
230               $f = getNewNameOf("$sourcedir/$f", $rFiles);
231             }
232             else {
233               my ($newname, $res1);
234               ($newname, $res1) = addFileCopyJob("$sourcedir/$f$ext",
235                                                   "$destdirOfSubdocuments",
236                                                   $rStatus->{"filetype"},
237                                                   $rFiles);
238               print "Added ($res1) file \"$sourcedir/$f$ext\" to be copied to \"$newname\"\n";
239               if ($ext ne "") {
240                 $newname =~ s/$ext$//;
241               }
242               $f = $newname;
243               $res += $res1;
244             }
245           }
246         }
247         if ($foundrelative) {
248           $rF->[$fidx] = join($separator, @{$filelist});
249           $l = join('', @{$rF});
250         }
251       }
252     }
253     print FO "$l\n";
254   }
255   close(FI);
256   close(FO);
257
258   closeLyxStack();
259   return($res);
260 }
261
262 sub copyFoundSubdocuments($)
263 {
264   my ($rFiles) = @_;
265   my $res = 0;
266   do {
267     $res = 0;
268     my %copylist = ();
269
270     for my $filename (keys  %{$rFiles}) {
271       next if (! copyJobPending($filename, $rFiles));
272       $copylist{$filename} = 1;
273     }
274     for my $f (keys %copylist) {
275       # Second loop needed, because here $rFiles may change
276       my ($res1, @destfiles) = copyJob($f, $rFiles);
277       $res += $res1;
278       for my $destfile (@destfiles) {
279         print "res1 = $res1 for \"$f\" to be copied to $destfile\n";
280       }
281     }
282   } while($res > 0);            #  loop, while $rFiles changed
283 }
284
285 sub copyJob($$)
286 {
287   my ($source, $rFiles) = @_;
288   my $sourcedir = dirname($source);
289   my $res = 0;
290   my @dest = ();
291
292   for my $k (values %type2hash) {
293     if ($rFiles->{$source}->{$k}) {
294       if (! $rFiles->{$source}->{$k . "copied"}) {
295         $rFiles->{$source}->{$k . "copied"} = 1;
296         my $dest = $rFiles->{$source}->{$k};
297         push(@dest, $dest);
298         if ($k eq "copyonly") {
299           diestack("Could not copy \"$source\" to \"$dest\"") if (! cp($source, $dest));
300         }
301         else {
302           interpretedCopy($source, $dest, $destdirOfSubdocuments, $rFiles);
303         }
304         $res += 1;
305       }
306     }
307   }
308   return($res, @dest);
309 }
310
311 # Trivial check
312 sub isrelativeFix($$$)
313 {
314   my ($f, $sourcedir, $ext) = @_;
315
316   return(1, $ext) if  (-e "$sourcedir/$f$ext");
317   return(0,0);
318 }
319
320 sub isrelative($$$)
321 {
322   my ($f, $sourcedir, $ext) = @_;
323
324   if (ref($ext) eq "ARRAY") {
325     for my $ext2 (@{$ext}) {
326       my @res = isrelativeFix($f, $sourcedir, $ext2);
327       if ($res[0]) {
328         return(@res);
329       }
330     }
331     return(0,0);
332   }
333   else {
334     return(isrelativeFix($f, $sourcedir, $ext));
335   }
336 }
337
338 sub createTemporaryFileName($$)
339 {
340   my ($source, $destdir) = @_;
341
342   # get the basename to be used for the template
343   my ($name, $path, $suffix) = fileparse($source, qr/\.[^.]*/);
344   #print "source = $source, name = $name, path = $path, suffix = $suffix\n";
345   my $template = "xx_$name" . "_";
346   my $fname = File::Temp::tempnam($destdir, $template);
347
348   # Append extension from source
349   if ($suffix ne "") {
350     $fname .= "$suffix";
351   }
352   return($fname);
353 }
354
355 # Check, if file not copied yet
356 sub copyJobPending($$)
357 {
358   my ($f, $rFiles) = @_;
359   for my $t (values %type2hash) {
360     if (defined($rFiles->{$f}->{$t})) {
361       return 1 if (! $rFiles->{$f}->{$t . "copied"});
362     }
363   }
364   return 0;
365 }
366
367 sub addNewJob($$$$$)
368 {
369   my ($source, $newname, $hashname, $rJob, $rFiles) = @_;
370
371   $rJob->{$hashname} = $newname;
372   $rJob->{$hashname . "copied"} = 0;
373   $rFiles->{$source} = $rJob;
374 }
375
376 sub addFileCopyJob($$$$)
377 {
378   my ($source, $destdirOfSubdocuments, $filetype, $rFiles) = @_;
379   my ($res, $newname) = (0, undef);
380   my $rJob = $rFiles->{$source};
381
382   my $hashname = $type2hash{$filetype};
383   if (! defined($hashname)) {
384     diestack("unknown filetype \"$filetype\"");
385   }
386   if (!defined($rJob->{$hashname})) {
387     addNewJob($source,
388                createTemporaryFileName($source, $destdirOfSubdocuments),
389                "$hashname", $rJob, $rFiles);
390     $res = 1;
391   }
392   $newname = $rJob->{$hashname};
393   return($newname, $res);
394 }
395
396 sub getNewNameOf($$)
397 {
398   my ($f, $rFiles) = @_;
399   my $resultf = $f;
400
401   if (defined($rFiles->{$f})) {
402     for my $t (values %type2hash) {
403       if (defined($rFiles->{$f}->{$t})) {
404         $resultf = $rFiles->{$f}->{$t};
405         last;
406       }
407     }
408   }
409   return($resultf);
410 }
411
412 sub getlangs($$)
413 {
414   my ($languagefile, $rencoding) = @_;
415
416   if (open(FI, $languagefile)) {
417     while (my $l = <FI>) {
418       if ($l =~ /^Language/) {
419         my ($lng, $enc) = &getLangEntry();
420         if (defined($lng)) {
421           $rencoding->{$lng} = $enc;
422         }
423       }
424     }
425     close(FI);
426   }
427 }
428
429 sub simplifylangs($)
430 {
431   my ($rencoding) = @_;
432   my $base = "";
433   my $enc = "";
434   my $differ = 0;
435   my @klist = ();
436   my @klist2 = ();
437   for my $k (reverse sort keys %{$rencoding}) {
438     my @tag = split('_', $k);
439     if ($tag[0] eq $base) {
440       push(@klist, $k);
441       if ($rencoding->{$k} ne $enc) {
442         $differ = 1;
443       }
444     }
445     else {
446       # new base, check that old base was OK
447       if ($base ne "") {
448         if ($differ == 0) {
449           $rencoding->{$base} = $enc;
450           push(@klist2, @klist);
451         }
452       }
453       @klist = ($k);
454       $base = $tag[0];
455       $enc = $rencoding->{$k};
456       $differ = 0;
457     }
458   }
459   if ($base ne "") {
460     # close handling for last entry too
461     if ($differ == 0) {
462       $rencoding->{$base} = $enc;
463       push(@klist2, @klist);
464     }
465   }
466   for my $k (@klist2) {
467     delete($rencoding->{$k});
468   }
469 }
470
471 sub getLangEntry()
472 {
473   my ($lng, $enc) = (undef, undef);
474   while (my $l = <FI>) {
475     chomp($l);
476     if ($l =~ /^\s*Encoding\s+([^ ]+)\s*$/) {
477       $enc = $1;
478     }
479     elsif ($l =~ /^\s*LangCode\s+([^ ]+)\s*$/) {
480       $lng = $1;
481     }
482     elsif ($l =~ /^\s*End\s*$/) {
483       last;
484     }
485   }
486   if (defined($lng) && defined($enc)) {
487     return($lng, $enc);
488   }
489   else {
490     return(undef, undef);
491   }
492 }