File Coverage

blib/lib/PDF/API3/Compat/API2/Resource/BaseFont.pm
Criterion Covered Total %
statement 26 261 9.9
branch 0 74 0.0
condition 0 56 0.0
subroutine 9 59 15.2
pod 45 50 90.0
total 80 500 16.0


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: BaseFont.pm,v 2.9 2007/10/16 20:08:19 areibens Exp $
31             #
32             #=======================================================================
33             package PDF::API3::Compat::API2::Resource::BaseFont;
34            
35             BEGIN {
36            
37 1     1   6 use utf8;
  1         3  
  1         7  
38 1     1   35 use Encode qw(:all);
  1         3  
  1         329  
39            
40 1     1   7 use PDF::API3::Compat::API2::Util;
  1         2  
  1         226  
41 1     1   6 use PDF::API3::Compat::API2::Basic::PDF::Utils;
  1         3  
  1         136  
42 1     1   7 use PDF::API3::Compat::API2::Resource;
  1         3  
  1         24  
43 1     1   7 use Compress::Zlib;
  1         3  
  1         406  
44            
45 1     1   7 use vars qw(@ISA $VERSION);
  1         2  
  1         115  
46            
47 1     1   23 @ISA = qw( PDF::API3::Compat::API2::Resource );
48            
49 1         39 ( $VERSION ) = sprintf '%i.%03i', split(/\./,('$Revision: 2.9 $' =~ /Revision: (\S+)\s/)[0]); # $Date: 2007/10/16 20:08:19 $
50            
51             }
52 1     1   6 no warnings qw[ deprecated recursion uninitialized ];
  1         2  
  1         4537  
53            
54             =item $font = PDF::API3::Compat::API2::Resource::BaseFont->new $pdf, $name
55            
56             Returns a font resource object.
57            
58             =cut
59            
60             sub new {
61 0     0 1   my ($class,$pdf,$name) = @_;
62 0           my $self;
63            
64 0 0         $class = ref $class if ref $class;
65 0           $self=$class->SUPER::new($pdf,$name);
66            
67 0 0         $pdf->new_obj($self) unless($self->is_obj($pdf));
68            
69 0           $self->{Type} = PDFName('Font');
70            
71 0           $self->{' apipdf'}=$pdf;
72 0           return($self);
73             }
74            
75             =item $font = PDF::API3::Compat::API2::Resource::BaseFont->new_api $api, $name
76            
77             Returns a font resource object. This method is different from 'new' that
78             it needs an PDF::API3::Compat::API2-object rather than a Text::PDF::File-object.
79            
80             =cut
81            
82             sub new_api {
83 0     0 1   my ($class,$api,@opts)=@_;
84            
85 0           my $obj=$class->new($api->{pdf},@opts);
86 0           $obj->{' api'}=$api;
87            
88 0           return($obj);
89             }
90            
91 0     0 0   sub data { return( $_[0]->{' data'} ); }
92            
93             =item $descriptor = $font->descrByData()
94            
95             Returns the fonts FontDescriptor key-structure based on the fonts data.
96            
97             =cut
98            
99             sub descrByData {
100 0     0 1   my $self=shift @_;
101            
102 0           my $des=PDFDict();
103 0           $self->{' apipdf'}->new_obj($des);
104            
105             ### $self->{'FontDescriptor'}=$des;
106            
107 0           $des->{'Type'}=PDFName('FontDescriptor');
108 0           $des->{'FontName'}=PDFName($self->fontname);
109            
110 0   0       my @w = map { PDFNum($_ || 0) } $self->fontbbox;
  0            
111 0           $des->{'FontBBox'}=PDFArray(@w);
112            
113             # unless($self->issymbol) {
114 0   0       $des->{'Ascent'}=PDFNum($self->ascender || 0);
115 0   0       $des->{'Descent'}=PDFNum($self->descender || 0);
116 0   0       $des->{'ItalicAngle'}=PDFNum($self->italicangle || 0.0);
117 0   0       $des->{'XHeight'}=PDFNum($self->xheight || (($self->fontbbox)[3]*0.5) || 500);
118 0   0       $des->{'CapHeight'}=PDFNum($self->capheight || ($self->fontbbox)[3] || 800);
119 0   0       $des->{'StemV'}=PDFNum($self->stemv || 0);
120 0   0       $des->{'StemH'}=PDFNum($self->stemh || 0);
121 0   0       $des->{'AvgWidth'}=PDFNum($self->avgwidth || 300);
122 0   0       $des->{'MissingWidth'}=PDFNum($self->missingwidth || 300);
123 0   0       $des->{'MaxWidth'}=PDFNum($self->maxwidth || $self->missingwidth || ($self->fontbbox)[2]);
124 0 0 0       $des->{'Flags'}=PDFNum($self->flags || 0) unless($self->data->{iscore});
125 0 0         if(defined $self->data->{panose}) {
126 0           $des->{Style}=PDFDict();
127 0           $des->{Style}->{Panose}=PDFStrHex($self->data->{panose});
128             }
129 0 0         $des->{FontFamily}=PDFStr($self->data->{fontfamily})
130             if(defined $self->data->{fontfamily});
131 0 0         $des->{FontWeight}=PDFNum($self->data->{fontweight})
132             if(defined $self->data->{fontweight});
133 0 0         $des->{FontStretch}=PDFName($self->data->{fontstretch})
134             if(defined $self->data->{fontstretch});
135             # }
136            
137 0           return($des);
138             }
139            
140             sub tounicodemap {
141 0     0 0   my $self=shift @_;
142            
143 0 0         return($self) if(defined $self->{ToUnicode});
144            
145 0           my $cmap=qq|\%\% Custom\n\%\% CMap\n\%\%\n/CIDInit /ProcSet findresource begin\n|;
146 0           $cmap.=qq|12 dict begin begincmap\n|;
147 0           $cmap.=qq|/CIDSystemInfo <<\n|;
148 0           $cmap.=sprintf(qq| /Registry (%s)\n|,$self->name);
149 0           $cmap.=qq| /Ordering (XYZ)\n|;
150 0           $cmap.=qq| /Supplement 0\n|;
151 0           $cmap.=qq|>> def\n|;
152 0           $cmap.=sprintf(qq|/CMapName /pdfapi2-%s+0 def\n|,$self->name);
153 0 0 0       if(UNIVERSAL::can($self,'uniByCId') && UNIVERSAL::can($self,'glyphNum')) {
154             # this is a type0 font
155 0           $cmap.=sprintf(qq|1 begincodespacerange <0000> <%04X> endcodespacerange\n|,$self->glyphNum-1);
156 0           for(my $j=0;$j<$self->glyphNum;$j++) {
157 0 0         my $i = $self->glyphNum - $j > 100 ? 100 : $self->glyphNum - $j;
158 0 0         if($j==0) {
    0          
159 0           $cmap.=qq|$i beginbfrange\n|;
160             } elsif($j%100 == 0) {
161 0           $cmap.=qq|endbfrange\n|;
162 0           $cmap.=qq|$i beginbfrange\n|;
163             }
164 0           $cmap.=sprintf(qq|<%04x> <%04x> <%04x>\n|,$j,$j,$self->uniByCId($j));
165             }
166 0           $cmap.="endbfrange\n";
167             } else {
168             # everything else is single byte font
169 0           $cmap.=qq|1 begincodespacerange\n<00> \nendcodespacerange\n|;
170 0           $cmap.=qq|256 beginbfchar\n|;
171 0           for(my $j=0; $j<256;$j++) {
172 0           $cmap.=sprintf(qq|<%02X> <%04X>\n|,$j,$self->uniByEnc($j));
173             }
174 0           $cmap.=qq|endbfchar\n|;
175             }
176 0           $cmap.=qq|endcmap CMapName currendict /CMap defineresource pop end end\n|;
177            
178 0           my $tuni=PDFDict();
179 0           $tuni->{Type}=PDFName('CMap');
180 0           $tuni->{CMapName}=PDFName(sprintf(qq|pdfapi2-%s+0|,$self->name));
181 0           $tuni->{CIDSystemInfo}=PDFDict();
182 0           $tuni->{CIDSystemInfo}->{Registry}=PDFStr($self->name);
183 0           $tuni->{CIDSystemInfo}->{Ordering}=PDFStr('XYZ');
184 0           $tuni->{CIDSystemInfo}->{Supplement}=PDFNum(0);
185            
186 0           $self->{' apipdf'}->new_obj($tuni);
187 0           $tuni->{' nofilt'}=1;
188 0           $tuni->{' stream'}=Compress::Zlib::compress($cmap);
189 0           $tuni->{Filter}=PDFArray(PDFName('FlateDecode'));
190 0           $self->{ToUnicode}=$tuni;
191 0           return($self);
192             }
193            
194            
195             =back
196            
197             =head1 FONT-MANAGEMENT RELATED METHODS
198            
199             =over 4
200            
201             =item $name = $font->fontname()
202            
203             Returns the fonts name (aka. display-name).
204            
205             =cut
206            
207 0     0 1   sub fontname { return( $_[0]->data->{fontname} ); }
208            
209             =item $name = $font->altname()
210            
211             Returns the fonts alternative-name (aka. windows-name for a postscript font).
212            
213             =cut
214            
215 0     0 1   sub altname { return( $_[0]->data->{altname} ); }
216            
217             =item $name = $font->subname()
218            
219             Returns the fonts subname (aka. font-variant, schriftschnitt).
220            
221             =cut
222            
223 0     0 1   sub subname { return( $_[0]->data->{subname} ); }
224            
225             =item $name = $font->apiname()
226            
227             Returns the fonts name to be used internally (should be equal to $font->name).
228            
229             =cut
230            
231 0     0 1   sub apiname { return( $_[0]->data->{apiname} ); }
232            
233             =item $issymbol = $font->issymbol()
234            
235             Returns the fonts symbol flag.
236            
237             =cut
238            
239 0     0 1   sub issymbol { return( $_[0]->data->{issymbol} ); }
240            
241             =item $iscff = $font->iscff()
242            
243             Returns the fonts compact-font-format flag.
244            
245             =cut
246            
247 0     0 1   sub iscff { return( $_[0]->data->{iscff} ); }
248            
249             =back
250            
251             =head1 TYPOGRAPHY RELATED METHODS
252            
253             =over 4
254            
255             =item ($llx, $lly, $urx, $ury) = $font->fontbbox()
256            
257             Returns the fonts bounding-box.
258            
259             =cut
260            
261 0     0 1   sub fontbbox { return( @{$_[0]->data->{fontbbox}} ); }
  0            
262            
263             =item $capheight = $font->capheight()
264            
265             Returns the fonts capheight value.
266            
267             =cut
268            
269 0     0 1   sub capheight { return( $_[0]->data->{capheight} ); }
270            
271             =item $xheight = $font->xheight()
272            
273             Returns the fonts xheight value.
274            
275             =cut
276            
277 0     0 1   sub xheight { return( $_[0]->data->{xheight} ); }
278            
279             =item $missingwidth = $font->missingwidth()
280            
281             Returns the fonts missingwidth value.
282            
283             =cut
284            
285 0     0 1   sub missingwidth { return( $_[0]->data->{missingwidth} ); }
286            
287             =item $maxwidth = $font->maxwidth()
288            
289             Returns the fonts maxwidth value.
290            
291             =cut
292            
293 0     0 1   sub maxwidth { return( $_[0]->data->{maxwidth} ); }
294            
295             =item $avgwidth = $font->avgwidth()
296            
297             Returns the fonts avgwidth value.
298            
299             =cut
300            
301             sub avgwidth {
302 0     0 1   my ($self) = @_;
303 0           my $aw=$self->data->{avgwidth};
304 0   0       $aw||=((
305             $self->wxByGlyph('a')*64 +
306             $self->wxByGlyph('b')*14 +
307             $self->wxByGlyph('c')*27 +
308             $self->wxByGlyph('d')*35 +
309             $self->wxByGlyph('e')*100 +
310             $self->wxByGlyph('f')*20 +
311             $self->wxByGlyph('g')*14 +
312             $self->wxByGlyph('h')*42 +
313             $self->wxByGlyph('i')*63 +
314             $self->wxByGlyph('j')* 3 +
315             $self->wxByGlyph('k')* 6 +
316             $self->wxByGlyph('l')*35 +
317             $self->wxByGlyph('m')*20 +
318             $self->wxByGlyph('n')*56 +
319             $self->wxByGlyph('o')*56 +
320             $self->wxByGlyph('p')*17 +
321             $self->wxByGlyph('q')* 4 +
322             $self->wxByGlyph('r')*49 +
323             $self->wxByGlyph('s')*56 +
324             $self->wxByGlyph('t')*71 +
325             $self->wxByGlyph('u')*31 +
326             $self->wxByGlyph('v')*10 +
327             $self->wxByGlyph('w')*18 +
328             $self->wxByGlyph('x')* 3 +
329             $self->wxByGlyph('y')*18 +
330             $self->wxByGlyph('z')* 2 +
331             $self->wxByGlyph('A')*64 +
332             $self->wxByGlyph('B')*14 +
333             $self->wxByGlyph('C')*27 +
334             $self->wxByGlyph('D')*35 +
335             $self->wxByGlyph('E')*100 +
336             $self->wxByGlyph('F')*20 +
337             $self->wxByGlyph('G')*14 +
338             $self->wxByGlyph('H')*42 +
339             $self->wxByGlyph('I')*63 +
340             $self->wxByGlyph('J')* 3 +
341             $self->wxByGlyph('K')* 6 +
342             $self->wxByGlyph('L')*35 +
343             $self->wxByGlyph('M')*20 +
344             $self->wxByGlyph('N')*56 +
345             $self->wxByGlyph('O')*56 +
346             $self->wxByGlyph('P')*17 +
347             $self->wxByGlyph('Q')* 4 +
348             $self->wxByGlyph('R')*49 +
349             $self->wxByGlyph('S')*56 +
350             $self->wxByGlyph('T')*71 +
351             $self->wxByGlyph('U')*31 +
352             $self->wxByGlyph('V')*10 +
353             $self->wxByGlyph('W')*18 +
354             $self->wxByGlyph('X')* 3 +
355             $self->wxByGlyph('Y')*18 +
356             $self->wxByGlyph('Z')* 2 +
357             $self->wxByGlyph('space')*332
358             ) / 2000);
359 0           return( int($aw) );
360             }
361            
362             =item $flags = $font->flags()
363            
364             Returns the fonts flags value.
365            
366             =cut
367            
368 0     0 1   sub flags { return( $_[0]->data->{flags} ); }
369            
370             =item $stemv = $font->stemv()
371            
372             Returns the fonts stemv value.
373            
374             =cut
375            
376 0     0 1   sub stemv { return( $_[0]->data->{stemv} ); }
377            
378             =item $stemh = $font->stemh()
379            
380             Returns the fonts stemh value.
381            
382             =cut
383            
384 0     0 1   sub stemh { return( $_[0]->data->{stemh} ); }
385            
386             =item $italicangle = $font->italicangle()
387            
388             Returns the fonts italicangle value.
389            
390             =cut
391            
392 0     0 1   sub italicangle { return( $_[0]->data->{italicangle} ); }
393            
394             =item $isfixedpitch = $font->isfixedpitch()
395            
396             Returns the fonts isfixedpitch flag.
397            
398             =cut
399            
400 0     0 1   sub isfixedpitch { return( $_[0]->data->{isfixedpitch} ); }
401            
402             =item $underlineposition = $font->underlineposition()
403            
404             Returns the fonts underlineposition value.
405            
406             =cut
407            
408 0     0 1   sub underlineposition { return( $_[0]->data->{underlineposition} ); }
409            
410             =item $underlinethickness = $font->underlinethickness()
411            
412             Returns the fonts underlinethickness value.
413            
414             =cut
415            
416 0     0 1   sub underlinethickness { return( $_[0]->data->{underlinethickness} ); }
417            
418             =item $ascender = $font->ascender()
419            
420             Returns the fonts ascender value.
421            
422             =cut
423            
424 0     0 1   sub ascender { return( $_[0]->data->{ascender} ); }
425            
426             =item $descender = $font->descender()
427            
428             Returns the fonts descender value.
429            
430             =cut
431            
432 0     0 1   sub descender { return( $_[0]->data->{descender} ); }
433            
434             =back
435            
436             =head1 GLYPH RELATED METHODS
437            
438             =over 4
439            
440             =item @names = $font->glyphNames()
441            
442             Returns the defined glyph-names of the font.
443            
444             =cut
445            
446 0     0 1   sub glyphNames { return ( keys %{$_[0]->data->{wx}} ); }
  0            
447            
448             =item $glNum = $font->glyphNum()
449            
450             Returns the number of defined glyph-names of the font.
451            
452             =cut
453            
454 0     0 1   sub glyphNum { return ( scalar keys %{$_[0]->data->{wx}} ); }
  0            
455            
456             =item $uni = $font->uniByGlyph $char
457            
458             Returns the unicode by glyph-name.
459            
460             =cut
461            
462 0     0 1   sub uniByGlyph { return( $_[0]->data->{n2u}->{$_[1]} ); }
463            
464             =item $uni = $font->uniByEnc $char
465            
466             Returns the unicode by the fonts encoding map.
467            
468             =cut
469            
470 0     0 1   sub uniByEnc { return($_[0]->data->{e2u}->[$_[1]] ); }
471            
472             =item $uni = $font->uniByMap $char
473            
474             Returns the unicode by the fonts default map.
475            
476             =cut
477            
478 0     0 1   sub uniByMap { return($_[0]->data->{uni}->[$_[1]]); }
479            
480             =item $char = $font->encByGlyph $glyph
481            
482             Returns the character by the given glyph-name of the fonts encoding map.
483            
484             =cut
485            
486 0   0 0 1   sub encByGlyph { return( $_[0]->data->{n2e}->{$_[1]} || 0 ); }
487            
488             =item $char = $font->encByUni $uni
489            
490             Returns the character by the given unicode of the fonts encoding map.
491            
492             =cut
493            
494 0   0 0 1   sub encByUni { return( $_[0]->data->{u2e}->{$_[1]} || $_[0]->data->{u2c}->{$_[1]} || 0 ); }
495            
496             =item $char = $font->mapByGlyph $glyph
497            
498             Returns the character by the given glyph-name of the fonts default map.
499            
500             =cut
501            
502 0   0 0 1   sub mapByGlyph { return( $_[0]->data->{n2c}->{$_[1]} || 0 ); }
503            
504             =item $char = $font->mapByUni $uni
505            
506             Returns the character by the given unicode of the fonts default map.
507            
508             =cut
509            
510 0   0 0 1   sub mapByUni { return( $_[0]->data->{u2c}->{$_[1]} || 0 ); }
511            
512             =item $name = $font->glyphByUni $unicode
513            
514             Returns the glyphs name by the fonts unicode map.
515             B non-standard glyph-names are mapped onto
516             the ms-symbol area (0xF000).
517            
518             =cut
519            
520 0   0 0 1   sub glyphByUni { return ( $_[0]->data->{u2n}->{$_[1]} || '.notdef' ); }
521            
522             =item $name = $font->glyphByEnc $char
523            
524             Returns the glyphs name by the fonts encoding map.
525            
526             =cut
527            
528             sub glyphByEnc {
529 0     0 1   my ($self,$e)=@_;
530 0           my $g=$self->data->{e2n}->[$e];
531 0           return( $g );
532             }
533            
534             =item $name = $font->glyphByMap $char
535            
536             Returns the glyphs name by the fonts default map.
537            
538             =cut
539            
540 0     0 1   sub glyphByMap { return ( $_[0]->data->{char}->[$_[1]] ); }
541            
542             =item $width = $font->wxByGlyph $glyph
543            
544             Returns the glyphs width.
545            
546             =cut
547            
548             sub wxByGlyph
549             {
550 0     0 1   my $self=shift;
551 0           my $val=shift;
552 0           my $ret=undef;
553 0 0         if(ref($self->data->{wx}) eq 'HASH')
554             {
555 0           $ret=$self->data->{wx}->{$val};
556 0 0         if(!defined($ret))
557             {
558 0           $ret=$self->missingwidth;
559             }
560 0 0         if(!defined($ret))
561             {
562 0           $ret=300;
563             }
564             }
565             else
566             {
567 0           my $cid=$self->cidByUni(uniByName($val));
568 0           $ret=$self->data->{wx}->[$cid];
569 0 0         if(!defined($ret))
570             {
571 0           $ret=$self->missingwidth;
572             }
573 0 0         if(!defined($ret))
574             {
575 0           $ret=300;
576             }
577             }
578 0           return $ret;
579             }
580            
581             =item $width = $font->wxByUni $uni
582            
583             Returns the unicodes width.
584            
585             =cut
586            
587             sub wxByUni
588             {
589 0     0 1   my $self=shift;
590 0           my $val=shift;
591 0           my $gid=$self->glyphByUni($val);
592 0           my $ret=$self->data->{wx}->{$gid};
593 0 0         if(!defined($ret))
594             {
595 0           $ret=$self->missingwidth;
596             }
597 0 0         if(!defined($ret))
598             {
599 0           $ret=300;
600             }
601 0           return $ret;
602             }
603            
604             =item $width = $font->wxByEnc $char
605            
606             Returns the characters width based on the current encoding.
607            
608             =cut
609            
610             sub wxByEnc
611             {
612 0     0 1   my ($self,$e)=@_;
613 0           my $g=$self->glyphByEnc($e);
614 0           my $ret=$self->data->{wx}->{$g};
615 0 0         if(!defined($ret))
616             {
617 0           $ret=$self->missingwidth;
618             }
619 0 0         if(!defined($ret))
620             {
621 0           $ret=300;
622             }
623 0           return $ret;
624             }
625            
626             =item $width = $font->wxByMap $char
627            
628             Returns the characters width based on the fonts default encoding.
629            
630             =cut
631            
632             sub wxByMap
633             {
634 0     0 1   my ($self,$m)=@_;
635 0           my $g=$self->glyphByMap($m);
636 0           my $ret=$self->data->{wx}->{$g};
637 0 0         if(!defined($ret))
638             {
639 0           $ret=$self->missingwidth;
640             }
641 0 0         if(!defined($ret))
642             {
643 0           $ret=300;
644             }
645 0           return $ret;
646             }
647            
648             =item $wd = $font->width $text
649            
650             Returns the width of $text as if it were at size 1.
651             B works only correctly if a proper perl-string
652             is used either in native or utf8 format (check utf8-flag).
653            
654             =cut
655            
656             sub width {
657 0     0 1   my ($self,$text)=@_;
658 0           my $width=0;
659 0 0         if(is_utf8($text)) {
660 0           $text=$self->strByUtf($text)
661             }
662 0           my $lastglyph='';
663 0           foreach my $n (unpack('C*',$text))
664             {
665 0           $width+=$self->wxByEnc($n);
666 0 0 0       if($self->{-dokern} && ref($self->data->{kern}))
667             {
668 0           $width+=$self->data->{kern}->{$lastglyph.':'.$self->data->{e2n}->[$n]};
669 0           $lastglyph=$self->data->{e2n}->[$n];
670             }
671             }
672 0           $width/=1000;
673 0           return($width);
674             }
675            
676             =item @widths = $font->width_array $text
677            
678             Returns the widths of the words in $text as if they were at size 1.
679            
680             =cut
681            
682             sub width_array {
683 0     0 1   my ($self,$text)=@_;
684 0 0         if(!is_utf8($text)) {
685 0           $text=$self->utfByStr($text);
686             }
687 0           my @text=split(/\s+/,$text);
688 0           my @widths=map { $self->width($_) } @text;
  0            
689 0           return(@widths);
690             }
691            
692             =back
693            
694             =head1 STRING METHODS
695            
696             =over 4
697            
698             =item $utf8string = $font->utfByStr $string
699            
700             Returns the utf8-string from string based on the fonts encoding map.
701            
702             =cut
703            
704             sub utfByStr {
705 0     0 1   my ($self,$s)=@_;
706 0           $s=pack('U*',map { $self->uniByEnc($_) } unpack('C*',$s));
  0            
707 0           utf8::upgrade($s);
708 0           return($s);
709             }
710            
711             =item $string = $font->strByUtf $utf8string
712            
713             Returns the encoded string from utf8-string based on the fonts encoding map.
714            
715             =cut
716            
717             sub strByUtf {
718 0     0 1   my ($self,$s)=@_;
719 0           $s=pack('C*',map { $self->encByUni($_) & 0xFF } unpack('U*',$s));
  0            
720 0           utf8::downgrade($s);
721 0           return($s);
722             }
723            
724             =item $pdfstring = $font->textByStr $text
725            
726             Returns a properly formatted representation of $text for use in the PDF.
727            
728             =cut
729            
730             sub textByStr
731             {
732 0     0 1   my ($self,$text)=@_;
733 0           my $newtext='';
734 0 0         if(is_utf8($text))
735             {
736 0           $text=$self->strByUtf($text);
737             }
738 0           $newtext=$text;
739 0           $newtext=~s/\\/\\\\/go;
740 0           $newtext=~s/([\x00-\x1f])/sprintf('\%03lo',ord($1))/ge;
  0            
741 0           $newtext=~s/([\{\}\[\]\(\)])/\\$1/g;
742 0           return($newtext);
743             }
744            
745             sub textByStrKern
746             {
747 0     0 0   my ($self,$text)=@_;
748 0 0 0       if($self->{-dokern} && ref($self->data->{kern}))
749             {
750 0           my $newtext=' ';
751 0 0         if(is_utf8($text))
752             {
753 0           $text=$self->strByUtf($text);
754             }
755            
756 0           my $lastglyph='';
757 0           my $tBefore=0;
758 0           foreach my $n (unpack('C*',$text))
759             {
760 0 0         if(defined $self->data->{kern}->{$lastglyph.':'.$self->data->{e2n}->[$n]})
761             {
762 0 0         $newtext.=') ' if($tBefore);
763 0           $newtext.=sprintf('%i ',-($self->data->{kern}->{$lastglyph.':'.$self->data->{e2n}->[$n]}));
764 0           $tBefore=0;
765             }
766 0           $lastglyph=$self->data->{e2n}->[$n];
767 0           my $t=pack('C',$n);
768 0           $t=~s/\\/\\\\/go;
769 0           $t=~s/([\x00-\x1f])/sprintf('\%03lo',ord($1))/ge;
  0            
770 0           $t=~s/([\{\}\[\]\(\)])/\\$1/g;
771 0 0         $newtext.='(' if(!$tBefore);
772 0           $newtext.="$t";
773 0           $tBefore=1;
774             }
775 0 0         $newtext.=') ' if($tBefore);
776 0           return($newtext);
777             }
778             else
779             {
780 0           return('('.$self->textByStr($text).')');
781             }
782             }
783            
784             sub text
785             {
786 0     0 0   my ($self,$text,$size,$ident)=@_;
787            
788 0           my $newtext=$self->textByStr($text);
789            
790 0 0 0       if(defined $size && $self->{-dokern})
    0          
791             {
792 0           $newtext=$self->textByStrKern($text);
793 0 0 0       if(defined($ident) && $ident!=0)
794             {
795 0           return("[ $ident $newtext ] TJ");
796             }
797             else
798             {
799 0           return("[ $newtext ] TJ");
800             }
801             }
802             elsif(defined $size)
803             {
804 0 0 0       if(defined($ident) && $ident!=0)
805             {
806 0           return("[ $ident ($newtext) ] TJ");
807             }
808             else
809             {
810 0           return("[ ($newtext) ] TJ");
811             }
812             }
813             else
814             {
815 0           return("($newtext)");
816             }
817             }
818            
819 0     0 0   sub isvirtual { return(0); }
820            
821             1;
822            
823             __END__