File Coverage

blib/lib/PDF/API3/Compat/API2/Resource/Font/neTrueType.pm
Criterion Covered Total %
statement 26 615 4.2
branch 0 270 0.0
condition 0 58 0.0
subroutine 9 31 29.0
pod 2 22 9.0
total 37 996 3.7


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 FILE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
21             # AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22             # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
23             # FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
24             # SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR CONTRIBUTORS
25             # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26             # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27             # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28             # OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29             # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30             # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31             # ARISING IN ANY WAY OUT OF THE USE OF THIS FILE, EVEN IF
32             # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33             #
34             # SEE THE GNU LESSER GENERAL PUBLIC LICENSE FOR MORE DETAILS.
35             #
36             # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU LESSER GENERAL PUBLIC
37             # LICENSE ALONG WITH THIS LIBRARY; IF NOT, WRITE TO THE
38             # FREE SOFTWARE FOUNDATION, INC., 59 TEMPLE PLACE - SUITE 330,
39             # BOSTON, MA 02111-1307, USA.
40             #
41             # $Id: neTrueType.pm,v 1.2 2008/01/04 08:10:42 areibens Exp $
42             #
43             #=======================================================================
44             package PDF::API3::Compat::API2::Resource::Font::neTrueType;
45            
46             =head1 NAME
47            
48             PDF::API3::Compat::API2::Resource::Font::neTrueType - Module for using 8bit nonembedded truetype Fonts.
49            
50             =head1 SYNOPSIS
51            
52             #
53             use PDF::API3::Compat::API2;
54             #
55             $pdf = PDF::API3::Compat::API2->new;
56             $cft = $pdf->nettfont('Times-Roman.ttf', -encode => 'latin1');
57             #
58            
59             =head1 METHODS
60            
61             =over 4
62            
63             =cut
64            
65             BEGIN {
66            
67 1     1   6 use utf8;
  1         2  
  1         9  
68 1     1   33 use Encode qw(:all);
  1         2  
  1         321  
69            
70 1     1   7 use File::Basename;
  1         3  
  1         82  
71            
72 1     1   5 use vars qw( @ISA $fonts $alias $subs $encodings $VERSION );
  1         3  
  1         79  
73 1     1   6 use PDF::API3::Compat::API2::Resource::Font;
  1         2  
  1         22  
74 1     1   6 use PDF::API3::Compat::API2::Util;
  1         3  
  1         233  
75 1     1   7 use PDF::API3::Compat::API2::Basic::PDF::Utils;
  1         3  
  1         209  
76            
77 1     1   23 @ISA=qw(PDF::API3::Compat::API2::Resource::Font);
78            
79 1         33 ( $VERSION ) = sprintf '%i.%03i', split(/\./,('$Revision: 1.2 $' =~ /Revision: (\S+)\s/)[0]); # $Date: 2008/01/04 08:10:42 $
80            
81             }
82 1     1   6 no warnings qw[ deprecated recursion uninitialized ];
  1         2  
  1         8561  
83            
84             =item $font = PDF::API3::Compat::API2::Resource::Font::neTrueType->new $pdf, $fontfile, %options
85            
86             Returns a corefont object.
87            
88             =cut
89            
90             =pod
91            
92             Valid %options are:
93            
94             I<-encode>
95             ... changes the encoding of the font from its default.
96             See I for the supported values.
97            
98             I<-pdfname> ... changes the reference-name of the font from its default.
99             The reference-name is normally generated automatically and can be
100             retrived via $pdfname=$font->name.
101            
102             =cut
103            
104             sub unpack_fixed
105             {
106 0     0 0   my ($dat) = @_;
107 0           my ($res, $frac) = unpack("nn", $dat);
108 0 0         $res -= 65536 if $res > 32767;
109 0           $res += $frac / 65536.;
110 0           return($res);
111             }
112            
113             sub unpack_f2dot14
114             {
115 0     0 0   my ($dat) = @_;
116 0           my $res = unpack("n", $dat);
117 0           my $frac = $res & 0x3fff;
118 0           $res >>= 14;
119 0 0         $res -= 4 if $res > 1;
120 0           $res += $frac / 16384.;
121 0           return($res);
122             }
123            
124             sub unpack_long
125             {
126 0     0 0   my ($dat) = @_;
127 0           my $res = unpack("N", $dat);
128 0 0         $res -= (1 << 32) if ($res >= 1 << 31);
129 0           return($res);
130             }
131            
132             sub unpack_ulong
133             {
134 0     0 0   my ($dat) = @_;
135 0           my $res = unpack("N", $dat);
136 0           return($res);
137             }
138            
139             sub unpack_short
140             {
141 0     0 0   my ($dat) = @_;
142 0           my $res = unpack("n", $dat);
143 0 0         $res -= 65536 if ($res >= 32768);
144 0           return($res);
145             }
146            
147             sub unpack_ushort
148             {
149 0     0 0   my ($dat) = @_;
150 0           my $res = unpack("n", $dat);
151 0           return($res);
152             }
153            
154             sub read_name_table
155             {
156 0     0 0   my ($data, $fh, $num, $stroff, $buf) = @_;
157             # read name table
158 0           seek($fh,$data->{name}->{OFF},0);
159            
160 0           read($fh,$buf, 6);
161            
162 0           ($num, $stroff) = unpack("x2nn", $buf);
163            
164 0           $data->{name}->{ARR}=[];
165            
166 0           for (my $i = 0; $i < $num; $i++)
167             {
168 0           read($fh,$buf, 12);
169 0           my ($pid, $eid, $lid, $nid, $len, $off) = unpack("n6", $buf);
170 0           push @{$data->{name}->{ARR}},[$pid, $eid, $lid, $nid, $len, $off];
  0            
171             }
172            
173 0           foreach my $arr ( @{$data->{name}->{ARR}} ) {
  0            
174 0           my ($pid, $eid, $lid, $nid, $len, $off) = @{$arr};
  0            
175 0           seek($fh,$data->{name}->{OFF} + $stroff + $off, 0);
176 0           read($fh, $buf, $len);
177            
178 0 0 0       if ($pid == 0 || $pid == 3 || ($pid == 2 && $eid == 1))
      0        
      0        
179 0 0         { $buf = pack('C*',map { $_>255 ? 20 : $_ } unpack('n*',$buf)); }
  0            
180            
181 0           $data->{name}->{strings}[$nid][$pid][$eid]{$lid} = $buf;
182             }
183             }
184            
185             sub read_os2_table
186             {
187 0     0 0   my ($data, $fh, $buf) = @_;
188            
189             # read OS/2 table
190 0           seek($fh,$data->{'OS/2'}->{OFF},0);
191 0           read($fh,$buf, 2);
192 0           my $os2ver=unpack_ushort($buf);
193            
194 0           seek($fh,$data->{'OS/2'}->{OFF}+4,0);
195 0           read($fh,$buf, 4);
196 0           ($data->{V}->{usWeightClass},$data->{V}->{usWidthClass})=unpack('nn',$buf);
197            
198 0           seek($fh,$data->{'OS/2'}->{OFF}+30,0);
199 0           read($fh,$buf, 12);
200 0           $data->{V}->{panoseHex}=unpack('H*',$buf);
201 0           $data->{V}->{panose}=$buf;
202 0           ($data->{V}->{sFamilyClass}, $data->{V}->{bFamilyType}, $data->{V}->{bSerifStyle}, $data->{V}->{bWeight},
203             $data->{V}->{bProportion}, $data->{V}->{bContrast}, $data->{V}->{bStrokeVariation}, $data->{V}->{bArmStyle},
204             $data->{V}->{bLetterform}, $data->{V}->{bMidline}, $data->{V}->{bXheight}) = unpack('nC*',$buf);
205            
206 0           $data->{V}->{flags} = 0;
207 0 0         $data->{V}->{flags} |= 1 if ($data->{V}->{'bProportion'} == 9);
208 0 0 0       $data->{V}->{flags} |= 2 unless ($data->{V}->{'bSerifStyle'} > 10 && $data->{V}->{'bSerifStyle'} < 14);
209 0 0         $data->{V}->{flags} |= 8 if ($data->{V}->{'bFamilyType'} == 2);
210 0           $data->{V}->{flags} |= 32; # if ($data->{V}->{'bFamilyType'} > 3);
211 0 0         $data->{V}->{flags} |= 64 if ($data->{V}->{'bLetterform'} > 8);
212            
213 0           seek($fh,$data->{'OS/2'}->{OFF}+42,0);
214 0           read($fh,$buf, 16);
215 0           $data->{V}->{ulUnicodeRange}=[ unpack('NNNN',$buf) ];
216 0           my @ulCodePageRange=();
217            
218 0 0         if($os2ver>0) {
219 0           seek($fh,$data->{'OS/2'}->{OFF}+78,0);
220 0           read($fh,$buf, 8);
221 0           $data->{V}->{ulCodePageRange}=[ unpack('NN',$buf) ];
222 0           read($fh,$buf, 4);
223 0           ($data->{V}->{xHeight},$data->{V}->{CapHeight})=unpack('nn',$buf);
224             }
225             }
226            
227             sub read_head_table
228             {
229 0     0 0   my ($data, $fh, $buf) = @_;
230            
231 0           seek($fh,$data->{'head'}->{OFF}+18,0);
232 0           read($fh,$buf, 2);
233 0           $data->{V}->{upem}=unpack_ushort($buf);
234 0           $data->{V}->{upemf}=1000/$data->{V}->{upem};
235            
236 0           seek($fh,$data->{'head'}->{OFF}+36,0);
237 0           read($fh,$buf, 2);
238 0           $data->{V}->{xMin}=unpack_short($buf);
239 0           read($fh,$buf, 2);
240 0           $data->{V}->{yMin}=unpack_short($buf);
241 0           read($fh,$buf, 2);
242 0           $data->{V}->{xMax}=unpack_short($buf);
243 0           read($fh,$buf, 2);
244 0           $data->{V}->{yMax}=unpack_short($buf);
245            
246 0           $data->{V}->{fontbbox}=[
247             int($data->{V}->{'xMin'} * $data->{V}->{upemf}),
248             int($data->{V}->{'yMin'} * $data->{V}->{upemf}),
249             int($data->{V}->{'xMax'} * $data->{V}->{upemf}),
250             int($data->{V}->{'yMax'} * $data->{V}->{upemf})
251             ];
252 0           seek($fh,$data->{'head'}->{OFF}+50,0);
253 0           read($fh,$data->{'head'}->{indexToLocFormat}, 2);
254 0           $data->{'head'}->{indexToLocFormat}=unpack_ushort($data->{'head'}->{indexToLocFormat});
255             }
256            
257             sub read_maxp_table
258             {
259 0     0 0   my ($data, $fh, $buf) = @_;
260            
261 0           seek($fh,$data->{'maxp'}->{OFF}+4,0);
262 0           read($fh,$buf, 2);
263 0           $data->{V}->{numGlyphs}=unpack_ushort($buf);
264 0           $data->{maxp}->{numGlyphs}=$data->{V}->{numGlyphs};
265             }
266            
267             sub read_hhea_table
268             {
269 0     0 0   my ($data, $fh, $buf) = @_;
270            
271 0           seek($fh,$data->{'hhea'}->{OFF}+4,0);
272 0           read($fh,$buf, 2);
273 0           $data->{V}->{ascender}=unpack_short($buf);
274            
275 0           read($fh,$buf, 2);
276 0           $data->{V}->{descender}=unpack_short($buf);
277            
278 0           read($fh,$buf, 2);
279 0           $data->{V}->{linegap}=unpack_short($buf);
280            
281 0           read($fh,$buf, 2);
282 0           $data->{V}->{advancewidthmax}=unpack_short($buf);
283            
284 0           seek($fh,$data->{'hhea'}->{OFF}+34,0);
285 0           read($fh,$buf, 2);
286 0           $data->{V}->{numberOfHMetrics}=unpack_ushort($buf);
287             }
288            
289             sub read_hmtx_table
290             {
291 0     0 0   my ($data, $fh, $buf) = @_;
292            
293 0           seek($fh,$data->{'hmtx'}->{OFF},0);
294 0           $data->{hmtx}->{wx}=[];
295            
296 0           foreach (1..$data->{V}->{numberOfHMetrics})
297             {
298 0           read($fh,$buf, 2);
299 0           my $wx=int(unpack_ushort($buf)*1000/$data->{V}->{upem});
300 0           push @{$data->{hmtx}->{wx}},$wx;
  0            
301 0           read($fh,$buf, 2);
302             }
303 0           $data->{V}->{missingwidth}=$data->{hmtx}->{wx}->[-1];
304             }
305            
306             sub read_cmap_table
307             {
308 0     0 0   my ($data, $fh, $buf) = @_;
309 0           my $cmap=$data->{cmap};
310 0           seek($fh,$cmap->{OFF},0);
311            
312 0           read($fh,$buf,4);
313 0           $cmap->{Num} = unpack("x2n", $buf);
314 0           $cmap->{Tables} = [];
315            
316 0           foreach my $i (0..$cmap->{Num})
317             {
318 0           my $s = {};
319 0           read($fh,$buf,8);
320 0           ($s->{Platform}, $s->{Encoding}, $s->{LOC}) = (unpack("nnN", $buf));
321 0           $s->{LOC} += $cmap->{OFF};
322 0           push(@{$cmap->{Tables}}, $s);
  0            
323             }
324            
325 0           foreach my $i (0..$cmap->{Num})
326             {
327 0           my $s = $cmap->{Tables}[$i];
328 0           seek($fh,$s->{LOC}, 0);
329 0           read($fh,$buf, 2);
330 0           $s->{Format} = unpack("n", $buf);
331            
332 0 0 0       if ($s->{Format} == 0)
    0          
    0          
    0          
    0          
    0          
333             {
334 0           my $len;
335 0           $fh->read($buf, 4);
336 0           ($len, $s->{Ver}) = unpack('n2', $buf);
337 0           $s->{val}={};
338 0           foreach my $j (0..255)
339             {
340 0           read($fh,$buf, 1);
341 0           $s->{val}->{$j}=unpack('C',$buf);
342             }
343             }
344             elsif ($s->{Format} == 2)
345             {
346             # cjk euc ?
347             }
348             elsif ($s->{Format} == 4)
349             {
350 0           my ($len,$count);
351 0           $fh->read($buf, 12);
352 0           ($len, $s->{Ver},$count) = unpack('n3', $buf);
353 0           $count >>= 1;
354 0           $s->{val}={};
355 0           read($fh, $buf, $len - 14);
356 0           foreach my $j (0..$count-1)
357             {
358 0           my $end = unpack("n", substr($buf, $j << 1, 2));
359 0           my $start = unpack("n", substr($buf, ($j << 1) + ($count << 1) + 2, 2));
360 0           my $delta = unpack("n", substr($buf, ($j << 1) + ($count << 2) + 2, 2));
361 0 0         $delta -= 65536 if $delta > 32767;
362 0           my $range = unpack("n", substr($buf, ($j << 1) + $count * 6 + 2, 2));
363 0           foreach my $k ($start..$end)
364             {
365 0           my $id=undef;
366            
367 0 0 0       if ($range == 0 || $range == 65535) # support the buggy FOG with its range=65535 for final segment
368             {
369 0           $id = $k + $delta;
370             }
371             else
372             {
373 0           $id = unpack("n",
374             substr($buf, ($j << 1) + $count * 6 +
375             2 + ($k - $start) * 2 + $range, 2)) + $delta;
376             }
377            
378 0 0         $id -= 65536 if($id >= 65536);
379 0 0         $s->{val}->{$k} = $id if($id);
380             }
381             }
382             }
383             elsif ($s->{Format} == 6)
384             {
385 0           my ($len,$start,$count);
386 0           $fh->read($buf, 8);
387 0           ($len, $s->{Ver},$start,$count) = unpack('n4', $buf);
388 0           $s->{val}={};
389 0           foreach my $j (0..$count-1)
390             {
391 0           read($fh,$buf, 2);
392 0           $s->{val}->{$start+$j}=unpack('n',$buf);
393             }
394             }
395             elsif ($s->{Format} == 10)
396             {
397 0           my ($len,$start,$count);
398 0           $fh->read($buf, 18);
399 0           ($len, $s->{Ver},$start,$count) = unpack('x2N4', $buf);
400 0           $s->{val}={};
401 0           foreach my $j (0..$count-1)
402             {
403 0           read($fh,$buf, 2);
404 0           $s->{val}->{$start+$j}=unpack('n',$buf);
405             }
406             }
407             elsif ($s->{Format} == 8 || $s->{Format} == 12)
408             {
409 0           my ($len,$count);
410 0           $fh->read($buf, 10);
411 0           ($len, $s->{Ver}) = unpack('x2N2', $buf);
412 0           $s->{val}={};
413 0 0         if($s->{Format} == 8)
414             {
415 0           read($fh, $buf, 8192);
416 0           read($fh, $buf, 4);
417             }
418             else
419             {
420 0           read($fh, $buf, 4);
421             }
422 0           $count = unpack('N', $buf);
423 0           foreach my $j (0..$count-1)
424             {
425 0           read($fh,$buf, 12);
426 0           my ($start,$end,$cid)=unpack('N3',$buf);
427 0           foreach my $k ($start..$end)
428             {
429 0           $s->{val}->{$k}=$cid+$k-$start;
430             }
431             }
432             }
433             }
434            
435 0           my $alt;
436 0           foreach my $s (@{$cmap->{Tables}})
  0            
437             {
438 0 0 0       if($s->{Platform} == 3)
    0 0        
439             {
440 0           $cmap->{mstable} = $s;
441 0 0 0       last if(($s->{Encoding} == 1) || ($s->{Encoding} == 0));
442             }
443             elsif($s->{Platform} == 0 || ($s->{Platform} == 2 && $s->{Encoding} == 1))
444             {
445 0           $alt = $s;
446             }
447             }
448 0 0 0       $cmap->{mstable}||=$alt if($alt);
449            
450 0           $data->{V}->{uni}=[];
451 0           foreach my $i (keys %{$cmap->{mstable}->{val}})
  0            
452             {
453 0           $data->{V}->{uni}->[$cmap->{mstable}->{val}->{$i}]=$i;
454             }
455            
456 0           foreach my $i (0..$data->{V}->{numGlyphs})
457             {
458 0   0       $data->{V}->{uni}->[$i]||=0;
459             }
460             }
461            
462             sub read_post_table
463             {
464 0     0 0   my ($data, $fh, $buf) = @_;
465 0           my $post=$data->{post};
466 0           seek($fh,$post->{OFF},0);
467            
468 0           my @base_set=qw[
469             .notdef .null nonmarkingreturn space exclam quotedbl numbersign dollar
470             percent ampersand quotesingle parenleft parenright asterisk plus comma
471             hyphen period slash zero one two three four five six seven eight nine
472             colon semicolon less equal greater question at A B C D E F G H I J K L
473             M N O P Q R S T U V W X Y Z bracketleft backslash bracketright
474             asciicircum underscore grave a b c d e f g h i j k l m n o p q r s t u
475             v w x y z braceleft bar braceright asciitilde Adieresis Aring Ccedilla
476             Eacute Ntilde Odieresis Udieresis aacute agrave acircumflex adieresis
477             atilde aring ccedilla eacute egrave ecircumflex edieresis iacute
478             igrave icircumflex idieresis ntilde oacute ograve ocircumflex
479             odieresis otilde uacute ugrave ucircumflex udieresis dagger degree
480             cent sterling section bullet paragraph germandbls registered copyright
481             trademark acute dieresis notequal AE Oslash infinity plusminus
482             lessequal greaterequal yen mu partialdiff summation product pi
483             integral ordfeminine ordmasculine Omega ae oslash questiondown
484             exclamdown logicalnot radical florin approxequal Delta guillemotleft
485             guillemotright ellipsis nonbreakingspace Agrave Atilde Otilde OE oe
486             endash emdash quotedblleft quotedblright quoteleft quoteright divide
487             lozenge ydieresis Ydieresis fraction currency guilsinglleft
488             guilsinglright fi fl daggerdbl periodcentered quotesinglbase
489             quotedblbase perthousand Acircumflex Ecircumflex Aacute Edieresis
490             Egrave Iacute Icircumflex Idieresis Igrave Oacute Ocircumflex apple
491             Ograve Uacute Ucircumflex Ugrave dotlessi circumflex tilde macron breve
492             dotaccent ring cedilla hungarumlaut ogonek caron Lslash lslash Scaron
493             scaron Zcaron zcaron brokenbar Eth eth Yacute yacute Thorn thorn minus
494             multiply onesuperior twosuperior threesuperior onehalf onequarter
495             threequarters franc Gbreve gbreve Idotaccent Scedilla scedilla Cacute
496             cacute Ccaron ccaron dcroat
497             ];
498            
499 0           read($fh,$buf, 4);
500 0           $post->{Format}=unpack('N',$buf);
501 0           read($fh,$buf,4);
502 0           $data->{V}->{italicangle}=unpack_fixed($buf);
503 0           read($fh,$buf,2);
504 0           $data->{V}->{underlineposition}=unpack_f2dot14($buf)*1000;
505 0           read($fh,$buf,2);
506 0           $data->{V}->{underlinethickness}=unpack_f2dot14($buf)*1000;
507 0           read($fh,$buf,4);
508 0           $data->{V}->{isfixedpitch}=unpack_ulong($buf);
509 0           read($fh,$buf,16);
510            
511 0 0         if($post->{Format} == 0x00010000)
    0          
    0          
    0          
512             {
513 0           $post->{Format}='10';
514 0           $post->{val}=[ @base_set ];
515 0           $post->{strings}={};
516 0           foreach my $i (0..257)
517             {
518 0           $post->{strings}->{$post->{val}->[$i]}=$i;
519             }
520             }
521             elsif($post->{Format} == 0x00020000)
522             {
523 0           $post->{Format}='20';
524 0           $post->{val}=[];
525 0           $post->{strings}={};
526 0           read($fh,$buf,2);
527 0           $post->{numGlyphs}=unpack_ushort($buf);
528 0           foreach my $i (0..$post->{numGlyphs}-1)
529             {
530 0           read($fh,$buf,2);
531 0           $post->{val}->[$i]=unpack_ushort($buf);
532             }
533 0           while(tell($fh) < $post->{OFF}+$post->{LEN})
534             {
535 0           read($fh,$buf,1);
536 0           my $strlen=unpack('C',$buf);
537 0           read($fh,$buf,$strlen);
538 0           push(@base_set,$buf);
539             }
540 0           foreach my $i (0..$post->{numGlyphs}-1)
541             {
542 0           $post->{val}->[$i]=$base_set[$post->{val}->[$i]];
543 0   0       $post->{strings}->{$post->{val}->[$i]}||=$i;
544             }
545             }
546             elsif($post->{Format} == 0x00025000)
547             {
548 0           $post->{Format}='25';
549 0           $post->{val}=[];
550 0           $post->{strings}={};
551 0           read($fh,$buf,2);
552 0           my $num=unpack_ushort($buf);
553 0           foreach my $i (0..$num)
554             {
555 0           read($fh,$buf,1);
556 0           $post->{val}->[$i]=$base_set[$i+unpack('c',$buf)];
557 0   0       $post->{strings}->{$post->{val}->[$i]}||=$i;
558             }
559             }
560             elsif($post->{Format} == 0x00030000)
561             {
562 0           $post->{Format}='30';
563 0           $post->{val}=[];
564 0           $post->{strings}={};
565             }
566            
567 0           $data->{V}->{name}=[];
568 0           foreach my $i (0..$data->{V}->{numGlyphs})
569             {
570 0   0       $data->{V}->{name}->[$i] = $post->{val}->[$i]
571             || nameByUni($data->{V}->{uni}->[$i])
572             || '.notdef';
573             }
574            
575 0           $data->{V}->{n2i}={};
576 0           foreach my $i (0..$data->{V}->{numGlyphs})
577             {
578 0   0       $data->{V}->{n2i}->{$data->{V}->{name}->[$i]}||=$i;
579             }
580             }
581            
582             sub read_loca_table
583             {
584 0     0 0   my ($data, $fh, $buf) = @_;
585            
586 0           seek($fh,$data->{'loca'}->{OFF},0);
587 0 0         my $ilen=$data->{'head'}->{indexToLocFormat} ? 4 : 2;
588 0 0         my $ipak=$data->{'head'}->{indexToLocFormat} ? 'N' : 'n';
589 0 0         my $isif=$data->{'head'}->{indexToLocFormat} ? 0 : 1;
590            
591 0           $data->{'loca'}->{gOFF}=[];
592            
593 0           for(my $i=0; $i<$data->{'maxp'}->{numGlyphs}+1; $i++)
594             {
595 0           read($fh, $buf, $ilen);
596 0           $buf=unpack($ipak,$buf);
597 0           $buf<<=$isif;
598 0           push @{$data->{'loca'}->{gOFF}},$buf;
  0            
599             }
600             }
601            
602             sub read_glyf_table
603             {
604 0     0 0   my ($data, $fh, $buf) = @_;
605            
606 0           $data->{'glyf'}->{glyphs}=[];
607            
608 0           for(my $i=0; $i<$data->{'maxp'}->{numGlyphs}; $i++)
609             {
610 0           my $G={};
611 0           $data->{'glyf'}->{glyphs}->[$i]=$G;
612 0 0         next if($data->{'loca'}->{gOFF}->[$i]-$data->{'loca'}->{gOFF}->[$i+1] == 0);
613 0           seek($fh,$data->{'loca'}->{gOFF}->[$i]+$data->{'glyf'}->{OFF},0);
614 0           read($fh, $buf, 2);
615 0           $G->{numOfContours}=unpack_short($buf);
616 0           read($fh, $buf, 2);
617 0           $G->{xMin}=unpack_short($buf);
618 0           read($fh, $buf, 2);
619 0           $G->{yMin}=unpack_short($buf);
620 0           read($fh, $buf, 2);
621 0           $G->{xMax}=unpack_short($buf);
622 0           read($fh, $buf, 2);
623 0           $G->{yMax}=unpack_short($buf);
624             }
625             }
626            
627             sub find_name
628             {
629 0     0 0   my ($self, $nid) = @_;
630 0           my ($res, $pid, $eid, $lid, $look, $k);
631            
632 0           my (@lookup) = ([3, 1, 1033], [3, 1, -1], [2, 1, -1], [2, 2, -1], [2, 0, -1],
633             [0, 0, 0], [1, 0, 0]);
634 0           foreach $look (@lookup)
635             {
636 0           ($pid, $eid, $lid) = @$look;
637 0 0         if ($lid == -1)
638             {
639 0           foreach $k (keys %{$self->{'strings'}->[$nid]->[$pid]->[$eid]})
  0            
640             {
641 0 0         if (($res = $self->{strings}->[$nid]->[$pid]->[$eid]->{$k}) ne '')
642             {
643 0           $lid = $k;
644 0           last;
645             }
646             }
647             } else
648 0           { $res = $self->{strings}->[$nid]->[$pid]->[$eid]->{$lid} }
649 0 0         if ($res ne '')
650 0 0         { return wantarray ? ($res, $pid, $eid, $lid) : $res; }
651             }
652 0           return '';
653             }
654            
655             sub readcffindex
656             {
657 0     0 0   my ($fh,$off,$buf)=@_;
658 0           my @idx=();
659 0           my $index=[];
660 0           seek($fh,$off,0);
661 0           read($fh,$buf,3);
662 0           my ($count,$offsize)=unpack('nC',$buf);
663 0           foreach (0..$count)
664             {
665 0           read($fh,$buf,$offsize);
666 0           $buf=substr("\x00\x00\x00$buf",-4,4);
667 0           my $id=unpack('N',$buf);
668 0           push @idx,$id;
669             }
670 0           my $dataoff=tell($fh)-1;
671            
672 0           foreach my $i (0..$count-1)
673             {
674 0           push @{$index},{ 'OFF' => $dataoff+$idx[$i], 'LEN' => $idx[$i+1]-$idx[$i] };
  0            
675             }
676 0           return($index);
677             }
678            
679             sub readcffdict
680             {
681 0     0 0   my ($fh,$off,$len,$foff,$buf)=@_;
682 0           my @idx=();
683 0           my $dict={};
684 0           seek($fh,$off,0);
685 0           my @st=();
686 0           while(tell($fh)<($off+$len))
687             {
688 0           read($fh,$buf,1);
689 0           my $b0=unpack('C',$buf);
690 0           my $v='';
691            
692 0 0         if($b0==12) # two byte commands
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
693             {
694 0           read($fh,$buf,1);
695 0           my $b1=unpack('C',$buf);
696 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          
697             {
698 0           $dict->{Copyright}={ 'SID' => splice(@st,-1) };
699             }
700             elsif($b1==1)
701             {
702 0           $dict->{isFixedPitch}=splice(@st,-1);
703             }
704             elsif($b1==2)
705             {
706 0           $dict->{ItalicAngle}=splice(@st,-1);
707             }
708             elsif($b1==3)
709             {
710 0           $dict->{UnderlinePosition}=splice(@st,-1);
711             }
712             elsif($b1==4)
713             {
714 0           $dict->{UnderlineThickness}=splice(@st,-1);
715             }
716             elsif($b1==5)
717             {
718 0           $dict->{PaintType}=splice(@st,-1);
719             }
720             elsif($b1==6)
721             {
722 0           $dict->{CharstringType}=splice(@st,-1);
723             }
724             elsif($b1==7)
725             {
726 0           $dict->{FontMatrix}=[ splice(@st,-4) ];
727             }
728             elsif($b1==8)
729             {
730 0           $dict->{StrokeWidth}=splice(@st,-1);
731             }
732             elsif($b1==20)
733             {
734 0           $dict->{SyntheticBase}=splice(@st,-1);
735             }
736             elsif($b1==21)
737             {
738 0           $dict->{PostScript}={ 'SID' => splice(@st,-1) };
739             }
740             elsif($b1==22)
741             {
742 0           $dict->{BaseFontName}={ 'SID' => splice(@st,-1) };
743             }
744             elsif($b1==23)
745             {
746 0           $dict->{BaseFontBlend}=[ splice(@st,0) ];
747             }
748             elsif($b1==24)
749             {
750 0           $dict->{MultipleMaster}=[ splice(@st,0) ];
751             }
752             elsif($b1==25)
753             {
754 0           $dict->{BlendAxisTypes}=[ splice(@st,0) ];
755             }
756             elsif($b1==30)
757             {
758 0           $dict->{ROS}=[ splice(@st,-3) ];
759             }
760             elsif($b1==31)
761             {
762 0           $dict->{CIDFontVersion}=splice(@st,-1);
763             }
764             elsif($b1==32)
765             {
766 0           $dict->{CIDFontRevision}=splice(@st,-1);
767             }
768             elsif($b1==33)
769             {
770 0           $dict->{CIDFontType}=splice(@st,-1);
771             }
772             elsif($b1==34)
773             {
774 0           $dict->{CIDCount}=splice(@st,-1);
775             }
776             elsif($b1==35)
777             {
778 0           $dict->{UIDBase}=splice(@st,-1);
779             }
780             elsif($b1==36)
781             {
782 0           $dict->{FDArray}={ 'OFF' => $foff+splice(@st,-1) };
783             }
784             elsif($b1==37)
785             {
786 0           $dict->{FDSelect}={ 'OFF' => $foff+splice(@st,-1) };
787             }
788             elsif($b1==38)
789             {
790 0           $dict->{FontName}={ 'SID' => splice(@st,-1) };
791             }
792             elsif($b1==39)
793             {
794 0           $dict->{Chameleon}=splice(@st,-1);
795             }
796 0           next;
797             }
798             elsif($b0<28) # commands
799             {
800 0 0         if($b0==0)
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
801             {
802 0           $dict->{Version}={ 'SID' => splice(@st,-1) };
803             }
804             elsif($b0==1)
805             {
806 0           $dict->{Notice}={ 'SID' => splice(@st,-1) };
807             }
808             elsif($b0==2)
809             {
810 0           $dict->{FullName}={ 'SID' => splice(@st,-1) };
811             }
812             elsif($b0==3)
813             {
814 0           $dict->{FamilyName}={ 'SID' => splice(@st,-1) };
815             }
816             elsif($b0==4)
817             {
818 0           $dict->{Weight}={ 'SID' => splice(@st,-1) };
819             }
820             elsif($b0==5)
821             {
822 0           $dict->{FontBBX}=[ splice(@st,-4) ];
823             }
824             elsif($b0==13)
825             {
826 0           $dict->{UniqueID}=splice(@st,-1);
827             }
828             elsif($b0==14)
829             {
830 0           $dict->{XUID}=[splice(@st,0)];
831             }
832             elsif($b0==15)
833             {
834 0           $dict->{CharSet}={ 'OFF' => $foff+splice(@st,-1) };
835             }
836             elsif($b0==16)
837             {
838 0           $dict->{Encoding}={ 'OFF' => $foff+splice(@st,-1) };
839             }
840             elsif($b0==17)
841             {
842 0           $dict->{CharStrings}={ 'OFF' => $foff+splice(@st,-1) };
843             }
844             elsif($b0==18)
845             {
846 0           $dict->{Private}={ 'LEN' => splice(@st,-1), 'OFF' => $foff+splice(@st,-1) };
847             }
848 0           next;
849             }
850             elsif($b0==28) # int16
851             {
852 0           read($fh,$buf,2);
853 0           $v=unpack('n',$buf);
854 0 0         $v=-(0x10000-$v) if($v>0x7fff);
855             }
856             elsif($b0==29) # int32
857             {
858 0           read($fh,$buf,4);
859 0           $v=unpack('N',$buf);
860 0 0         $v=-$v+0xffffffff+1 if($v>0x7fffffff);
861             }
862             elsif($b0==30) # float
863             {
864 0           $e=1;
865 0           while($e)
866             {
867 0           read($fh,$buf,1);
868 0           $v0=unpack('C',$buf);
869 0           foreach my $m ($v0>>8,$v0&0xf)
870             {
871 0 0         if($m<10)
    0          
    0          
    0          
    0          
    0          
872             {
873 0           $v.=$m;
874             }
875             elsif($m==10)
876             {
877 0           $v.='.';
878             }
879             elsif($m==11)
880             {
881 0           $v.='E+';
882             }
883             elsif($m==12)
884             {
885 0           $v.='E-';
886             }
887             elsif($m==14)
888             {
889 0           $v.='-';
890             }
891             elsif($m==15)
892             {
893 0           $e=0;
894 0           last;
895             }
896             }
897             }
898             }
899             elsif($b0==31) # command
900             {
901 0           $v="c=$b0";
902 0           next;
903             }
904             elsif($b0<247) # 1 byte signed
905             {
906 0           $v=$b0-139;
907             }
908             elsif($b0<251) # 2 byte plus
909             {
910 0           read($fh,$buf,1);
911 0           $v=unpack('C',$buf);
912 0           $v=($b0-247)*256+($v+108);
913             }
914             elsif($b0<255) # 2 byte minus
915             {
916 0           read($fh,$buf,1);
917 0           $v=unpack('C',$buf);
918 0           $v=-($b0-251)*256-$v-108;
919             }
920 0           push @st,$v;
921             }
922            
923 0           return($dict);
924             }
925            
926            
927             sub get_otf_data {
928 0     0 0   my $file=shift @_;
929 0           my $filename=basename($file);
930 0           my $fh=IO::File->new($file);
931 0           my $data={};
932 0           binmode($fh,':raw');
933 0           my($buf,$ver,$num,$i);
934            
935 0           read($fh,$buf, 12);
936 0           ($ver, $num) = unpack("Nn", $buf);
937            
938 0 0 0       $ver == 1 << 16 # TTF version 1
      0        
939             || $ver == 0x74727565 # support Mac sfnts
940             || $ver == 0x4F54544F # OpenType with diverse Outlines
941             or next; #die "$file not a valid true/opentype font";
942            
943 0           for ($i = 0; $i < $num; $i++)
944             {
945 0 0         read($fh,$buf, 16) || last; #die "Reading table entry";
946 0           my ($name, $check, $off, $len) = unpack("a4NNN", $buf);
947 0           $data->{$name} = {
948             OFF => $off,
949             LEN => $len,
950             };
951             }
952            
953 0 0 0       next unless(defined $data->{name} && defined $data->{'OS/2'});
954            
955 0           $data->{V}={};
956            
957 0           read_name_table($data,$fh);
958            
959 0           read_os2_table($data,$fh);
960            
961 0           read_maxp_table($data,$fh);
962            
963 0           read_head_table($data,$fh);
964            
965 0           read_hhea_table($data,$fh);
966            
967 0           read_hmtx_table($data,$fh);
968            
969 0           read_cmap_table($data,$fh);
970            
971 0           read_post_table($data,$fh);
972            
973 0           if(0)
974             {
975             read_loca_table($data,$fh);
976             read_glyf_table($data,$fh);
977             }
978            
979 0           $data->{V}->{fontfamily}=find_name($data->{name},1);
980 0           $data->{V}->{fontname}=find_name($data->{name},4);
981 0           $data->{V}->{stylename}=find_name($data->{name},2);
982            
983 0           my $name = lc find_name($data->{name},1);
984 0           my $subname = lc find_name($data->{name},2);
985 0           my $slant='';
986            
987 0 0         if (defined $subname) {
988 0           $weight_name = "$subname";
989             } else {
990 0           $weight_name = "Regular";
991             }
992 0           $weight_name =~ s/-/ /g;
993            
994 0           $_ = $weight_name;
995 0 0         if (/^(regular|normal|medium)$/i) {
    0          
    0          
    0          
996 0           $weight_name = "Regular";
997 0           $slant = "";
998 0           $subname='';
999             } elsif (/^bold$/i) {
1000 0           $weight_name = "Bold";
1001 0           $slant = "";
1002 0           $subname='';
1003             } elsif (/^bold *(italic|oblique)$/i) {
1004 0           $weight_name = "Bold";
1005 0           $slant = "-Italic";
1006 0           $subname='';
1007             } elsif (/^(italic|oblique)$/i) {
1008 0           $weight_name = "Regular";
1009 0           $slant = "-Italic";
1010 0           $subname='';
1011             } else {
1012             # we need to find it via the OS/2 table
1013 0 0         if($data->{V}->{usWeightClass} == 0) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1014 0           $weight_name = "Regular";
1015             } elsif($data->{V}->{usWeightClass} < 150) {
1016 0           $weight_name = "Thin";
1017             } elsif($data->{V}->{usWeightClass} < 250) {
1018 0           $weight_name = "ExtraLight";
1019             } elsif($data->{V}->{usWeightClass} < 350) {
1020 0           $weight_name = "Light";
1021             } elsif($data->{V}->{usWeightClass} < 450) {
1022 0           $weight_name = "Regular";
1023             } elsif($data->{V}->{usWeightClass} < 550) {
1024 0           $weight_name = "Regular";
1025             } elsif($data->{V}->{usWeightClass} < 650) {
1026 0           $weight_name = "SemiBold";
1027             } elsif($data->{V}->{usWeightClass} < 750) {
1028 0           $weight_name = "Bold";
1029             } elsif($data->{V}->{usWeightClass} < 850) {
1030 0           $weight_name = "ExtraBold";
1031             } else {
1032 0           $weight_name = "Black";
1033             }
1034             # $slant = "";
1035             # $subname='';
1036             }
1037            
1038 0           $data->{V}->{fontweight}=$data->{V}->{usWeightClass};
1039            
1040 0 0         if($data->{V}->{usWidthClass} == 1) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1041 0           $setwidth_name = "-UltraCondensed";
1042 0           $data->{V}->{fontstretch}="UltraCondensed";
1043             } elsif($data->{V}->{usWidthClass} == 2) {
1044 0           $setwidth_name = "-ExtraCondensed";
1045 0           $data->{V}->{fontstretch}="ExtraCondensed";
1046             } elsif($data->{V}->{usWidthClass} == 3) {
1047 0           $setwidth_name = "-Condensed";
1048 0           $data->{V}->{fontstretch}="Condensed";
1049             } elsif($data->{V}->{usWidthClass} == 4) {
1050 0           $setwidth_name = "-SemiCondensed";
1051 0           $data->{V}->{fontstretch}="SemiCondensed";
1052             } elsif($data->{V}->{usWidthClass} == 5) {
1053 0           $setwidth_name = "";
1054 0           $data->{V}->{fontstretch}="Normal";
1055             } elsif($data->{V}->{usWidthClass} == 6) {
1056 0           $setwidth_name = "-SemiExpanded";
1057 0           $data->{V}->{fontstretch}="SemiExpanded";
1058             } elsif($data->{V}->{usWidthClass} == 7) {
1059 0           $setwidth_name = "-Expanded";
1060 0           $data->{V}->{fontstretch}="Expanded";
1061             } elsif($data->{V}->{usWidthClass} == 8) {
1062 0           $setwidth_name = "-ExtraExpanded";
1063 0           $data->{V}->{fontstretch}="ExtraExpanded";
1064             } elsif($data->{V}->{usWidthClass} == 9) {
1065 0           $setwidth_name = "-UltraExpanded";
1066 0           $data->{V}->{fontstretch}="UltraExpanded";
1067             } else {
1068 0           $setwidth_name = ""; # normal | condensed | narrow | semicondensed
1069 0           $data->{V}->{fontstretch}="Normal";
1070             }
1071            
1072 0           $data->{V}->{fontname}=$name;
1073 0           $data->{V}->{subname}="$weight_name$slant$setwidth_name";
1074 0           $data->{V}->{subname}=~s|\-| |g;
1075            
1076 0 0         if(defined $data->{'CFF '})
1077             {
1078             # read CFF table
1079 0           seek($fh,$data->{'CFF '}->{OFF},0);
1080 0           read($fh,$buf, 4);
1081 0           my ($cffmajor,$cffminor,$cffheadsize,$cffglobaloffsize)=unpack('C4',$buf);
1082            
1083 0           $data->{'CFF '}->{name}=readcffindex($fh,$data->{'CFF '}->{OFF}+$cffheadsize);
1084 0           foreach my $dict (@{$data->{'CFF '}->{name}})
  0            
1085             {
1086 0           seek($fh,$dict->{OFF},0);
1087 0           read($fh,$dict->{VAL},$dict->{LEN});
1088             }
1089            
1090 0           $data->{'CFF '}->{topdict}=readcffindex($fh,$data->{'CFF '}->{name}->[-1]->{OFF}+$data->{'CFF '}->{name}->[-1]->{LEN});
1091 0           foreach my $dict (@{$data->{'CFF '}->{topdict}})
  0            
1092             {
1093 0           $dict->{VAL}=readcffdict($fh,$dict->{OFF},$dict->{LEN},$data->{'CFF '}->{OFF});
1094             }
1095            
1096 0           $data->{'CFF '}->{string}=readcffindex($fh,$data->{'CFF '}->{topdict}->[-1]->{OFF}+$data->{'CFF '}->{topdict}->[-1]->{LEN});
1097 0           foreach my $dict (@{$data->{'CFF '}->{string}})
  0            
1098             {
1099 0           seek($fh,$dict->{OFF},0);
1100 0           read($fh,$dict->{VAL},$dict->{LEN});
1101             }
1102 0           push @{$data->{'CFF '}->{string}},{ 'VAL' => '001.000' };
  0            
1103 0           push @{$data->{'CFF '}->{string}},{ 'VAL' => '001.001' };
  0            
1104 0           push @{$data->{'CFF '}->{string}},{ 'VAL' => '001.002' };
  0            
1105 0           push @{$data->{'CFF '}->{string}},{ 'VAL' => '001.003' };
  0            
1106 0           push @{$data->{'CFF '}->{string}},{ 'VAL' => 'Black' };
  0            
1107 0           push @{$data->{'CFF '}->{string}},{ 'VAL' => 'Bold' };
  0            
1108 0           push @{$data->{'CFF '}->{string}},{ 'VAL' => 'Book' };
  0            
1109 0           push @{$data->{'CFF '}->{string}},{ 'VAL' => 'Light' };
  0            
1110 0           push @{$data->{'CFF '}->{string}},{ 'VAL' => 'Medium' };
  0            
1111 0           push @{$data->{'CFF '}->{string}},{ 'VAL' => 'Regular' };
  0            
1112 0           push @{$data->{'CFF '}->{string}},{ 'VAL' => 'Roman' };
  0            
1113 0           push @{$data->{'CFF '}->{string}},{ 'VAL' => 'Semibold' };
  0            
1114            
1115 0           foreach my $dict (@{$data->{'CFF '}->{topdict}})
  0            
1116             {
1117 0           foreach my $k (keys %{$dict->{VAL}})
  0            
1118             {
1119 0           my $dt=$dict->{VAL}->{$k};
1120 0 0         if($k eq 'ROS')
1121             {
1122 0           $dict->{VAL}->{$k}->[0]=$data->{'CFF '}->{string}->[$dict->{VAL}->{$k}->[0]-391]->{VAL};
1123 0           $dict->{VAL}->{$k}->[1]=$data->{'CFF '}->{string}->[$dict->{VAL}->{$k}->[1]-391]->{VAL};
1124 0           $data->{V}->{$k}=$dict->{VAL}->{$k};
1125 0           next;
1126             }
1127 0 0 0       next unless(ref($dt) eq 'HASH' && defined $dt->{SID});
1128 0 0         if($dt->{SID}>=379)
1129             {
1130 0           $dict->{VAL}->{$k}=$data->{'CFF '}->{string}->[$dt->{SID}-391]->{VAL};
1131             }
1132             }
1133             }
1134             }
1135            
1136 0           close($fh);
1137            
1138 0           nameByUni();
1139            
1140 0           my $g = scalar @{$data->{V}->{uni}};
  0            
1141 0           $data->{V}->{wx}={};
1142 0           for(my $i = 0; $i<$g ; $i++)
1143             {
1144 0 0         if(defined $data->{hmtx}->{wx}->[$i])
1145             {
1146 0           $data->{V}->{wx}->{nameByUni($data->{V}->{uni}->[$i])} = $data->{hmtx}->{wx}->[$i];
1147             }
1148             else
1149             {
1150 0           $data->{V}->{wx}->{nameByUni($data->{V}->{uni}->[$i])} = $data->{hmtx}->{wx}->[-1];
1151             }
1152             }
1153            
1154 0           $data->{V}->{glyphs}=$data->{glyf}->{glyphs};
1155 0           $data=$data->{V};
1156 0           $data->{firstchar}=0;
1157 0           $data->{lastchar}=255;
1158            
1159 0 0         $data->{flags} |= 1 if($data->{isfixedpitch} > 0);
1160 0 0         $data->{flags} |= 64 if($data->{italicangle} != 0);
1161 0 0         $data->{flags} |= (1<<18) if($data->{usWeightClass} >= 600);
1162            
1163 0           return($data);
1164             }
1165            
1166            
1167             sub new
1168             {
1169 0     0 1   my ($class,$pdf,$name,%opts) = @_;
1170 0           my ($self,$data);
1171 0           $data=get_otf_data($name);
1172            
1173 0 0         $class = ref $class if ref $class;
1174 0           $self = $class->SUPER::new($pdf, $data->{apiname}.pdfkey().'~'.time());
1175 0 0         $pdf->new_obj($self) unless($self->is_obj($pdf));
1176 0           $self->{' data'}=$data;
1177 0 0         $self->{-dokern}=1 if($opts{-dokern});
1178            
1179 0           $self->{'Subtype'} = PDFName('TrueType');
1180 0 0         if($opts{-fontname})
1181             {
1182 0           $self->{'BaseFont'} = PDFName($opts{-fontname});
1183             }
1184             else
1185             {
1186 0           my $fn=$data->{fontfamily};
1187 0           $fn=~s|\s+||go;
1188 0 0 0       if(($data->{stylename}=~m<(italic|oblique)>i) && ($data->{usWeightClass}>600))
    0          
    0          
1189             {
1190 0           $fn.=',BoldItalic';
1191             }
1192             elsif($data->{stylename}=~m<(italic|oblique)>i)
1193             {
1194 0           $fn.=',Italic';
1195             }
1196             elsif($data->{usWeightClass}>600)
1197             {
1198 0           $fn.=',Bold';
1199             }
1200            
1201 0           $self->{'BaseFont'} = PDFName($fn);
1202             }
1203 0 0         if($opts{-pdfname})
1204             {
1205 0           $self->name($opts{-pdfname});
1206             }
1207            
1208 0           $self->{FontDescriptor}=$self->descrByData();
1209 0           $self->encodeByData($opts{-encode});
1210            
1211 0           return($self);
1212             }
1213            
1214             =item $font = PDF::API3::Compat::API2::Resource::Font::neTrueType->new_api $api, $fontname, %options
1215            
1216             Returns a ne-truetype 8bit only object. This method is different from 'new' that
1217             it needs an PDF::API3::Compat::API2-object rather than a PDF::API3::Compat::API2::PDF::File-object.
1218            
1219             =cut
1220            
1221             sub new_api
1222             {
1223 0     0 1   my ($class,$api,@opts)=@_;
1224            
1225 0           my $obj=$class->new($api->{pdf},@opts);
1226            
1227 0 0         $api->{pdf}->new_obj($obj) unless($obj->is_obj($api->{pdf}));
1228            
1229 0           $api->{pdf}->out_obj($api->{pages});
1230 0           return($obj);
1231             }
1232            
1233            
1234             1;
1235            
1236             __END__