1 # This script generates various 'interesting' fonts, and outputs an HTML file
 
   2 # containing the subsetted fonts and the original fonts.
 
   3 # View the output in browsers (preferably multiple, on multiple platforms) to
 
   4 # make sure the output looks the same as the original.
 
   9 use lib 'ext/Font-TTF/lib';
 
  17 # The following fonts need to exist in a directory called 'testfonts':
 
  21     LinLibertine_Re-4.1.8.ttf
 
  30 die "Run '$0', or '$0 n' where n is the number of the test to rebuild\n"
 
  31     if defined $index and $index !~ /^\d+$/;
 
  34     # These aren't proper tests (they drop features that affect the rendering)
 
  35     # TODO: fix them so they are proper, and test that they're really dropping the
 
  37 #     [ [qw(DejaVuSans.ttf FedraSansPro-Demi.ttf)], ["fluffily لا f"], [20], [qw(aalt ccmp dlig fina hlig init liga locl medi rlig salt kern mark mkmk)] ],
 
  38 #     [ [qw(DejaVuSans.ttf FedraSansPro-Demi.ttf)], ["fluffily لا f"], [20], [qw(liga)] ],
 
  39 #     [ [qw(DejaVuSans.ttf FedraSansPro-Demi.ttf)], ["fluffily لا f"], [20], [qw(fina init rlig)] ],
 
  40 #     [ [qw(DejaVuSans.ttf FedraSansPro-Demi.ttf)], ["fluffily لا f"], [20], [] ],
 
  43     [ [@all], ["Hello world ABC abc 123"], [20] ],
 
  45     # Substitution and NFC issues
 
  46     [ [qw(GenBasR.ttf DejaVuSans.ttf FedraSansPro-Demi.ttf)], [
 
  52         "i<span class='h'>\x{0300}</span>",
 
  54     [ [qw(DejaVuSans.ttf FedraSansPro-Demi.ttf)], [
 
  55         "s\x{0323}\x{0307}", # s, combining dot below, combining dot above
 
  56         "s\x{0307}\x{0323}", # s, combining dot above, combining dot below
 
  57         "\x{1e61}\x{0323}", # s with dot above, combining dot below
 
  58         "\x{1e63}\x{0307}", # s with dot below, combining dot above
 
  59         "\x{212b}", # angstrom
 
  63     [ [qw(LinLibertine_Re-4.1.8.ttf DejaVuSans.ttf FedraSansPro-Demi.ttf)], [
 
  65         "f<span>l</span>uf<span>f</span>ily",
 
  66         "f<span class='h'>l</span>uf<span class='h'>f</span>ily",
 
  70     [ [qw(DejaVuSans.ttf FedraSansPro-Demi.ttf calibri.ttf)],
 
  71         ["|VAVAV|", "ToToT", "x//x"], [20], ['kern'] ],
 
  74     [ [@all], ["VABC(123) fTo fluffiest f<span class='h'>f</span>i!\@#,. \x{00e2}\x{00eb}I\x{0303}o\x{0300}u\x{030a}\x{0305}\x{0303} i\x{0331}\x{0301} \x{0d23}\x{0d4d}\x{200d} παρακαλώ хэлло  你好 表示问候 やあ التل<span class='h'>ف</span>ون הלו"], [20, 8] ],
 
  78 my $common_css = <<EOF;
 
  80     font-family: Courier, monospace;
 
  88     text-decoration: underline;
 
  95     border: 1px #aaa solid;
 
 104     if (not $font_cache{$fn}) {
 
 105         my $s = new Font::Subsetter();
 
 107         $font_cache{$fn} = $s;
 
 109     return Clone::clone($font_cache{$fn});
 
 113 # if (0) { my $j = 0;
 
 114 for my $j (0..$#all) {
 
 116     (my $eot_fn = $fn) =~ s/\.[ot]tf$/.eot/i;
 
 117     if (not -e "testfonts/$eot_fn") {
 
 118         Font::EOTWrapper::convert("testfonts/$fn", "testfonts/$eot_fn");
 
 120     $common_css .= <<EOF;
 
 122     font-family: original-$j;
 
 123     src: url(../testfonts/$eot_fn);
 
 126     font-family: original-$j;
 
 127     src: url(../testfonts/$fn) format("truetype");
 
 130     $std_fonts{$all[$j]} = "original-$j";
 
 136 if (not defined $index) {
 
 137     open $out, '>', 'testoutput/tests.html' or die $!;
 
 138     binmode $out, ':utf8';
 
 142 <meta charset="utf-8">
 
 143 <title>Font tests</title>
 
 151 for my $test (@tests) {
 
 152     for my $fn (@{$test->[0]}) {
 
 153         for my $text (@{$test->[1]}) {
 
 155             next if defined $index and $index != $i;
 
 157             print encode('utf-8', "$fn -- $text\n");
 
 159             (my $text_plain = $text) =~ s/<.*?>//g;
 
 163                 $features = { DEFAULT => 0 };
 
 164                 $features->{$_} = 1 for @{$test->[3]};
 
 167             my $s = new_font("testfonts/$fn");
 
 168             $s->subset("testfonts/$fn", $text_plain, { features => $features });
 
 169             my $path = sprintf '%03d', $i;
 
 170             $s->write("testoutput/$path.ttf");
 
 171             my $old_glyphs = $s->num_glyphs_old;
 
 172             my $new_glyphs = $s->num_glyphs_new;
 
 173             my @glyph_names = $s->glyph_names;
 
 176             Font::EOTWrapper::convert("testoutput/$path.ttf", "testoutput/$path.eot");
 
 178             my $fragment = <<EOF;
 
 180 \@font-face { /* for IE */
 
 181     font-family: subsetted-$i;
 
 185     font-family: subsetted-$i;
 
 186     src: url($path.ttf) format("truetype");
 
 191             for my $size (@{$test->[2]}) {
 
 193 <p title="$fn -- $path -- $old_glyphs vs $new_glyphs" class="box"><span style="font-family: $std_fonts{$fn}; font-size: ${size}pt">$text</span>
 
 195 <span style="font-family: subsetted-$i; font-size: ${size}pt">$text</span></p>
 
 199             print $out qq{\n\n$fragment<a href="$path.html">#</a>} if not defined $index;
 
 201             open my $html, '>', "testoutput/$path.html";
 
 202             binmode $html, ':utf8';
 
 205 <meta charset="utf-8">
 
 206 <title>Font test $path</title>
 
 209 .glyphs { font-family: serif; font-size: 10pt; }
 
 210 .sizes { font-size: 8pt; }
 
 214             print $html qq{<p class="glyphs">}, (join '   ', map "$_", sort @glyph_names), qq{</p>};
 
 215             print $html qq{<pre class="sizes">}, dump_sizes("testoutput/$path.ttf"), qq{</pre>};
 
 217         print $out "<hr>\n" if not defined $index;
 
 223     my $font = Font::TTF::Font->open($fn) or die "Failed to open $fn: $!";
 
 227     for (sort keys %$font) {
 
 229         my $l = $font->{$_}{' LENGTH'};
 
 233     $out .= "Total: $s\n";