1 package Font::TTF::OldCmap;
5 Font::TTF::OldCmap - Character map table
7 This module is deprecated
11 Looks after the character map. The primary structure used for handling a cmap
12 is the L<Font::TTF::Segarr> which handles the segmented arrays of format 4 tables,
13 and in a simpler form for format 0 tables.
15 Due to the complexity of working with segmented arrays, most of the handling of
16 such arrays is via methods rather than via instance variables.
18 One important feature of a format 4 table is that it always contains a segment
19 with a final address of 0xFFFF. If you are creating a table from scratch this is
20 important (although L<Font::TTF::Segarr> can work quite happily without it).
23 =head1 INSTANCE VARIABLES
25 The instance variables listed here are not preceeded by a space due to their
26 emulating structural information in the font.
32 Number of subtables in this table
36 An array of subtables ([0..Num-1])
40 Each subtables also has its own instance variables which are, again, not
47 The platform number for this subtable
51 The encoding number for this subtable
55 Gives the stored format of this subtable
59 Gives the version (or language) information for this subtable
63 This points to a L<Font::TTF::Segarr> which contains the content of the particular
74 require Font::TTF::Table;
75 require Font::TTF::Segarr;
77 @ISA = qw(Font::TTF::Table);
82 Reads the cmap into memory. Format 4 subtables read the whole subtable and
83 fill in the segmented array accordingly.
85 Format 2 subtables are not read at all.
92 my ($dat, $i, $j, $k, $id, @ids, $s);
93 my ($start, $end, $range, $delta, $form, $len, $num, $ver);
94 my ($fh) = $self->{' INFILE'};
96 $self->SUPER::read or return $self;
98 $self->{'Num'} = unpack("x2n", $dat);
99 $self->{'Tables'} = [];
100 for ($i = 0; $i < $self->{'Num'}; $i++)
104 ($s->{'Platform'}, $s->{'Encoding'}, $s->{'LOC'}) = (unpack("nnN", $dat));
105 $s->{'LOC'} += $self->{' OFFSET'};
106 push(@{$self->{'Tables'}}, $s);
108 for ($i = 0; $i < $self->{'Num'}; $i++)
110 $s = $self->{'Tables'}[$i];
111 $fh->seek($s->{'LOC'}, 0);
113 ($form, $len, $ver) = (unpack("n3", $dat));
115 $s->{'Format'} = $form;
119 $s->{'val'} = Font::TTF::Segarr->new;
120 $fh->read($dat, 256);
121 $s->{'val'}->fastadd_segment(0, 2, unpack("C*", $dat));
126 my ($start, $ecount);
129 ($start, $ecount) = unpack("n2", $dat);
130 $fh->read($dat, $ecount << 1);
131 $s->{'val'} = Font::TTF::Segarr->new;
132 $s->{'val'}->fastadd_segment($start, 2, unpack("n*", $dat));
133 $s->{'Start'} = $start;
134 $s->{'Num'} = $ecount;
137 # no idea what to do here yet
141 $num = unpack("n", $dat);
143 $fh->read($dat, $len - 14);
144 $s->{'val'} = Font::TTF::Segarr->new;
145 for ($j = 0; $j < $num; $j++)
147 $end = unpack("n", substr($dat, $j << 1, 2));
148 $start = unpack("n", substr($dat, ($j << 1) + ($num << 1) + 2, 2));
149 $delta = unpack("n", substr($dat, ($j << 1) + ($num << 2) + 2, 2));
150 $delta -= 65536 if $delta > 32767;
151 $range = unpack("n", substr($dat, ($j << 1) + $num * 6 + 2, 2));
153 for ($k = $start; $k <= $end; $k++)
156 { $id = $k + $delta; }
158 { $id = unpack("n", substr($dat, ($j << 1) + $num * 6 +
159 2 + ($k - $start) * 2 + $range, 2)) + $delta; }
160 $id -= 65536 if $id > 65536;
163 $s->{'val'}->fastadd_segment($start, 0, @ids);
166 $s->{'Num'} = 0x10000; # always ends here
167 $s->{'Start'} = $s->{'val'}[0]{'START'};
174 =head2 $t->ms_lookup($uni)
176 Given a Unicode value in the MS table (Platform 3, Encoding 1) locates that
177 table and looks up the appropriate glyph number from it.
183 my ($self, $uni) = @_;
185 $self->find_ms || return undef unless (defined $self->{' mstable'});
186 return $self->{' mstable'}{'val'}->at($uni);
192 Finds the Microsoft Unicode table and sets the C<mstable> instance variable
193 to it if found. Returns the table it finds.
201 return $self->{' mstable'} if defined $self->{' mstable'};
203 for ($i = 0; $i < $self->{'Num'}; $i++)
205 $s = $self->{'Tables'}[$i];
206 if ($s->{'Platform'} == 3)
208 $self->{' mstable'} = $s;
209 last if ($s->{'Encoding'} == 1);
210 } elsif ($s->{'Platform'} == 0 || ($s->{'Platform'} == 2 && $s->{'Encoding'} == 1))
211 { $self->{' mstable'} = $s; }
219 Writes out a cmap table to a filehandle. If it has not been read, then
220 just copies from input file to output
226 my ($self, $fh) = @_;
227 my ($loc, $s, $i, $base_loc, $j);
229 return $self->SUPER::out($fh) unless $self->{' read'};
231 $base_loc = $fh->tell();
232 $fh->print(pack("n2", 0, $self->{'Num'}));
234 for ($i = 0; $i < $self->{'Num'}; $i++)
235 { $fh->print(pack("nnN", $self->{'Tables'}[$i]{'Platform'}, $self->{'Tables'}[$i]{'Encoding'}, 0)); }
237 for ($i = 0; $i < $self->{'Num'}; $i++)
239 $s = $self->{'Tables'}[$i];
241 $s->{' outloc'} = $fh->tell();
242 $fh->print(pack("n3", $s->{'Format'}, 0, $s->{'Ver'})); # come back for length
243 if ($s->{'Format'} == 0)
245 $fh->print(pack("C256", $s->{'val'}->at(0, 256)));
246 } elsif ($s->{'Format'} == 6)
248 $fh->print(pack("n2", $s->{'Start'}, $s->{'Num'}));
249 $fh->print(pack("n*", $s->{'val'}->at($s->{'Start'}, $s->{'Num'})));
250 } elsif ($s->{'Format'} == 2)
252 } elsif ($s->{'Format'} == 4)
254 my ($num, $sRange, $eSel);
255 my (@deltas, $delta, @range, $flat, $k, $segs, $count);
257 $num = $#{$s->{'val'}} + 1;
259 for ($sRange = 1, $eSel = 0; $sRange <= $num; $eSel++)
262 $fh->print(pack("n4", $num * 2, $sRange, $eSel, ($num * 2) - $sRange));
263 $fh->print(pack("n*", map {$_->{'START'} + $_->{'LEN'} - 1} @$segs));
264 $fh->print(pack("n", 0));
265 $fh->print(pack("n*", map {$_->{'START'}} @$segs));
267 for ($j = 0; $j < $num; $j++)
269 $delta = $segs->[$j]{'VAL'}[0]; $flat = 1;
270 for ($k = 1; $k < $segs->[$j]{'LEN'}; $k++)
272 if ($segs->[$j]{'VAL'}[$k] == 0)
274 if ($delta + $k != $segs->[$j]{'VAL'}[$k])
280 push (@range, $flat);
281 push (@deltas, ($delta ? $delta - $segs->[$j]{'START'} : 0));
283 $fh->print(pack("n*", @deltas));
286 for ($j = 0; $j < $num; $j++)
288 $delta = $deltas[$j];
289 if ($delta != 0 && $range[$j] == 1)
293 $range[$j] = ($count + $num - $j) << 1;
294 $count += $segs->[$j]{'LEN'};
298 $fh->print(pack("n*", @range));
300 for ($j = 0; $j < $num; $j++)
302 next if ($range[$j] == 0);
303 for ($k = 0; $k < $segs->[$j]{'LEN'}; $k++)
304 { $fh->print(pack("n", $segs->[$j]{'VAL'}[$k])); }
309 $fh->seek($s->{' outloc'} + 2, 0);
310 $fh->print(pack("n", $loc - $s->{' outloc'}));
311 $fh->seek($base_loc + 8 + ($i << 3), 0);
312 $fh->print(pack("N", $s->{' outloc'} - $base_loc));
319 =head2 @map = $t->reverse([$num])
321 Returns a reverse map of the table of given number or the Microsoft
322 cmap. I.e. given a glyph gives the Unicode value for it.
328 my ($self, $tnum) = @_;
329 my ($table) = defined $tnum ? $self->{'Tables'}[$tnum] : $self->find_ms;
330 my (@res, $i, $s, $first);
332 foreach $s (@{$table->{'val'}})
334 $first = $s->{'START'};
335 map {$res[$_] = $first unless $res[$_]; $first++;} @{$s->{'VAL'}};
348 No support for format 2 tables (MBCS)
354 Martin Hosken Martin_Hosken@sil.org. See L<Font::TTF::Font> for copyright and