Font::TTF::EBDT - Embeeded Bitmap Data Table


Font-TTF documentation Contained in the Font-TTF distribution.

Index


Code Index:

NAME

Top

Font::TTF::EBDT - Embeeded Bitmap Data Table

DESCRIPTION

Top

Contains the metrics and bitmap image data.

INSTANCE VARIABLES

Top

Only has 'bitmap' instance variable. It is an array of assosiative array keyed by glyph-id. The element is an object which consists of metric information and image data.

bitmap object

METHODS

Top

$t->read

Reads the embedded bitmap data from the TTF file into memory. This routine should be called _after_ {'EBLC'}->read.

$t->update

Update EBLC information using EBDT data.

$t->out($fh)

Outputs the bitmap data of embedded bitmap for this font.

BUGS

Top

Only Format 7 is implemented. XML output is not supported (yet).

AUTHOR

Top

NIIBE Yutaka gniibe@fsij.org. See Font::TTF::Font for copyright and licensing.

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


Font-TTF documentation Contained in the Font-TTF distribution.
package Font::TTF::EBDT;

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

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


sub read
{
    my ($self) = shift;
    my ($fh) = $self->{' INFILE'};
    my ($i, $dat);
    my ($eblc) = $self->{' PARENT'}->{'EBLC'};
    my ($bst_array);

    $eblc->read;
    $self->SUPER::read || return $self;

    # ebdtHeader
    $fh->read($dat, 4);	# version

    $bst_array = $eblc->{'bitmapSizeTable'};

    for ($i = 0; $i < $eblc->{'Num'}; $i++)
    {
        my ($bst) = $bst_array->[$i];
        my ($format) = $bst->{'imageFormat'};
        my ($offset) = $bst->{'imageDataOffset'};
        my ($j);
        my ($ist_array) = $eblc->{'indexSubTableArray'}[$i];
        my ($bitmap) = {};

        die "Only EBDT format 7 is implemented." unless  ($format == 7);

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

        for ($j = 0; $j < $bst->{'numberOfIndexSubTables'}; $j++) {
            my ($ista) = $ist_array->[$j];
            my ($offsetArray) = $eblc->{'indexSubTable'}[$i][$j];
            my ($p, $o0, $c);

#           if ($fh->tell != $self->{' OFFSET'} + $offset) {
#               $fh->seek($self->{' OFFSET'} + $offset, 0);
#           }

            $p = 0;
            $o0 = $offsetArray->[$p++];
            for ($c = $ista->{'firstGlyphIndex'}; $c <= $ista->{'lastGlyphIndex'}; $c++)
            {
                my ($b) = {};
                my ($o1) = $offsetArray->[$p++];
                my ($len) = $o1 - $o0 - 8;

#               if ($fh->tell != $self->{' OFFSET'} + $offset + $o0) {
#                   $fh->seek($self->{' OFFSET'} + $offset + $o0, 0);
#               }

                $fh->read($dat, 8);
                ($b->{'height'},
                 $b->{'width'},
                 $b->{'horiBearingX'},
                 $b->{'horiBearingY'},
                 $b->{'horiAdvance'},
                 $b->{'vertBearingX'},
                 $b->{'vertBearingY'},
                 $b->{'vertAdvance'})
                    = unpack("cccccccc", $dat);

                $fh->read($dat, $len);
                $b->{'imageData'} = $dat;
                $b->{'format'} = 7; # bitmap and bigMetrics

                $bitmap->{$c} = $b;
                $o0 = $o1;
            }

            $offset += $o0;
        }
    }

    $self;
}


sub get_regions
{
    my (@l) = @_;
    my (@r) = ();
    my ($e);
    my ($first);
    my ($last);

    $first = $l[0];
    $last = $first - 1;
    foreach $e (@l) {
        if ($last + 1 != $e) {	# not contiguous
            $r[++$#r] = [$first, $last];
            $first = $e;
        }

        $last = $e;
    }

    $r[++$#r] = [$first, $last];
    @r;
}

sub update
{
    my ($self) = @_;
    my ($eblc) = $self->{' PARENT'}->{'EBLC'};
    my ($bst_array) = [];
    my ($offset) = 4;
    my ($i);
    my ($bitmap_array) = $self->{'bitmap'};
    my ($istao) = 8 + 48 * $eblc->{'Num'};

    $eblc->{'bitmapSizeTable'} = $bst_array;

    for ($i = 0; $i < $eblc->{'Num'}; $i++) {
        my ($bst) = {};
        my ($ist_array) = [];
        my ($j);
        my ($bitmap) = $bitmap_array->[$i];
        my (@regions) = get_regions(sort {$a <=> $b} keys (%$bitmap));
        my ($aotis) = 8 * (1+$#regions);

        $bst->{'indexFormat'} = 1;
        $bst->{'imageFormat'} = 7;
        $bst->{'imageDataOffset'} = $offset;
        $bst->{'numberOfIndexSubTables'} = 1+$#regions;
        $bst->{'indexSubTableArrayOffset'} = $istao;
        $bst->{'colorRef'} = 0;

        $bst->{'startGlyphIndex'} = $regions[0][0];
        $bst->{'endGlyphIndex'} = $regions[-1][1];
        $bst->{'bitDepth'} = 1;
        $bst->{'flags'} = 1;	# Horizontal
        $bst_array->[$i] = $bst;

        $eblc->{'indexSubTableArray'}[$i] = $ist_array;
        for ($j = 0; $j <= $#regions; $j++) {
            my ($ista) = {};
            my ($offsetArray) = [];
            my ($p, $o0, $c);
            $ist_array->[$j] = $ista;

            $ista->{'firstGlyphIndex'} = $regions[$j][0];
            $ista->{'lastGlyphIndex'} = $regions[$j][1];
            $ista->{'additionalOffsetToIndexSubtable'} = $aotis;
            $eblc->{'indexSubTable'}[$i][$j] = $offsetArray;
            $p = 0;
            $o0 = 0;
            for ($c = $regions[$j][0]; $c <= $regions[$j][1]; $c++) {
                my ($b) = $bitmap->{$c};

                $offsetArray->[$p++] = $o0;
                $o0 += 8 + length($b->{'imageData'});
            }

            $offsetArray->[$p++] = $o0;

            $aotis += ($regions[$j][1] - $regions[$j][0] + 1 + 1)*4;
            $offset += $o0;

            # Do we need the element of 0x10007 and absolute offset here,
            # at the end of offsetArray?
#               if ($j + 1 <= $#regions) {
#       	$offsetArray->[$p++] = 0x10007;
#       	$offsetArray->[$p++] = $offset;
#       	$aotis += 8;
#           }
        }

        $istao += $aotis + 8;
        $bst->{'indexTablesSize'} = $aotis + 8;
    }
}

sub out
{
    my ($self, $fh) = @_;
    my ($eblc) = $self->{' PARENT'}->{'EBLC'};
    my ($i);
    my ($bitmap_array) = $self->{'bitmap'};

    $fh->print(pack("N", 0x00020000));

    for ($i = 0; $i < $eblc->{'Num'}; $i++) {
        my ($j);
        my ($bitmap) = $bitmap_array->[$i];
        my (@regions) = get_regions(sort {$a <=> $b} keys (%$bitmap));

        for ($j = 0; $j <= $#regions; $j++) {
            my ($c);

            for ($c = $regions[$j][0]; $c <= $regions[$j][1]; $c++) {
                my ($b) = $bitmap->{$c};

                $fh->print(pack("cccccccc",
                                $b->{'height'}, $b->{'width'},
                                $b->{'horiBearingX'}, $b->{'horiBearingY'},
                                $b->{'horiAdvance'}, $b->{'vertBearingX'},
                                $b->{'vertBearingY'}, $b->{'vertAdvance'}));
                $fh->print($b->{'imageData'});
            }
        }
    }
}

1;