<(common.inc.plp)><: my $font = $Request; Html({ title => 'font coverage '.($font ? "for $font" : 'sheet'), version => '1.2', keywords => [qw( unicode font glyph char character support overview cover coverage script block symbol sign mark reference table )], stylesheet => [qw( light dark mono circus red )], data => [qw( unicode-cover.inc.pl )], }); if ($font) { my ($fontmeta, @cover) = do "ttfsupport/$font.inc.pl"; $fontmeta or die "Unknown font $font\n"; my $map = eval { $get{map} or return; my $groupinfo = do 'unicode-cover.inc.pl' or die $@ || $!; my ($cat, $name) = split m{/}, $get{map}, 2 or die "invalid map\n"; if (!$name) { ($cat, $name) = ('table', $cat); } my $row = $groupinfo->{$cat}->{$name} or die "unknown character group $cat/$name\n"; my $query = $row->{query}; my @map; for (map { split /[^\d-]/ } $query) { my @range = split /-/, $_, 2; m/^[0-9]+$/ or die "Invalid code point $_ in query $query\n" for @range; push @map, $_ for $range[0] .. ($range[1] // $range[0]); } return \@map; }; die $@ if $@; require Unicode::UCD; my $pagerows = 0x200; my $pagecols = 32; my $offset = eval { local $_ = $get{q} || 0; return $_ if /\A\d+\z/; # numeric return hex $1 if /\A (?: 0?x | u\W* ) ([0-9a-f]+) \z/ix; # hexadecimal return $_->[0]->[0] for Unicode::UCD::charblock(ucfirst) || (); # block die "Unknown offset query '$_'\n"; }; die $@ if $@; say "

Font coverage

"; say "

$_

" for EscapeHTML($fontmeta->{name}); printf("

Version %s released %s contains %d glyphs.", !!$_->[2] && qq( title="revision $_->[2]"), $_->[1], $_->[0], scalar @cover, ) for [ grep { $_ } ($fontmeta->{date} || '?') =~ s/T.*//r, EscapeHTML($fontmeta->{version}), $fontmeta->{revision}, ]; for ($fontmeta->{os}) { say '
'; print ucfirst join(' ', "distributed", (map { "by $_" } $fontmeta->{oscorp} || "various sources"), (map { "with $_" } $_ || ()), ('and published as freeware "Core Web font"') x ($_ eq 'Windows 2000'), (map { "under a $_ license" } map { $fontmeta->{license} ? qq($_) : $_ } $_ && $_ ne 'Android' ? 'proprietary' : 'free', ), ); print '.'; } say '

'; say "

$_

" for EscapeHTML($fontmeta->{copyright}) || (); require Shiar_Sheet::FormatChar; my $glyphs = Shiar_Sheet::FormatChar->new; my %cover = map { ($_ => 1) } @cover; # lookup map say <<"EOT"; EOT say ''; my $offsetlink = '?' . join('&', (map { $_ . '=' . EncodeURI($get{$_}) } grep { defined $get{$_} } qw{ map }), 'q', ); say "" for join(' ', grep {$_} $offset > $pagerows && sprintf('', $offsetlink, 0), $offset > 0 && sprintf( '', $offsetlink, $offset - $pagerows, ), sprintf('U+%04X', $map ? $map->[$offset] : $offset), Unicode::UCD::charblock($map ? $map->[$offset] : $offset), $offset + $pagerows < ($map ? @{$map} : 0x11_0000) && sprintf( '', $offsetlink, $offset + $pagerows, ), ); for my $cp ($offset .. $offset+$pagerows-1) { $cp = $map->[$cp] or next if $map; state $colpos; my $block = Unicode::UCD::charblock($cp); if ($block ne (state $sameblock = $block) and $block ne 'No_Block') { print ''; printf '
$_
%s', $pagecols+1, $block unless $block eq 'No_Block'; say ''; $sameblock = $block; $colpos = 0; } if ($map) { # compare previous code point and indicate gaps state $lastcp = 0; if ($cp != ++$lastcp) { if (!$colpos or $colpos++ % $pagecols > $pagecols - 3) { # nearly last column, start new row $colpos = 0; } else { # mark repositioning in existing row printf '%X', $cp; } $lastcp = $cp; } } say sprintf '
%X', $cp if $colpos++ % $pagecols == 0; my $info = $glyphs->glyph_info($cp); my ($class, $name, $mnem, $entity, $string) = @{$info}; my $np = $class =~ /\bC\S\b/; # noprint if control or invalid # display literal character, with placeholder circle if non-spacing/enclosing my $html = ($class =~ /\bM[ne]\b/ && chr 9676) . EscapeHTML(chr $cp); say sprintf '%s', !$class ? ('l0', $cp, '', '') : $cover{$cp} ? $np ? 'l2' : 'l5' : $np ? 'Xi' : 'l1', $cp, !!$name && ": $name", ($cover{$cp} || !$np) && $html; } say '
'; exit; } :>

Font coverage

Character support of Unicode blocks and presets.

<: my $cover = do 'unicode-cover.inc.pl' or die $@ || $!; my @ossel = @{ $cover->{osdefault} }; my @fontlist = map { @{ $cover->{os}->{$_} } } @ossel; my @rows = ( 'version/11', 'version/63', 'block/Latin-1 Supplement', 'block/Latin Extended-A', 'block/Latin Extended Additional', 'block/Latin Extended-B', 'script/Latin', 'script/Greek', 'script/Cyrillic', 'script/Arabic', 'script/Hebrew', 'script/Devanagari', 'script/Thai', 'script/Hangul', 'table/japanese', 'script/Han', 'table/ipa', 'table/punctuation', 'block/Dingbats', 'table/symbols', 'category/Sc', # currency 'table/math', 'category/Sm', # mathematical 'table/arrows/single', 'table/lines/single', 'table/block', 'table/lines', 'table/html', ); if (my $group = $get{q}) { my $grouprows = $cover->{$group} or die "Unknown character category $_\n"; @rows = map { "$group/$_" } sort keys %{$grouprows}; } # output character list print ''; print ''; print "" for map { scalar @{ $cover->{os}->{$_} } } @ossel; print ''; print ''; print ''; for (@rows) { my ($group, $name) = split m{/}, $_, 2; my $row = $cover->{$group}->{$name}; print ''; $name = sprintf 'Unicode v%.1f', $name / 10 if $group eq 'version'; $name = sprintf '%s', EncodeURI("/chars/$group/$name"), EscapeHTML($name) if $row->{count} and $row->{count} < 1280; print ''; } say "
'; for my $os (@ossel) { my $osfonts = $cover->{os}->{$os}; my $osfont = $cover->{fonts}->[ $osfonts->[0] ]; # first font printf '%s', scalar @{$osfonts}, $osfont->{os} || '' } print '
'; printf('%s', map { EscapeHTML($_) } join("\n", $_->{name}, $_->{description}), "/font/$_->{file}", $_->{abbr}, ) for @{ $cover->{fonts} }[@fontlist]; say '
', $name; print '', $row->{count}; for my $count (@{ $row->{support} }[@fontlist]) { if (not defined $count) { print '?'; next; } if (not $count) { print '✘'; next; } if ($count == $row->{count}) { print '✔'; next; } my $rel = $count / $row->{count}; my $class = $rel < .5 ? 2 : $rel < .9 ? 3 : 4; printf '%d', "l$class", $rel*10; } say '
\n"; :>