The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package Font::TTF::EBLC;

=head1 NAME

Font::TTF::EBLC - Embeeded Bitmap Location Table

=head1 DESCRIPTION

Contains the sizes and glyph ranges of bitmaps, and the offsets to
glyph bitmap data in indexSubTables for EBDT.

Possibly contains glyph metrics information.

=head1 INSTANCE VARIABLES

The information specified 'B<(R)>ead only' is read only, those
are calculated from EBDT, when it is 'update'-ed.

=over 4

=item bitmapSizeTable

An array of tables of following information

=over 8

=item indexSubTableArrayOffset (R)

=item indexTablesSize (R)

=item numberOfIndexSubTables (R)

=item colorRef

=item hori

=item vert

=item startGlyphIndex (R)

=item endGlyphIndex (R)

=item ppemX

=item ppemY

=item bitDepth

=item flags

=back

=item indexSubTableArray (R)

An array which contains range information.

=item indexSubTable (R)

An array which contains offsets of EBDT table.

=back

=head1 METHODS

=cut

use strict;
use vars qw(@ISA);
require Font::TTF::Table;

@ISA = qw(Font::TTF::Table);


=head2 $t->read

Reads the location information of embedded bitmap from the TTF file into memory

=cut

sub read
{
    my ($self) = @_;

    $self->SUPER::read or return $self;

    my ($fh) = $self->{' INFILE'};
    my ($i, $dat);
    my ($indexSubTableArrayOffset,
        $indexTablesSize,
        $numberOfIndexSubTables,
        $colorRef);
    my ($startGlyphIndex,
        $endGlyphIndex,
        $ppemX, $ppemY,
        $bitDepth, $flags);
    my (@hori, @vert);
    my ($bst, $ista, $ist);
    my ($j);


    # eblcHeader
    $fh->read($dat, 4);
    $self->{'version'} = unpack("N",$dat);

    $fh->read($dat, 4);
    $self->{'Num'} = unpack("N",$dat);

    # bitmapSizeTable
    for ($i = 0; $i < $self->{'Num'}; $i++) {
        $fh->read($dat, 16);
        ($indexSubTableArrayOffset, $indexTablesSize,
         $numberOfIndexSubTables, $colorRef) = unpack("NNNN", $dat);
        $fh->read($dat, 12); @hori = unpack("cccccccccccc", $dat);
        $fh->read($dat, 12); @vert = unpack("cccccccccccc", $dat);

        $fh->read($dat, 8);
        ($startGlyphIndex, $endGlyphIndex,
         $ppemX, $ppemY, $bitDepth, $flags) = unpack("nnCCCC", $dat);

        $self->{'bitmapSizeTable'}[$i] = {
            'indexSubTableArrayOffset' => $indexSubTableArrayOffset,
            'indexTablesSize' => $indexTablesSize,
            'numberOfIndexSubTables' => $numberOfIndexSubTables,
            'colorRef' => $colorRef,
            'hori' => [@hori],
            'vert' => [@vert],
            'startGlyphIndex' => $startGlyphIndex,
            'endGlyphIndex' => $endGlyphIndex,
            'ppemX' => $ppemX,
            'ppemY' => $ppemY,
            'bitDepth' => $bitDepth,
            'flags' => $flags
            };
    }

    for ($i = 0; $i < $self->{'Num'}; $i++) {
        my ($count, $x);

        $bst = $self->{'bitmapSizeTable'}[$i];

        for ($j = 0; $j < $bst->{'numberOfIndexSubTables'}; $j++) {
            $ista = {};

            # indexSubTableArray
            $self->{'indexSubTableArray'}[$i][$j] = $ista;
            $fh->read($dat, 8);
            ($ista->{'firstGlyphIndex'},
             $ista->{'lastGlyphIndex'},
             $ista->{'additionalOffsetToIndexSubtable'})
                = unpack("nnN", $dat);
        }

        # indexSubTable
        # indexSubHeader
        $fh->read($dat, 8);
        ($bst->{'indexFormat'}, 
         $bst->{'imageFormat'}, 
         $bst->{'imageDataOffset'}) = unpack("nnN", $dat);

        die "Only indexFormat == 1 is supported" unless ($bst->{'indexFormat'} == 1);

        for ($j = 0; $j < $bst->{'numberOfIndexSubTables'}; $j++) {
            $ista = $self->{'indexSubTableArray'}[$i][$j];
            $count = $ista->{'lastGlyphIndex'} - $ista->{'firstGlyphIndex'} + 1 + 1;
            $fh->seek($self->{' OFFSET'} + $bst->{'indexSubTableArrayOffset'}
                      + $ista->{'additionalOffsetToIndexSubtable'} + 8, 0);

#           $count += 2 if $j < $bst->{'numberOfIndexSubTables'} - 1;

            $fh->read($dat, 4*$count);

            $self->{'indexSubTable'}[$i][$j] = [unpack("N*", $dat)];
        }
    }

    $self;
}

=head2 $t->out($fh)

Outputs the location information of embedded bitmap for this font.

=cut

sub out
{
    my ($self, $fh) = @_;
    my ($i);

    return $self->SUPER::out($fh) unless $self->{' read'};

    my ($bst_array) = $self->{'bitmapSizeTable'};

    $fh->print(pack("N", 0x00020000));
    $fh->print(pack("N", $self->{'Num'}));

    for ($i = 0; $i < $self->{'Num'}; $i++) {
        my ($bst) = $bst_array->[$i];

        $fh->print(pack("NNNN", 
                        $bst->{'indexSubTableArrayOffset'},
                        $bst->{'indexTablesSize'},
                        $bst->{'numberOfIndexSubTables'},
                        $bst->{'colorRef'}));
        $fh->print(pack("cccccccccccc", @{$bst->{'hori'}}));
        $fh->print(pack("cccccccccccc", @{$bst->{'vert'}}));
        $fh->print(pack("nnCCCC", $bst->{'startGlyphIndex'}, 
                        $bst->{'endGlyphIndex'}, $bst->{'ppemX'},
                        $bst->{'ppemY'}, $bst->{'bitDepth'}, $bst->{'flags'}));
    }

    for ($i = 0; $i < $self->{'Num'}; $i++) {
        my ($bst) = $bst_array->[$i];
        my ($j);

        for ($j = 0; $j < $bst->{'numberOfIndexSubTables'}; $j++) {
            my ($ista) = $self->{'indexSubTableArray'}[$i][$j];

            $fh->print("nnN",
                       $ista->{'firstGlyphIndex'},
                       $ista->{'lastGlyphIndex'},
                       $ista->{'additionalOffsetToIndexSubtable'});
        }

        $fh->print(pack("nnN", $bst->{'indexFormat'}, $bst->{'imageFormat'}, 
                        $bst->{'imageDataOffset'}));

        die "Only indexFormat == 1 is supported" unless ($bst->{'indexFormat'} == 1);

        for ($j = 0; $j < $bst->{'numberOfIndexSubTables'}; $j++) {
            $fh->print(pack("N*", $self->{'indexSubTable'}[$i][$j]));
        }
    }
}

1;

=head1 BUGS

Only indexFormat ==1 is implemented.  XML output is not supported (yet).

=head1 AUTHOR

NIIBE Yutaka L<mailto:gniibe@fsij.org>.  
This was written at the CodeFest Akihabara 2006 hosted by FSIJ.

Patch sent with licensing requirements??

=head1 LICENSING

Copyright (c) 1998-2016, SIL International (http://www.sil.org) 

This module is released under the terms of the Artistic License 2.0. 
For details, see the full text of the license in the file LICENSE.



=cut