File Coverage

blib/lib/Font/TTF/Loca.pm
Criterion Covered Total %
statement 47 49 95.9
branch 20 32 62.5
condition 3 4 75.0
subroutine 6 7 85.7
pod 5 5 100.0
total 81 97 83.5


line stmt bran cond sub pod time code
1             package Font::TTF::Loca;
2              
3             =head1 NAME
4              
5             Font::TTF::Loca - the Locations table, which is intimately tied to the glyf table
6              
7             =head1 DESCRIPTION
8              
9             The location table holds the directory of locations of each glyph within the
10             glyf table. Due to this relationship and the unimportance of the actual locations
11             when it comes to holding glyphs in memory, reading the location table results
12             in the creation of glyph objects for each glyph and stores them here.
13             So if you are looking for glyphs, do not look in the C table, look here
14             instead.
15              
16             Things get complicated if you try to change the glyph list within the one table.
17             The recommendation is to create another clean location object to replace this
18             table in the font, ensuring that the old table is read first and to transfer
19             or copy glyphs across from the read table to the new table.
20              
21             =head1 INSTANCE VARIABLES
22              
23             The instance variables do not start with a space
24              
25             =over 4
26              
27             =item glyphs
28              
29             An array of glyph objects for each glyph.
30              
31             =item glyphtype
32              
33             A string containing the class name to create for each new glyph. If empty,
34             defaults to L.
35              
36             =back
37              
38             =head1 METHODS
39              
40             =cut
41              
42 1     1   4 use strict;
  1         1  
  1         31  
43 1     1   3 use vars qw(@ISA);
  1         1  
  1         590  
44             @ISA = qw(Font::TTF::Table);
45              
46             require Font::TTF::Glyph;
47              
48              
49             =head2 $t->new
50              
51             Creates a new location table making sure it has a glyphs array
52              
53             =cut
54              
55             sub new
56             {
57 2     2 1 5 my ($class) = shift;
58 2         13 my ($res) = $class->SUPER::new(@_);
59 2         14 $res->{'glyphs'} = [];
60 2         11 $res;
61             }
62              
63             =head2 $t->read
64              
65             Reads the location table creating glyph objects (L) for each glyph
66             allowing their later reading.
67              
68             =cut
69              
70             sub read
71             {
72 4     4 1 15 my ($self) = @_;
73              
74             # Do this before $self->SUPER::read because this can alter the file pointer:
75 4         19 my ($glyfLoc) = $self->{' PARENT'}{'glyf'}->_read->{' OFFSET'}; # May seek on $fh!
76              
77 4 100       19 $self->SUPER::read or return $self;
78              
79 2         5 my ($fh) = $self->{' INFILE'};
80 2         8 my ($locFmt) = $self->{' PARENT'}{'head'}{'indexToLocFormat'};
81 2         6 my ($numGlyphs) = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
82 2         3 my ($dat, $last, $i, $loc);
83              
84 2 50       16 $fh->read($dat, $locFmt ? 4 : 2);
85 2 50       29 $last = unpack($locFmt ? "N" : "n", $dat);
86 2         8 for ($i = 0; $i < $numGlyphs; $i++)
87             {
88 196 50       525 $fh->read($dat, $locFmt ? 4 : 2);
89 196 50       993 $loc = unpack($locFmt ? "N" : "n", $dat);
90 196 50 50     1620 $self->{'glyphs'}[$i] = ($self->{'glyphtype'} || "Font::TTF::Glyph")->new(
    50          
    50          
    50          
    100          
91             LOC => $last << ($locFmt ? 0 : 1),
92             OUTLOC => $last << ($locFmt ? 0 : 1),
93             PARENT => $self->{' PARENT'},
94             INFILE => $self->{' PARENT'}{'glyf'}{' INFILE'},
95             BASE => $glyfLoc,
96             OUTLEN => ($loc - $last) << ($locFmt ? 0 : 1),
97             LEN => ($loc - $last) << ($locFmt ? 0 : 1)) if ($loc != $last);
98 196         435 $last = $loc;
99             }
100 2         7 $self;
101             }
102              
103              
104             =head2 $t->out($fh)
105              
106             Writes the location table out to $fh. Notice that not having read the location
107             table implies that the glyf table has not been read either, so the numbers in
108             the location table are still valid. Let's hope that C and
109             C haven't changed otherwise we are in big trouble.
110              
111             The function uses the OUTLOC location in the glyph calculated when the glyf
112             table was attempted to be output.
113              
114             =cut
115              
116             sub out
117             {
118 2     2 1 4 my ($self, $fh) = @_;
119 2         8 my ($locFmt) = $self->{' PARENT'}{'head'}{'indexToLocFormat'};
120 2         7 my ($numGlyphs) = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
121 2         3 my ($count, $i, $offset, $g);
122              
123 2 50       8 return $self->SUPER::out($fh) unless ($self->{' read'});
124              
125 2         4 $count = 0;
126 2         8 for ($i = 0; $i < $numGlyphs; $i++)
127             {
128 196   100     415 $g = ($self->{'glyphs'}[$i]) || "";
129 196 100       276 unless ($g)
130             {
131 8         9 $count++;
132 8         13 next;
133             } else
134             {
135 188 50       236 if ($locFmt)
136 0         0 { $fh->print(pack("N", $g->{' OUTLOC'}) x ($count + 1)); }
137             else
138 188         737 { $fh->print(pack("n", $g->{' OUTLOC'} >> 1) x ($count + 1)); }
139 188         814 $count = 0;
140 188         510 $offset = $g->{' OUTLOC'} + $g->{' OUTLEN'};
141             }
142             }
143 2 50       42 $fh->print(pack($locFmt ? "N" : "n", ($locFmt ? $offset: $offset >> 1)) x ($count + 1));
    50          
144             }
145              
146              
147             =head2 $t->out_xml($context, $depth)
148              
149             No need to output a loca table, this is dynamically generated
150              
151             =cut
152              
153             sub out_xml
154 0     0 1 0 { return $_[0]; }
155              
156              
157             =head2 $t->glyphs_do(&func)
158              
159             Calls func for each glyph in this location table in numerical order:
160              
161             &func($glyph, $glyph_num)
162              
163             =cut
164              
165             sub glyphs_do
166             {
167 2     2 1 28 my ($self, $func) = @_;
168 2         2 my ($i);
169              
170 2         4 for ($i = 0; $i <= $#{$self->{'glyphs'}}; $i++)
  198         516  
171 196 100       756 { &$func($self->{'glyphs'}[$i], $i) if defined $self->{'glyphs'}[$i]; }
172 2         7 $self;
173             }
174              
175             1;
176              
177             =head1 BUGS
178              
179             None known
180              
181             =head1 AUTHOR
182              
183             Martin Hosken L.
184              
185              
186             =head1 LICENSING
187              
188             Copyright (c) 1998-2014, SIL International (http://www.sil.org)
189              
190             This module is released under the terms of the Artistic License 2.0.
191             For details, see the full text of the license in the file LICENSE.
192              
193              
194              
195             =cut
196              
197