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. 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