| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Text::Amuse::Compile::Fonts; | 
| 2 | 62 |  |  | 62 |  | 1084 | use utf8; | 
|  | 62 |  |  |  |  | 161 |  | 
|  | 62 |  |  |  |  | 474 |  | 
| 3 | 62 |  |  | 62 |  | 2149 | use strict; | 
|  | 62 |  |  |  |  | 148 |  | 
|  | 62 |  |  |  |  | 1301 |  | 
| 4 | 62 |  |  | 62 |  | 368 | use warnings; | 
|  | 62 |  |  |  |  | 135 |  | 
|  | 62 |  |  |  |  | 2224 |  | 
| 5 | 62 |  |  | 62 |  | 2066 | use Types::Standard qw/ArrayRef InstanceOf/; | 
|  | 62 |  |  |  |  | 226534 |  | 
|  | 62 |  |  |  |  | 664 |  | 
| 6 | 62 |  |  | 62 |  | 74957 | use JSON::MaybeXS qw/decode_json/; | 
|  | 62 |  |  |  |  | 262518 |  | 
|  | 62 |  |  |  |  | 3886 |  | 
| 7 | 62 |  |  | 62 |  | 26549 | use Text::Amuse::Compile::Fonts::Family; | 
|  | 62 |  |  |  |  | 211 |  | 
|  | 62 |  |  |  |  | 2330 |  | 
| 8 | 62 |  |  | 62 |  | 27845 | use Text::Amuse::Compile::Fonts::File; | 
|  | 62 |  |  |  |  | 201 |  | 
|  | 62 |  |  |  |  | 2074 |  | 
| 9 | 62 |  |  | 62 |  | 435 | use Moo; | 
|  | 62 |  |  |  |  | 138 |  | 
|  | 62 |  |  |  |  | 253 |  | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | =head1 NAME | 
| 12 |  |  |  |  |  |  |  | 
| 13 |  |  |  |  |  |  | Text::Amuse::Compile::Fonts - class for fonts management | 
| 14 |  |  |  |  |  |  |  | 
| 15 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | # hash to hold the fonts file, where $wd is the font directory | 
| 18 |  |  |  |  |  |  | my %fontfiles = map { $_ => File::Spec->catfile($wd, $_ . '.otf') } (qw/regular italic | 
| 19 |  |  |  |  |  |  | bold bolditalic/); | 
| 20 |  |  |  |  |  |  | my $fonts = Text::Amuse::Compile::Fonts->new([ | 
| 21 |  |  |  |  |  |  | { | 
| 22 |  |  |  |  |  |  | name => 'Example Serif', | 
| 23 |  |  |  |  |  |  | type => 'serif', | 
| 24 |  |  |  |  |  |  | desc => 'example font', | 
| 25 |  |  |  |  |  |  | regular => $fontfiles{regular}, | 
| 26 |  |  |  |  |  |  | italic => $fontfiles{italic}, | 
| 27 |  |  |  |  |  |  | bold => $fontfiles{bold}, | 
| 28 |  |  |  |  |  |  | bolditalic => $fontfiles{bolditalic}, | 
| 29 |  |  |  |  |  |  | }, | 
| 30 |  |  |  |  |  |  | # more fonts here | 
| 31 |  |  |  |  |  |  | ]); | 
| 32 |  |  |  |  |  |  | # or you can pass the same structure if you got it serialized to | 
| 33 |  |  |  |  |  |  | # json and saved to a file. | 
| 34 |  |  |  |  |  |  | my $fonts = Text::Amuse::Compile::Fonts->new($json_file); | 
| 35 |  |  |  |  |  |  | my @fonts = $fonts->all_fonts; | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  |  | 
| 38 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 39 |  |  |  |  |  |  |  | 
| 40 |  |  |  |  |  |  | This class has the purpose to hold the list of available fonts, which | 
| 41 |  |  |  |  |  |  | has to be provided to the constructor via a json file or as an | 
| 42 |  |  |  |  |  |  | arrayref of L objects. | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | To build a json file with some default fonts, you may want to try | 
| 45 |  |  |  |  |  |  | L script installed with this | 
| 46 |  |  |  |  |  |  | distribution. | 
| 47 |  |  |  |  |  |  |  | 
| 48 |  |  |  |  |  |  | =head1 CONSTRUCTOR | 
| 49 |  |  |  |  |  |  |  | 
| 50 |  |  |  |  |  |  | =head2 new($file_or_arrayref_with_fonts) | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | The constructor accept either a file or an arrayref with fonts specifications. | 
| 53 |  |  |  |  |  |  |  | 
| 54 |  |  |  |  |  |  | Each font specification is used to construct a | 
| 55 |  |  |  |  |  |  | L object, which in turn may | 
| 56 |  |  |  |  |  |  | contain L objects. | 
| 57 |  |  |  |  |  |  |  | 
| 58 |  |  |  |  |  |  | Keys of the hashref inside the arrayref: | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | =over 4 | 
| 61 |  |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  | =item name | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | The name of the font. This is the system name, something that | 
| 65 |  |  |  |  |  |  | fontconfig will understand. You can try with fc-list to see if you can | 
| 66 |  |  |  |  |  |  | find it. Mandatory. | 
| 67 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | =item type | 
| 69 |  |  |  |  |  |  |  | 
| 70 |  |  |  |  |  |  | The type of the file. Can be either C, C or C. | 
| 71 |  |  |  |  |  |  | Mandatory. | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | =item desc | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | An optional free form description. | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  | =item regular | 
| 78 |  |  |  |  |  |  |  | 
| 79 |  |  |  |  |  |  | The path to the regular font file (.ttf or .otf or .woff) | 
| 80 |  |  |  |  |  |  |  | 
| 81 |  |  |  |  |  |  | =item italic | 
| 82 |  |  |  |  |  |  |  | 
| 83 |  |  |  |  |  |  | The path to the italic font file (.ttf or .otf or .woff) | 
| 84 |  |  |  |  |  |  |  | 
| 85 |  |  |  |  |  |  | =item bold | 
| 86 |  |  |  |  |  |  |  | 
| 87 |  |  |  |  |  |  | The path to the bold font file (.ttf or .otf or .woff) | 
| 88 |  |  |  |  |  |  |  | 
| 89 |  |  |  |  |  |  | =item bolditalic | 
| 90 |  |  |  |  |  |  |  | 
| 91 |  |  |  |  |  |  | The path to the bolditalic font file (.ttf or .otf or .woff) | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | =back | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  | Please note that the paths to the files are optional. They are used | 
| 96 |  |  |  |  |  |  | only for the EPUB generation, when the files are embedded in the final | 
| 97 |  |  |  |  |  |  | file. | 
| 98 |  |  |  |  |  |  |  | 
| 99 |  |  |  |  |  |  | Also note that the name of the fonts is not arbitrary. Fontconfig | 
| 100 |  |  |  |  |  |  | needs to recognize it for a successful LaTeX compilation. | 
| 101 |  |  |  |  |  |  |  | 
| 102 |  |  |  |  |  |  | =head1 ACCESSORS | 
| 103 |  |  |  |  |  |  |  | 
| 104 |  |  |  |  |  |  | =head2 list | 
| 105 |  |  |  |  |  |  |  | 
| 106 |  |  |  |  |  |  | The arrayref with the L objects. | 
| 107 |  |  |  |  |  |  |  | 
| 108 |  |  |  |  |  |  | =head1 METHODS | 
| 109 |  |  |  |  |  |  |  | 
| 110 |  |  |  |  |  |  | =head2 all_fonts | 
| 111 |  |  |  |  |  |  |  | 
| 112 |  |  |  |  |  |  | Return the list of fonts, as a plain list | 
| 113 |  |  |  |  |  |  |  | 
| 114 |  |  |  |  |  |  | =head2 serif_fonts | 
| 115 |  |  |  |  |  |  |  | 
| 116 |  |  |  |  |  |  | As above, but only the serif fonts | 
| 117 |  |  |  |  |  |  |  | 
| 118 |  |  |  |  |  |  | =head2 mono_fonts | 
| 119 |  |  |  |  |  |  |  | 
| 120 |  |  |  |  |  |  | As above, but only the mono fonts | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  | =head2 sans_fonts | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | As above, but only the sans fonts | 
| 125 |  |  |  |  |  |  |  | 
| 126 |  |  |  |  |  |  | =head2 all_fonts_with_files | 
| 127 |  |  |  |  |  |  |  | 
| 128 |  |  |  |  |  |  | Return the list of fonts which have the paths to the font file. | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  | =head2 serif_fonts_with_files | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | As above, but only the serif fonts | 
| 133 |  |  |  |  |  |  |  | 
| 134 |  |  |  |  |  |  | =head2 mono_fonts_with_files | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  | As above, but only the mono fonts | 
| 137 |  |  |  |  |  |  |  | 
| 138 |  |  |  |  |  |  | =head2 sans_fonts_with_files | 
| 139 |  |  |  |  |  |  |  | 
| 140 |  |  |  |  |  |  | As above, but only the sans fonts | 
| 141 |  |  |  |  |  |  |  | 
| 142 |  |  |  |  |  |  | =head2 default_font_list | 
| 143 |  |  |  |  |  |  |  | 
| 144 |  |  |  |  |  |  | Return an arrayref with the default font definitions | 
| 145 |  |  |  |  |  |  |  | 
| 146 |  |  |  |  |  |  | =head2 fonts_for_language($babel_lang) | 
| 147 |  |  |  |  |  |  |  | 
| 148 |  |  |  |  |  |  | Return the list of language-specific fonts. | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  | =head1 INTERNALS | 
| 151 |  |  |  |  |  |  |  | 
| 152 |  |  |  |  |  |  | =head2 BUILDARGS | 
| 153 |  |  |  |  |  |  |  | 
| 154 |  |  |  |  |  |  | Construct the font list from either the data structure or the file path. | 
| 155 |  |  |  |  |  |  |  | 
| 156 |  |  |  |  |  |  | =cut | 
| 157 |  |  |  |  |  |  |  | 
| 158 |  |  |  |  |  |  | has list => (is => 'ro', | 
| 159 |  |  |  |  |  |  | isa => ArrayRef[InstanceOf['Text::Amuse::Compile::Fonts::Family']]); | 
| 160 |  |  |  |  |  |  |  | 
| 161 |  |  |  |  |  |  | sub all_fonts { | 
| 162 | 1096 |  |  | 1096 | 1 | 2595 | my $self = shift; | 
| 163 | 1096 |  |  |  |  | 1970 | return @{$self->list}; | 
|  | 1096 |  |  |  |  | 7015 |  | 
| 164 |  |  |  |  |  |  | } | 
| 165 |  |  |  |  |  |  |  | 
| 166 |  |  |  |  |  |  | sub serif_fonts { | 
| 167 | 499 |  |  | 499 | 1 | 43256 | my $self = shift; | 
| 168 | 499 |  |  |  |  | 1094 | return grep { $_->is_serif } @{$self->list}; | 
|  | 24834 |  |  |  |  | 44558 |  | 
|  | 499 |  |  |  |  | 2275 |  | 
| 169 |  |  |  |  |  |  | } | 
| 170 |  |  |  |  |  |  |  | 
| 171 |  |  |  |  |  |  | sub mono_fonts { | 
| 172 | 499 |  |  | 499 | 1 | 40145 | my $self = shift; | 
| 173 | 499 |  |  |  |  | 1224 | return grep { $_->is_mono } @{$self->list}; | 
|  | 24834 |  |  |  |  | 45280 |  | 
|  | 499 |  |  |  |  | 2144 |  | 
| 174 |  |  |  |  |  |  | } | 
| 175 |  |  |  |  |  |  |  | 
| 176 |  |  |  |  |  |  | sub sans_fonts { | 
| 177 | 497 |  |  | 497 | 1 | 40273 | my $self = shift; | 
| 178 | 497 |  |  |  |  | 1056 | return grep { $_->is_sans } @{$self->list}; | 
|  | 24730 |  |  |  |  | 45250 |  | 
|  | 497 |  |  |  |  | 2146 |  | 
| 179 |  |  |  |  |  |  | } | 
| 180 |  |  |  |  |  |  |  | 
| 181 |  |  |  |  |  |  | sub all_fonts_with_files { | 
| 182 | 1 |  |  | 1 | 1 | 292 | my $self = shift; | 
| 183 | 1 |  |  |  |  | 2 | return grep { $_->has_files } @{$self->list}; | 
|  | 3 |  |  |  |  | 96 |  | 
|  | 1 |  |  |  |  | 6 |  | 
| 184 |  |  |  |  |  |  | } | 
| 185 |  |  |  |  |  |  |  | 
| 186 |  |  |  |  |  |  | sub serif_fonts_with_files { | 
| 187 | 1 |  |  | 1 | 1 | 297 | my $self = shift; | 
| 188 | 1 | 100 |  |  |  | 2 | return grep { $_->is_serif && $_->has_files } @{$self->list}; | 
|  | 3 |  |  |  |  | 18 |  | 
|  | 1 |  |  |  |  | 5 |  | 
| 189 |  |  |  |  |  |  | } | 
| 190 |  |  |  |  |  |  |  | 
| 191 |  |  |  |  |  |  | sub sans_fonts_with_files { | 
| 192 | 1 |  |  | 1 | 1 | 328 | my $self = shift; | 
| 193 | 1 | 100 |  |  |  | 2 | return grep { $_->is_sans && $_->has_files } @{$self->list}; | 
|  | 3 |  |  |  |  | 17 |  | 
|  | 1 |  |  |  |  | 5 |  | 
| 194 |  |  |  |  |  |  | } | 
| 195 |  |  |  |  |  |  |  | 
| 196 |  |  |  |  |  |  | sub mono_fonts_with_files { | 
| 197 | 1 |  |  | 1 | 1 | 291 | my $self = shift; | 
| 198 | 1 | 100 |  |  |  | 3 | return grep { $_->is_mono && $_->has_files } @{$self->list}; | 
|  | 3 |  |  |  |  | 8 |  | 
|  | 1 |  |  |  |  | 5 |  | 
| 199 |  |  |  |  |  |  | } | 
| 200 |  |  |  |  |  |  |  | 
| 201 |  |  |  |  |  |  | sub fonts_for_language { | 
| 202 | 870 |  |  | 870 | 1 | 2377 | my ($self, $slot, $babel_lang) = @_; | 
| 203 | 870 | 50 | 33 |  |  | 4009 | die "Missing arguments" unless $slot && $babel_lang; | 
| 204 | 870 | 100 |  |  |  | 2515 | if ($slot eq 'main') { | 
| 205 | 289 |  |  |  |  | 669 | $slot = 'serif'; | 
| 206 |  |  |  |  |  |  | } | 
| 207 |  |  |  |  |  |  | # print Dumper([$self->all_fonts]); | 
| 208 |  |  |  |  |  |  | return grep { | 
| 209 | 870 | 100 | 100 |  |  | 2622 | $_->type eq $slot and $_->has_languages and $_->for_babel_language($babel_lang) | 
|  | 41355 |  |  |  |  | 298004 |  | 
| 210 |  |  |  |  |  |  | } $self->all_fonts; | 
| 211 |  |  |  |  |  |  | } | 
| 212 |  |  |  |  |  |  |  | 
| 213 |  |  |  |  |  |  |  | 
| 214 |  |  |  |  |  |  | sub BUILDARGS { | 
| 215 | 1033 |  |  | 1033 | 1 | 107432 | my ($class, $arg) = @_; | 
| 216 | 1033 |  |  |  |  | 2090 | my $list; | 
| 217 | 1033 | 100 |  |  |  | 3642 | if ($arg) { | 
| 218 | 19 | 100 |  |  |  | 66 | if (my $ref = ref($arg)) { | 
| 219 | 15 | 50 |  |  |  | 43 | if ($ref eq 'ARRAY') { | 
| 220 | 15 |  |  |  |  | 37 | $list = $arg; | 
| 221 |  |  |  |  |  |  | } | 
| 222 |  |  |  |  |  |  | else { | 
| 223 | 0 |  |  |  |  | 0 | die "Argument to ->new must be either a file or an arrayref"; | 
| 224 |  |  |  |  |  |  | } | 
| 225 |  |  |  |  |  |  | } | 
| 226 |  |  |  |  |  |  | else { | 
| 227 | 4 |  |  |  |  | 15 | eval { | 
| 228 | 4 | 50 |  |  |  | 183 | open (my $fh, '<', $arg) or die "Cannot open $arg $!"; | 
| 229 | 4 |  |  |  |  | 36 | local $/ = undef; | 
| 230 | 4 |  |  |  |  | 150 | my $body = <$fh>; | 
| 231 | 4 |  |  |  |  | 57 | close $fh; | 
| 232 | 4 |  |  |  |  | 133 | $list = decode_json($body); | 
| 233 |  |  |  |  |  |  | }; | 
| 234 | 4 | 50 |  |  |  | 23 | if ($@) { | 
| 235 | 0 |  |  |  |  | 0 | warn $@; | 
| 236 | 0 |  |  |  |  | 0 | $list = undef; | 
| 237 |  |  |  |  |  |  | } | 
| 238 |  |  |  |  |  |  | } | 
| 239 |  |  |  |  |  |  | } | 
| 240 | 1033 |  | 66 |  |  | 5540 | $list ||= $class->default_font_list; | 
| 241 | 1033 |  |  |  |  | 2364 | my @out; | 
| 242 | 1033 |  |  |  |  | 3170 | foreach my $fontref (@$list) { | 
| 243 | 51772 |  |  |  |  | 3216335 | my $font = { %$fontref }; # do a copy do avoid mangling the argument. | 
| 244 | 51772 | 50 | 33 |  |  | 207077 | if ($font->{name} and $font->{type}) { | 
| 245 | 51772 |  | 66 |  |  | 106947 | $font->{desc} ||= $font->{name}; | 
| 246 | 51772 |  |  |  |  | 90814 | foreach my $type (qw/regular bold italic bolditalic/) { | 
| 247 | 207084 | 100 |  |  |  | 407107 | if (my $file = delete $font->{$type}) { | 
| 248 | 143 |  |  |  |  | 2675 | my $obj = Text::Amuse::Compile::Fonts::File->new(file => $file, | 
| 249 |  |  |  |  |  |  | shape => $type | 
| 250 |  |  |  |  |  |  | ); | 
| 251 | 141 |  |  |  |  | 4323 | $font->{$type} = $obj; | 
| 252 |  |  |  |  |  |  | } | 
| 253 |  |  |  |  |  |  | } | 
| 254 | 51770 |  |  |  |  | 984641 | push @out, Text::Amuse::Compile::Fonts::Family->new(%$font); | 
| 255 |  |  |  |  |  |  | } | 
| 256 |  |  |  |  |  |  | } | 
| 257 | 1030 |  |  |  |  | 137090 | return { list => \@out }; | 
| 258 |  |  |  |  |  |  | } | 
| 259 |  |  |  |  |  |  |  | 
| 260 |  |  |  |  |  |  | sub default_font_list { | 
| 261 |  |  |  |  |  |  | return [ | 
| 262 |  |  |  |  |  |  | { | 
| 263 | 1014 |  |  | 1014 | 1 | 67380 | name => 'CMU Serif', | 
| 264 |  |  |  |  |  |  | desc => 'Computer Modern', | 
| 265 |  |  |  |  |  |  | type => 'serif', | 
| 266 |  |  |  |  |  |  | }, | 
| 267 |  |  |  |  |  |  | { | 
| 268 |  |  |  |  |  |  | name => 'DejaVu Serif', | 
| 269 |  |  |  |  |  |  | name => 'DejaVu Serif', | 
| 270 |  |  |  |  |  |  | type => 'serif', | 
| 271 |  |  |  |  |  |  | }, | 
| 272 |  |  |  |  |  |  | { | 
| 273 |  |  |  |  |  |  | name => 'FreeSerif', | 
| 274 |  |  |  |  |  |  | name => 'FreeSerif', | 
| 275 |  |  |  |  |  |  | type => 'serif', | 
| 276 |  |  |  |  |  |  | }, | 
| 277 |  |  |  |  |  |  | { | 
| 278 |  |  |  |  |  |  | name => 'Linux Libertine O', | 
| 279 |  |  |  |  |  |  | desc => 'Linux Libertine', | 
| 280 |  |  |  |  |  |  | type => 'serif', | 
| 281 |  |  |  |  |  |  | }, | 
| 282 |  |  |  |  |  |  | { | 
| 283 |  |  |  |  |  |  | name => 'TeX Gyre Termes', | 
| 284 |  |  |  |  |  |  | desc => 'TeX Gyre Termes (Times)', | 
| 285 |  |  |  |  |  |  | type => 'serif', | 
| 286 |  |  |  |  |  |  | }, | 
| 287 |  |  |  |  |  |  | { | 
| 288 |  |  |  |  |  |  | name => 'TeX Gyre Pagella', | 
| 289 |  |  |  |  |  |  | desc => 'TeX Gyre Pagella (Palatino)', | 
| 290 |  |  |  |  |  |  | type => 'serif', | 
| 291 |  |  |  |  |  |  | }, | 
| 292 |  |  |  |  |  |  | { | 
| 293 |  |  |  |  |  |  | name => 'TeX Gyre Schola', | 
| 294 |  |  |  |  |  |  | desc => 'TeX Gyre Schola (Century)', | 
| 295 |  |  |  |  |  |  | type => 'serif', | 
| 296 |  |  |  |  |  |  | }, | 
| 297 |  |  |  |  |  |  | { | 
| 298 |  |  |  |  |  |  | name => 'TeX Gyre Bonum', | 
| 299 |  |  |  |  |  |  | desc => 'TeX Gyre Bonum (Bookman)', | 
| 300 |  |  |  |  |  |  | type => 'serif', | 
| 301 |  |  |  |  |  |  | }, | 
| 302 |  |  |  |  |  |  | { name => 'Coelacanth',     desc => 'Coelacanth (no bolditalic)', type => 'serif' }, | 
| 303 |  |  |  |  |  |  | { name => 'Alegreya',       desc => 'Alegreya',       type => 'serif' }, | 
| 304 |  |  |  |  |  |  | { name => 'Arvo',           desc => 'Arvo',           type => 'serif' }, | 
| 305 |  |  |  |  |  |  | { name => 'Lora',           desc => 'Lora',           type => 'serif' }, | 
| 306 |  |  |  |  |  |  | { name => 'Merriweather',   desc => 'Merriweather',   type => 'serif' }, | 
| 307 |  |  |  |  |  |  | { name => 'Vollkorn',       desc => 'Vollkorn',       type => 'serif' }, | 
| 308 |  |  |  |  |  |  | # arabic | 
| 309 |  |  |  |  |  |  | { name => 'Amiri',          desc => 'Amiri',          type => 'serif' }, | 
| 310 |  |  |  |  |  |  | { name => 'Scheherazade',   desc => 'Scheherazade',   type => 'serif' }, | 
| 311 |  |  |  |  |  |  | { | 
| 312 |  |  |  |  |  |  | name => 'Antykwa Poltawskiego', | 
| 313 |  |  |  |  |  |  | desc => 'Antykwa Półtawskiego', | 
| 314 |  |  |  |  |  |  | type => 'serif', | 
| 315 |  |  |  |  |  |  | }, | 
| 316 |  |  |  |  |  |  | { | 
| 317 |  |  |  |  |  |  | name => 'Antykwa Torunska', | 
| 318 |  |  |  |  |  |  | desc => 'Antykwa Toruńska', | 
| 319 |  |  |  |  |  |  | type => 'serif', | 
| 320 |  |  |  |  |  |  | }, | 
| 321 |  |  |  |  |  |  | { | 
| 322 |  |  |  |  |  |  | name => 'Charis SIL', | 
| 323 |  |  |  |  |  |  | desc => 'Charis SIL (Bitstream Charter)', | 
| 324 |  |  |  |  |  |  | type => 'serif', | 
| 325 |  |  |  |  |  |  | }, | 
| 326 |  |  |  |  |  |  | { | 
| 327 |  |  |  |  |  |  | name => 'PT Serif', | 
| 328 |  |  |  |  |  |  | desc => 'Paratype (cyrillic)', | 
| 329 |  |  |  |  |  |  | type => 'serif', | 
| 330 |  |  |  |  |  |  | }, | 
| 331 |  |  |  |  |  |  | { | 
| 332 |  |  |  |  |  |  | name => 'Noto Serif', | 
| 333 |  |  |  |  |  |  | desc => 'Noto Serif', | 
| 334 |  |  |  |  |  |  | type => 'serif', | 
| 335 |  |  |  |  |  |  | }, | 
| 336 |  |  |  |  |  |  | { | 
| 337 |  |  |  |  |  |  | name => 'Gentium Book Basic', | 
| 338 |  |  |  |  |  |  | desc => 'Gentium', | 
| 339 |  |  |  |  |  |  | type => 'serif', | 
| 340 |  |  |  |  |  |  | }, | 
| 341 |  |  |  |  |  |  | { | 
| 342 |  |  |  |  |  |  | name => 'Cormorant Garamond', | 
| 343 |  |  |  |  |  |  | desc => 'Garamond', | 
| 344 |  |  |  |  |  |  | type => 'serif', | 
| 345 |  |  |  |  |  |  | }, | 
| 346 |  |  |  |  |  |  | { | 
| 347 |  |  |  |  |  |  | name => 'CMU Sans Serif', | 
| 348 |  |  |  |  |  |  | desc => 'Computer Modern Sans Serif', | 
| 349 |  |  |  |  |  |  | type => 'sans', | 
| 350 |  |  |  |  |  |  | }, | 
| 351 |  |  |  |  |  |  | { | 
| 352 |  |  |  |  |  |  | name => 'TeX Gyre Heros', | 
| 353 |  |  |  |  |  |  | desc => 'TeX Gyre Heros (Helvetica)', | 
| 354 |  |  |  |  |  |  | type => 'sans', | 
| 355 |  |  |  |  |  |  | }, | 
| 356 |  |  |  |  |  |  | { | 
| 357 |  |  |  |  |  |  | name => 'TeX Gyre Adventor', | 
| 358 |  |  |  |  |  |  | desc => 'TeX Gyre Adventor (Avant Garde Gothic)', | 
| 359 |  |  |  |  |  |  | type => 'sans', | 
| 360 |  |  |  |  |  |  | }, | 
| 361 |  |  |  |  |  |  | { | 
| 362 |  |  |  |  |  |  | name => 'Iwona', | 
| 363 |  |  |  |  |  |  | desc => 'Iwona', | 
| 364 |  |  |  |  |  |  | type => 'sans', | 
| 365 |  |  |  |  |  |  | }, | 
| 366 |  |  |  |  |  |  | { | 
| 367 |  |  |  |  |  |  | name => 'DejaVu Sans', | 
| 368 |  |  |  |  |  |  | desc => 'DejaVu Sans', | 
| 369 |  |  |  |  |  |  | type => 'sans', | 
| 370 |  |  |  |  |  |  | }, | 
| 371 |  |  |  |  |  |  | { | 
| 372 |  |  |  |  |  |  | name => 'PT Sans', | 
| 373 |  |  |  |  |  |  | desc => 'PT Sans (cyrillic)', | 
| 374 |  |  |  |  |  |  | type => 'sans', | 
| 375 |  |  |  |  |  |  | }, | 
| 376 |  |  |  |  |  |  | { | 
| 377 |  |  |  |  |  |  | name => 'Noto Sans', | 
| 378 |  |  |  |  |  |  | desc => 'Noto Sans', | 
| 379 |  |  |  |  |  |  | type => 'sans', | 
| 380 |  |  |  |  |  |  | }, | 
| 381 |  |  |  |  |  |  | { name => 'Alegreya Sans',   desc => 'Alegreya Sans',   type => 'sans' }, | 
| 382 |  |  |  |  |  |  | { name => 'Archivo Narrow',  desc => 'Archivo Narrow',  type => 'sans' }, | 
| 383 |  |  |  |  |  |  | { name => 'Fira Sans',      desc => 'Fira Sans',      type => 'sans' }, | 
| 384 |  |  |  |  |  |  | { name => 'Karla',          desc => 'Karla',          type => 'sans' }, | 
| 385 |  |  |  |  |  |  | { name => 'Libre Franklin', desc => 'Libre Franklin', type => 'sans' }, | 
| 386 |  |  |  |  |  |  | { name => 'Poppins',        desc => 'Poppins',        type => 'sans' }, | 
| 387 |  |  |  |  |  |  | { name => 'Rubik',          desc => 'Rubik',          type => 'sans' }, | 
| 388 |  |  |  |  |  |  | { name => 'Source Sans Pro',  desc => 'Source Sans Pro',  type => 'sans' }, | 
| 389 |  |  |  |  |  |  | { | 
| 390 |  |  |  |  |  |  | name => 'CMU Typewriter Text', | 
| 391 |  |  |  |  |  |  | desc => 'Computer Modern Typewriter Text', | 
| 392 |  |  |  |  |  |  | type => 'mono', | 
| 393 |  |  |  |  |  |  | }, | 
| 394 |  |  |  |  |  |  | { | 
| 395 |  |  |  |  |  |  | name => 'DejaVu Sans Mono', | 
| 396 |  |  |  |  |  |  | desc => 'DejaVu Sans Mono', | 
| 397 |  |  |  |  |  |  | type => 'mono', | 
| 398 |  |  |  |  |  |  | }, | 
| 399 |  |  |  |  |  |  | { | 
| 400 |  |  |  |  |  |  | name => 'TeX Gyre Cursor', | 
| 401 |  |  |  |  |  |  | desc => 'TeX Gyre Cursor (Courier)', | 
| 402 |  |  |  |  |  |  | type => 'mono', | 
| 403 |  |  |  |  |  |  | }, | 
| 404 |  |  |  |  |  |  | { name => 'Anonymous Pro', desc => 'Anonymous Pro', type => 'mono' }, | 
| 405 |  |  |  |  |  |  | { name => 'Space Mono',    desc => 'Space Mono',    type => 'mono' }, | 
| 406 |  |  |  |  |  |  | { | 
| 407 |  |  |  |  |  |  | "languages" =>  [ "zh" ], | 
| 408 |  |  |  |  |  |  | "name" =>  "Source Han Serif SC", | 
| 409 |  |  |  |  |  |  | "desc" =>  "Source Han Serif SC (Simplified Chinese)", | 
| 410 |  |  |  |  |  |  | "type" =>  "serif" | 
| 411 |  |  |  |  |  |  | }, | 
| 412 |  |  |  |  |  |  | { | 
| 413 |  |  |  |  |  |  | "languages" =>  [ "ja" ], | 
| 414 |  |  |  |  |  |  | "name" =>  "Source Han Serif", | 
| 415 |  |  |  |  |  |  | "desc" =>  "Source Han Serif (Japanese)", | 
| 416 |  |  |  |  |  |  | "type" =>  "serif" | 
| 417 |  |  |  |  |  |  | }, | 
| 418 |  |  |  |  |  |  | { | 
| 419 |  |  |  |  |  |  | "languages" =>  [ "ko" ], | 
| 420 |  |  |  |  |  |  | "name" =>  "Source Han Serif K", | 
| 421 |  |  |  |  |  |  | "desc" =>  "Source Han Serif K (Korean)", | 
| 422 |  |  |  |  |  |  | "type" =>  "serif" | 
| 423 |  |  |  |  |  |  | }, | 
| 424 |  |  |  |  |  |  | { | 
| 425 |  |  |  |  |  |  | "languages" =>  [ "zh" ], | 
| 426 |  |  |  |  |  |  | "name" =>  "Source Han Sans SC", | 
| 427 |  |  |  |  |  |  | "desc" =>  "Source Han Sans SC (Simplified Chinese)", | 
| 428 |  |  |  |  |  |  | "type" =>  "sans" | 
| 429 |  |  |  |  |  |  | }, | 
| 430 |  |  |  |  |  |  | { | 
| 431 |  |  |  |  |  |  | "languages" =>  [ "ja" ], | 
| 432 |  |  |  |  |  |  | "name" =>  "Source Han Sans", | 
| 433 |  |  |  |  |  |  | "desc" =>  "Source Han Sans (Japanese)", | 
| 434 |  |  |  |  |  |  | "type" =>  "sans" | 
| 435 |  |  |  |  |  |  | }, | 
| 436 |  |  |  |  |  |  | { | 
| 437 |  |  |  |  |  |  | "languages" =>  [ "ko" ], | 
| 438 |  |  |  |  |  |  | "name" =>  "Source Han Sans K", | 
| 439 |  |  |  |  |  |  | "desc" =>  "Source Han Sans K (Korean)", | 
| 440 |  |  |  |  |  |  | "type" =>  "sans" | 
| 441 |  |  |  |  |  |  | }, | 
| 442 |  |  |  |  |  |  | { | 
| 443 |  |  |  |  |  |  | "languages" =>  [ "zh" ], | 
| 444 |  |  |  |  |  |  | "name" =>  "FandolSong", | 
| 445 |  |  |  |  |  |  | "desc" =>  "FandolSong", | 
| 446 |  |  |  |  |  |  | "type" =>  "sans" | 
| 447 |  |  |  |  |  |  | }, | 
| 448 |  |  |  |  |  |  | { | 
| 449 |  |  |  |  |  |  | "languages" =>  [ "zh" ], | 
| 450 |  |  |  |  |  |  | "desc" =>  "FandolHei", | 
| 451 |  |  |  |  |  |  | "name" =>  "FandolHei", | 
| 452 |  |  |  |  |  |  | "type" =>  "serif" | 
| 453 |  |  |  |  |  |  | }, | 
| 454 |  |  |  |  |  |  | ]; | 
| 455 |  |  |  |  |  |  | } | 
| 456 |  |  |  |  |  |  |  | 
| 457 |  |  |  |  |  |  |  | 
| 458 |  |  |  |  |  |  | 1; |