line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package PDF::Builder::Resource::Font::SynFont; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
1140
|
use base 'PDF::Builder::Resource::Font'; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
107
|
|
4
|
|
|
|
|
|
|
|
5
|
1
|
|
|
1
|
|
7
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
21
|
|
6
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
50
|
|
7
|
|
|
|
|
|
|
#no warnings qw[ deprecated recursion uninitialized ]; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
our $VERSION = '3.023'; # VERSION |
10
|
|
|
|
|
|
|
our $LAST_UPDATE = '3.022'; # manually update whenever code is changed |
11
|
|
|
|
|
|
|
|
12
|
1
|
|
|
1
|
|
6
|
use Math::Trig; # CAUTION: deg2rad(0) = deg2rad(360) = 0! |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
209
|
|
13
|
1
|
|
|
1
|
|
9
|
use Unicode::UCD 'charinfo'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
88
|
|
14
|
|
|
|
|
|
|
|
15
|
1
|
|
|
1
|
|
7
|
use PDF::Builder::Util; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
132
|
|
16
|
1
|
|
|
1
|
|
7
|
use PDF::Builder::Basic::PDF::Utils; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
2418
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 NAME |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
PDF::Builder::Resource::Font::SynFont - Module for using synthetic Fonts. |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=head1 SYNOPSIS |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
# |
25
|
|
|
|
|
|
|
use PDF::Builder; |
26
|
|
|
|
|
|
|
# |
27
|
|
|
|
|
|
|
$pdf = PDF::Builder->new(); |
28
|
|
|
|
|
|
|
$cft = $pdf->corefont('Times-Roman'); # ttfont, etc. also works |
29
|
|
|
|
|
|
|
$sft = $pdf->synfont($cft, -condense => .75); # condense by 25% |
30
|
|
|
|
|
|
|
# |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
This works for I, I, and I; but does not |
33
|
|
|
|
|
|
|
work for I or I. |
34
|
|
|
|
|
|
|
See also L. |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
=head1 METHODS |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
=over 4 |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=cut |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=item $font = PDF::Builder::Resource::Font::SynFont->new($pdf, $fontobj, %options) |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
Returns a synfont object. |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=cut |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
=pod |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
Valid %options are: |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
I<-encode> |
53
|
|
|
|
|
|
|
... changes the encoding of the font from its default. |
54
|
|
|
|
|
|
|
See I for the supported values. B only single byte |
55
|
|
|
|
|
|
|
encodings are supported. Multibyte encodings such as UTF-8 are invalid. |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
I<-pdfname> |
58
|
|
|
|
|
|
|
... changes the reference-name of the font from its default. |
59
|
|
|
|
|
|
|
The reference-name is normally generated automatically and can be |
60
|
|
|
|
|
|
|
retrieved via $pdfname=$font->name(). |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
I<-condense> |
63
|
|
|
|
|
|
|
... condense/expand factor (0.1-0.9 = condense, 1 = normal, 1.1+ = expand). |
64
|
|
|
|
|
|
|
It's the multiplier for character widths vs. normal. |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
I<-oblique> |
67
|
|
|
|
|
|
|
... italic angle (+/-) in degrees, where the character box is skewed. While |
68
|
|
|
|
|
|
|
it's unlikely that anyone will want to slant characters at +/-360 degrees, they |
69
|
|
|
|
|
|
|
should be aware that these will be treated as an angle of 0 degrees (deg2rad() |
70
|
|
|
|
|
|
|
wraps around). 0 degrees of italic slant (obliqueness) is the default. |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
I<-bold> |
73
|
|
|
|
|
|
|
... embolding factor (0.1+, bold=1, heavy=2, ...). It is additional outline |
74
|
|
|
|
|
|
|
B (B), which expands the character outwards. |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
I<-space> |
77
|
|
|
|
|
|
|
... additional charspacing in em (0-1000). |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
I<-caps> |
80
|
|
|
|
|
|
|
... create synthetic small-caps. 0 = no, 1 = yes. These are capitals of |
81
|
|
|
|
|
|
|
lowercase letters, at 80% height and 88% width. |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=back |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
=cut |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
sub new |
88
|
|
|
|
|
|
|
{ |
89
|
0
|
|
|
0
|
1
|
|
my ($class, $pdf, $font, @opts) = @_; |
90
|
|
|
|
|
|
|
|
91
|
0
|
|
|
|
|
|
my ($self); |
92
|
0
|
|
|
|
|
|
my %opts = @opts; |
93
|
0
|
|
|
|
|
|
my $first = 1; |
94
|
0
|
|
|
|
|
|
my $last = 255; |
95
|
0
|
|
0
|
|
|
|
my $cond = $opts{'-condense'} || 1; |
96
|
0
|
|
0
|
|
|
|
my $oblique = $opts{'-oblique'} || 0; |
97
|
0
|
|
0
|
|
|
|
my $space = $opts{'-space'} || '0'; |
98
|
0
|
|
0
|
|
|
|
my $bold = ($opts{'-bold'} || 0)*10; # convert to em |
99
|
|
|
|
|
|
|
# -caps |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# 5 elements apparently not used anywhere |
102
|
|
|
|
|
|
|
#$self->{' cond'} = $cond; |
103
|
|
|
|
|
|
|
#$self->{' oblique'} = $oblique; |
104
|
|
|
|
|
|
|
#$self->{' bold'} = $bold; |
105
|
|
|
|
|
|
|
#$self->{' boldmove'} = 0.001; |
106
|
|
|
|
|
|
|
#$self->{' space'} = $space; |
107
|
|
|
|
|
|
|
# only available in TT fonts. besides, multibyte encodings not supported |
108
|
0
|
0
|
|
|
|
|
if (defined $opts{'-encode'}) { |
109
|
0
|
0
|
|
|
|
|
if ($opts{'-encode'} =~ m/^utf/i) { |
110
|
0
|
|
|
|
|
|
die "Invalid multibyte encoding for synfont: $opts{'-encode'}\n"; |
111
|
|
|
|
|
|
|
# TBD probably more multibyte encodings to check |
112
|
|
|
|
|
|
|
} |
113
|
0
|
|
|
|
|
|
$font->encodeByName($opts{'-encode'}); |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
0
|
0
|
|
|
|
|
$class = ref $class if ref $class; |
117
|
|
|
|
|
|
|
$self = $class->SUPER::new($pdf, |
118
|
|
|
|
|
|
|
pdfkey() |
119
|
|
|
|
|
|
|
.('+' . $font->name()) |
120
|
|
|
|
|
|
|
.($opts{'-caps'} ? '+Caps' : '') |
121
|
0
|
0
|
|
|
|
|
.($opts{'-pdfname'} ? '+'.$opts{'-pdfname'} : '') |
|
|
0
|
|
|
|
|
|
122
|
|
|
|
|
|
|
); |
123
|
0
|
0
|
|
|
|
|
$pdf->new_obj($self) unless $self->is_obj($pdf); |
124
|
0
|
|
|
|
|
|
$self->{' font'} = $font; |
125
|
0
|
|
0
|
|
|
|
$self->{' data'} = { |
126
|
|
|
|
|
|
|
'type' => 'Type3', |
127
|
|
|
|
|
|
|
'ascender' => $font->ascender(), |
128
|
|
|
|
|
|
|
'capheight' => $font->capheight(), |
129
|
|
|
|
|
|
|
'descender' => $font->descender(), |
130
|
|
|
|
|
|
|
'iscore' => '0', |
131
|
|
|
|
|
|
|
'isfixedpitch' => $font->isfixedpitch(), |
132
|
|
|
|
|
|
|
'italicangle' => $font->italicangle() + $oblique, |
133
|
|
|
|
|
|
|
'missingwidth' => ($font->missingwidth()||300) * $cond, |
134
|
|
|
|
|
|
|
'underlineposition' => $font->underlineposition(), |
135
|
|
|
|
|
|
|
'underlinethickness' => $font->underlinethickness(), |
136
|
|
|
|
|
|
|
'xheight' => $font->xheight(), |
137
|
|
|
|
|
|
|
'firstchar' => $first, |
138
|
|
|
|
|
|
|
'lastchar' => $last, |
139
|
|
|
|
|
|
|
'char' => [ '.notdef' ], |
140
|
|
|
|
|
|
|
'uni' => [ 0 ], |
141
|
|
|
|
|
|
|
'u2e' => { 0 => 0 }, |
142
|
|
|
|
|
|
|
'fontbbox' => '', |
143
|
|
|
|
|
|
|
'wx' => { 'space' => '600' }, |
144
|
|
|
|
|
|
|
}; |
145
|
|
|
|
|
|
|
|
146
|
0
|
0
|
|
|
|
|
if (ref($font->fontbbox())) { |
147
|
0
|
|
|
|
|
|
$self->data()->{'fontbbox'} = [ @{$font->fontbbox()} ]; |
|
0
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
} else { |
149
|
0
|
|
|
|
|
|
$self->data()->{'fontbbox'} = [ $font->fontbbox() ]; |
150
|
|
|
|
|
|
|
} |
151
|
0
|
|
|
|
|
|
$self->data()->{'fontbbox'}->[0] *= $cond; |
152
|
0
|
|
|
|
|
|
$self->data()->{'fontbbox'}->[2] *= $cond; |
153
|
|
|
|
|
|
|
|
154
|
0
|
|
|
|
|
|
$self->{'Subtype'} = PDFName('Type3'); |
155
|
0
|
|
|
|
|
|
$self->{'FirstChar'} = PDFNum($first); |
156
|
0
|
|
|
|
|
|
$self->{'LastChar'} = PDFNum($last); |
157
|
0
|
|
|
|
|
|
$self->{'FontMatrix'} = PDFArray(map { PDFNum($_) } ( 0.001, 0, 0, 0.001, 0, 0 ) ); |
|
0
|
|
|
|
|
|
|
158
|
0
|
|
|
|
|
|
$self->{'FontBBox'} = PDFArray(map { PDFNum($_) } ( $self->fontbbox() ) ); |
|
0
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
|
160
|
0
|
|
|
|
|
|
my $procs = PDFDict(); |
161
|
0
|
|
|
|
|
|
$pdf->new_obj($procs); |
162
|
0
|
|
|
|
|
|
$self->{'CharProcs'} = $procs; |
163
|
|
|
|
|
|
|
|
164
|
0
|
|
|
|
|
|
$self->{'Resources'} = PDFDict(); |
165
|
0
|
|
|
|
|
|
$self->{'Resources'}->{'ProcSet'} = PDFArray(map { PDFName($_) } qw[ PDF Text ImageB ImageC ImageI ]); |
|
0
|
|
|
|
|
|
|
166
|
0
|
|
|
|
|
|
my $xo = PDFDict(); |
167
|
0
|
|
|
|
|
|
$self->{'Resources'}->{'Font'} = $xo; |
168
|
0
|
|
|
|
|
|
$self->{'Resources'}->{'Font'}->{'FSN'} = $font; |
169
|
0
|
|
|
|
|
|
foreach my $w ($first .. $last) { |
170
|
0
|
|
|
|
|
|
$self->data()->{'char'}->[$w] = $font->glyphByEnc($w); |
171
|
|
|
|
|
|
|
# possible non-standard name... use $w as Unicode value |
172
|
0
|
|
0
|
|
|
|
$self->data()->{'uni'}->[$w] = (uniByName($self->data()->{'char'}->[$w]))||$w; |
173
|
0
|
|
|
|
|
|
$self->data()->{'u2e'}->{$self->data()->{'uni'}->[$w]} = $w; |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
0
|
0
|
|
|
|
|
if ($font->isa('PDF::Builder::Resource::CIDFont')) { |
177
|
0
|
|
|
|
|
|
$self->{'Encoding'} = PDFDict(); |
178
|
0
|
|
|
|
|
|
$self->{'Encoding'}->{'Type'} = PDFName('Encoding'); |
179
|
0
|
|
|
|
|
|
$self->{'Encoding'}->{'Differences'} = PDFArray(); |
180
|
0
|
|
|
|
|
|
foreach my $w ($first .. $last) { |
181
|
0
|
0
|
0
|
|
|
|
if (defined $self->data()->{'char'}->[$w] && |
182
|
|
|
|
|
|
|
$self->data()->{'char'}->[$w] ne '.notdef') { |
183
|
0
|
|
|
|
|
|
$self->{'Encoding'}->{'Differences'}->add_elements(PDFNum($w),PDFName($self->data()->{'char'}->[$w])); |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
} else { |
187
|
0
|
|
|
|
|
|
$self->{'Encoding'} = $font->{'Encoding'}; |
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
|
190
|
0
|
|
|
|
|
|
my @widths = (); |
191
|
0
|
|
|
|
|
|
foreach my $w ($first .. $last) { |
192
|
|
|
|
|
|
|
# $w is the "standard encoding" (similar to Windows-1252) PDF |
193
|
|
|
|
|
|
|
# single byte encoding. first 32 .notdef, 255 = U+00FF ydieresis |
194
|
0
|
0
|
|
|
|
|
if ($self->data()->{'char'}->[$w] eq '.notdef') { |
195
|
0
|
|
|
|
|
|
push @widths, $self->missingwidth(); |
196
|
0
|
|
|
|
|
|
next; |
197
|
|
|
|
|
|
|
} |
198
|
0
|
|
|
|
|
|
my $char = PDFDict(); |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
#my $wth = int($font->width(chr($w)) * 1000 * $cond + 2 * $space); |
201
|
0
|
|
|
|
|
|
my $uni = $self->data()->{'uni'}->[$w]; |
202
|
0
|
|
|
|
|
|
my $wth = int($font->width(chr($uni)) * 1000 * $cond + 2*$space); |
203
|
|
|
|
|
|
|
|
204
|
0
|
|
|
|
|
|
$procs->{$font->glyphByEnc($w)} = $char; |
205
|
|
|
|
|
|
|
#$char->{'Filter'} = PDFArray(PDFName('FlateDecode')); |
206
|
0
|
|
|
|
|
|
$char->{' stream'} = $wth." 0 ".join(' ',map { int($_) } $self->fontbbox())." d1\n"; |
|
0
|
|
|
|
|
|
|
207
|
0
|
|
|
|
|
|
$char->{' stream'} .= "BT\n"; |
208
|
0
|
0
|
|
|
|
|
$char->{' stream'} .= join(' ', 1, 0, tan(deg2rad($oblique)), 1, 0, 0)." Tm\n" if $oblique; |
209
|
0
|
0
|
|
|
|
|
$char->{' stream'} .= "2 Tr ".($bold)." w\n" if $bold; |
210
|
|
|
|
|
|
|
#my $ci = charinfo($self->data()->{'uni'}->[$w]); |
211
|
0
|
|
|
|
|
|
my $ci = {}; |
212
|
0
|
0
|
|
|
|
|
if ($self->data()->{'uni'}->[$w] ne '') { |
213
|
0
|
|
|
|
|
|
$ci = charinfo($self->data()->{'uni'}->[$w]); |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
# Small Caps |
217
|
|
|
|
|
|
|
# |
218
|
|
|
|
|
|
|
# Most Unicode characters simply don't appear in the synthetic |
219
|
|
|
|
|
|
|
# font, which is limited to 255 "standard" encoding points. -encode |
220
|
|
|
|
|
|
|
# still will be single byte. |
221
|
|
|
|
|
|
|
# |
222
|
|
|
|
|
|
|
# SynFont seems to have trouble with some accented characters, even |
223
|
|
|
|
|
|
|
# though 'upper' is correct and they are in the standard encoding, |
224
|
|
|
|
|
|
|
# particularly if the string is decoded to UTF-8. Keep in mind that |
225
|
|
|
|
|
|
|
# synfont() only creates a 255 character "standard" encoding font, so |
226
|
|
|
|
|
|
|
# you need to apply it to each "plane" of the original font. |
227
|
|
|
|
|
|
|
# |
228
|
|
|
|
|
|
|
# Some single characters (eszett within the standard encoding, long s |
229
|
|
|
|
|
|
|
# outside it) don't have 'upper' defined and are left as-is (or |
230
|
|
|
|
|
|
|
# skipped entirely, if outside the encoding) unless first replaced by |
231
|
|
|
|
|
|
|
# ASCII lowercase ('ss' and 's' respectively). While we're at it, |
232
|
|
|
|
|
|
|
# replace certain Unicode ligatures with ASCII equivalents so they |
233
|
|
|
|
|
|
|
# will be small-capped correctly instead of ignored. Don't forget to |
234
|
|
|
|
|
|
|
# set proper width for multi-letter replacements. |
235
|
|
|
|
|
|
|
# |
236
|
0
|
|
|
|
|
|
my $hasUpper = 0; # if no small caps, still need to output something |
237
|
0
|
0
|
|
|
|
|
if ($opts{'-caps'}) { |
238
|
|
|
|
|
|
|
# not all characters have an 'upper' equivalent code point. Some |
239
|
|
|
|
|
|
|
# have U+0000 (dummy entry). |
240
|
0
|
|
|
|
|
|
my $ch; |
241
|
0
|
|
|
|
|
|
my $multiChar = 0; |
242
|
0
|
0
|
0
|
|
|
|
$hasUpper = 1 if defined $ci->{'upper'} && $ci->{'upper'}; |
243
|
|
|
|
|
|
|
|
244
|
0
|
0
|
|
|
|
|
if ($hasUpper) { |
245
|
|
|
|
|
|
|
# standard upper case character and width spec'd by font |
246
|
0
|
|
|
|
|
|
$ch = $self->encByUni(hex($ci->{'upper'})); |
247
|
0
|
|
|
|
|
|
$wth = int($font->width(chr($ch)) * 800 * $cond * 1.1 + 2* $space); |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
# let's handle some special cases where !$hasUpper |
250
|
|
|
|
|
|
|
# ($hasUpper set to 1) |
251
|
|
|
|
|
|
|
# only characters to be substituted here, unless there is something |
252
|
|
|
|
|
|
|
# in other encodings to deal with |
253
|
|
|
|
|
|
|
# TBD it does not seem to be possible on non-base planes (plane 1+) |
254
|
|
|
|
|
|
|
# to access ASCII letters to build a substitute for ligatures |
255
|
|
|
|
|
|
|
# (e.g., replace U+FB01 fi ligature with F+I) |
256
|
0
|
0
|
|
|
|
|
if ($uni == 0xDF) { # eszett (German sharp s) |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
257
|
0
|
|
|
|
|
|
$hasUpper = 1; |
258
|
0
|
|
|
|
|
|
$multiChar = 1; |
259
|
|
|
|
|
|
|
# actually, some fonts have a U+1E9E uppercase Eszett, but |
260
|
|
|
|
|
|
|
# since that won't be in any single byte encoding, we use SS |
261
|
0
|
|
|
|
|
|
$wth = 2*(int($font->width('S') * 800 * $cond*1.1 + 2*$space)); |
262
|
0
|
|
|
|
|
|
$ch = $font->text('S').$font->text('S'); |
263
|
|
|
|
|
|
|
} elsif ($uni == 0x0131) { # dotless i |
264
|
|
|
|
|
|
|
# standard encoding doesn't see Unicode point |
265
|
0
|
|
|
|
|
|
$hasUpper = 1; |
266
|
0
|
|
|
|
|
|
$multiChar = 1; |
267
|
0
|
|
|
|
|
|
$wth = int($font->width('I') * 800 * $cond*1.1 + 2*$space); |
268
|
0
|
|
|
|
|
|
$ch = $font->text('I'); |
269
|
|
|
|
|
|
|
} elsif ($uni == 0x0237) { # dotless j |
270
|
|
|
|
|
|
|
# standard encoding doesn't see Unicode point |
271
|
0
|
|
|
|
|
|
$hasUpper = 1; |
272
|
0
|
|
|
|
|
|
$multiChar = 1; |
273
|
0
|
|
|
|
|
|
$wth = int($font->width('J') * 800 * $cond*1.1 + 2*$space); |
274
|
0
|
|
|
|
|
|
$ch = $font->text('J'); |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
|
277
|
0
|
0
|
|
|
|
|
if ($hasUpper) { |
278
|
|
|
|
|
|
|
# this is a lowercase letter, etc. that has an uppercase version |
279
|
|
|
|
|
|
|
# 80% height x 88% (110% aspect ratio @ 80% font size) width. |
280
|
|
|
|
|
|
|
# slightly wider to thicken stems and make look better. |
281
|
|
|
|
|
|
|
# $ch and $wth already set, either default or special case |
282
|
0
|
|
|
|
|
|
$char->{' stream'} .= "/FSN 800 Tf\n"; |
283
|
0
|
|
|
|
|
|
$char->{' stream'} .= ($cond * 110)." Tz\n"; |
284
|
0
|
0
|
|
|
|
|
$char->{' stream'} .= " [ -$space ] TJ\n" if $space; |
285
|
0
|
0
|
|
|
|
|
if ($multiChar) { |
286
|
0
|
|
|
|
|
|
$ch =~ s/>/g; |
287
|
0
|
|
|
|
|
|
$ch =~ s/\)\(//g; |
288
|
0
|
|
|
|
|
|
$char->{' stream'} .= "$ch"; |
289
|
|
|
|
|
|
|
} else { |
290
|
0
|
|
|
|
|
|
$char->{' stream'} .= $font->text(chr($ch)); |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
# uc chr($uni) supposed to be always equivalent to |
293
|
|
|
|
|
|
|
# chr hex($ci->{'upper'}), according to "futuramedium" |
294
|
|
|
|
|
|
|
# HOWEVER, uc doesn't seem to know what to do with non-ASCII chars |
295
|
|
|
|
|
|
|
#$wth = int($font->width(uc chr($uni)) * 800 * $cond * 1.1 + 2* $space); |
296
|
|
|
|
|
|
|
#$char->{' stream'} .= $font->text(uc chr($uni)); |
297
|
|
|
|
|
|
|
#$wth = int($font->width(chr(hex($ci->{'upper'}))) * 800 * $cond * 1.1 + 2* $space); |
298
|
|
|
|
|
|
|
#$char->{' stream'} .= $font->text(chr(hex($ci->{'upper'}))); |
299
|
|
|
|
|
|
|
} # else fall through to standard handling below |
300
|
|
|
|
|
|
|
} # small caps requested |
301
|
|
|
|
|
|
|
|
302
|
0
|
0
|
|
|
|
|
if (!$hasUpper) { |
303
|
|
|
|
|
|
|
# Applies to all not small-caps too! |
304
|
|
|
|
|
|
|
# does not have an uppercase ('upper') equivalent, so |
305
|
|
|
|
|
|
|
# output at standard height and aspect ratio |
306
|
0
|
|
|
|
|
|
$char->{' stream'} .= "/FSN 1000 Tf\n"; |
307
|
0
|
0
|
|
|
|
|
$char->{' stream'} .= ($cond * 100)." Tz\n" if $cond != 1; |
308
|
0
|
0
|
|
|
|
|
$char->{' stream'} .= " [ -$space ] TJ\n" if $space; |
309
|
|
|
|
|
|
|
#$char->{' stream'} .= $font->text(chr($w)); |
310
|
0
|
|
|
|
|
|
$char->{' stream'} .= $font->text(chr($uni)); |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
# finale... all modifications to font have been done |
314
|
0
|
|
|
|
|
|
$char->{' stream'} .= " Tj\nET "; |
315
|
0
|
|
|
|
|
|
push @widths, $wth; |
316
|
0
|
|
|
|
|
|
$self->data()->{'wx'}->{$font->glyphByEnc($w)} = $wth; |
317
|
0
|
|
|
|
|
|
$pdf->new_obj($char); |
318
|
|
|
|
|
|
|
} # loop through 255 standard encoding points |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
# the array as 0 elements at this point! 'space' (among others) IS defined, |
321
|
|
|
|
|
|
|
# so copy that, but TBD what kind of fallback if no such element exists? |
322
|
|
|
|
|
|
|
# $procs->{'.notdef'} = $procs->{$font->data()->{'char'}->[32]}; |
323
|
0
|
|
|
|
|
|
$procs->{'.notdef'} = $procs->{'space'}; |
324
|
|
|
|
|
|
|
|
325
|
0
|
|
|
|
|
|
$self->{'Widths'} = PDFArray(map { PDFNum($_) } @widths); |
|
0
|
|
|
|
|
|
|
326
|
0
|
|
|
|
|
|
$self->data()->{'e2n'} = $self->data()->{'char'}; |
327
|
0
|
|
|
|
|
|
$self->data()->{'e2u'} = $self->data()->{'uni'}; |
328
|
|
|
|
|
|
|
|
329
|
0
|
|
|
|
|
|
$self->data()->{'u2c'} = {}; |
330
|
0
|
|
|
|
|
|
$self->data()->{'u2e'} = {}; |
331
|
0
|
|
|
|
|
|
$self->data()->{'u2n'} = {}; |
332
|
0
|
|
|
|
|
|
$self->data()->{'n2c'} = {}; |
333
|
0
|
|
|
|
|
|
$self->data()->{'n2e'} = {}; |
334
|
0
|
|
|
|
|
|
$self->data()->{'n2u'} = {}; |
335
|
|
|
|
|
|
|
|
336
|
0
|
|
|
|
|
|
foreach my $n (reverse 0 .. 255) { |
337
|
|
|
|
|
|
|
$self->data()->{'n2c'}->{$self->data()->{'char'}->[$n] || '.notdef'} = |
338
|
0
|
0
|
0
|
|
|
|
$n unless defined $self->data()->{'n2c'}->{$self->data()->{'char'}->[$n] || '.notdef'}; |
|
|
|
0
|
|
|
|
|
339
|
|
|
|
|
|
|
$self->data()->{'n2e'}->{$self->data()->{'e2n'}->[$n] || '.notdef'} = |
340
|
0
|
0
|
0
|
|
|
|
$n unless defined $self->data()->{'n2e'}->{$self->data()->{'e2n'}->[$n] || '.notdef'}; |
|
|
|
0
|
|
|
|
|
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
$self->data()->{'n2u'}->{$self->data()->{'e2n'}->[$n] || '.notdef'} = |
343
|
0
|
0
|
0
|
|
|
|
$self->data()->{'e2u'}->[$n] unless defined $self->data()->{'n2u'}->{$self->data()->{'e2n'}->[$n] || '.notdef'}; |
|
|
|
0
|
|
|
|
|
344
|
|
|
|
|
|
|
$self->data()->{'n2u'}->{$self->data()->{'char'}->[$n] || '.notdef'} = |
345
|
0
|
0
|
0
|
|
|
|
$self->data()->{'uni'}->[$n] unless defined $self->data()->{'n2u'}->{$self->data()->{'char'}->[$n] || '.notdef'}; |
|
|
|
0
|
|
|
|
|
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
$self->data()->{'u2c'}->{$self->data()->{'uni'}->[$n]} = |
348
|
0
|
0
|
|
|
|
|
$n unless defined $self->data()->{'u2c'}->{$self->data()->{'uni'}->[$n]}; |
349
|
|
|
|
|
|
|
$self->data()->{'u2e'}->{$self->data()->{'e2u'}->[$n]} = |
350
|
0
|
0
|
|
|
|
|
$n unless defined $self->data()->{'u2e'}->{$self->data()->{'e2u'}->[$n]}; |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
$self->data()->{'u2n'}->{$self->data()->{'e2u'}->[$n]} = |
353
|
0
|
0
|
0
|
|
|
|
($self->data()->{'e2n'}->[$n] || '.notdef') unless defined $self->data()->{'u2n'}->{$self->data()->{'e2u'}->[$n]}; |
354
|
|
|
|
|
|
|
$self->data()->{'u2n'}->{$self->data()->{'uni'}->[$n]} = |
355
|
0
|
0
|
0
|
|
|
|
($self->data()->{'char'}->[$n] || '.notdef') unless defined $self->data()->{'u2n'}->{$self->data()->{'uni'}->[$n]}; |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
|
358
|
0
|
|
|
|
|
|
return $self; |
359
|
|
|
|
|
|
|
} |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
1; |