Font-TTF-Scripts

 view release on metacpan or  search on metacpan

scripts/ttf2woff  view on Meta::CPAN

#!/usr/bin/perl

use strict;
use Font::TTF::Font;
use IO::String;
use Getopt::Std;
use Pod::Usage;
use Compress::Zlib;

my %opts;
our ($if);
my ($string);
our ($CHAIN_CALL);
my ($ofh);

unless ($CHAIN_CALL)
{
    getopts('chm:p:v:', \%opts);

    unless (defined $ARGV[1] || defined $opts{'h'})
    {
        pod2usage(1);
        exit;
    }

    if ($opts{'h'})
    {
        pod2usage( -verbose => 2, -noperldoc => 1);
        exit;
    }

    $if = Font::TTF::Font->open($ARGV[0]);
}

my $iswoff = exists $if->{' WOFF'};
# For now, just quit if input font is already a woff.
# Someone else may want to add this functionality later
# but it will involve decompressing tables to confirm the checksums

die "input font is already a woff font\n" if $iswoff;

if ($opts{'c'})
{
	# Force checksum recalcuation by copying font
	
	# If font has non-empty DSIG, delete it first:
	my $dsig = $if->{'DSIG'};
	delete $if->{'DSIG'} if ($dsig && !$dsig->isempty);
	
	#Copy the rest of the font to string file:
    my ($tfh) = IO::String->new($string);
    my (@tlist) = sort {$if->{$a}{' OFFSET'} <=> $if->{$b}{' OFFSET'}}
                    grep(length($_) == 4, keys %{$if});
    $if->out($tfh, @tlist);
    
    # release original font to free up memory:
    $if->{'DSIG'} = $dsig if $dsig;
    $if->release;
    
    # Now open copied font:
    $tfh = IO::String->new($string);
    $if = Font::TTF::Font->open($tfh);
}

my $cWarnings = 0;

$ofh = IO::File->new("> $ARGV[1]") || die "Can't open $ARGV[1] for writing";
binmode $ofh;

# re-read the header to initialize font-wide csum

my ($msum);

my $ntables = 0;
map {$ntables++ if length($_) == 4} keys %{$if};
$if->{' INFILE'}->seek($if->{' OFFSET'}, 0);
$if->{' INFILE'}->read($msum, 12 + $ntables * 16);
$msum = unpack('%32N*', $msum); 

my (%whdr);
my (@tlist) = sort {$if->{$a}{' OFFSET'} <=> $if->{$b}{' OFFSET'}}
                    grep(length($_) == 4, keys %{$if});
my (@trmap) = sort {$tlist[$a] cmp $tlist[$b]} (0 .. $#tlist);
my ($t, @tmap);
foreach (@trmap) { $tmap[$_] = $t++; }
$whdr{'num'} = scalar @tlist;
$whdr{'total'} =  12 + $whdr{'num'} * 16;
if ($opts{'v'})
{
    ($whdr{'major'}, $whdr{'minor'}) = ($opts{v} =~ /(\d+)(?:\.(\d+))/);
}
out_whdr($ofh, \%whdr);
my ($curroffset) = align4($ofh, $ofh->tell());
for (my $i = 0; $i < $whdr{'num'}; $i++)
{
    my (%d);
    my ($n) = $tlist[$i];
    my ($t) = $if->{$n};
    my ($idat, $odat);
    my ($csum);

    $whdr{'dir'}[$tmap[$i]] = \%d;
    $whdr{'total'} += ($t->{' LENGTH'} + 3) & ~3;
    $d{'tag'} = $n;
    $d{'offset'} = $curroffset;
    $d{'orglen'} = $t->{' LENGTH'};
    $d{'csum'} = $t->{' CSUM'};
    if ($t->{' OFFSET'} & 3)
    { warn "table '$n' isn't long-aligned\n"; $cWarnings++;}
    $t->{' INFILE'}->seek($t->{' OFFSET'}, 0);
    $t->{' INFILE'}->read($idat, $t->{' LENGTH'});
    # Pad string and verify checksum:
    $odat = $idat;
    $odat .= substr("\000" x 4, $t->{' LENGTH'} & 3) if  $t->{' LENGTH'} & 3; 
    $csum = unpack('%32N*', $odat); 
    if ($n eq 'head')
    {



( run in 1.504 second using v1.01-cache-2.11-cpan-71847e10f99 )