312 lines
7.2 KiB
Perl
312 lines
7.2 KiB
Perl
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);
|
|
my ($i, $dat);
|
|
my ($eblc) = $self->{' PARENT'}->{'EBLC'};
|
|
my ($bst_array);
|
|
|
|
$eblc->read;
|
|
$self->SUPER::read || return $self;
|
|
$fh = $self->{' INFILE'};
|
|
|
|
# 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) = @_;
|
|
|
|
return $self->SUPER::out($fh) unless $self->{' read'};
|
|
|
|
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<mailto:gniibe@fsij.org>.
|
|
This was written at the CodeFest Akihabara 2006 hosted by FSIJ.
|
|
|
|
?? patch sent with licensing requirements or not?
|
|
|
|
|
|
=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
|
|
|