| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Font::TTF::Glyph; |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
Font::TTF::Glyph - Holds a information for a single glyph |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
This is a single glyph description as held in a TT font. On creation only its |
|
10
|
|
|
|
|
|
|
header is read. Thus you can get the bounding box of each glyph without having |
|
11
|
|
|
|
|
|
|
to read all the other information. |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 INSTANCE VARIABLES |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
In addition to the named variables in a glyph header (C etc.), there are |
|
16
|
|
|
|
|
|
|
also all capital instance variables for holding working information, mostly |
|
17
|
|
|
|
|
|
|
from the location table. |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=head2 Variables for all glyphs: |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
The standard attributes each glyph has are: |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=over 4 |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
=item numberOfContours |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
For simple glyphs this will be the count of contours. For compound glyphs this will be -1. |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
=item xMin |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
=item yMin |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
=item xMax |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=item yMax |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
These identify the bounding box of the glyph. |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
=back |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
There are also other, derived, instance variables for each glyph which are read |
|
42
|
|
|
|
|
|
|
when the whole glyph is read (via C): |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=over 4 |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=item instLen |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
Number of bytes in the hinting instructions (Warning this variable is deprecated, |
|
49
|
|
|
|
|
|
|
use C{'hints'})> instead). |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=item hints |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
The string containing the hinting code for the glyph |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=back |
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
=head2 Variables for simple glyphs (numberOfContours E= 0): |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=over 4 |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
=item endPoints |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
An array of endpoints for each contour in the glyph. There are |
|
64
|
|
|
|
|
|
|
C contours in a glyph. The number of points in a glyph is |
|
65
|
|
|
|
|
|
|
equal to the highest endpoint of a contour. |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=item numPoints |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
This is a generated value which contains the total number of points for this simple glyph. |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=back |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
There are also a number of arrays indexed by point number: |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=over 4 |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
=item flags |
|
78
|
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
The flags associated with reading this point. The flags for a point are |
|
80
|
|
|
|
|
|
|
recalculated for a point when it is Cd. Thus the flags are not very |
|
81
|
|
|
|
|
|
|
useful. The only important bit is bit 0 which indicates whether the point is |
|
82
|
|
|
|
|
|
|
an 'on' curve point, or an 'off' curve point. |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
=item x |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
The absolute x co-ordinate of the point. |
|
87
|
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
=item y |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
The absolute y co-ordinate of the point |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=back |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
=head2 Variables for compound glyphs (numberOfContours == -1): |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=over 4 |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=item metric |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
This holds the component number (not its glyph number) of the component from |
|
101
|
|
|
|
|
|
|
which the metrics for this glyph should be taken. |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=item comps |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
This is an array of hashes for each component. Each hash has a number of |
|
106
|
|
|
|
|
|
|
elements: |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
=over 4 |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
=item glyph |
|
111
|
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
The glyph number of the glyph which comprises this component of the composite. |
|
113
|
|
|
|
|
|
|
NOTE: In some badly generated fonts, C may contain a numerical value |
|
114
|
|
|
|
|
|
|
but that glyph might not actually exist in the font file. This could |
|
115
|
|
|
|
|
|
|
occur in any glyph, but is particularly likely for glyphs that have |
|
116
|
|
|
|
|
|
|
no strokes, such as SPACE, U+00A0 NO-BREAK SPACE, or |
|
117
|
|
|
|
|
|
|
U+200B ZERO WIDTH SPACE. |
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=item args |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
An array of two arguments which may be an x, y co-ordinate or two attachment |
|
122
|
|
|
|
|
|
|
points (one on the base glyph the other on the component). See flags for details. |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=item flag |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
The flag for this component |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
=item scale |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
A 4 number array for component scaling. This allows stretching, rotating, etc. |
|
131
|
|
|
|
|
|
|
Note that scaling applies to placement co-ordinates (rather than attachment points) |
|
132
|
|
|
|
|
|
|
before locating rather than after. |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=back |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=item numPoints |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
This is a generated value which contains the number of components read in for this |
|
139
|
|
|
|
|
|
|
compound glyph. |
|
140
|
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=back |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
=head2 Private instance variables: |
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
=over 4 |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=item INFILE (P) |
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
The input file form which to read any information |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=item LOC (P) |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
Location relative to the start of the glyf table in the read file |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=item BASE (P) |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
The location of the glyf table in the read file |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=item LEN (P) |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
This is the number of bytes required by the glyph. It should be kept up to date |
|
162
|
|
|
|
|
|
|
by calling the C method whenever any of the glyph content changes. |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
=item OUTLOC (P) |
|
165
|
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
Location relative to the start of the glyf table. This variable is only active |
|
167
|
|
|
|
|
|
|
whilst the output process is going on. It is used to inform the location table |
|
168
|
|
|
|
|
|
|
where the glyph is located, since the glyf table is output before the loca |
|
169
|
|
|
|
|
|
|
table due to alphabetical ordering. |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=item OUTLEN (P) |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
This indicates the length of the glyph data when it is output. This more |
|
174
|
|
|
|
|
|
|
accurately reflects the internal memory form than the C variable which |
|
175
|
|
|
|
|
|
|
only reflects the read file length. The C variable is only set after |
|
176
|
|
|
|
|
|
|
calling C or C. |
|
177
|
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
=back |
|
179
|
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
=head2 Editing |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
If you want to edit a glyph in some way, then you should read_dat the glyph, then |
|
183
|
|
|
|
|
|
|
make your changes and then update the glyph or set the $g->{' isDirty'} variable. |
|
184
|
|
|
|
|
|
|
The application must ensure that the following instance variables are |
|
185
|
|
|
|
|
|
|
correct, from which update will calculate the rest, including the bounding box |
|
186
|
|
|
|
|
|
|
information. |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
numPoints |
|
189
|
|
|
|
|
|
|
numberOfContours |
|
190
|
|
|
|
|
|
|
endPoints |
|
191
|
|
|
|
|
|
|
x, y, flags (only flags bit 0) |
|
192
|
|
|
|
|
|
|
instLen |
|
193
|
|
|
|
|
|
|
hints |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
For components, the numPoints, x, y, endPoints & flags are not required but |
|
196
|
|
|
|
|
|
|
the following information is required for each component. |
|
197
|
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
flag (bits 2, 10, 11, 12) |
|
199
|
|
|
|
|
|
|
glyph |
|
200
|
|
|
|
|
|
|
args |
|
201
|
|
|
|
|
|
|
scale |
|
202
|
|
|
|
|
|
|
metric (glyph instance variable) |
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=head1 METHODS |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=cut |
|
208
|
|
|
|
|
|
|
|
|
209
|
1
|
|
|
1
|
|
3
|
use strict; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
30
|
|
|
210
|
1
|
|
|
1
|
|
4
|
use vars qw(%fields @field_info); |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
36
|
|
|
211
|
1
|
|
|
1
|
|
4
|
use Font::TTF::Utils; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
62
|
|
|
212
|
1
|
|
|
1
|
|
4
|
use Font::TTF::Table; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
2690
|
|
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
@field_info = ( |
|
215
|
|
|
|
|
|
|
'numberOfContours' => 's', |
|
216
|
|
|
|
|
|
|
'xMin' => 's', |
|
217
|
|
|
|
|
|
|
'yMin' => 's', |
|
218
|
|
|
|
|
|
|
'xMax' => 's', |
|
219
|
|
|
|
|
|
|
'yMax' => 's'); |
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
sub init |
|
222
|
|
|
|
|
|
|
{ |
|
223
|
1
|
|
|
1
|
0
|
2
|
my ($k, $v, $c, $i); |
|
224
|
1
|
|
|
|
|
5
|
for ($i = 0; $i < $#field_info; $i += 2) |
|
225
|
|
|
|
|
|
|
{ |
|
226
|
5
|
|
|
|
|
12
|
($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]); |
|
227
|
5
|
50
|
33
|
|
|
18
|
next unless defined $k && $k ne ""; |
|
228
|
5
|
|
|
|
|
12
|
$fields{$k} = $v; |
|
229
|
|
|
|
|
|
|
} |
|
230
|
|
|
|
|
|
|
} |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
=head1 Font::TTF::Glyph->new(%parms) |
|
234
|
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
Creates a new glyph setting various instance variables |
|
236
|
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=cut |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
sub new |
|
240
|
|
|
|
|
|
|
{ |
|
241
|
188
|
|
|
188
|
0
|
667
|
my ($class, %parms) = @_; |
|
242
|
188
|
|
|
|
|
216
|
my ($self) = {}; |
|
243
|
188
|
|
|
|
|
186
|
my ($p); |
|
244
|
|
|
|
|
|
|
|
|
245
|
188
|
|
|
|
|
312
|
bless $self, $class; |
|
246
|
188
|
|
|
|
|
411
|
foreach $p (keys %parms) |
|
247
|
1316
|
|
|
|
|
1990
|
{ $self->{" $p"} = $parms{$p}; } |
|
248
|
188
|
100
|
|
|
|
469
|
init unless defined $fields{'xMin'}; |
|
249
|
188
|
|
|
|
|
696
|
$self; |
|
250
|
|
|
|
|
|
|
} |
|
251
|
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
=head2 $g->read |
|
254
|
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
Reads the header component of the glyph (numberOfContours and bounding box) and also the |
|
256
|
|
|
|
|
|
|
glyph content, but into a data field rather than breaking it down into |
|
257
|
|
|
|
|
|
|
its constituent structures. Use read_dat for this. |
|
258
|
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
=cut |
|
260
|
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
sub read |
|
262
|
|
|
|
|
|
|
{ |
|
263
|
188
|
|
|
188
|
1
|
186
|
my ($self) = @_; |
|
264
|
188
|
|
|
|
|
276
|
my ($fh) = $self->{' INFILE'}; |
|
265
|
188
|
|
|
|
|
156
|
my ($dat); |
|
266
|
|
|
|
|
|
|
|
|
267
|
188
|
50
|
33
|
|
|
367
|
return $self if (defined $self->{' read'} && $self->{' read'} > 0); |
|
268
|
188
|
|
|
|
|
442
|
$self->{' read'} = 1; |
|
269
|
188
|
|
|
|
|
630
|
$fh->seek($self->{' LOC'} + $self->{' BASE'}, 0); |
|
270
|
188
|
|
|
|
|
2234
|
$fh->read($self->{' DAT'}, $self->{' LEN'}); |
|
271
|
188
|
|
|
|
|
2923
|
TTF_Read_Fields($self, $self->{' DAT'}, \%fields); |
|
272
|
188
|
|
|
|
|
240
|
$self; |
|
273
|
|
|
|
|
|
|
} |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
=head2 $g->read_dat |
|
277
|
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
Reads the contents of the glyph (components and curves, etc.) from the memory |
|
279
|
|
|
|
|
|
|
store C into structures within the object. |
|
280
|
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
=cut |
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
sub read_dat |
|
284
|
|
|
|
|
|
|
{ |
|
285
|
188
|
|
|
188
|
1
|
666
|
my ($self) = @_; |
|
286
|
188
|
|
|
|
|
166
|
my ($dat, $num, $max, $i, $flag, $len, $val, $val1, $fp); |
|
287
|
|
|
|
|
|
|
|
|
288
|
188
|
50
|
33
|
|
|
426
|
return $self if (defined $self->{' read'} && $self->{' read'} > 1); |
|
289
|
188
|
50
|
|
|
|
524
|
$self->read unless $self->{' read'}; |
|
290
|
188
|
|
|
|
|
272
|
$dat = $self->{' DAT'}; |
|
291
|
188
|
|
|
|
|
194
|
$fp = 10; |
|
292
|
188
|
|
|
|
|
204
|
$num = $self->{'numberOfContours'}; |
|
293
|
188
|
100
|
|
|
|
290
|
if ($num > 0) |
|
|
|
50
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
{ |
|
295
|
184
|
|
|
|
|
572
|
$self->{'endPoints'} = [unpack("n*", substr($dat, $fp, $num << 1))]; |
|
296
|
184
|
|
|
|
|
203
|
$fp += $num << 1; |
|
297
|
184
|
|
|
|
|
160
|
$max = 0; |
|
298
|
184
|
|
|
|
|
139
|
foreach (@{$self->{'endPoints'}}) |
|
|
184
|
|
|
|
|
355
|
|
|
299
|
260
|
50
|
|
|
|
579
|
{ $max = $_ if $_ > $max; } |
|
300
|
|
|
|
|
|
|
# print STDERR join(",", unpack('C*', $self->{" DAT"})); |
|
301
|
|
|
|
|
|
|
# printf STDERR ("(%d,%d in %d=%d @ %d)", scalar @{$self->{'endPoints'}}, $max, length($dat), $self->{' LEN'}, $fp); |
|
302
|
184
|
50
|
|
|
|
175
|
$max++ if (@{$self->{'endPoints'}}); |
|
|
184
|
|
|
|
|
357
|
|
|
303
|
184
|
|
|
|
|
484
|
$self->{'numPoints'} = $max; |
|
304
|
184
|
|
|
|
|
393
|
$self->{'instLen'} = unpack("n", substr($dat, $fp)); |
|
305
|
184
|
|
|
|
|
417
|
$self->{'hints'} = substr($dat, $fp + 2, $self->{'instLen'}); |
|
306
|
184
|
|
|
|
|
206
|
$fp += 2 + $self->{'instLen'}; |
|
307
|
|
|
|
|
|
|
# read the flags array |
|
308
|
184
|
|
|
|
|
374
|
for ($i = 0; $i < $max; $i++) |
|
309
|
|
|
|
|
|
|
{ |
|
310
|
5498
|
|
|
|
|
6549
|
$flag = unpack("C", substr($dat, $fp++)); |
|
311
|
5498
|
|
|
|
|
5873
|
$self->{'flags'}[$i] = $flag; |
|
312
|
5498
|
100
|
|
|
|
11684
|
if ($flag & 8) |
|
313
|
|
|
|
|
|
|
{ |
|
314
|
1474
|
|
|
|
|
1787
|
$len = unpack("C", substr($dat, $fp++)); |
|
315
|
1474
|
|
|
|
|
2324
|
while ($len-- > 0) |
|
316
|
|
|
|
|
|
|
{ |
|
317
|
2976
|
|
|
|
|
2126
|
$i++; |
|
318
|
2976
|
|
|
|
|
6641
|
$self->{'flags'}[$i] = $flag; |
|
319
|
|
|
|
|
|
|
} |
|
320
|
|
|
|
|
|
|
} |
|
321
|
|
|
|
|
|
|
} |
|
322
|
|
|
|
|
|
|
#read the x array |
|
323
|
184
|
|
|
|
|
409
|
for ($i = 0; $i < $max; $i++) |
|
324
|
|
|
|
|
|
|
{ |
|
325
|
8474
|
|
|
|
|
7673
|
$flag = $self->{'flags'}[$i]; |
|
326
|
8474
|
100
|
|
|
|
10506
|
if ($flag & 2) |
|
|
|
100
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
{ |
|
328
|
6630
|
|
|
|
|
8298
|
$val = unpack("C", substr($dat, $fp++)); |
|
329
|
6630
|
100
|
|
|
|
10241
|
$val = -$val unless ($flag & 16); |
|
330
|
|
|
|
|
|
|
} elsif ($flag & 16) |
|
331
|
1310
|
|
|
|
|
1120
|
{ $val = 0; } |
|
332
|
|
|
|
|
|
|
else |
|
333
|
|
|
|
|
|
|
{ |
|
334
|
534
|
|
|
|
|
1443
|
$val = TTF_Unpack("s", substr($dat, $fp)); |
|
335
|
534
|
|
|
|
|
771
|
$fp += 2; |
|
336
|
|
|
|
|
|
|
} |
|
337
|
8474
|
100
|
|
|
|
22060
|
$self->{'x'}[$i] = $i == 0 ? $val : $self->{'x'}[$i - 1] + $val; |
|
338
|
|
|
|
|
|
|
} |
|
339
|
|
|
|
|
|
|
#read the y array |
|
340
|
184
|
|
|
|
|
345
|
for ($i = 0; $i < $max; $i++) |
|
341
|
|
|
|
|
|
|
{ |
|
342
|
8474
|
|
|
|
|
7734
|
$flag = $self->{'flags'}[$i]; |
|
343
|
8474
|
100
|
|
|
|
10032
|
if ($flag & 4) |
|
|
|
100
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
{ |
|
345
|
6774
|
|
|
|
|
8269
|
$val = unpack("C", substr($dat, $fp++)); |
|
346
|
6774
|
100
|
|
|
|
10440
|
$val = -$val unless ($flag & 32); |
|
347
|
|
|
|
|
|
|
} elsif ($flag & 32) |
|
348
|
1074
|
|
|
|
|
870
|
{ $val = 0; } |
|
349
|
|
|
|
|
|
|
else |
|
350
|
|
|
|
|
|
|
{ |
|
351
|
626
|
|
|
|
|
1649
|
$val = TTF_Unpack("s", substr($dat, $fp)); |
|
352
|
626
|
|
|
|
|
892
|
$fp += 2; |
|
353
|
|
|
|
|
|
|
} |
|
354
|
8474
|
100
|
|
|
|
21328
|
$self->{'y'}[$i] = $i == 0 ? $val : $self->{'y'}[$i - 1] + $val; |
|
355
|
|
|
|
|
|
|
} |
|
356
|
|
|
|
|
|
|
} |
|
357
|
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
# compound glyph |
|
359
|
|
|
|
|
|
|
elsif ($num < 0) |
|
360
|
|
|
|
|
|
|
{ |
|
361
|
4
|
|
|
|
|
4
|
$flag = 1 << 5; # cheat to get the loop going |
|
362
|
4
|
|
|
|
|
10
|
for ($i = 0; $flag & 32; $i++) |
|
363
|
|
|
|
|
|
|
{ |
|
364
|
8
|
|
|
|
|
28
|
($flag, $self->{'comps'}[$i]{'glyph'}) = unpack("n2", substr($dat, $fp)); |
|
365
|
8
|
|
|
|
|
9
|
$fp += 4; |
|
366
|
8
|
|
|
|
|
10
|
$self->{'comps'}[$i]{'flag'} = $flag; |
|
367
|
8
|
100
|
|
|
|
13
|
if ($flag & 1) # ARGS1_AND_2_ARE_WORDS |
|
368
|
|
|
|
|
|
|
{ |
|
369
|
4
|
|
|
|
|
10
|
$self->{'comps'}[$i]{'args'} = [TTF_Unpack("s2", substr($dat, $fp))]; |
|
370
|
4
|
|
|
|
|
8
|
$fp += 4; |
|
371
|
|
|
|
|
|
|
} else |
|
372
|
|
|
|
|
|
|
{ |
|
373
|
4
|
|
|
|
|
13
|
$self->{'comps'}[$i]{'args'} = [unpack("c2", substr($dat, $fp))]; |
|
374
|
4
|
|
|
|
|
6
|
$fp += 2; |
|
375
|
|
|
|
|
|
|
} |
|
376
|
|
|
|
|
|
|
|
|
377
|
8
|
50
|
|
|
|
23
|
if ($flag & 8) |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
{ |
|
379
|
0
|
|
|
|
|
0
|
$val = TTF_Unpack("F", substr($dat, $fp)); |
|
380
|
0
|
|
|
|
|
0
|
$fp += 2; |
|
381
|
0
|
|
|
|
|
0
|
$self->{'comps'}[$i]{'scale'} = [$val, 0, 0, $val]; |
|
382
|
|
|
|
|
|
|
} elsif ($flag & 64) |
|
383
|
|
|
|
|
|
|
{ |
|
384
|
0
|
|
|
|
|
0
|
($val, $val1) = TTF_Unpack("F2", substr($dat, $fp)); |
|
385
|
0
|
|
|
|
|
0
|
$fp += 4; |
|
386
|
0
|
|
|
|
|
0
|
$self->{'comps'}[$i]{'scale'} = [$val, 0, 0, $val1]; |
|
387
|
|
|
|
|
|
|
} elsif ($flag & 128) |
|
388
|
|
|
|
|
|
|
{ |
|
389
|
0
|
|
|
|
|
0
|
$self->{'comps'}[$i]{'scale'} = [TTF_Unpack("F4", substr($dat, $fp))]; |
|
390
|
0
|
|
|
|
|
0
|
$fp += 8; |
|
391
|
|
|
|
|
|
|
} |
|
392
|
8
|
50
|
|
|
|
20
|
$self->{'metric'} = $i if ($flag & 512); |
|
393
|
|
|
|
|
|
|
} |
|
394
|
4
|
|
|
|
|
24
|
$self->{'numPoints'} = $i; |
|
395
|
4
|
50
|
|
|
|
10
|
if ($flag & 256) # HAVE_INSTRUCTIONS |
|
396
|
|
|
|
|
|
|
{ |
|
397
|
0
|
|
|
|
|
0
|
$self->{'instLen'} = unpack("n", substr($dat, $fp)); |
|
398
|
0
|
|
|
|
|
0
|
$self->{'hints'} = substr($dat, $fp + 2, $self->{'instLen'}); |
|
399
|
0
|
|
|
|
|
0
|
$fp += 2 + $self->{'instLen'}; |
|
400
|
|
|
|
|
|
|
} |
|
401
|
|
|
|
|
|
|
} |
|
402
|
188
|
50
|
|
|
|
331
|
return undef if ($fp > length($dat)); |
|
403
|
188
|
|
|
|
|
233
|
$self->{' read'} = 2; |
|
404
|
188
|
|
|
|
|
568
|
$self; |
|
405
|
|
|
|
|
|
|
} |
|
406
|
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
=head2 $g->out($fh) |
|
409
|
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
Writes the glyph data to outfile |
|
411
|
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
=cut |
|
413
|
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
sub out |
|
415
|
|
|
|
|
|
|
{ |
|
416
|
188
|
|
|
188
|
1
|
185
|
my ($self, $fh) = @_; |
|
417
|
|
|
|
|
|
|
|
|
418
|
188
|
50
|
|
|
|
440
|
$self->read unless $self->{' read'}; |
|
419
|
188
|
50
|
|
|
|
324
|
$self->update if $self->{' isDirty'}; |
|
420
|
188
|
|
|
|
|
447
|
$fh->print($self->{' DAT'}); |
|
421
|
188
|
|
|
|
|
1335
|
$self->{' OUTLEN'} = length($self->{' DAT'}); |
|
422
|
188
|
|
|
|
|
283
|
$self; |
|
423
|
|
|
|
|
|
|
} |
|
424
|
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
=head2 $g->out_xml($context, $depth) |
|
427
|
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
Outputs an XML description of the glyph |
|
429
|
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
=cut |
|
431
|
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
sub out_xml |
|
433
|
|
|
|
|
|
|
{ |
|
434
|
0
|
|
|
0
|
1
|
0
|
my ($self, $context, $depth) = @_; |
|
435
|
0
|
|
|
|
|
0
|
my ($addr) = ($self =~ m/\((.+)\)$/o); |
|
436
|
0
|
|
|
|
|
0
|
my ($k, $ndepth); |
|
437
|
|
|
|
|
|
|
|
|
438
|
0
|
0
|
|
|
|
0
|
if ($context->{'addresses'}{$addr}) |
|
439
|
|
|
|
|
|
|
{ |
|
440
|
0
|
|
|
|
|
0
|
$context->{'fh'}->printf("%s\n", $depth, $context->{'gid'}, $context->{'addresses'}{$addr}); |
|
441
|
0
|
|
|
|
|
0
|
return $self; |
|
442
|
|
|
|
|
|
|
} |
|
443
|
|
|
|
|
|
|
else |
|
444
|
|
|
|
|
|
|
{ |
|
445
|
0
|
|
|
|
|
0
|
$context->{'fh'}->printf("%s\n", $depth, $context->{'gid'}); |
|
446
|
|
|
|
|
|
|
} |
|
447
|
|
|
|
|
|
|
|
|
448
|
0
|
|
|
|
|
0
|
$ndepth = $depth . $context->{'indent'}; |
|
449
|
0
|
|
|
|
|
0
|
$self->read_dat; |
|
450
|
0
|
|
|
|
|
0
|
foreach $k (sort grep {$_ !~ m/^\s/o} keys %{$self}) |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
451
|
|
|
|
|
|
|
{ |
|
452
|
0
|
|
|
|
|
0
|
$self->XML_element($context, $ndepth, $k, $self->{$k}); |
|
453
|
|
|
|
|
|
|
} |
|
454
|
0
|
|
|
|
|
0
|
$context->{'fh'}->print("$depth\n"); |
|
455
|
0
|
|
|
|
|
0
|
delete $context->{'done_points'}; |
|
456
|
0
|
|
|
|
|
0
|
$self; |
|
457
|
|
|
|
|
|
|
} |
|
458
|
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
sub XML_element |
|
461
|
|
|
|
|
|
|
{ |
|
462
|
0
|
|
|
0
|
0
|
0
|
my ($self, $context, $depth, $key, $val) = @_; |
|
463
|
0
|
|
|
|
|
0
|
my ($fh) = $context->{'fh'}; |
|
464
|
0
|
|
|
|
|
0
|
my ($dind) = $depth . $context->{'indent'}; |
|
465
|
0
|
|
|
|
|
0
|
my ($i); |
|
466
|
|
|
|
|
|
|
|
|
467
|
0
|
0
|
0
|
|
|
0
|
if ($self->{'numberOfContours'} >= 0 && ($key eq 'x' || $key eq 'y' || $key eq 'flags')) |
|
|
|
0
|
0
|
|
|
|
|
|
468
|
|
|
|
|
|
|
{ |
|
469
|
0
|
0
|
|
|
|
0
|
return $self if ($context->{'done_points'}); |
|
470
|
0
|
|
|
|
|
0
|
$context->{'done_points'} = 1; |
|
471
|
|
|
|
|
|
|
|
|
472
|
0
|
|
|
|
|
0
|
$fh->print("$depth\n"); |
|
473
|
0
|
|
|
|
|
0
|
for ($i = 0; $i <= $#{$self->{'flags'}}; $i++) |
|
|
0
|
|
|
|
|
0
|
|
|
474
|
0
|
|
|
|
|
0
|
{ $fh->printf("%s\n", $dind, |
|
475
|
|
|
|
|
|
|
$self->{'x'}[$i], $self->{'y'}[$i], $self->{'flags'}[$i]); } |
|
476
|
0
|
|
|
|
|
0
|
$fh->print("$depth\n"); |
|
477
|
|
|
|
|
|
|
} |
|
478
|
|
|
|
|
|
|
elsif ($key eq 'hints') |
|
479
|
|
|
|
|
|
|
{ |
|
480
|
0
|
|
|
|
|
0
|
my ($dat); |
|
481
|
0
|
|
|
|
|
0
|
$fh->print("$depth\n"); |
|
482
|
|
|
|
|
|
|
# Font::TTF::Utils::XML_hexdump($context, $depth . $context->{'indent'}, $self->{'hints'}); |
|
483
|
0
|
|
0
|
|
|
0
|
$dat = Font::TTF::Utils::XML_binhint($self->{'hints'}) || ""; |
|
484
|
0
|
|
|
|
|
0
|
$dat =~ s/\n(?!$)/\n$depth$context->{'indent'}/mg; |
|
485
|
0
|
|
|
|
|
0
|
$fh->print("$depth$context->{'indent'}$dat"); |
|
486
|
0
|
|
|
|
|
0
|
$fh->print("$depth\n"); |
|
487
|
|
|
|
|
|
|
} |
|
488
|
|
|
|
|
|
|
else |
|
489
|
0
|
|
|
|
|
0
|
{ return Font::TTF::Table::XML_element(@_); } |
|
490
|
|
|
|
|
|
|
|
|
491
|
0
|
|
|
|
|
0
|
$self; |
|
492
|
|
|
|
|
|
|
} |
|
493
|
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
=head2 $g->dirty($val) |
|
495
|
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
This sets the dirty flag to the given value or 1 if no given value. It returns the |
|
497
|
|
|
|
|
|
|
value of the flag |
|
498
|
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
=cut |
|
500
|
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
sub dirty |
|
502
|
|
|
|
|
|
|
{ |
|
503
|
0
|
|
|
0
|
1
|
0
|
my ($self, $val) = @_; |
|
504
|
0
|
|
|
|
|
0
|
my ($res) = $self->{' isDirty'}; |
|
505
|
|
|
|
|
|
|
|
|
506
|
0
|
0
|
|
|
|
0
|
$self->{' isDirty'} = defined $val ? $val : 1; |
|
507
|
0
|
|
|
|
|
0
|
$res; |
|
508
|
|
|
|
|
|
|
} |
|
509
|
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
=head2 $g->update |
|
511
|
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
Generates a C<$self->{'DAT'}> from the internal structures, if the data has |
|
513
|
|
|
|
|
|
|
been read into structures in the first place. If you are building a glyph |
|
514
|
|
|
|
|
|
|
from scratch you will need to set the instance variable C<' isDirty'>. |
|
515
|
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
=cut |
|
517
|
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
sub update |
|
519
|
|
|
|
|
|
|
{ |
|
520
|
188
|
|
|
188
|
1
|
196
|
my ($self) = @_; |
|
521
|
188
|
|
|
|
|
157
|
my ($dat, $loc, $len, $flag, $x, $y, $i, $comp, $num, @rflags, $repeat); |
|
522
|
|
|
|
|
|
|
|
|
523
|
188
|
50
|
|
|
|
542
|
return $self unless ($self->{' isDirty'}); |
|
524
|
0
|
|
|
|
|
|
$self->read_dat->update_bbox; |
|
525
|
0
|
|
|
|
|
|
$self->{' DAT'} = TTF_Out_Fields($self, \%fields, 10); |
|
526
|
0
|
|
|
|
|
|
$num = $self->{'numberOfContours'}; |
|
527
|
0
|
0
|
|
|
|
|
if ($num > 0) |
|
|
|
0
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
{ |
|
529
|
0
|
|
|
|
|
|
$self->{' DAT'} .= pack("n*", @{$self->{'endPoints'}}); |
|
|
0
|
|
|
|
|
|
|
|
530
|
0
|
|
|
|
|
|
$len = $self->{'instLen'}; |
|
531
|
0
|
|
|
|
|
|
$self->{' DAT'} .= pack("n", $len); |
|
532
|
0
|
0
|
|
|
|
|
$self->{' DAT'} .= pack("a" . $len, substr($self->{'hints'}, 0, $len)) if ($len > 0); |
|
533
|
0
|
|
|
|
|
|
$repeat = 0; |
|
534
|
0
|
|
|
|
|
|
for ($i = 0; $i < $self->{'numPoints'}; $i++) |
|
535
|
|
|
|
|
|
|
{ |
|
536
|
0
|
|
|
|
|
|
$flag = $self->{'flags'}[$i] & 1; |
|
537
|
0
|
0
|
|
|
|
|
if ($i == 0) |
|
538
|
|
|
|
|
|
|
{ |
|
539
|
0
|
|
|
|
|
|
$x = $self->{'x'}[$i]; |
|
540
|
0
|
|
|
|
|
|
$y = $self->{'y'}[$i]; |
|
541
|
|
|
|
|
|
|
} else |
|
542
|
|
|
|
|
|
|
{ |
|
543
|
0
|
|
|
|
|
|
$x = $self->{'x'}[$i] - $self->{'x'}[$i - 1]; |
|
544
|
0
|
|
|
|
|
|
$y = $self->{'y'}[$i] - $self->{'y'}[$i - 1]; |
|
545
|
|
|
|
|
|
|
} |
|
546
|
0
|
0
|
|
|
|
|
$flag |= 16 if ($x == 0); |
|
547
|
0
|
0
|
|
|
|
|
$flag |= 32 if ($y == 0); |
|
548
|
0
|
0
|
0
|
|
|
|
if (($flag & 16) == 0 && $x < 256 && $x > -256) |
|
|
|
|
0
|
|
|
|
|
|
549
|
|
|
|
|
|
|
{ |
|
550
|
0
|
|
|
|
|
|
$flag |= 2; |
|
551
|
0
|
0
|
|
|
|
|
$flag |= 16 if ($x >= 0); |
|
552
|
|
|
|
|
|
|
} |
|
553
|
0
|
0
|
0
|
|
|
|
if (($flag & 32) == 0 && $y < 256 && $y > -256) |
|
|
|
|
0
|
|
|
|
|
|
554
|
|
|
|
|
|
|
{ |
|
555
|
0
|
|
|
|
|
|
$flag |= 4; |
|
556
|
0
|
0
|
|
|
|
|
$flag |= 32 if ($y >= 0); |
|
557
|
|
|
|
|
|
|
} |
|
558
|
0
|
0
|
0
|
|
|
|
if ($i > 0 && $rflags[-1] == $flag && $repeat < 255) |
|
|
|
|
0
|
|
|
|
|
|
559
|
|
|
|
|
|
|
{ |
|
560
|
0
|
|
|
|
|
|
$repeat++; |
|
561
|
|
|
|
|
|
|
} else |
|
562
|
|
|
|
|
|
|
{ |
|
563
|
0
|
0
|
|
|
|
|
if ($repeat) |
|
564
|
|
|
|
|
|
|
{ |
|
565
|
0
|
|
|
|
|
|
$rflags[-1] |= 8; |
|
566
|
0
|
|
|
|
|
|
push @rflags, $repeat; |
|
567
|
|
|
|
|
|
|
} |
|
568
|
0
|
|
|
|
|
|
push @rflags, $flag; |
|
569
|
0
|
|
|
|
|
|
$repeat = 0; |
|
570
|
|
|
|
|
|
|
} |
|
571
|
0
|
|
|
|
|
|
$self->{'flags'}[$i] = $flag; |
|
572
|
|
|
|
|
|
|
} |
|
573
|
|
|
|
|
|
|
# Add final repeat if needed, then pack up the flag bytes: |
|
574
|
0
|
0
|
|
|
|
|
if ($repeat) |
|
575
|
|
|
|
|
|
|
{ |
|
576
|
0
|
|
|
|
|
|
$rflags[-1] |= 8; |
|
577
|
0
|
|
|
|
|
|
push @rflags, $repeat; |
|
578
|
|
|
|
|
|
|
} |
|
579
|
0
|
|
|
|
|
|
$self->{' DAT'} .= pack("C*", @rflags); |
|
580
|
0
|
|
|
|
|
|
for ($i = 0; $i < $self->{'numPoints'}; $i++) |
|
581
|
|
|
|
|
|
|
{ |
|
582
|
0
|
|
|
|
|
|
$flag = $self->{'flags'}[$i]; |
|
583
|
0
|
0
|
|
|
|
|
$x = $self->{'x'}[$i] - (($i == 0) ? 0 : $self->{'x'}[$i - 1]); |
|
584
|
0
|
0
|
|
|
|
|
if (($flag & 18) == 0) |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
585
|
0
|
|
|
|
|
|
{ $self->{' DAT'} .= TTF_Pack("s", $x); } |
|
586
|
|
|
|
|
|
|
elsif (($flag & 18) == 18) |
|
587
|
0
|
|
|
|
|
|
{ $self->{' DAT'} .= pack("C", $x); } |
|
588
|
|
|
|
|
|
|
elsif (($flag & 18) == 2) |
|
589
|
0
|
|
|
|
|
|
{ $self->{' DAT'} .= pack("C", -$x); } |
|
590
|
|
|
|
|
|
|
} |
|
591
|
0
|
|
|
|
|
|
for ($i = 0; $i < $self->{'numPoints'}; $i++) |
|
592
|
|
|
|
|
|
|
{ |
|
593
|
0
|
|
|
|
|
|
$flag = $self->{'flags'}[$i]; |
|
594
|
0
|
0
|
|
|
|
|
$y = $self->{'y'}[$i] - (($i == 0) ? 0 : $self->{'y'}[$i - 1]); |
|
595
|
0
|
0
|
|
|
|
|
if (($flag & 36) == 0) |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
596
|
0
|
|
|
|
|
|
{ $self->{' DAT'} .= TTF_Pack("s", $y); } |
|
597
|
|
|
|
|
|
|
elsif (($flag & 36) == 36) |
|
598
|
0
|
|
|
|
|
|
{ $self->{' DAT'} .= pack("C", $y); } |
|
599
|
|
|
|
|
|
|
elsif (($flag & 36) == 4) |
|
600
|
0
|
|
|
|
|
|
{ $self->{' DAT'} .= pack("C", -$y); } |
|
601
|
|
|
|
|
|
|
} |
|
602
|
|
|
|
|
|
|
} |
|
603
|
|
|
|
|
|
|
|
|
604
|
|
|
|
|
|
|
elsif ($num < 0) |
|
605
|
|
|
|
|
|
|
{ |
|
606
|
0
|
|
|
|
|
|
for ($i = 0; $i <= $#{$self->{'comps'}}; $i++) |
|
|
0
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
{ |
|
608
|
0
|
|
|
|
|
|
$comp = $self->{'comps'}[$i]; |
|
609
|
0
|
|
|
|
|
|
$flag = $comp->{'flag'} & 7158; # bits 2,10,11,12 |
|
610
|
0
|
0
|
0
|
|
|
|
$flag |= 1 unless ($comp->{'args'}[0] > -129 && $comp->{'args'}[0] < 128 |
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
611
|
|
|
|
|
|
|
&& $comp->{'args'}[1] > -129 && $comp->{'args'}[1] < 128); |
|
612
|
0
|
0
|
|
|
|
|
if (defined $comp->{'scale'}) |
|
613
|
|
|
|
|
|
|
{ |
|
614
|
0
|
0
|
0
|
|
|
|
if ($comp->{'scale'}[1] == 0 && $comp->{'scale'}[2] == 0) |
|
615
|
|
|
|
|
|
|
{ |
|
616
|
0
|
0
|
|
|
|
|
if ($comp->{'scale'}[0] == $comp->{'scale'}[3]) |
|
617
|
0
|
0
|
0
|
|
|
|
{ $flag |= 8 unless ($comp->{'scale'}[0] == 0 |
|
618
|
|
|
|
|
|
|
|| $comp->{'scale'}[0] == 1); } |
|
619
|
|
|
|
|
|
|
else |
|
620
|
0
|
|
|
|
|
|
{ $flag |= 64; } |
|
621
|
|
|
|
|
|
|
} else |
|
622
|
0
|
|
|
|
|
|
{ $flag |= 128; } |
|
623
|
|
|
|
|
|
|
} |
|
624
|
|
|
|
|
|
|
|
|
625
|
0
|
0
|
0
|
|
|
|
$flag |= 512 if (defined $self->{'metric'} && $self->{'metric'} == $i); |
|
626
|
0
|
0
|
|
|
|
|
if ($i == $#{$self->{'comps'}}) |
|
|
0
|
|
|
|
|
|
|
|
627
|
0
|
0
|
0
|
|
|
|
{ $flag |= 256 if (defined $self->{'instLen'} && $self->{'instLen'} > 0); } |
|
628
|
|
|
|
|
|
|
else |
|
629
|
0
|
|
|
|
|
|
{ $flag |= 32; } |
|
630
|
|
|
|
|
|
|
|
|
631
|
0
|
|
|
|
|
|
$self->{' DAT'} .= pack("n", $flag); |
|
632
|
0
|
|
|
|
|
|
$self->{' DAT'} .= pack("n", $comp->{'glyph'}); |
|
633
|
0
|
|
|
|
|
|
$comp->{'flag'} = $flag; |
|
634
|
|
|
|
|
|
|
|
|
635
|
0
|
0
|
|
|
|
|
if ($flag & 1) |
|
636
|
0
|
|
|
|
|
|
{ $self->{' DAT'} .= TTF_Pack("s2", @{$comp->{'args'}}); } |
|
|
0
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
else |
|
638
|
0
|
|
|
|
|
|
{ $self->{' DAT'} .= pack("CC", @{$comp->{'args'}}); } |
|
|
0
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
|
|
640
|
0
|
0
|
|
|
|
|
if ($flag & 8) |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
641
|
0
|
|
|
|
|
|
{ $self->{' DAT'} .= TTF_Pack("F", $comp->{'scale'}[0]); } |
|
642
|
|
|
|
|
|
|
elsif ($flag & 64) |
|
643
|
0
|
|
|
|
|
|
{ $self->{' DAT'} .= TTF_Pack("F2", $comp->{'scale'}[0], $comp->{'scale'}[3]); } |
|
644
|
|
|
|
|
|
|
elsif ($flag & 128) |
|
645
|
0
|
|
|
|
|
|
{ $self->{' DAT'} .= TTF_Pack("F4", @{$comp->{'scale'}}); } |
|
|
0
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
} |
|
647
|
0
|
0
|
0
|
|
|
|
if (defined $self->{'instLen'} && $self->{'instLen'} > 0) |
|
648
|
|
|
|
|
|
|
{ |
|
649
|
0
|
|
|
|
|
|
$len = $self->{'instLen'}; |
|
650
|
0
|
|
|
|
|
|
$self->{' DAT'} .= pack("n", $len); |
|
651
|
0
|
|
|
|
|
|
$self->{' DAT'} .= pack("a" . $len, substr($self->{'hints'}, 0, $len)); |
|
652
|
|
|
|
|
|
|
} |
|
653
|
|
|
|
|
|
|
} |
|
654
|
0
|
|
|
|
|
|
my ($olen) = length($self->{' DAT'}); |
|
655
|
0
|
0
|
|
|
|
|
$self->{' DAT'} .= ("\000") x (4 - ($olen & 3)) if ($olen & 3); |
|
656
|
0
|
|
|
|
|
|
$self->{' OUTLEN'} = length($self->{' DAT'}); |
|
657
|
0
|
|
|
|
|
|
$self->{' read'} = 2; # changed from 1 to 2 so we don't read_dat() again |
|
658
|
|
|
|
|
|
|
# we leave numPoints and instLen since maxp stats use this |
|
659
|
0
|
|
|
|
|
|
$self; |
|
660
|
|
|
|
|
|
|
} |
|
661
|
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
=head2 $g->update_bbox |
|
664
|
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
Updates the bounding box for this glyph according to the points in the glyph |
|
666
|
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
=cut |
|
668
|
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
sub update_bbox |
|
670
|
|
|
|
|
|
|
{ |
|
671
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
|
672
|
0
|
|
|
|
|
|
my ($num, $maxx, $minx, $maxy, $miny, $i, $comp, $x, $y, $compg); |
|
673
|
|
|
|
|
|
|
|
|
674
|
0
|
0
|
0
|
|
|
|
return $self unless (defined $self->{' read'} && $self->{' read'} > 1); # only if read_dat done |
|
675
|
0
|
|
|
|
|
|
$miny = $minx = 65537; $maxx = $maxy = -65537; |
|
|
0
|
|
|
|
|
|
|
|
676
|
0
|
|
|
|
|
|
$num = $self->{'numberOfContours'}; |
|
677
|
0
|
0
|
|
|
|
|
if ($num > 0) |
|
|
|
0
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
{ |
|
679
|
0
|
|
|
|
|
|
for ($i = 0; $i < $self->{'numPoints'}; $i++) |
|
680
|
|
|
|
|
|
|
{ |
|
681
|
0
|
|
|
|
|
|
($x, $y) = ($self->{'x'}[$i], $self->{'y'}[$i]); |
|
682
|
|
|
|
|
|
|
|
|
683
|
0
|
0
|
|
|
|
|
$maxx = $x if ($x > $maxx); |
|
684
|
0
|
0
|
|
|
|
|
$minx = $x if ($x < $minx); |
|
685
|
0
|
0
|
|
|
|
|
$maxy = $y if ($y > $maxy); |
|
686
|
0
|
0
|
|
|
|
|
$miny = $y if ($y < $miny); |
|
687
|
|
|
|
|
|
|
} |
|
688
|
|
|
|
|
|
|
} |
|
689
|
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
elsif ($num < 0) |
|
691
|
|
|
|
|
|
|
{ |
|
692
|
0
|
|
|
|
|
|
foreach $comp (@{$self->{'comps'}}) |
|
|
0
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
{ |
|
694
|
0
|
|
|
|
|
|
my ($gnx, $gny, $gxx, $gxy); |
|
695
|
0
|
|
|
|
|
|
my ($sxx, $sxy, $syx, $syy); |
|
696
|
|
|
|
|
|
|
|
|
697
|
0
|
|
|
|
|
|
my $otherg = $self->{' PARENT'}{'loca'}{'glyphs'}[$comp->{'glyph'}]; |
|
698
|
|
|
|
|
|
|
# work around bad fonts: see documentation for 'comps' above |
|
699
|
0
|
0
|
|
|
|
|
next unless (defined $otherg); |
|
700
|
0
|
|
|
|
|
|
$compg = $otherg->read->update_bbox; |
|
701
|
0
|
|
|
|
|
|
($gnx, $gny, $gxx, $gxy) = @{$compg}{'xMin', 'yMin', 'xMax', 'yMax'}; |
|
|
0
|
|
|
|
|
|
|
|
702
|
0
|
0
|
0
|
|
|
|
if (defined $comp->{'scale'}) |
|
|
|
0
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
{ |
|
704
|
0
|
|
|
|
|
|
($sxx, $sxy, $syx, $syy) = @{$comp->{'scale'}}; |
|
|
0
|
|
|
|
|
|
|
|
705
|
0
|
|
|
|
|
|
($gnx, $gny, $gxx, $gxy) = ($gnx*$sxx+$gny*$syx + $comp->{'args'}[0], |
|
706
|
|
|
|
|
|
|
$gnx*$sxy+$gny*$syy + $comp->{'args'}[1], |
|
707
|
|
|
|
|
|
|
$gxx*$sxx+$gxy*$syx + $comp->{'args'}[0], |
|
708
|
|
|
|
|
|
|
$gxx*$sxy+$gxy*$syy + $comp->{'args'}[1]); |
|
709
|
|
|
|
|
|
|
} elsif ($comp->{'args'}[0] || $comp->{'args'}[1]) |
|
710
|
|
|
|
|
|
|
{ |
|
711
|
0
|
|
|
|
|
|
$gnx += $comp->{'args'}[0]; |
|
712
|
0
|
|
|
|
|
|
$gny += $comp->{'args'}[1]; |
|
713
|
0
|
|
|
|
|
|
$gxx += $comp->{'args'}[0]; |
|
714
|
0
|
|
|
|
|
|
$gxy += $comp->{'args'}[1]; |
|
715
|
|
|
|
|
|
|
} |
|
716
|
0
|
0
|
|
|
|
|
($gnx, $gxx) = ($gxx, $gnx) if $gnx > $gxx; |
|
717
|
0
|
0
|
|
|
|
|
($gny, $gxy) = ($gxy, $gny) if $gny > $gxy; |
|
718
|
0
|
0
|
|
|
|
|
$maxx = $gxx if $gxx > $maxx; |
|
719
|
0
|
0
|
|
|
|
|
$minx = $gnx if $gnx < $minx; |
|
720
|
0
|
0
|
|
|
|
|
$maxy = $gxy if $gxy > $maxy; |
|
721
|
0
|
0
|
|
|
|
|
$miny = $gny if $gny < $miny; |
|
722
|
|
|
|
|
|
|
} |
|
723
|
|
|
|
|
|
|
} |
|
724
|
0
|
|
|
|
|
|
$self->{'xMax'} = $maxx; |
|
725
|
0
|
|
|
|
|
|
$self->{'xMin'} = $minx; |
|
726
|
0
|
|
|
|
|
|
$self->{'yMax'} = $maxy; |
|
727
|
0
|
|
|
|
|
|
$self->{'yMin'} = $miny; |
|
728
|
0
|
|
|
|
|
|
$self; |
|
729
|
|
|
|
|
|
|
} |
|
730
|
|
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
=head2 $g->maxInfo |
|
733
|
|
|
|
|
|
|
|
|
734
|
|
|
|
|
|
|
Returns lots of information about a glyph so that the C table can update |
|
735
|
|
|
|
|
|
|
itself. Returns array containing contributions of this glyph to maxPoints, maxContours, |
|
736
|
|
|
|
|
|
|
maxCompositePoints, maxCompositeContours, maxSizeOfInstructions, maxComponentElements, |
|
737
|
|
|
|
|
|
|
and maxComponentDepth. |
|
738
|
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
=cut |
|
740
|
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
sub maxInfo |
|
742
|
|
|
|
|
|
|
{ |
|
743
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
|
744
|
0
|
|
|
|
|
|
my (@res, $i, @n); |
|
745
|
|
|
|
|
|
|
|
|
746
|
0
|
|
|
|
|
|
$self->read_dat; # make sure we've read some data |
|
747
|
0
|
0
|
|
|
|
|
$res[4] = length($self->{'hints'}) if defined $self->{'hints'}; |
|
748
|
0
|
|
|
|
|
|
$res[6] = 1; |
|
749
|
0
|
0
|
|
|
|
|
if ($self->{'numberOfContours'} > 0) |
|
|
|
0
|
|
|
|
|
|
|
750
|
|
|
|
|
|
|
{ |
|
751
|
0
|
|
|
|
|
|
$res[0] = $self->{'numPoints'}; |
|
752
|
0
|
|
|
|
|
|
$res[1] = $self->{'numberOfContours'}; |
|
753
|
|
|
|
|
|
|
} elsif ($self->{'numberOfContours'} < 0) |
|
754
|
|
|
|
|
|
|
{ |
|
755
|
0
|
|
|
|
|
|
for ($i = 0; $i <= $#{$self->{'comps'}}; $i++) |
|
|
0
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
{ |
|
757
|
0
|
|
|
|
|
|
my $otherg = |
|
758
|
|
|
|
|
|
|
$self->{' PARENT'}{'loca'}{'glyphs'} |
|
759
|
|
|
|
|
|
|
[$self->{'comps'}[$i]{'glyph'}]; |
|
760
|
|
|
|
|
|
|
|
|
761
|
|
|
|
|
|
|
# work around bad fonts: see documentation for 'comps' above |
|
762
|
0
|
0
|
|
|
|
|
next unless (defined $otherg ); |
|
763
|
|
|
|
|
|
|
|
|
764
|
0
|
|
|
|
|
|
@n = $otherg->maxInfo; |
|
765
|
|
|
|
|
|
|
|
|
766
|
0
|
0
|
|
|
|
|
$res[2] += $n[2] == 0 ? $n[0] : $n[2]; |
|
767
|
0
|
0
|
|
|
|
|
$res[3] += $n[3] == 0 ? $n[1] : $n[3]; |
|
768
|
0
|
|
|
|
|
|
$res[5]++; |
|
769
|
0
|
0
|
|
|
|
|
$res[6] = $n[6] + 1 if ($n[6] >= $res[6]); |
|
770
|
|
|
|
|
|
|
} |
|
771
|
|
|
|
|
|
|
} |
|
772
|
0
|
|
|
|
|
|
@res; |
|
773
|
|
|
|
|
|
|
} |
|
774
|
|
|
|
|
|
|
|
|
775
|
|
|
|
|
|
|
=head2 $g->empty |
|
776
|
|
|
|
|
|
|
|
|
777
|
|
|
|
|
|
|
Empties the glyph of all information to the level of not having been read. |
|
778
|
|
|
|
|
|
|
Useful for saving memory in apps with many glyphs being read |
|
779
|
|
|
|
|
|
|
|
|
780
|
|
|
|
|
|
|
=cut |
|
781
|
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
sub empty |
|
783
|
|
|
|
|
|
|
{ |
|
784
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
|
785
|
0
|
|
|
|
|
|
my (%keep) = map {(" $_" => 1)} ('LOC', 'OUTLOC', 'PARENT', 'INFILE', 'BASE', |
|
|
0
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
'OUTLEN', 'LEN'); |
|
787
|
0
|
0
|
|
|
|
|
map {delete $self->{$_} unless $keep{$_}} keys %$self; |
|
|
0
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
|
|
789
|
0
|
|
|
|
|
|
$self; |
|
790
|
|
|
|
|
|
|
} |
|
791
|
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
=head2 $g->get_points |
|
794
|
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
This method creates point information for a compound glyph. The information is |
|
796
|
|
|
|
|
|
|
stored in the same place as if the glyph was not a compound, but since |
|
797
|
|
|
|
|
|
|
numberOfContours is negative, the glyph is still marked as being a compound |
|
798
|
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
=cut |
|
800
|
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
sub get_points |
|
802
|
|
|
|
|
|
|
{ |
|
803
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
|
804
|
0
|
|
|
|
|
|
my ($comp, $compg, $nump, $e, $i); |
|
805
|
|
|
|
|
|
|
|
|
806
|
0
|
|
|
|
|
|
$self->read_dat; |
|
807
|
0
|
0
|
|
|
|
|
return undef unless ($self->{'numberOfContours'} < 0); |
|
808
|
|
|
|
|
|
|
|
|
809
|
0
|
|
|
|
|
|
foreach $comp (@{$self->{'comps'}}) |
|
|
0
|
|
|
|
|
|
|
|
810
|
|
|
|
|
|
|
{ |
|
811
|
0
|
|
|
|
|
|
$compg = $self->{' PARENT'}{'loca'}{'glyphs'}[$comp->{'glyph'}]; |
|
812
|
|
|
|
|
|
|
# work around bad fonts: see documentation for 'comps' above |
|
813
|
0
|
0
|
|
|
|
|
next unless (defined $compg ); |
|
814
|
0
|
|
|
|
|
|
$compg->get_points; |
|
815
|
|
|
|
|
|
|
|
|
816
|
0
|
|
|
|
|
|
for ($i = 0; $i < $compg->{'numPoints'}; $i++) |
|
817
|
|
|
|
|
|
|
{ |
|
818
|
0
|
|
|
|
|
|
my ($x, $y) = ($compg->{'x'}[$i], $compg->{'y'}[$i]); |
|
819
|
0
|
0
|
|
|
|
|
if (defined $comp->{'scale'}) |
|
820
|
|
|
|
|
|
|
{ |
|
821
|
0
|
|
|
|
|
|
($x, $y) = ($x * $comp->{'scale'}[0] + $y * $comp->{'scale'}[2], |
|
822
|
|
|
|
|
|
|
$x * $comp->{'scale'}[1] + $y * $comp->{'scale'}[3]); |
|
823
|
|
|
|
|
|
|
} |
|
824
|
0
|
0
|
|
|
|
|
if (defined $comp->{'args'}) |
|
825
|
0
|
|
|
|
|
|
{ ($x, $y) = ($x + $comp->{'args'}[0], $y + $comp->{'args'}[1]); } |
|
826
|
0
|
|
|
|
|
|
push (@{$self->{'x'}}, $x); |
|
|
0
|
|
|
|
|
|
|
|
827
|
0
|
|
|
|
|
|
push (@{$self->{'y'}}, $y); |
|
|
0
|
|
|
|
|
|
|
|
828
|
0
|
|
|
|
|
|
push (@{$self->{'flags'}}, $compg->{'flags'}[$i]); |
|
|
0
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
} |
|
830
|
0
|
|
|
|
|
|
foreach $e (@{$compg->{'endPoints'}}) |
|
|
0
|
|
|
|
|
|
|
|
831
|
0
|
|
|
|
|
|
{ push (@{$self->{'endPoints'}}, $e + $nump); } |
|
|
0
|
|
|
|
|
|
|
|
832
|
0
|
|
|
|
|
|
$nump += $compg->{'numPoints'}; |
|
833
|
|
|
|
|
|
|
} |
|
834
|
0
|
|
|
|
|
|
$self->{'numPoints'} = $nump; |
|
835
|
0
|
|
|
|
|
|
$self; |
|
836
|
|
|
|
|
|
|
} |
|
837
|
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
|
|
839
|
|
|
|
|
|
|
=head2 $g->get_refs |
|
840
|
|
|
|
|
|
|
|
|
841
|
|
|
|
|
|
|
Returns an array of all the glyph ids that are used to make up this glyph. That |
|
842
|
|
|
|
|
|
|
is all the compounds and their references and so on. If this glyph is not a |
|
843
|
|
|
|
|
|
|
compound, then returns an empty array. |
|
844
|
|
|
|
|
|
|
|
|
845
|
|
|
|
|
|
|
Please note the warning about bad fonts that reference nonexistant glyphs |
|
846
|
|
|
|
|
|
|
under INSTANCE VARIABLES above. This function will not attempt to |
|
847
|
|
|
|
|
|
|
filter out nonexistant glyph numbers. |
|
848
|
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
=cut |
|
850
|
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
sub get_refs |
|
852
|
|
|
|
|
|
|
{ |
|
853
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
|
854
|
0
|
|
|
|
|
|
my (@res, $g); |
|
855
|
|
|
|
|
|
|
|
|
856
|
0
|
|
|
|
|
|
$self->read_dat; |
|
857
|
0
|
0
|
|
|
|
|
return unless ($self->{'numberOfContours'} < 0); |
|
858
|
0
|
|
|
|
|
|
foreach $g (@{$self->{'comps'}}) |
|
|
0
|
|
|
|
|
|
|
|
859
|
|
|
|
|
|
|
{ |
|
860
|
0
|
|
|
|
|
|
push (@res, $g->{'glyph'}); |
|
861
|
0
|
|
|
|
|
|
my $otherg = $self->{' PARENT'}{'loca'}{'glyphs'}[$g->{'glyph'}]; |
|
862
|
|
|
|
|
|
|
# work around bad fonts: see documentation for 'comps' above |
|
863
|
0
|
0
|
|
|
|
|
next unless (defined $otherg); |
|
864
|
0
|
|
|
|
|
|
my @list = $otherg->get_refs; |
|
865
|
0
|
|
|
|
|
|
push(@res, @list); |
|
866
|
|
|
|
|
|
|
} |
|
867
|
0
|
|
|
|
|
|
return @res; |
|
868
|
|
|
|
|
|
|
} |
|
869
|
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
1; |
|
871
|
|
|
|
|
|
|
|
|
872
|
|
|
|
|
|
|
=head1 BUGS |
|
873
|
|
|
|
|
|
|
|
|
874
|
|
|
|
|
|
|
=over 4 |
|
875
|
|
|
|
|
|
|
|
|
876
|
|
|
|
|
|
|
=item * |
|
877
|
|
|
|
|
|
|
|
|
878
|
|
|
|
|
|
|
The instance variables used here are somewhat clunky and inconsistent with |
|
879
|
|
|
|
|
|
|
the other tables. |
|
880
|
|
|
|
|
|
|
|
|
881
|
|
|
|
|
|
|
=item * |
|
882
|
|
|
|
|
|
|
|
|
883
|
|
|
|
|
|
|
C doesn't re-calculate the bounding box or C. |
|
884
|
|
|
|
|
|
|
|
|
885
|
|
|
|
|
|
|
=back |
|
886
|
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
=head1 AUTHOR |
|
888
|
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
Martin Hosken L. |
|
890
|
|
|
|
|
|
|
|
|
891
|
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
=head1 LICENSING |
|
893
|
|
|
|
|
|
|
|
|
894
|
|
|
|
|
|
|
Copyright (c) 1998-2014, SIL International (http://www.sil.org) |
|
895
|
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
This module is released under the terms of the Artistic License 2.0. |
|
897
|
|
|
|
|
|
|
For details, see the full text of the license in the file LICENSE. |
|
898
|
|
|
|
|
|
|
|
|
899
|
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
|
|
901
|
|
|
|
|
|
|
=cut |
|
902
|
|
|
|
|
|
|
|