X-Git-Url: https://git.mdrn.pl/librarian.git/blobdiff_plain/ef7911fba9c330552599bc6eb9dc22606246dd7e..68b03397a0872d10d3627cea2b92ae36bd59183c:/font-optimizer/ext/Font-TTF/lib/Font/TTF/EBDT.pm?ds=sidebyside diff --git a/font-optimizer/ext/Font-TTF/lib/Font/TTF/EBDT.pm b/font-optimizer/ext/Font-TTF/lib/Font/TTF/EBDT.pm new file mode 100644 index 0000000..257e8d7 --- /dev/null +++ b/font-optimizer/ext/Font-TTF/lib/Font/TTF/EBDT.pm @@ -0,0 +1,285 @@ +package Font::TTF::EBDT; + +=head1 NAME + +Font::TTF::EBDT - Embeeded Bitmap Data Table + +=head1 DESCRIPTION + +Contains the metrics and bitmap image data. + +=head1 INSTANCE VARIABLES + +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. + +=over 4 + +=item bitmap object + +=over 8 +=item format +Only 7 is supported. +=item height +=item width +=item horiBearingX +=item horiBearingY +=item horiAdvance +=item vertBearingX +=item vertBearingY +=item vertAdvance +=item imageData + +=back + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + + +=head2 $t->read + +Reads the embedded bitmap data from the TTF file into memory. +This routine should be called _after_ {'EBLC'}->read. + +=cut + +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; +} + + +=head2 $t->update + +Update EBLC information using EBDT data. + +=cut + +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; + } +} + +=head2 $t->out($fh) + +Outputs the bitmap data of embedded bitmap for this font. + +=cut + +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; + +=head1 BUGS + +Only Format 7 is implemented. XML output is not supported (yet). + +=head1 AUTHOR + +NIIBE Yutaka L. See L for copyright and +licensing. + +This was written at the CodeFest Akihabara 2006 hosted by FSIJ. + +=cut +