<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">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&lt;(R)&gt;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-&gt;read

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

=cut

sub read
{
    my ($self) = @_;
    my ($fh) = $self-&gt;{' 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);

    $self-&gt;SUPER::read or return $self;

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

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

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

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

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

    for ($i = 0; $i &lt; $self-&gt;{'Num'}; $i++) {
        my ($count, $x);

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

        for ($j = 0; $j &lt; $bst-&gt;{'numberOfIndexSubTables'}; $j++) {
            $ista = {};

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

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

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

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

#           $count += 2 if $j &lt; $bst-&gt;{'numberOfIndexSubTables'} - 1;

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

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

    $self;
}

=head2 $t-&gt;out($fh)

Outputs the location information of embedded bitmap for this font.

=cut

sub out
{
    my ($self, $fh) = @_;
    my ($i);
    my ($bst_array) = $self-&gt;{'bitmapSizeTable'};

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

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

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

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

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

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

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

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

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

1;

=head1 BUGS

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

=head1 AUTHOR

NIIBE Yutaka L&lt;gniibe@fsij.org&gt;.  See L&lt;Font::TTF::Font&gt; for copyright and
licensing.

This was written at the CodeFest Akihabara 2006 hosted by FSIJ.

=cut

</pre></body></html>