almost done, kerning todo
[librarian.git] / librarian / font-optimizer / ext / Font-TTF / lib / Font / TTF / EBLC.pm
1 package Font::TTF::EBLC;
2
3 =head1 NAME
4
5 Font::TTF::EBLC - Embeeded Bitmap Location Table
6
7 =head1 DESCRIPTION
8
9 Contains the sizes and glyph ranges of bitmaps, and the offsets to
10 glyph bitmap data in indexSubTables for EBDT.
11
12 Possibly contains glyph metrics information.
13
14 =head1 INSTANCE VARIABLES
15 The information specified 'B<(R)>ead only' is read only, those
16 are calculated from EBDT, when it is 'update'-ed.
17
18 =over 4
19
20 =item bitmapSizeTable
21 An array of tables of following information
22
23 =over 8
24 =item indexSubTableArrayOffset (R)
25 =item indexTablesSize (R)
26 =item numberOfIndexSubTables (R)
27 =item colorRef
28 =item hori
29 =item vert
30 =item startGlyphIndex (R)
31 =item endGlyphIndex (R)
32 =item ppemX
33 =item ppemY
34 =item bitDepth
35 =item flags
36 =back
37
38 =item indexSubTableArray (R)
39 An array which contains range information.
40
41 =item indexSubTable (R)
42 An array which contains offsets of EBDT table.
43
44 =back
45
46 =head1 METHODS
47
48 =cut
49
50 use strict;
51 use vars qw(@ISA);
52 require Font::TTF::Table;
53
54 @ISA = qw(Font::TTF::Table);
55
56
57 =head2 $t->read
58
59 Reads the location information of embedded bitmap from the TTF file into memory
60
61 =cut
62
63 sub read
64 {
65     my ($self) = @_;
66     my ($fh) = $self->{' INFILE'};
67     my ($i, $dat);
68     my ($indexSubTableArrayOffset,
69         $indexTablesSize,
70         $numberOfIndexSubTables,
71         $colorRef);
72     my ($startGlyphIndex,
73         $endGlyphIndex,
74         $ppemX, $ppemY,
75         $bitDepth, $flags);
76     my (@hori, @vert);
77     my ($bst, $ista, $ist);
78     my ($j);
79
80     $self->SUPER::read or return $self;
81
82     # eblcHeader
83     $fh->read($dat, 4);
84     $self->{'version'} = unpack("N",$dat);
85
86     $fh->read($dat, 4);
87     $self->{'Num'} = unpack("N",$dat);
88
89     # bitmapSizeTable
90     for ($i = 0; $i < $self->{'Num'}; $i++) {
91         $fh->read($dat, 16);
92         ($indexSubTableArrayOffset, $indexTablesSize,
93          $numberOfIndexSubTables, $colorRef) = unpack("NNNN", $dat);
94         $fh->read($dat, 12); @hori = unpack("cccccccccccc", $dat);
95         $fh->read($dat, 12); @vert = unpack("cccccccccccc", $dat);
96
97         $fh->read($dat, 8);
98         ($startGlyphIndex, $endGlyphIndex,
99          $ppemX, $ppemY, $bitDepth, $flags) = unpack("nnCCCC", $dat);
100
101         $self->{'bitmapSizeTable'}[$i] = {
102             'indexSubTableArrayOffset' => $indexSubTableArrayOffset,
103             'indexTablesSize' => $indexTablesSize,
104             'numberOfIndexSubTables' => $numberOfIndexSubTables,
105             'colorRef' => $colorRef,
106             'hori' => [@hori],
107             'vert' => [@vert],
108             'startGlyphIndex' => $startGlyphIndex,
109             'endGlyphIndex' => $endGlyphIndex,
110             'ppemX' => $ppemX,
111             'ppemY' => $ppemY,
112             'bitDepth' => $bitDepth,
113             'flags' => $flags
114             };
115     }
116
117     for ($i = 0; $i < $self->{'Num'}; $i++) {
118         my ($count, $x);
119
120         $bst = $self->{'bitmapSizeTable'}[$i];
121
122         for ($j = 0; $j < $bst->{'numberOfIndexSubTables'}; $j++) {
123             $ista = {};
124
125             # indexSubTableArray
126             $self->{'indexSubTableArray'}[$i][$j] = $ista;
127             $fh->read($dat, 8);
128             ($ista->{'firstGlyphIndex'},
129              $ista->{'lastGlyphIndex'},
130              $ista->{'additionalOffsetToIndexSubtable'})
131                 = unpack("nnN", $dat);
132         }
133
134         # indexSubTable
135         # indexSubHeader
136         $fh->read($dat, 8);
137         ($bst->{'indexFormat'}, 
138          $bst->{'imageFormat'}, 
139          $bst->{'imageDataOffset'}) = unpack("nnN", $dat);
140
141         die "Only indexFormat == 1 is supported" unless ($bst->{'indexFormat'} == 1);
142
143         for ($j = 0; $j < $bst->{'numberOfIndexSubTables'}; $j++) {
144             $ista = $self->{'indexSubTableArray'}[$i][$j];
145             $count = $ista->{'lastGlyphIndex'} - $ista->{'firstGlyphIndex'} + 1 + 1;
146             $fh->seek($self->{' OFFSET'} + $bst->{'indexSubTableArrayOffset'}
147                       + $ista->{'additionalOffsetToIndexSubtable'} + 8, 0);
148
149 #           $count += 2 if $j < $bst->{'numberOfIndexSubTables'} - 1;
150
151             $fh->read($dat, 4*$count);
152
153             $self->{'indexSubTable'}[$i][$j] = [unpack("N*", $dat)];
154         }
155     }
156
157     $self;
158 }
159
160 =head2 $t->out($fh)
161
162 Outputs the location information of embedded bitmap for this font.
163
164 =cut
165
166 sub out
167 {
168     my ($self, $fh) = @_;
169     my ($i);
170     my ($bst_array) = $self->{'bitmapSizeTable'};
171
172     $fh->print(pack("N", 0x00020000));
173     $fh->print(pack("N", $self->{'Num'}));
174
175     for ($i = 0; $i < $self->{'Num'}; $i++) {
176         my ($bst) = $bst_array->[$i];
177
178         $fh->print(pack("NNNN", 
179                         $bst->{'indexSubTableArrayOffset'},
180                         $bst->{'indexTablesSize'},
181                         $bst->{'numberOfIndexSubTables'},
182                         $bst->{'colorRef'}));
183         $fh->print(pack("cccccccccccc", @{$bst->{'hori'}}));
184         $fh->print(pack("cccccccccccc", @{$bst->{'vert'}}));
185         $fh->print(pack("nnCCCC", $bst->{'startGlyphIndex'}, 
186                         $bst->{'endGlyphIndex'}, $bst->{'ppemX'},
187                         $bst->{'ppemY'}, $bst->{'bitDepth'}, $bst->{'flags'}));
188     }
189
190     for ($i = 0; $i < $self->{'Num'}; $i++) {
191         my ($bst) = $bst_array->[$i];
192         my ($j);
193
194         for ($j = 0; $j < $bst->{'numberOfIndexSubTables'}; $j++) {
195             my ($ista) = $self->{'indexSubTableArray'}[$i][$j];
196
197             $fh->print("nnN",
198                        $ista->{'firstGlyphIndex'},
199                        $ista->{'lastGlyphIndex'},
200                        $ista->{'additionalOffsetToIndexSubtable'});
201         }
202
203         $fh->print(pack("nnN", $bst->{'indexFormat'}, $bst->{'imageFormat'}, 
204                         $bst->{'imageDataOffset'}));
205
206         die "Only indexFormat == 1 is supported" unless ($bst->{'indexFormat'} == 1);
207
208         for ($j = 0; $j < $bst->{'numberOfIndexSubTables'}; $j++) {
209             $fh->print(pack("N*", $self->{'indexSubTable'}[$i][$j]));
210         }
211     }
212 }
213
214 1;
215
216 =head1 BUGS
217
218 Only indexFormat ==1 is implemented.  XML output is not supported (yet).
219
220 =head1 AUTHOR
221
222 NIIBE Yutaka L<gniibe@fsij.org>.  See L<Font::TTF::Font> for copyright and
223 licensing.
224
225 This was written at the CodeFest Akihabara 2006 hosted by FSIJ.
226
227 =cut
228