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 3 4 75.0
total 98 186 52.6


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