File Coverage

blib/lib/PDF/API3/Compat/API2/Resource/CIDFont/TrueType/FontFile.pm
Criterion Covered Total %
statement 33 388 8.5
branch 0 194 0.0
condition 0 48 0.0
subroutine 11 26 42.3
pod 2 14 14.2
total 46 670 6.8


line stmt bran cond sub pod time code
1             #=======================================================================
2             # ____ ____ _____ _ ____ ___ ____
3             # | _ \| _ \| ___| _ _ / \ | _ \_ _| |___ \
4             # | |_) | | | | |_ (_) (_) / _ \ | |_) | | __) |
5             # | __/| |_| | _| _ _ / ___ \| __/| | / __/
6             # |_| |____/|_| (_) (_) /_/ \_\_| |___| |_____|
7             #
8             # A Perl Module Chain to faciliate the Creation and Modification
9             # of High-Quality "Portable Document Format (PDF)" Files.
10             #
11             # Copyright 1999-2005 Alfred Reibenschuh .
12             #
13             #=======================================================================
14             #
15             # This library is free software; you can redistribute it and/or
16             # modify it under the terms of the GNU Lesser General Public
17             # License as published by the Free Software Foundation; either
18             # version 2 of the License, or (at your option) any later version.
19             #
20             # This library is distributed in the hope that it will be useful,
21             # but WITHOUT ANY WARRANTY; without even the implied warranty of
22             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23             # Lesser General Public License for more details.
24             #
25             # You should have received a copy of the GNU Lesser General Public
26             # License along with this library; if not, write to the
27             # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
28             # Boston, MA 02111-1307, USA.
29             #
30             # $Id: FontFile.pm,v 2.6 2008/01/04 08:08:39 areibens Exp $
31             #
32             #=======================================================================
33             package PDF::API3::Compat::API2::Resource::CIDFont::TrueType::FontFile;
34            
35             BEGIN {
36            
37 1     1   6 use utf8;
  1         2  
  1         10  
38 1     1   33 use Encode qw(:all);
  1         2  
  1         417  
39 1     1   7 use PDF::API3::Compat::API2::Util;
  1         1  
  1         207  
40            
41 1     1   9 use PDF::API3::Compat::API2::Basic::PDF::Utils;
  1         2  
  1         126  
42 1     1   5 use PDF::API3::Compat::API2::Basic::PDF::Dict;
  1         2  
  1         30  
43 1     1   5 use PDF::API3::Compat::API2::Basic::TTF::Font;
  1         1  
  1         19  
44 1     1   2596 use Data::Dumper;
  1         6488  
  1         81  
45 1     1   10 use POSIX;
  1         2  
  1         11  
46            
47 1     1   3846 use vars qw( @ISA $VERSION $cmap );
  1         3  
  1         158  
48            
49 1     1   43 @ISA = qw( PDF::API3::Compat::API2::Basic::PDF::Dict );
50            
51 1         16 ( $VERSION ) = sprintf '%i.%03i', split(/\./,('$Revision: 2.6 $' =~ /Revision: (\S+)\s/)[0]); # $Date: 2008/01/04 08:08:39 $
52 1         31 $cmap={};
53             }
54 1     1   6 no warnings qw[ recursion uninitialized ];
  1         3  
  1         5288  
55            
56            
57             sub _look_for_cmap ($) {
58 0     0     my $fname=lc(shift);
59 0           $fname=~s/[^a-z0-9]+//gi;
60 0 0         return({%{$cmap->{$fname}}}) if(defined $cmap->{$fname});
  0            
61 0           eval "require PDF::API3::Compat::API2::Resource::CIDFont::CMap::$fname; ";
62 0 0         unless($@){
63 0           return({%{$cmap->{$fname}}});
  0            
64             } else {
65 0           die "requested cmap '$fname' not installed ";
66             }
67             }
68            
69             sub readcffindex
70             {
71 0     0 0   my ($fh,$off,$buf)=@_;
72 0           my @idx=();
73 0           my $index=[];
74 0           seek($fh,$off,0);
75 0           read($fh,$buf,3);
76 0           my ($count,$offsize)=unpack('nC',$buf);
77 0           foreach (0..$count)
78             {
79 0           read($fh,$buf,$offsize);
80 0           $buf=substr("\x00\x00\x00$buf",-4,4);
81 0           my $id=unpack('N',$buf);
82 0           push @idx,$id;
83             }
84 0           my $dataoff=tell($fh)-1;
85            
86 0           foreach my $i (0..$count-1)
87             {
88 0           push @{$index},{ 'OFF' => $dataoff+$idx[$i], 'LEN' => $idx[$i+1]-$idx[$i] };
  0            
89             }
90 0           return($index);
91             }
92            
93             sub readcffdict
94             {
95 0     0 0   my ($fh,$off,$len,$foff,$buf)=@_;
96 0           my @idx=();
97 0           my $dict={};
98 0           seek($fh,$off,0);
99 0           my @st=();
100 0           while(tell($fh)<($off+$len))
101             {
102 0           read($fh,$buf,1);
103 0           my $b0=unpack('C',$buf);
104 0           my $v='';
105            
106 0 0         if($b0==12) # two byte commands
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
107             {
108 0           read($fh,$buf,1);
109 0           my $b1=unpack('C',$buf);
110 0 0         if($b1==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          
111             {
112 0           $dict->{Copyright}={ 'SID' => splice(@st,-1) };
113             }
114             elsif($b1==1)
115             {
116 0           $dict->{isFixedPitch}=splice(@st,-1);
117             }
118             elsif($b1==2)
119             {
120 0           $dict->{ItalicAngle}=splice(@st,-1);
121             }
122             elsif($b1==3)
123             {
124 0           $dict->{UnderlinePosition}=splice(@st,-1);
125             }
126             elsif($b1==4)
127             {
128 0           $dict->{UnderlineThickness}=splice(@st,-1);
129             }
130             elsif($b1==5)
131             {
132 0           $dict->{PaintType}=splice(@st,-1);
133             }
134             elsif($b1==6)
135             {
136 0           $dict->{CharstringType}=splice(@st,-1);
137             }
138             elsif($b1==7)
139             {
140 0           $dict->{FontMatrix}=[ splice(@st,-4) ];
141             }
142             elsif($b1==8)
143             {
144 0           $dict->{StrokeWidth}=splice(@st,-1);
145             }
146             elsif($b1==20)
147             {
148 0           $dict->{SyntheticBase}=splice(@st,-1);
149             }
150             elsif($b1==21)
151             {
152 0           $dict->{PostScript}={ 'SID' => splice(@st,-1) };
153             }
154             elsif($b1==22)
155             {
156 0           $dict->{BaseFontName}={ 'SID' => splice(@st,-1) };
157             }
158             elsif($b1==23)
159             {
160 0           $dict->{BaseFontBlend}=[ splice(@st,0) ];
161             }
162             elsif($b1==24)
163             {
164 0           $dict->{MultipleMaster}=[ splice(@st,0) ];
165             }
166             elsif($b1==25)
167             {
168 0           $dict->{BlendAxisTypes}=[ splice(@st,0) ];
169             }
170             elsif($b1==30)
171             {
172 0           $dict->{ROS}=[ splice(@st,-3) ];
173             }
174             elsif($b1==31)
175             {
176 0           $dict->{CIDFontVersion}=splice(@st,-1);
177             }
178             elsif($b1==32)
179             {
180 0           $dict->{CIDFontRevision}=splice(@st,-1);
181             }
182             elsif($b1==33)
183             {
184 0           $dict->{CIDFontType}=splice(@st,-1);
185             }
186             elsif($b1==34)
187             {
188 0           $dict->{CIDCount}=splice(@st,-1);
189             }
190             elsif($b1==35)
191             {
192 0           $dict->{UIDBase}=splice(@st,-1);
193             }
194             elsif($b1==36)
195             {
196 0           $dict->{FDArray}={ 'OFF' => $foff+splice(@st,-1) };
197             }
198             elsif($b1==37)
199             {
200 0           $dict->{FDSelect}={ 'OFF' => $foff+splice(@st,-1) };
201             }
202             elsif($b1==38)
203             {
204 0           $dict->{FontName}={ 'SID' => splice(@st,-1) };
205             }
206             elsif($b1==39)
207             {
208 0           $dict->{Chameleon}=splice(@st,-1);
209             }
210 0           next;
211             }
212             elsif($b0<28) # commands
213             {
214 0 0         if($b0==0)
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
215             {
216 0           $dict->{Version}={ 'SID' => splice(@st,-1) };
217             }
218             elsif($b0==1)
219             {
220 0           $dict->{Notice}={ 'SID' => splice(@st,-1) };
221             }
222             elsif($b0==2)
223             {
224 0           $dict->{FullName}={ 'SID' => splice(@st,-1) };
225             }
226             elsif($b0==3)
227             {
228 0           $dict->{FamilyName}={ 'SID' => splice(@st,-1) };
229             }
230             elsif($b0==4)
231             {
232 0           $dict->{Weight}={ 'SID' => splice(@st,-1) };
233             }
234             elsif($b0==5)
235             {
236 0           $dict->{FontBBX}=[ splice(@st,-4) ];
237             }
238             elsif($b0==13)
239             {
240 0           $dict->{UniqueID}=splice(@st,-1);
241             }
242             elsif($b0==14)
243             {
244 0           $dict->{XUID}=[splice(@st,0)];
245             }
246             elsif($b0==15)
247             {
248 0           $dict->{CharSet}={ 'OFF' => $foff+splice(@st,-1) };
249             }
250             elsif($b0==16)
251             {
252 0           $dict->{Encoding}={ 'OFF' => $foff+splice(@st,-1) };
253             }
254             elsif($b0==17)
255             {
256 0           $dict->{CharStrings}={ 'OFF' => $foff+splice(@st,-1) };
257             }
258             elsif($b0==18)
259             {
260 0           $dict->{Private}={ 'LEN' => splice(@st,-1), 'OFF' => $foff+splice(@st,-1) };
261             }
262 0           next;
263             }
264             elsif($b0==28) # int16
265             {
266 0           read($fh,$buf,2);
267 0           $v=unpack('n',$buf);
268 0 0         $v=-(0x10000-$v) if($v>0x7fff);
269             }
270             elsif($b0==29) # int32
271             {
272 0           read($fh,$buf,4);
273 0           $v=unpack('N',$buf);
274 0 0         $v=-$v+0xffffffff+1 if($v>0x7fffffff);
275             }
276             elsif($b0==30) # float
277             {
278 0           $e=1;
279 0           while($e)
280             {
281 0           read($fh,$buf,1);
282 0           $v0=unpack('C',$buf);
283 0           foreach my $m ($v0>>8,$v0&0xf)
284             {
285 0 0         if($m<10)
    0          
    0          
    0          
    0          
    0          
286             {
287 0           $v.=$m;
288             }
289             elsif($m==10)
290             {
291 0           $v.='.';
292             }
293             elsif($m==11)
294             {
295 0           $v.='E+';
296             }
297             elsif($m==12)
298             {
299 0           $v.='E-';
300             }
301             elsif($m==14)
302             {
303 0           $v.='-';
304             }
305             elsif($m==15)
306             {
307 0           $e=0;
308 0           last;
309             }
310             }
311             }
312             }
313             elsif($b0==31) # command
314             {
315 0           $v="c=$b0";
316 0           next;
317             }
318             elsif($b0<247) # 1 byte signed
319             {
320 0           $v=$b0-139;
321             }
322             elsif($b0<251) # 2 byte plus
323             {
324 0           read($fh,$buf,1);
325 0           $v=unpack('C',$buf);
326 0           $v=($b0-247)*256+($v+108);
327             }
328             elsif($b0<255) # 2 byte minus
329             {
330 0           read($fh,$buf,1);
331 0           $v=unpack('C',$buf);
332 0           $v=-($b0-251)*256-$v-108;
333             }
334 0           push @st,$v;
335             }
336            
337 0           return($dict);
338             }
339            
340             sub read_kern_table
341             {
342 0     0 0   my $font=shift @_;
343 0           my $upem=shift @_;
344 0           my $self=shift @_;
345 0           my $fh=$font->{' INFILE'};
346 0           my $data=undef;
347            
348 0 0         return(undef) unless($font->{kern});
349            
350 0           my $buf = undef;
351            
352 0           seek($fh,$font->{kern}->{' OFFSET'}+2,0);
353 0           read($fh,$buf, 2);
354 0           my $num=unpack('n',$buf);
355 0           foreach my $n (1..$num)
356             {
357 0           read($fh, $buf, 6);
358 0           my ($ver, $len, $cov) = unpack('n3', $buf);
359 0           $len-=6;
360 0           my $fmt=$cov>>8;
361 0 0         if($fmt==0)
    0          
362             {
363 0   0       $data||={};
364 0           read($fh, $buf, 8);
365 0           my $nc = unpack('n', $buf);
366 0           foreach (1..$nc)
367             {
368 0           read($fh, $buf, 6);
369 0           my ($idx1,$idx2,$val)=unpack('nnn',$buf);
370 0 0         $val-=65536 if($val>32767);
371 0 0         $val= $val < 0 ? -floor($val*1000/$upem) : -ceil($val*1000/$upem);
372 0 0         if($val != 0)
373             {
374 0           $data->{"$idx1:$idx2"}=$val;
375 0           $data->{$self->data->{g2n}->[$idx1].':'.$self->data->{g2n}->[$idx2]}=$val;
376             }
377             }
378             }
379             elsif($fmt==2)
380             {
381 0           read($fh, $buf, $len);
382             }
383             else
384             {
385 0           read($fh, $buf, $len);
386             }
387             }
388             ##print Dumper($data);
389 0           return($data);
390             }
391            
392             sub readcffstructs
393             {
394 0     0 0   my $font=shift @_;
395 0           my $fh=$font->{' INFILE'};
396 0           my $data={};
397             # read CFF table
398 0           seek($fh,$font->{'CFF '}->{' OFFSET'},0);
399 0           read($fh,$buf, 4);
400 0           my ($cffmajor,$cffminor,$cffheadsize,$cffglobaloffsize)=unpack('C4',$buf);
401            
402 0           $data->{name}=readcffindex($fh,$font->{'CFF '}->{' OFFSET'}+$cffheadsize);
403 0           foreach my $dict (@{$data->{name}})
  0            
404             {
405 0           seek($fh,$dict->{OFF},0);
406 0           read($fh,$dict->{VAL},$dict->{LEN});
407             }
408            
409 0           $data->{topdict}=readcffindex($fh,$data->{name}->[-1]->{OFF}+$data->{name}->[-1]->{LEN});
410 0           foreach my $dict (@{$data->{topdict}})
  0            
411             {
412 0           $dict->{VAL}=readcffdict($fh,$dict->{OFF},$dict->{LEN},$font->{'CFF '}->{' OFFSET'});
413             }
414            
415 0           $data->{string}=readcffindex($fh,$data->{topdict}->[-1]->{OFF}+$data->{topdict}->[-1]->{LEN});
416 0           foreach my $dict (@{$data->{string}})
  0            
417             {
418 0           seek($fh,$dict->{OFF},0);
419 0           read($fh,$dict->{VAL},$dict->{LEN});
420             }
421 0           push @{$data->{string}},{ 'VAL' => '001.000' };
  0            
422 0           push @{$data->{string}},{ 'VAL' => '001.001' };
  0            
423 0           push @{$data->{string}},{ 'VAL' => '001.002' };
  0            
424 0           push @{$data->{string}},{ 'VAL' => '001.003' };
  0            
425 0           push @{$data->{string}},{ 'VAL' => 'Black' };
  0            
426 0           push @{$data->{string}},{ 'VAL' => 'Bold' };
  0            
427 0           push @{$data->{string}},{ 'VAL' => 'Book' };
  0            
428 0           push @{$data->{string}},{ 'VAL' => 'Light' };
  0            
429 0           push @{$data->{string}},{ 'VAL' => 'Medium' };
  0            
430 0           push @{$data->{string}},{ 'VAL' => 'Regular' };
  0            
431 0           push @{$data->{string}},{ 'VAL' => 'Roman' };
  0            
432 0           push @{$data->{string}},{ 'VAL' => 'Semibold' };
  0            
433            
434 0           foreach my $dict (@{$data->{topdict}})
  0            
435             {
436 0           foreach my $k (keys %{$dict->{VAL}})
  0            
437             {
438 0           my $dt=$dict->{VAL}->{$k};
439 0 0         if($k eq 'ROS')
440             {
441 0           $dict->{VAL}->{$k}->[0]=$data->{string}->[$dict->{VAL}->{$k}->[0]-391]->{VAL};
442 0           $dict->{VAL}->{$k}->[1]=$data->{string}->[$dict->{VAL}->{$k}->[1]-391]->{VAL};
443 0           next;
444             }
445 0 0 0       next unless(ref($dt) eq 'HASH' && defined $dt->{SID});
446 0 0         if($dt->{SID}>=379)
447             {
448 0           $dict->{VAL}->{$k}=$data->{string}->[$dt->{SID}-391]->{VAL};
449             }
450             }
451             }
452 0           my $dict={};
453 0           foreach my $k (qw[ CIDCount CIDFontVersion FamilyName FontBBX FullName ROS Weight XUID ])
454             {
455 0 0         $dict->{$k}=$data->{topdict}->[0]->{VAL}->{$k} if(defined $data->{topdict}->[0]->{VAL}->{$k});
456             }
457 0           return($dict);
458             }
459            
460             sub new {
461 0     0 1   my ($class,$pdf,$file,%opts)=@_;
462 0           my $data={};
463            
464 0 0         die "cannot find font '$file' ..." unless(-f $file);
465 0           my $font=PDF::API3::Compat::API2::Basic::TTF::Font->open($file);
466 0           $data->{obj}=$font;
467            
468 0 0         $class = ref $class if ref $class;
469 0           $self=$class->SUPER::new();
470            
471 0           $self->{Filter}=PDFArray(PDFName('FlateDecode'));
472 0           $self->{' font'}=$font;
473 0           $self->{' data'}=$data;
474            
475 0 0         $data->{noembed} = $opts{-noembed}==1 ? 1 : 0;
476 0 0         $data->{iscff} = (defined $font->{'CFF '}) ? 1 : 0;
477            
478 0 0         $self->{Subtype}=PDFName('Type1C') if($data->{iscff});
479            
480 0           $data->{fontfamily}=$font->{'name'}->read->find_name(1);
481 0           $data->{fontname}=$font->{'name'}->read->find_name(4);
482            
483 0           $font->{'OS/2'}->read;
484 0           my @stretch=qw[
485             Normal
486             UltraCondensed
487             ExtraCondensed
488             Condensed
489             SemiCondensed
490             Normal
491             SemiExpanded
492             Expanded
493             ExtraExpanded
494             UltraExpanded
495             ];
496 0   0       $data->{fontstretch}=$stretch[$font->{'OS/2'}->{usWidthClass}] || 'Normal';
497            
498 0           $data->{fontweight}=$font->{'OS/2'}->{usWeightClass};
499            
500 0           $data->{panose}=pack('n',$font->{'OS/2'}->{sFamilyClass});
501            
502 0           foreach my $p (qw[bFamilyType bSerifStyle bWeight bProportion bContrast bStrokeVariation bArmStyle bLetterform bMidline bXheight])
503             {
504 0           $data->{panose}.=pack('C',$font->{'OS/2'}->{$p});
505             }
506            
507 0           $data->{apiname}=$data->{fontname};
508 0           $data->{apiname}=~s/[^A-Za-z0-9]+/ /og;
509 0           $data->{apiname}=join('',map { $_=~s/[^A-Za-z0-9]+//og; $_=ucfirst(lc(substr($_,0,2))); $_; } split(/\s+/,$data->{apiname}));
  0            
  0            
  0            
510 0           $data->{fontname}=~s/[\x00-\x1f\s]//og;
511            
512 0           $data->{altname}=$font->{'name'}->find_name(1);
513 0           $data->{altname}=~s/[\x00-\x1f\s]//og;
514            
515 0           $data->{subname}=$font->{'name'}->find_name(2);
516 0           $data->{subname}=~s/[\x00-\x1f\s]//og;
517            
518 0   0       $font->{cmap}->read->find_ms($opts{-isocmap}||0);
519 0 0         if(defined $font->{cmap}->find_ms)
520             {
521 0   0       $data->{issymbol} = ($font->{cmap}->find_ms->{'Platform'} == 3 && $font->{cmap}->read->find_ms->{'Encoding'} == 0) || 0;
522             }
523             else
524             {
525 0           $data->{issymbol} = 0;
526             }
527            
528 0           $data->{upem}=$font->{'head'}->read->{'unitsPerEm'};
529            
530 0           $data->{fontbbox}=[
531             int($font->{'head'}->{'xMin'} * 1000 / $data->{upem}),
532             int($font->{'head'}->{'yMin'} * 1000 / $data->{upem}),
533             int($font->{'head'}->{'xMax'} * 1000 / $data->{upem}),
534             int($font->{'head'}->{'yMax'} * 1000 / $data->{upem})
535             ];
536            
537 0           $data->{stemv}=0;
538 0           $data->{stemh}=0;
539            
540 0   0       $data->{missingwidth}=int($font->{'hhea'}->read->{'advanceWidthMax'} * 1000 / $data->{upem}) || 1000;
541 0           $data->{maxwidth}=int($font->{'hhea'}->{'advanceWidthMax'} * 1000 / $data->{upem});
542 0           $data->{ascender}=int($font->{'hhea'}->read->{'Ascender'} * 1000 / $data->{upem});
543 0           $data->{descender}=int($font->{'hhea'}{'Descender'} * 1000 / $data->{upem});
544            
545 0           $data->{flags} = 0;
546 0 0         $data->{flags} |= 1 if ($font->{'OS/2'}->read->{'bProportion'} == 9);
547 0 0 0       $data->{flags} |= 2 unless ($font->{'OS/2'}{'bSerifStyle'} > 10 && $font->{'OS/2'}{'bSerifStyle'} < 14);
548 0 0         $data->{flags} |= 8 if ($font->{'OS/2'}{'bFamilyType'} == 2);
549 0           $data->{flags} |= 32; # if ($font->{'OS/2'}{'bFamilyType'} > 3);
550 0 0         $data->{flags} |= 64 if ($font->{'OS/2'}{'bLetterform'} > 8);;
551            
552 0   0       $data->{capheight}=$font->{'OS/2'}->{CapHeight} || int($data->{fontbbox}->[3]*0.8);
553 0   0       $data->{xheight}=$font->{'OS/2'}->{xHeight} || int($data->{fontbbox}->[3]*0.4);
554            
555 0 0         if($data->{issymbol})
556             {
557 0           $data->{e2u}=[0xf000 .. 0xf0ff];
558             }
559             else
560             {
561 0           $data->{e2u}=[ unpack('U*',decode('cp1252', pack('C*',0..255))) ];
562             }
563            
564 0 0 0       if(($font->{'post'}->read->{FormatType} == 3) && defined($font->{cmap}->read->find_ms))
565             {
566 0           $data->{g2n} = [];
567 0           foreach my $u (sort {$a<=>$b} keys %{$font->{cmap}->read->find_ms->{val}})
  0            
  0            
568             {
569 0           my $n=nameByUni($u);
570 0           $data->{g2n}->[$font->{cmap}->read->find_ms->{val}->{$u}]=$n;
571             }
572             }
573             else
574             {
575 0 0         $data->{g2n} = [ map { $_ || '.notdef' } @{$font->{'post'}->read->{'VAL'}} ];
  0            
  0            
576             }
577            
578 0           $data->{italicangle}=$font->{'post'}->{italicAngle};
579 0           $data->{isfixedpitch}=$font->{'post'}->{isFixedPitch};
580 0           $data->{underlineposition}=$font->{'post'}->{underlinePosition};
581 0           $data->{underlinethickness}=$font->{'post'}->{underlineThickness};
582            
583 0 0         if($self->iscff)
584             {
585 0           $data->{cff}=readcffstructs($font);
586             }
587            
588 0 0         if(defined $data->{cff}->{ROS})
589             {
590 0           my %cffcmap=(
591             'Adobe:Japan1'=>'japanese',
592             'Adobe:Korea1'=>'korean',
593             'Adobe:CNS1'=>'traditional',
594             'Adobe:GB1'=>'simplified',
595             );
596 0           my $ccmap=_look_for_cmap($cffcmap{"$data->{cff}->{ROS}->[0]:$data->{cff}->{ROS}->[1]"});
597 0           $data->{u2g}=$ccmap->{u2g};
598 0           $data->{g2u}=$ccmap->{g2u};
599             }
600             else
601             {
602 0           $data->{u2g} = {};
603            
604 0           my $gmap=$font->{cmap}->read->find_ms->{val};
605 0           foreach my $u (sort {$a<=>$b} keys %{$gmap})
  0            
  0            
606             {
607 0   0       my $uni=$u||0;
608 0           $data->{u2g}->{$uni}=$gmap->{$uni};
609             }
610 0 0         $data->{g2u}=[ map { $_ || 0 } $font->{'cmap'}->read->reverse ];
  0            
611             }
612            
613 0 0         if($data->{issymbol})
614             {
615 0   0       map { $data->{u2g}->{$_} ||= $font->{'cmap'}->read->ms_lookup($_) } (0xf000 .. 0xf0ff);
  0            
616 0   0       map { $data->{u2g}->{$_ & 0xff} ||= $font->{'cmap'}->read->ms_lookup($_) } (0xf000 .. 0xf0ff);
  0            
617             }
618            
619 0 0 0       $data->{e2n}=[ map { $data->{g2n}->[$data->{u2g}->{$_} || 0] || '.notdef' } @{$data->{e2u}} ];
  0            
  0            
620            
621 0 0 0       $data->{e2g}=[ map { $data->{u2g}->{$_ || 0} || 0 } @{$data->{e2u}} ];
  0            
  0            
622 0           $data->{u2e}={};
623 0           foreach my $n (reverse 0..255)
624             {
625 0 0         $data->{u2e}->{$data->{e2u}->[$n]}=$n unless(defined $data->{u2e}->{$data->{e2u}->[$n]});
626             }
627            
628 0           $data->{u2n}={ map { $data->{g2u}->[$_] => $data->{g2n}->[$_] } (0 .. (scalar @{$data->{g2u}} -1)) };
  0            
  0            
629            
630 0           $data->{wx}=[];
631 0           foreach my $w (0..(scalar @{$data->{g2u}}-1))
  0            
632             {
633 0   0       $data->{wx}->[$w]=int($font->{'hmtx'}->read->{'advance'}[$w]*1000/$data->{upem})
634             || $data->{missingwidth};
635             }
636            
637 0           $data->{kern}=read_kern_table($font,$data->{upem},$self);
638 0 0         delete $data->{kern} unless(defined $data->{kern});
639            
640 0           $data->{fontname}=~s/\s+//og;
641 0           $data->{fontfamily}=~s/\s+//og;
642 0           $data->{apiname}=~s/\s+//og;
643 0           $data->{altname}=~s/\s+//og;
644 0           $data->{subname}=~s/\s+//og;
645            
646 0           $self->subsetByCId(0);
647            
648 0           return($self,$data);
649             }
650            
651 0     0 0   sub font { return( $_[0]->{' font'} ); }
652 0     0 0   sub data { return( $_[0]->{' data'} ); }
653 0     0 0   sub iscff { return( $_[0]->data->{iscff} ); }
654            
655 0 0   0 0   sub haveKernPairs { return( $_[0]->data->{kern} ? 1 : 0 ); }
656            
657             sub kernPairCid
658             {
659 0     0 0   my ($self, $i1, $i2) = @_;
660 0 0 0       return(0) if($i1==0 || $i2==0);
661 0   0       return($self->data->{kern}->{"$i1:$i2"} || 0);
662             }
663            
664             sub subsetByCId
665             {
666 0     0 0   my $self = shift @_;
667 0           my $g = shift @_;
668 0           $self->data->{subset}=1;
669 0           vec($self->data->{subvec},$g,1)=1;
670 0 0         return if($self->iscff);
671 0 0         if(defined $self->font->{loca}->read->{glyphs}->[$g]) {
672 0           $self->font->{loca}->read->{glyphs}->[$g]->read;
673 0           map { vec($self->data->{subvec},$_,1)=1; } $self->font->{loca}->{glyphs}->[$g]->get_refs;
  0            
674             }
675             }
676            
677             sub subvec {
678 0     0 0   my $self = shift @_;
679 0 0         return(1) if($self->iscff);
680 0           my $g = shift @_;
681 0           return(vec($self->data->{subvec},$g,1));
682             }
683            
684 0     0 0   sub glyphNum { return ( $_[0]->font->{'maxp'}->read->{'numGlyphs'} ); }
685            
686             sub outobjdeep {
687 0     0 1   my ($self, $fh, $pdf, %opts) = @_;
688            
689 0 0         return $self->SUPER::outobjdeep($fh, $pdf) if defined $opts{'passthru'};
690            
691 0           my $f = $self->font;
692            
693 0 0         if($self->iscff) {
694 0           $f->{'CFF '}->read_dat;
695 0           $self->{' stream'} = $f->{'CFF '}->{' dat'};
696             } else {
697 0 0 0       if ($self->data->{subset} && !$self->data->{nosubset}) {
698 0           $f->{'glyf'}->read;
699 0           for (my $i = 0; $i < $self->glyphNum; $i++) {
700 0 0         next if($self->subvec($i));
701 0           $f->{'loca'}{'glyphs'}->[$i] = undef;
702             # print STDERR "$i,";
703             }
704             }
705            
706 0 0         if($self->data->{noembed} != 1)
707             {
708 0           $self->{' stream'} = "";
709 0           my $ffh;
710 0           CORE::open($ffh, '+>', \$self->{' stream'});
711 0           binmode($ffh,':raw');
712 0           $f->out($ffh, 'cmap', 'cvt ', 'fpgm', 'glyf', 'head', 'hhea', 'hmtx', 'loca', 'maxp', 'prep');
713 0           $self->{'Length1'}=PDFNum(length($self->{' stream'}));
714 0           CORE::close($ffh);
715             }
716             }
717            
718 0           $self->SUPER::outobjdeep($fh, $pdf, %opts);
719             }
720            
721            
722             1;
723            
724             __END__