line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
2
|
|
|
|
|
|
|
package PostScript::File::Metrics; |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# Copyright 2009 Christopher J. Madsen |
5
|
|
|
|
|
|
|
# |
6
|
|
|
|
|
|
|
# Author: Christopher J. Madsen |
7
|
|
|
|
|
|
|
# Created: 29 Oct 2009 |
8
|
|
|
|
|
|
|
# |
9
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or modify |
10
|
|
|
|
|
|
|
# it under the same terms as Perl itself. |
11
|
|
|
|
|
|
|
# |
12
|
|
|
|
|
|
|
# This program is distributed in the hope that it will be useful, |
13
|
|
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
14
|
|
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the |
15
|
|
|
|
|
|
|
# GNU General Public License or the Artistic License for more details. |
16
|
|
|
|
|
|
|
# |
17
|
|
|
|
|
|
|
# ABSTRACT: Metrics for PostScript fonts |
18
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
19
|
|
|
|
|
|
|
|
20
|
14
|
|
|
14
|
|
299806
|
use 5.008; |
|
14
|
|
|
|
|
56
|
|
21
|
|
|
|
|
|
|
our $VERSION = '2.11'; ## no critic |
22
|
|
|
|
|
|
|
# This file is part of PostScript-File 2.23 (October 10, 2015) |
23
|
|
|
|
|
|
|
|
24
|
14
|
|
|
14
|
|
77
|
use strict; |
|
14
|
|
|
|
|
24
|
|
|
14
|
|
|
|
|
308
|
|
25
|
14
|
|
|
14
|
|
67
|
use warnings; |
|
14
|
|
|
|
|
25
|
|
|
14
|
|
|
|
|
433
|
|
26
|
14
|
|
|
14
|
|
71
|
use Carp qw(carp croak); |
|
14
|
|
|
|
|
25
|
|
|
14
|
|
|
|
|
1062
|
|
27
|
14
|
|
|
14
|
|
11959
|
use Encode qw(find_encoding); |
|
14
|
|
|
|
|
158046
|
|
|
14
|
|
|
|
|
4419
|
|
28
|
|
|
|
|
|
|
|
29
|
14
|
|
|
14
|
|
17688
|
use PostScript::File ':metrics_methods'; # Import some methods |
|
14
|
|
|
|
|
45
|
|
|
14
|
|
|
|
|
4823
|
|
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
our (%Info, %Metrics); |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
#===================================================================== |
34
|
|
|
|
|
|
|
# Generate accessor methods: |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
BEGIN { |
37
|
14
|
|
|
14
|
|
36
|
my ($code, $error, $success) = ''; |
38
|
14
|
|
|
|
|
38
|
foreach my $attribute (qw( |
39
|
|
|
|
|
|
|
full_name |
40
|
|
|
|
|
|
|
family |
41
|
|
|
|
|
|
|
weight |
42
|
|
|
|
|
|
|
fixed_pitch |
43
|
|
|
|
|
|
|
italic_angle |
44
|
|
|
|
|
|
|
version |
45
|
|
|
|
|
|
|
)) { |
46
|
84
|
|
|
|
|
208
|
$code .= "sub $attribute { shift->{info}{$attribute} };\n"; |
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
|
49
|
14
|
|
|
|
|
33
|
foreach my $attribute (qw( |
50
|
|
|
|
|
|
|
underline_position |
51
|
|
|
|
|
|
|
underline_thickness |
52
|
|
|
|
|
|
|
cap_height |
53
|
|
|
|
|
|
|
x_height |
54
|
|
|
|
|
|
|
ascender |
55
|
|
|
|
|
|
|
descender |
56
|
|
|
|
|
|
|
)) { |
57
|
84
|
|
|
|
|
210
|
$code .= <<"END SUB"; |
58
|
|
|
|
|
|
|
sub $attribute { |
59
|
|
|
|
|
|
|
my \$self = shift; |
60
|
|
|
|
|
|
|
my \$v = \$self->{info}{$attribute}; |
61
|
|
|
|
|
|
|
defined \$v ? \$v * \$self->{factor} : \$v; |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
END SUB |
64
|
|
|
|
|
|
|
} |
65
|
|
|
|
|
|
|
|
66
|
14
|
|
|
|
|
29
|
{ local $@; |
|
14
|
|
|
|
|
22
|
|
67
|
14
|
0
|
|
0
|
1
|
5642
|
$success = eval "$code ; 'OK'"; ## no critic ProhibitStringyEval |
|
0
|
0
|
|
0
|
1
|
0
|
|
|
0
|
0
|
|
0
|
1
|
0
|
|
|
0
|
0
|
|
0
|
1
|
0
|
|
|
0
|
0
|
|
0
|
1
|
0
|
|
|
0
|
0
|
|
0
|
1
|
0
|
|
|
0
|
|
|
0
|
1
|
0
|
|
|
0
|
|
|
0
|
1
|
0
|
|
|
0
|
|
|
0
|
1
|
0
|
|
|
0
|
|
|
0
|
1
|
0
|
|
|
0
|
|
|
0
|
1
|
0
|
|
|
0
|
|
|
0
|
1
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
68
|
14
|
|
|
|
|
42
|
$error = $@; |
69
|
|
|
|
|
|
|
} # end local $@ |
70
|
|
|
|
|
|
|
|
71
|
14
|
50
|
33
|
|
|
20649
|
unless ($success and $success eq 'OK') { |
72
|
0
|
|
0
|
|
|
0
|
$error ||= 'eval died with false $@'; |
73
|
0
|
|
|
|
|
0
|
die "$code\n$error"; |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
} # end BEGIN |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
78
|
|
|
|
|
|
|
sub font_bbox |
79
|
|
|
|
|
|
|
{ |
80
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
81
|
|
|
|
|
|
|
|
82
|
0
|
|
|
|
|
0
|
my $bbox = $self->{info}{font_bbox}; |
83
|
|
|
|
|
|
|
|
84
|
0
|
0
|
|
|
|
0
|
if (1 != (my $f = $self->{factor})) { |
85
|
0
|
|
|
|
|
0
|
[ map { $_ * $f } @$bbox ]; |
|
0
|
|
|
|
|
0
|
|
86
|
|
|
|
|
|
|
} else { |
87
|
0
|
|
|
|
|
0
|
$bbox; |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
} # end font_bbox |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
92
|
0
|
|
|
0
|
1
|
0
|
sub auto_hyphen { shift->{auto_hyphen} } |
93
|
0
|
|
|
0
|
1
|
0
|
sub size { shift->{size} } |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
#===================================================================== |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
sub new |
99
|
|
|
|
|
|
|
{ |
100
|
13
|
|
|
13
|
1
|
948
|
my ($class, $font, $size, $encoding) = @_; |
101
|
|
|
|
|
|
|
|
102
|
13
|
0
|
33
|
|
|
74
|
$encoding ||= ($font eq 'Symbol' ? 'sym' : 'std'); |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
# Load the metrics if necessary: |
105
|
13
|
50
|
|
|
|
78
|
unless ($Metrics{$font}{$encoding}) { |
106
|
|
|
|
|
|
|
# First, try to load a pre-compiled package: |
107
|
13
|
|
|
|
|
59
|
my $package = _get_package_name($font, $encoding); |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
## no critic (ProhibitStringyEval) |
110
|
13
|
50
|
33
|
|
|
26
|
unless (do { local $@; eval "require $package; 1" } |
|
13
|
|
|
|
|
31
|
|
|
13
|
|
|
|
|
1236
|
|
111
|
|
|
|
|
|
|
and $Metrics{$font}{$encoding}) { |
112
|
|
|
|
|
|
|
# No pre-compiled package, we'll have to read the AFM file: |
113
|
|
|
|
|
|
|
## use critic |
114
|
0
|
|
|
|
|
0
|
require PostScript::File::Metrics::Loader; |
115
|
|
|
|
|
|
|
|
116
|
0
|
|
|
|
|
0
|
PostScript::File::Metrics::Loader::load($font, [$encoding]); |
117
|
|
|
|
|
|
|
} # end unless metrics have been pre-generated |
118
|
|
|
|
|
|
|
} # end unless the metrics are loaded |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
# Create the Metrics object: |
121
|
|
|
|
|
|
|
my $self = bless { |
122
|
|
|
|
|
|
|
info => $Info{$font}, |
123
|
13
|
|
33
|
|
|
136
|
metrics => $Metrics{$font}{$encoding} |
124
|
|
|
|
|
|
|
|| croak "Failed to load metrics for $font in encoding $encoding", |
125
|
|
|
|
|
|
|
}, $class; |
126
|
|
|
|
|
|
|
|
127
|
13
|
50
|
33
|
|
|
120
|
$self->{encoding} = find_encoding($encoding) |
128
|
|
|
|
|
|
|
or croak "Unknown encoding $encoding" |
129
|
|
|
|
|
|
|
unless $encoding =~ /^(?:std|sym)$/; |
130
|
13
|
|
|
|
|
3584
|
$self->set_auto_hyphen(1); |
131
|
13
|
|
|
|
|
58
|
$self->set_size($size); |
132
|
13
|
|
|
|
|
112
|
$self->set_wrap_chars; |
133
|
|
|
|
|
|
|
} # end new |
134
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
sub set_size |
138
|
|
|
|
|
|
|
{ |
139
|
13
|
|
|
13
|
1
|
33
|
my ($self, $size) = @_; |
140
|
|
|
|
|
|
|
|
141
|
13
|
|
50
|
|
|
63
|
$self->{size} = $size || 1000; |
142
|
|
|
|
|
|
|
|
143
|
13
|
50
|
|
|
|
70
|
$self->{factor} = ($size ? $size/1000.0 : 1); |
144
|
|
|
|
|
|
|
|
145
|
13
|
|
|
|
|
28
|
$self; |
146
|
|
|
|
|
|
|
} # end set_size |
147
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
sub width |
151
|
|
|
|
|
|
|
{ |
152
|
157
|
|
|
157
|
1
|
230
|
my $self = shift; # $string |
153
|
|
|
|
|
|
|
|
154
|
157
|
50
|
33
|
|
|
670
|
return 0.0 unless defined $_[0] and length $_[0]; |
155
|
|
|
|
|
|
|
|
156
|
157
|
|
|
|
|
232
|
my $wx = $self->{metrics}; |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
my $string = $_[1] ? $_[0] : $self->encode_text( |
159
|
157
|
0
|
|
|
|
287
|
$self->{auto_hyphen} ? $self->convert_hyphens($_[0]) : $_[0] |
|
|
50
|
|
|
|
|
|
160
|
|
|
|
|
|
|
); |
161
|
|
|
|
|
|
|
|
162
|
157
|
|
|
|
|
197
|
my $width = 0; |
163
|
157
|
|
|
|
|
891
|
$width += $wx->[$_] for unpack("C*", $string); |
164
|
|
|
|
|
|
|
|
165
|
157
|
|
|
|
|
560
|
$width * $self->{factor}; |
166
|
|
|
|
|
|
|
} # end width |
167
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
sub wrap |
171
|
|
|
|
|
|
|
{ |
172
|
15
|
|
|
15
|
1
|
17193
|
my $self = shift; |
173
|
15
|
|
|
|
|
23
|
my $width = shift; |
174
|
15
|
|
|
|
|
21
|
my $text = shift; |
175
|
15
|
100
|
|
|
|
42
|
my %param = @_ ? %{+shift} : (); |
|
4
|
|
|
|
|
16
|
|
176
|
|
|
|
|
|
|
|
177
|
15
|
|
|
|
|
26
|
my $maxlines = delete $param{maxlines}; |
178
|
15
|
|
|
|
|
18
|
my $quiet = delete $param{quiet}; |
179
|
15
|
|
|
|
|
19
|
my $warnings = delete $param{warnings}; |
180
|
|
|
|
|
|
|
my $re = (exists($param{chars}) |
181
|
|
|
|
|
|
|
? $self->_build_wrap_re(delete $param{chars}) |
182
|
15
|
100
|
|
|
|
38
|
: $self->{wrap_re}); |
183
|
|
|
|
|
|
|
|
184
|
15
|
50
|
|
|
|
38
|
carp "Unknown wrap parameter(s) @{[ keys %param ]}" if %param; |
|
0
|
|
|
|
|
0
|
|
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
# Remove CRs; convert ZWSP to CR: |
187
|
15
|
|
|
|
|
28
|
$text =~ s/\r//g; |
188
|
15
|
100
|
|
|
|
55
|
$text =~ s/\x{200B}/\r/g if Encode::is_utf8($text); |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
$text = $self->encode_text( |
191
|
15
|
50
|
|
|
|
64
|
$self->{auto_hyphen} ? $self->convert_hyphens($text) : $text |
192
|
|
|
|
|
|
|
); |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
# Do word wrapping: |
195
|
15
|
|
|
|
|
54
|
my @lines = ''; |
196
|
|
|
|
|
|
|
|
197
|
15
|
|
|
|
|
29
|
for ($text) { |
198
|
136
|
100
|
|
|
|
295
|
if (m/\G[ \t\r]*\n/gc) { |
199
|
6
|
|
|
|
|
13
|
push @lines, ''; |
200
|
|
|
|
|
|
|
} else { |
201
|
130
|
100
|
|
|
|
853
|
m/\G($re)/g or last; |
202
|
118
|
|
|
|
|
210
|
my $word = $1; |
203
|
|
|
|
|
|
|
check_word: |
204
|
155
|
100
|
|
|
|
414
|
if ($self->width($lines[-1] . $word, 1) <= $width) { |
|
|
100
|
|
|
|
|
|
205
|
117
|
|
|
|
|
237
|
$lines[-1] .= $word; |
206
|
|
|
|
|
|
|
} elsif ($lines[-1] eq '') { |
207
|
1
|
|
|
|
|
2
|
$lines[-1] = $word; |
208
|
1
|
|
|
|
|
3
|
my $w = sprintf("%s is too wide (%g) for field width %g", |
209
|
|
|
|
|
|
|
$word, $self->width($word, 1), $width); |
210
|
1
|
50
|
|
|
|
4
|
push @$warnings, $w if $warnings; |
211
|
1
|
50
|
|
|
|
99
|
carp $w unless $quiet; |
212
|
|
|
|
|
|
|
} else { |
213
|
37
|
|
|
|
|
56
|
push @lines, ''; |
214
|
37
|
|
|
|
|
96
|
$word =~ s/^[ \t\r]+//; |
215
|
37
|
|
|
|
|
203
|
goto check_word; |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
} # end else not at LF |
218
|
|
|
|
|
|
|
|
219
|
124
|
100
|
100
|
|
|
432
|
if (defined $maxlines and @lines >= $maxlines) { |
220
|
3
|
50
|
|
|
|
18
|
$lines[-1] .= $1 if m/\G(.*[^ \t\r\n])/sg; |
221
|
3
|
100
|
66
|
|
|
19
|
if (($warnings or not $quiet) and |
|
|
|
66
|
|
|
|
|
222
|
|
|
|
|
|
|
(my $linewidth = $self->width($lines[-1], 1)) > $width) { |
223
|
1
|
|
|
|
|
13
|
my $w = sprintf("'%s' is too wide (%g) for field width %g", |
224
|
|
|
|
|
|
|
$lines[-1], $linewidth, $width); |
225
|
1
|
50
|
|
|
|
6
|
push @$warnings, $w if $warnings; |
226
|
1
|
50
|
|
|
|
169
|
carp $w unless $quiet; |
227
|
|
|
|
|
|
|
} # end if issuing warning about last line |
228
|
3
|
|
|
|
|
87
|
last; |
229
|
|
|
|
|
|
|
} # end if reached maximum number of lines |
230
|
|
|
|
|
|
|
|
231
|
121
|
|
|
|
|
142
|
redo; # Only the "last" statement above can exit |
232
|
|
|
|
|
|
|
} # end for $text |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
# Remove any remaining CR (ZWSP) chars: |
235
|
15
|
|
|
|
|
62
|
s/\r//g for @lines; |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
# Remove the last line if it's blank ($text ended with newline): |
238
|
15
|
100
|
100
|
|
|
63
|
pop @lines unless @lines == 1 or length $lines[-1]; |
239
|
|
|
|
|
|
|
|
240
|
15
|
50
|
|
|
|
39
|
if ($self->{auto_hyphen}) { |
241
|
|
|
|
|
|
|
# At this point, any hyphen-minus characters are unambiguously |
242
|
|
|
|
|
|
|
# MINUS SIGN. Protect them from further processing: |
243
|
15
|
|
|
|
|
24
|
map { $self->decode_text($_, 1) } @lines; |
|
57
|
|
|
|
|
155
|
|
244
|
|
|
|
|
|
|
} else { |
245
|
0
|
|
|
|
|
0
|
@lines; |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
} # end wrap |
248
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
sub set_wrap_chars |
252
|
|
|
|
|
|
|
{ |
253
|
13
|
|
|
13
|
1
|
26
|
my $self = shift; |
254
|
|
|
|
|
|
|
|
255
|
13
|
|
|
|
|
62
|
$self->{wrap_re} = $self->_build_wrap_re(@_); |
256
|
|
|
|
|
|
|
|
257
|
13
|
|
|
|
|
70
|
$self; |
258
|
|
|
|
|
|
|
} # end set_wrap_chars |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
261
|
|
|
|
|
|
|
our %_wrap_re_cache; |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
sub _build_wrap_re |
264
|
|
|
|
|
|
|
{ |
265
|
14
|
|
|
14
|
|
30
|
my ($self, $chars) = @_; |
266
|
|
|
|
|
|
|
|
267
|
14
|
100
|
|
|
|
56
|
if (not defined $chars) { |
268
|
13
|
|
|
|
|
26
|
$chars = '-/'; |
269
|
13
|
50
|
|
|
|
56
|
if ($self->{encoding}) { |
270
|
13
|
|
|
|
|
73
|
$chars .= "\xAD"; |
271
|
|
|
|
|
|
|
# Only cp1252 has en dash & em dash: |
272
|
13
|
100
|
|
|
|
195
|
$chars .= "\x{2013}\x{2014}" if $self->{encoding}->name eq 'cp1252'; |
273
|
|
|
|
|
|
|
} |
274
|
|
|
|
|
|
|
} # end if $chars not supplied (use default) |
275
|
|
|
|
|
|
|
|
276
|
14
|
|
|
|
|
117
|
$chars = $self->encode_text($chars); |
277
|
|
|
|
|
|
|
|
278
|
14
|
|
33
|
|
|
165
|
return $_wrap_re_cache{$chars} ||= do { |
279
|
14
|
100
|
|
|
|
49
|
if (length $chars) { |
280
|
13
|
|
|
|
|
73
|
$chars =~ s/(.)/ sprintf '\x%02X', ord $1 /seg; |
|
41
|
|
|
|
|
200
|
|
281
|
|
|
|
|
|
|
|
282
|
13
|
|
|
|
|
946
|
qr( |
283
|
|
|
|
|
|
|
[ \t\r]* |
284
|
|
|
|
|
|
|
(?: [^$chars \t\r\n]+ | |
285
|
|
|
|
|
|
|
[$chars]+ [^$chars \t\r\n]* ) |
286
|
|
|
|
|
|
|
[$chars]* |
287
|
|
|
|
|
|
|
)x; |
288
|
|
|
|
|
|
|
} else { |
289
|
1
|
|
|
|
|
6
|
qr( [ \t\r]* [^ \t\r\n]+ )x; |
290
|
|
|
|
|
|
|
} |
291
|
|
|
|
|
|
|
}; |
292
|
|
|
|
|
|
|
} # end _build_wrap_re |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
295
|
|
|
|
|
|
|
# Return the package in which the font's metrics are stored: |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
sub _get_package_name |
298
|
|
|
|
|
|
|
{ |
299
|
13
|
|
|
13
|
|
32
|
my ($font, $encoding) = @_; |
300
|
|
|
|
|
|
|
|
301
|
13
|
|
|
|
|
31
|
my $package = $encoding; |
302
|
13
|
|
|
|
|
80
|
$package =~ s/-/_/g; |
303
|
13
|
|
|
|
|
42
|
$package .= " $font"; |
304
|
13
|
|
|
|
|
83
|
$package =~ s/\W+/::/g; |
305
|
|
|
|
|
|
|
|
306
|
13
|
|
|
|
|
52
|
"PostScript::File::Metrics::$package"; |
307
|
|
|
|
|
|
|
} # end _get_package_name |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
#===================================================================== |
310
|
|
|
|
|
|
|
# Package Return Value: |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
1; |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
__END__ |