File Coverage

blib/lib/PDF/Builder/Resource/CIDFont/CJKFont.pm
Criterion Covered Total %
statement 69 109 63.3
branch 12 36 33.3
condition 5 25 20.0
subroutine 9 12 75.0
pod 2 4 50.0
total 97 186 52.1


line stmt bran cond sub pod time code
1             package PDF::Builder::Resource::CIDFont::CJKFont;
2              
3 2     2   1458 use base 'PDF::Builder::Resource::CIDFont';
  2         3  
  2         503  
4              
5 2     2   12 use strict;
  2         3  
  2         40  
6 2     2   7 use warnings;
  2         5  
  2         107  
7              
8             our $VERSION = '3.024'; # VERSION
9             our $LAST_UPDATE = '3.024'; # manually update whenever code is changed
10              
11 2     2   13 use PDF::Builder::Util;
  2         3  
  2         234  
12 2     2   13 use PDF::Builder::Basic::PDF::Utils;
  2         3  
  2         2775  
13              
14             our $fonts = {};
15             our $cmap = {};
16             our $alias;
17             our $subs;
18              
19             =head1 NAME
20              
21             PDF::Builder::Resource::CIDFont::CJKFont - Base class for CJK fonts
22              
23             =head1 METHODS
24              
25             =over
26              
27             =item $font = PDF::Builder::Resource::CIDFont::CJKFont->new($pdf, $cjkname, %options)
28              
29             Returns a cjk-font object.
30              
31             =over
32              
33             * Traditional Chinese: Ming Ming-Bold Ming-Italic Ming-BoldItalic
34              
35             * Simplified Chinese: Song Song-Bold Song-Italic Song-BoldItalic
36              
37             * Korean: MyungJo MyungJo-Bold MyungJo-Italic MyungJo-BoldItalic
38              
39             * Japanese (Mincho): KozMin KozMin-Bold KozMin-Italic KozMin-BoldItalic
40              
41             * Japanese (Gothic): KozGo KozGo-Bold KozGo-Italic KozGo-BoldItalic
42              
43             =back
44              
45             Defined Options:
46              
47             encode ... specify fonts encoding for non-utf8 text.
48              
49             =cut
50              
51             sub _look_for_font {
52 1     1   3 my $fname = lc(shift);
53              
54 1         2 $fname =~ s/[^a-z0-9]+//gi;
55 1 50       4 $fname = $alias->{$fname} if defined $alias->{$fname};
56 1 50       4 return {%{$fonts->{$fname}}} if defined $fonts->{$fname};
  0         0  
57              
58 1 50       2 if (defined $subs->{$fname}) {
59 0         0 my $data = _look_for_font($subs->{$fname}->{'-alias'});
60 0         0 foreach my $k (keys %{$subs->{$fname}}) {
  0         0  
61 0 0       0 next if $k =~ /^\-/;
62 0 0       0 if (substr($k, 0, 1) eq '+') {
63 0         0 $data->{substr($k, 1)} .= $subs->{$fname}->{$k};
64             } else {
65 0         0 $data->{$k} = $subs->{$fname}->{$k};
66             }
67             }
68 0         0 $fonts->{$fname} = $data;
69 0         0 return {%$data};
70             }
71              
72 1         48 eval "require 'PDF/Builder/Resource/CIDFont/CJKFont/$fname.data'"; ## no critic
73 1 50       17 unless ($@) {
74 1         2 return {%{$fonts->{$fname}}};
  1         14  
75             } else {
76 0         0 die "requested font '$fname' not installed ";
77             }
78             }
79              
80             # identical routine in Resource/CIDFont/TrueType/FontFile.pm
81             sub _look_for_cmap {
82 1     1   2 my $map = shift;
83 1         3 my $fname = lc($map);
84              
85 1         3 $fname =~ s/[^a-z0-9]+//gi;
86 1 50       3 return {%{$cmap->{$fname}}} if defined $cmap->{$fname};
  0         0  
87 1         54 eval "require 'PDF/Builder/Resource/CIDFont/CMap/$fname.cmap'"; ## no critic
88 1 50       25 unless ($@) {
89 1         5 return {%{$cmap->{$fname}}};
  1         19  
90             } else {
91 0         0 die "requested cmap '$map' not installed ";
92             }
93             }
94              
95             # compare to TrueType/FontFile.pm: .data and .cmap files are apparently
96             # required when using cjkfont(), so no looking at internal cmap tables
97             sub new {
98 1     1 1 3 my ($class, $pdf, $name, @opts) = @_;
99              
100 1         2 my %opts = ();
101 1 50       5 %opts = @opts if (scalar @opts)%2 == 0;
102             # copy dashed option names to preferred undashed names
103 1 50 33     4 if (defined $opts{'-encode'} && !defined $opts{'encode'}) { $opts{'encode'} = delete($opts{'-encode'}); }
  0         0  
104 1   50     7 $opts{'encode'} ||= 'ident';
105              
106 1         2 my $data = _look_for_font($name);
107              
108 1         4 my $cmap = _look_for_cmap($data->{'cmap'});
109              
110 1         4 $data->{'u2g'} = { %{$cmap->{'u2g'}} };
  1         17489  
111 1         1179 $data->{'g2u'} = [ @{$cmap->{'g2u'}} ];
  1         777  
112              
113 1 50       11 $class = ref $class if ref $class;
114             # ensure that apiname is initialized
115 1   50     21 my $key = ($data->{'apiname'} // '') . pdfkey();
116 1         29 my $self = $class->SUPER::new($pdf, $key);
117 1 50 33     8 $pdf->new_obj($self) if defined($pdf) && !$self->is_obj($pdf);
118              
119 1         4 $self->{' data'} = $data;
120              
121 1 50 33     9 if (defined $opts{'encode'} && $opts{'encode'} ne 'ident') {
122 0         0 $self->data->{'encode'} = $opts{'encode'};
123             }
124              
125 1         8 my $emap = {
126             'reg' => 'Adobe',
127             'ord' => 'Identity',
128             'sup' => 0,
129             'map' => 'Identity',
130             'dir' => 'H',
131             'dec' => 'ident',
132             };
133              
134 1 50       5 if (defined $cmap->{'ccs'}) {
135 1         3 $emap->{'reg'} = $cmap->{'ccs'}->[0];
136 1         3 $emap->{'ord'} = $cmap->{'ccs'}->[1];
137 1         3 $emap->{'sup'} = $cmap->{'ccs'}->[2];
138             }
139              
140             #if (defined $cmap->{'cmap'} && defined $cmap->{'cmap'}->{$opts{'encode'}} ) {
141             # $emap->{'dec'} = $cmap->{'cmap'}->{$opts{'encode'}}->[0];
142             # $emap->{'map'} = $cmap->{'cmap'}->{$opts{'encode'}}->[1];
143             #} elsif (defined $cmap->{'cmap'} && defined $cmap->{'cmap'}->{'utf8'}) {
144             # $emap->{'dec'} = $cmap->{'cmap'}->{'utf8'}->[0];
145             # $emap->{'map'} = $cmap->{'cmap'}->{'utf8'}->[1];
146             #}
147              
148 1         8 $self->data()->{'decode'} = $emap->{'dec'};
149              
150             $self->{'BaseFont'} = PDFName(join('-',
151             $self->fontname(),
152             $emap->{'map'},
153 1         7 $emap->{'dir'}));
154             $self->{'Encoding'} = PDFName(join('-',
155             $emap->{'map'},
156 1         9 $emap->{'dir'}));
157              
158 1         7 my $des = $self->descrByData();
159 1         4 my $de = $self->{' de'};
160              
161 1         3 $de->{'FontDescriptor'} = $des;
162 1         3 $de->{'Subtype'} = PDFName('CIDFontType0');
163 1         2 $de->{'BaseFont'} = PDFName($self->fontname());
164 1         3 $de->{'DW'} = PDFNum($self->missingwidth());
165 1         13 $de->{'CIDSystemInfo'}->{'Registry'} = PDFString($emap->{'reg'}, 'x');
166 1         7 $de->{'CIDSystemInfo'}->{'Ordering'} = PDFString($emap->{'ord'}, 'x');
167 1         4 $de->{'CIDSystemInfo'}->{'Supplement'} = PDFNum($emap->{'sup'});
168             ## $de->{'CIDToGIDMap'} = PDFName($emap->{'map'}); # ttf only
169              
170 1         9 return $self;
171             }
172              
173             sub tounicodemap {
174 0     0 0   my $self = shift;
175              
176             # no-op since PDF knows its char-collection
177 0           return $self;
178             }
179              
180             sub glyphByCId {
181 0     0 0   my ($self, $cid) = @_;
182              
183 0           my $uni = $self->uniByCId($cid);
184 0           return nameByUni($uni);
185             }
186              
187             sub outobjdeep {
188 0     0 1   my ($self, $fh, $pdf) = @_;
189              
190 0           my $notdefbefore = 1;
191              
192 0           my $wx = PDFArray();
193 0           $self->{' de'}->{'W'} = $wx;
194 0           my $ml;
195              
196 0           foreach my $i (0 .. (scalar @{$self->data()->{'g2u'}} - 1 )) {
  0            
197 0 0 0       if (ref($self->data()->{'wx'}) eq 'ARRAY' &&
    0 0        
      0        
      0        
198             (defined $self->data()->{'wx'}->[$i]) &&
199             ($self->data()->{'wx'}->[$i] != $self->missingwidth()) ) {
200 0 0         if ($notdefbefore) {
201 0           $notdefbefore = 0;
202 0           $ml = PDFArray();
203 0           $wx->add_elements(PDFNum($i), $ml);
204             }
205 0           $ml->add_elements(PDFNum($self->data()->{'wx'}->[$i]));
206             } elsif (ref($self->data()->{'wx'}) eq 'HASH' &&
207             (defined $self->data()->{'wx'}->{$i}) &&
208             ($self->data()->{'wx'}->{$i} != $self->missingwidth()) ) {
209 0 0         if ($notdefbefore) {
210 0           $notdefbefore = 0;
211 0           $ml = PDFArray();
212 0           $wx->add_elements(PDFNum($i), $ml);
213             }
214 0           $ml->add_elements(PDFNum($self->data()->{'wx'}->{$i}));
215             } else {
216 0           $notdefbefore = 1;
217             }
218             }
219              
220 0           return $self->SUPER::outobjdeep($fh, $pdf);
221             }
222              
223             BEGIN {
224              
225 2     2   43 $alias = {
226             'traditional' => 'adobemingstdlightacro',
227             'traditionalbold' => 'mingbold',
228             'traditionalitalic' => 'mingitalic',
229             'traditionalbolditalic' => 'mingbolditalic',
230             'ming' => 'adobemingstdlightacro',
231              
232             'simplified' => 'adobesongstdlightacro',
233             'simplifiedbold' => 'songbold',
234             'simplifieditalic' => 'songitalic',
235             'simplifiedbolditalic' => 'songbolditalic',
236             'song' => 'adobesongstdlightacro',
237              
238             'korean' => 'adobemyungjostdmediumacro',
239             'koreanbold' => 'myungjobold',
240             'koreanitalic' => 'myungjoitalic',
241             'koreanbolditalic' => 'myungjobolditalic',
242             'myungjo' => 'adobemyungjostdmediumacro',
243              
244             'japanese' => 'kozminproregularacro',
245             'japanesebold' => 'kozminbold',
246             'japaneseitalic' => 'kozminitalic',
247             'japanesebolditalic' => 'kozminbolditalic',
248             'kozmin' => 'kozminproregularacro',
249             'kozgo' => 'kozgopromediumacro',
250              
251             };
252 2         103 $subs = {
253             # Chinese Traditional (i.e., ROC/Taiwan) Fonts
254             'mingitalic' => {
255             '-alias' => 'adobemingstdlightacro',
256             '+fontname' => ',Italic',
257             },
258             'mingbold' => {
259             '-alias' => 'adobemingstdlightacro',
260             '+fontname' => ',Bold',
261             },
262             'mingbolditalic' => {
263             '-alias' => 'adobemingstdlightacro',
264             '+fontname' => ',BoldItalic',
265             },
266             # Chinese Simplified (i.e., PRC/Mainland China) Fonts
267             'songitalic' => {
268             '-alias' => 'adobesongstdlightacro',
269             '+fontname' => ',Italic',
270             },
271             'songbold' => {
272             '-alias' => 'adobesongstdlightacro',
273             '+fontname' => ',Bold',
274             },
275             'songbolditalic' => {
276             '-alias' => 'adobesongstdlightacro',
277             '+fontname' => ',BoldItalic',
278             },
279             # Japanese Gothic (i.e., sans serif) Fonts
280             'kozgoitalic' => {
281             '-alias' => 'kozgopromediumacro',
282             '+fontname' => ',Italic',
283             },
284             'kozgobold' => {
285             '-alias' => 'kozgopromediumacro',
286             '+fontname' => ',Bold',
287             },
288             'kozgobolditalic' => {
289             '-alias' => 'kozgopromediumacro',
290             '+fontname' => ',BoldItalic',
291             },
292             # Japanese Mincho (i.e., serif) Fonts
293             'kozminitalic' => {
294             '-alias' => 'kozminproregularacro',
295             '+fontname' => ',Italic',
296             },
297             'kozminbold' => {
298             '-alias' => 'kozminproregularacro',
299             '+fontname' => ',Bold',
300             },
301             'kozminbolditalic' => {
302             '-alias' => 'kozminproregularacro',
303             '+fontname' => ',BoldItalic',
304             },
305             # Korean Fonts
306             'myungjoitalic' => {
307             '-alias' => 'adobemyungjostdmediumacro',
308             '+fontname' => ',Italic',
309             },
310             'myungjobold' => {
311             '-alias' => 'adobemyungjostdmediumacro',
312             '+fontname' => ',Bold',
313             },
314             'myungjobolditalic' => {
315             '-alias' => 'adobemyungjostdmediumacro',
316             '+fontname' => ',BoldItalic',
317             },
318             };
319              
320             }
321              
322             =back
323              
324             =cut
325              
326             1;