remove &tex_de_er().
[chise/omega.git] / outCMAP
1 #!/usr/bin/perl
2
3 # ver.0.2
4
5 use strict;
6 use vars qw($omegadb_path
7             $opt_protrude $opt_order
8             $opt_in_cs $opt_out_cs
9             $opt_help $usage
10             $in_cs $out_cs $i @chars
11             @order %order
12             $char $char_id $out_char
13             $ids $ids_argc %ids $idsdb
14             $idsdata_file $ids_start $font_start
15             %utf8mcs_map_from
16             $inotp $perl56 $perl58
17             @CDP @HZK @GT
18             );
19 use Getopt::Long;
20 use utf8;
21 use Fcntl ':flock';
22 use Chise_utils ':all';
23
24 my $omegadb_path="/usr/local/lib/chise/omega";
25
26 ### Options ###
27
28 $opt_order='jtcgk';
29 $opt_protrude=0;# 1=true, 0=false.
30
31 ###
32 my $strictly_forbidden_after = '「【『[(〈“‘‘(〔{《{\[\(\x{3016}{「';
33 #       \x{3016} | # white 【
34
35 my $forbidden_after = "\x{0000}";
36
37 # ¥¥$$〒♯##¢¢££@@§
38 my $slightly_forbidden_after = '¥¥$$〒♯##¢¢££@@§';
39
40 # $strictly_forbidden_before
41 # All these characters are allowed to protrude
42 # in the right margin
43 my $strictly_forbidden_before=
44     '!,.:;?、。!,.:;?。\)#}’”〉》」』】〕\x{3017})]}}」\]';
45 ###       \x{3017} | # white 】
46
47 my $forbidden_before
48     = 'ー々ぁぃぅぇぉゃゅょっゎァィゥェォャュョッヮヵヶ';
49
50 my $slightly_forbidden_before
51     = '\x{000a}\#\-‐−‰′″℃゛゜ゝゞヽヾ"%-゙゚';
52
53 my $asian = '\x{1100}-\x{11FF}\x{2E80}-\x{D7AF}\x{F900}-\x{FAFF}\x{FE30}-\x{FE4F}\x{FF00}-';
54
55 my $space = '\x{0020}\x{0009}\x{000A}\x{000C}\x{000D}';
56
57 if($^V and $^V ge v5.8){
58     $perl58=1;
59 }elsif($^V and $^V ge v5.6){
60     $perl56=1;
61 }else{
62     print STDERR "This versin is not supported.";
63     exit 1;
64 }
65 if($perl58){
66     eval "use Encode";
67     binmode(STDIN, ':encoding(utf8)');
68     binmode(STDOUT, ':encoding(utf8)');
69 }
70
71 &GetOptions("in=s"=>\$opt_in_cs,
72             "out=s"=>\$opt_out_cs,
73             "help",\$opt_help);
74
75 $usage=<<EOF;
76 Usage: $0 -i <input coding system> -o <cmap encoding>
77     input coding system:
78       Utf8mcs, Utf8cns, Utf8gb, Utf8jis, Utf8ks
79     cmap encoding:
80       UniCNS, UniGB, UniJIS, UniKS, UniMulti
81 EOF
82
83 if($opt_in_cs or $opt_out_cs){
84     $in_cs=$opt_in_cs;
85     $out_cs=$opt_out_cs;
86 }elsif(@ARGV==0){
87     ($in_cs,$out_cs)=($0=~/(Utf8.+)To(\w+)/);
88     $inotp=1;
89 }
90
91 # $in_cs:
92 #   Utf8mcs,Utf8cns,Utf8gb,Utf8jis,Utf8ks,
93 # $out_cs:
94 #   UniCNS,UniGB,UniJIS,UniKS,UniMulti
95
96 $in_cs=~s/Utf8/ucs\@/;
97
98 if($opt_help
99    or not defined($in_cs)
100    or not defined($out_cs)){
101     print $usage;
102     exit 1;
103 }
104
105 $omegadb_path=~s!/$!!;
106
107 $idsdata_file="$omegadb_path/idsdata.pl";
108 $ids_start=0x00; 
109 $font_start=0;
110
111 if(-e $idsdata_file){
112     open(IDSDATA,"+<$idsdata_file") or die;
113     flock(IDSDATA,LOCK_EX);
114     seek(IDSDATA,0,0);
115     while(<IDSDATA>){
116         eval $_;
117     }
118     seek(IDSDATA,0,0);
119 #         require $idsdata_file;
120 }else{
121     open(IDSDATA,">$idsdata_file") or die;
122     flock(IDSDATA,LOCK_EX);
123     seek(IDSDATA,0,0);
124 }
125
126 $ids_argc=0;
127 $ids="";
128
129 @GT=(#"=gt","=gt-k",
130      "=gt-pj-1","=gt-pj-2","=gt-pj-3","=gt-pj-4","=gt-pj-5","=gt-pj-6","=gt-pj-7","=gt-pj-8","=gt-pj-9","=gt-pj-10","=gt-pj-11"
131      #,"=gt-pj-k1","=gt-pj-k2"
132      );
133 @HZK=("=hanziku-1","=hanziku-10","=hanziku-11","=hanziku-12","=hanziku-2","=hanziku-3","=hanziku-4","=hanziku-5","=hanziku-6","=hanziku-7","=hanziku-8","=hanziku-9");
134 @CDP=("=big5-cdp");
135
136 %order=('c'=>'UniCNS',
137         'g'=>'UniGB',
138         'j'=>'UniJIS',
139         'k'=>'UniKS',
140         't'=>'GT',
141 #       not implemented yet.
142 #       'h'=>'HZK',
143 #       'd'=>'CDP',
144         );
145
146 if(defined($opt_order)){
147     if($opt_order=~/^[cgjkt]*$/){
148         @order=split(//,$opt_order);
149         @order=map {$order{$_}} @order;
150     }else{
151         print STDERR "Invalid order!\n";
152         exit 1;
153     }
154 }
155
156 while(<>){
157     if($perl56){
158         # for perl 5.6
159         if($inotp){
160             s/(.)/pack("c",&get_char_id(unpack("U",$1),$in_cs))/ge;
161         }else{
162             s/(.)/pack("U",&get_char_id(unpack("U",$1),$in_cs))/ge;
163         }
164     }elsif($perl58){
165         # for perl 5.8.
166         $_=decode('utf8', $_);
167         s/(.)/pack("U",&get_char_id(unpack("U",$1),$in_cs))/ge;
168     }
169     s/(amp.+?;)/&de_er($1)/ge;
170 #    s/(&.+?;)/&tex_de_er($1)/ge;
171     @chars=split(//);
172     for($i=0;$i<=$#chars;$i++){
173         $char=$chars[$i];
174         $char_id=unpack("U",$char);
175
176         if($char_id<=0x20){
177             print $chars[$i];
178             next;
179         }elsif($char_id>0x20 and $char_id<=0xff){
180             # Basic Latin
181             # Latin-1 Supplement
182             print &latin_parse();
183             next;
184         }elsif($char_id>=0x2ff0 and $char_id<=0x2fff){
185             # Ideographic Description Characters
186             print &ids_parse();
187             next;
188         }elsif($char_id >= 0x20000 && $char_id <=0x2a6df){
189             # CJK Unified Ideographs Extension B
190             if(not defined($ids{$char}) and $ids{$char}[1]>=0){
191                 $ids{$char}[0]=$font_start;
192                 $ids{$char}[1]=$ids_start;
193                 $ids_start++;
194                 if($ids_start>255){
195                     $ids_start=0;
196                     $font_start++;
197                 }
198             }
199             print "{\\fontencoding{OT1}\\fontfamily{" .
200                 sprintf("chise%03d",$ids{$char}[0]) .
201                 "}\\selectfont\\char$ids{$char}[1]}",&add_break($i);
202             next;
203         }else{
204             if(($out_char=&get_output_char($char_id,$out_cs))){
205                 print $out_char,&add_break($i);
206             }else{
207                 print &get_macro_for_ids(&get_ids($char)),&add_break($i);
208             }
209         }
210     }
211 }
212
213 print IDSDATA 'use utf8;',"\n";
214 foreach $ids (keys %ids){
215     print IDSDATA '$ids{\'',$ids,'\'}=[',join ",",@{$ids{$ids}},"];\n" if($perl56);
216     print IDSDATA '$ids{\'',encode('utf8',$ids),'\'}=[',join ",",@{$ids{$ids}},"];\n" if($perl58);
217 }
218 print IDSDATA '$font_start=',$font_start,";\n";
219 print IDSDATA '$ids_start=',$ids_start,";\n";
220 print IDSDATA "1;";
221 flock(IDSDATA,LOCK_UN);
222
223 exit 0;
224
225 sub add_break{
226     my($i)=@_;
227
228     if($i<($#chars-1)){
229         if(($chars[$i+1]=~m/[$strictly_forbidden_before]/o)
230            and($chars[$i+2]=~m/[$strictly_forbidden_before]/o)){
231             return "\\CJKunbreakablekernone ";
232         }elsif($opt_protrude){
233             if(($chars[$i+1]=~m/[$strictly_forbidden_before]/o)
234                and($chars[$i+2]=~m/[^$strictly_forbidden_before]/o)){
235                 return "\\CJKunbreakablekernone \\CJKprotrude ";
236             }
237         }
238     }
239     if(($i<$#chars)
240        and($chars[$i+1]=~m/[$strictly_forbidden_before]/o)){
241         return "\\CJKunbreakablekernone ";
242     }
243     if($chars[$i]=~m/[$strictly_forbidden_after]/o){
244         return "\\CJKunbreakablekernone ";
245     }
246     if(($i<$#chars)
247        and($chars[$i+1]=~m/[$forbidden_before]/o)){
248         return "\\CJKunbreakablekerntwo ";
249
250     }
251     if($chars[$i]=~m/[$forbidden_after]/o){
252         return "\\CJKunbreakablekerntwo ";
253     }
254     if(($i<$#chars)
255        and($chars[$i+1]=~m/[$slightly_forbidden_before]/o)){
256         return "\\CJKunbreakablekernthree ";
257     }
258     if($chars[$i]=~m/[$slightly_forbidden_after]/o){
259         return "\\CJKunbreakablekernthree ";
260     }
261     if($chars[$i]=~m/[$asian]/o){
262         return "\\CJKbreakablekern ";
263     }
264     if(($i<$#chars)and($chars[$i+1]=~m/[$asian]/o)){
265         return "\\CJKbreakablekern ";
266     }
267 }
268
269 sub latin_parse{
270     # arguments: none
271     # return: string for output with TeX macro.
272     my($char_id);
273     my $out_str=$chars[$i];
274     $i++;
275     while($i<=$#chars){
276         $char_id=unpack("U",$chars[$i]);
277         if($char_id<=0xff){
278             $out_str.=pack("U",$char_id);
279         }else{
280             $i--;
281             last;
282         }
283         $i++;
284     }
285     return '{\fontfamily{\rmdefault}\selectfont {'.$out_str.'}}';
286 }
287
288 sub ids_parse{
289     # arguments: none
290     # return: character for output,
291     #          TeX macro for ids,
292     #          or GETA character if ids is invalid.
293     my($ids,$ids_argc)=&ids_rest("",0,$chars[$i]);
294
295     while($ids_argc>0){
296         # We are in IDS.
297         $i++;
298         if($i>$#chars){
299             print STDERR "IDS parse error: $ids\n";
300 #           return pack("U",0xfffd);
301             return pack("U",0x3013);
302         }
303
304         ($ids,$ids_argc)=&ids_rest($ids,$ids_argc,$chars[$i]);
305         if($ids_argc==0){
306             if(($char_id=&get_char_id_for_ids($ids))
307                and($out_char=&get_output_char($char_id,$out_cs))){
308                 return $out_char;
309             }else{
310                 return &get_macro_for_ids($ids) if($perl56);
311                 return encode('utf8', &get_macro_for_ids($ids)) if($perl58);
312             }
313         }
314     }
315 }
316
317 sub ids_rest{
318     # arguments: <ids>, <rest number of arguments for ids>, <character>
319     # return: ids and rest number of arguments for ids.
320     my($ids,$ids_argc,$char)=@_;
321     my($argc);
322     $argc=&ids_argc($char);
323     if($argc){
324         $ids_argc+= $ids_argc==0 ? $argc : $argc-1;
325     }else{
326         $ids_argc--;
327     }
328     $ids.=$char if($perl56);
329     $ids.=encode('utf8',$char) if($perl58);
330     return ($ids,$ids_argc);
331 }
332
333 sub get_macro_for_ids{
334     # argument: <ids>
335     # return: TeX macro for ids
336     #          or GETA character if ids is invalid for KAGE.
337     my($ids)=@_;
338     $ids=&normalize_ids($ids,"UniJIS");
339 #    return pack("U",0xfffd) if(($ids!~/[$idc]/)
340     return pack("U",0x3013) if(($ids!~/[$idc]/)
341                                or($ids=~/[\x{10000}-]/));
342                     #irregular for KAGE.
343     if(not defined($ids{$ids}) and $ids{$ids}[1]>=0){
344         $ids{$ids}[0]=$font_start;
345         $ids{$ids}[1]=$ids_start;
346         $ids_start++;
347     }
348     if($ids_start>255){
349         $ids_start=0;
350         $font_start++;
351     }
352     return "{\\fontencoding{OT1}\\fontfamily{"
353         .sprintf("chise%03d",$ids{$ids}[0])
354         ."}\\selectfont\\char$ids{$ids}[1]}";
355 }
356
357 sub normalize_ids{
358     # argument: <ids>, <output coding system>
359     # return: ids or GETA character if ids is invalid for KAGE.
360     my($ids,$out_cs)=@_;
361     $ids = decode('utf8', $ids) if $perl58;
362     $out_cs=~s/Uni(.+)/'ucs@'.lc($1)/e;
363
364     my $output_ids="";
365     my($char,$char_id,$output_char_id);
366     while($ids=~m/(.)/g){
367         $char=$1;
368         $char_id=unpack("U",$char);
369         if($char=~/[$idc]/){
370             $output_ids.=$char;
371         }elsif($output_char_id=&get_char_attribute($char,"=$out_cs")){
372             $output_ids.=pack("U",$output_char_id);
373         }elsif($output_char_id=&get_char_attribute($char,"=ucs")){
374             $output_ids.=pack("U",$output_char_id);
375         }else{
376 #           return pack("U",0xfffd);
377             return pack("U",0x3013);
378         }
379     }
380     return $output_ids;
381 }
382
383 sub get_output_char{
384     # argument: <char-id>
385     # return: character in output coding system or TeX macro.
386     my($char_id,$out_cs)=@_;
387     my($char,$out_char_id,$suffix);
388     my($gt,$hzk,$cdp);
389
390     $char=pack('U',$char_id);
391
392     if($out_cs eq 'UniJIS'
393        and &get_char_attribute($char,"adobe-unijis-utf16-h")){
394         if($out_char_id=&get_char_attribute($char,'=ucs@jis')
395            or $out_char_id=&get_char_attribute($char,'=ucs')
396            or $out_char_id=&get_char_attribute($char,'=>ucs@jis')
397            or $out_char_id=&get_char_attribute($char,'=>ucs')
398            ){
399             return pack("U",$out_char_id);
400         }
401     }elsif($out_cs eq 'UniGB'
402            and &get_char_attribute($char,"adobe-unigb-ucs2-h")){
403         if($out_char_id=&get_char_attribute($char,'=ucs@gb')
404            or $out_char_id=&get_char_attribute($char,'=ucs')
405            or $out_char_id=&get_char_attribute($char,'=>ucs@gb')
406            or $out_char_id=&get_char_attribute($char,'=>ucs')
407            ){
408             return pack("U",$out_char_id);
409         }
410     }elsif($out_cs eq 'UniCNS'
411            and &get_char_attribute($char,"adobe-unicns-ucs2-h")){
412         if($out_char_id=&get_char_attribute($char,'=ucs@cns')
413            or $out_char_id=&get_char_attribute($char,'=ucs')
414            or $out_char_id=&get_char_attribute($char,'=>ucs@cns')
415            or $out_char_id=&get_char_attribute($char,'=>ucs')
416            ){
417             return pack("U",$out_char_id);
418         }
419     }elsif($out_cs eq 'UniKS'
420            and &get_char_attribute($char,"adobe-uniks-ucs2-h")){
421         if($out_char_id=&get_char_attribute($char,'=ucs@ks')
422            or $out_char_id=&get_char_attribute($char,'=ucs')
423            or $out_char_id=&get_char_attribute($char,'=>ucs@ks')
424            or $out_char_id=&get_char_attribute($char,'=>ucs')
425            ){
426             return pack("U",$out_char_id);
427         }
428     }elsif($out_cs eq 'UniMulti'){
429         foreach $out_cs (@order){
430     
431             if($out_cs eq 'UniJIS'
432                and &get_char_attribute($char,"adobe-unijis-utf16-h")){
433                 if($out_char_id=&get_char_attribute($char,'=ucs@jis')
434                    or $out_char_id=&get_char_attribute($char,'=ucs')
435                    or $out_char_id=&get_char_attribute($char,'=>ucs@jis')
436                    or $out_char_id=&get_char_attribute($char,'=>ucs')
437                    ){
438                     return '{\selectjisfont\char'.$out_char_id.'}';
439                 }
440             }elsif($out_cs eq 'UniGB'
441                    and &get_char_attribute($char,"adobe-unigb-ucs2-h")){
442                 if($out_char_id=&get_char_attribute($char,'=ucs@gb')
443                    or $out_char_id=&get_char_attribute($char,'=ucs')
444                    or $out_char_id=&get_char_attribute($char,'=>ucs@gb')
445                    or $out_char_id=&get_char_attribute($char,'=>ucs')
446                    ){
447                     return '{\selectgbsfont\char'.$out_char_id.'}';
448                 }
449             }elsif($out_cs eq 'UniCNS'
450                    and &get_char_attribute($char,"adobe-unicns-ucs2-h")){
451                 if($out_char_id=&get_char_attribute($char,'=ucs@cns')
452                    or $out_char_id=&get_char_attribute($char,'=ucs')
453                    or $out_char_id=&get_char_attribute($char,'=>ucs@cns')
454                    or $out_char_id=&get_char_attribute($char,'=>ucs')
455                    ){
456                     return '{\selectcnsfont\char'.$out_char_id.'}';
457                 }
458             }elsif($out_cs eq 'UniKS'
459                    and &get_char_attribute($char,"adobe-uniks-ucs2-h")){
460                 if($out_char_id=&get_char_attribute($char,'=ucs@ks')
461                    or $out_char_id=&get_char_attribute($char,'=ucs')
462                    or $out_char_id=&get_char_attribute($char,'=>ucs@ks')
463                    or $out_char_id=&get_char_attribute($char,'=>ucs')
464                    ){
465                     return '{\selectksxfont\char'.$out_char_id.'}';
466                 }
467             }elsif($out_cs eq 'GT'){
468                 return $gt if($gt=&get_macro_for_GT($char_id));
469             }elsif($out_cs eq 'HZK'){
470                 return $hzk if($hzk=&get_macro_for_HZK($char_id));
471             }elsif($out_cs eq 'CDP'){
472                 return $cdp if($cdp=&get_macro_for_CDP($char_id));
473             }
474         }
475     }
476     return undef;
477 }
478
479 sub get_ids{
480     # argument: <character>
481     # return: ids
482     my($char)=@_;
483     my $ids="";
484     $ids=&get_char_attribute($char,"ids-aggregated")
485         or &get_char_attribute($char,"ids");
486 #       or &get_char_attribute($char,"ideographic-structure");
487     $ids=decode('utf8', $ids) if($perl58);
488 #    $ids=~s/[? ()]//g;
489     return $ids;
490 }
491
492 sub get_char_id_for_ids{
493     # argument: <ideographic description sequence>
494     # return: char-id
495     my($ids)=@_;
496     my($output_char);
497     $ids=decode('utf8', $ids) if($perl58);
498
499     if(($output_char)=&get_chars_matching("ids",$ids)){
500         return unpack("U",$output_char);
501     }else{
502         return undef;
503     }
504 }
505
506 sub get_char_id{
507     # argument: <char-id>, <input coding system>
508     # return:   char-id.
509     my($char_id,$in_cs)=@_;
510     my($output_char);
511
512     return $char_id if($in_cs eq 'ucs@mcs');
513
514     if(($output_char)=&get_chars_matching("=$in_cs",$char_id)){
515         return unpack("U",$output_char);
516     }else{
517         return $char_id;
518     }
519 }
520
521 sub get_macro_for_GT{
522     # argument: <char-id>
523     # return: TeX macro for GT fonts.
524     my($char_id)=@_;
525     my($char,$gt,$GT);
526     $char=pack("U",$char_id);
527     foreach (@GT){
528         if($gt=&get_char_attribute($char,$_)){
529             m/gt\-pj\-(\d+)/ and $GT=$1;
530             last;
531         }
532     }
533     if($gt){
534         return "{\\fontencoding{OT1}\\fontfamily{"
535             .sprintf("gt%02d",$GT)
536             ."}\\selectfont\\char".($gt|0x8080)."}";
537     }else{
538         return undef;
539     }
540 }
541
542 sub get_macro_for_HZK{
543     my($char_id)=@_;
544     my($char,$hzk,$HZK);
545     $char=pack("U",$char_id);
546     foreach (@HZK){
547         if($hzk=&get_char_attribute($char,$_)){
548             m/hanziku\-(\d+)/ and $HZK=$1;
549             last;
550         }
551     }
552     if($hzk){
553         return "{\\fontencoding{OT1}\\fontfamily{".sprintf("hzk%02d",$HZK)."}\\selectfont\\char".($hzk|0x8080)."}";
554     }else{
555         return undef;
556     }
557 }
558
559 sub get_macro_for_CDP{
560     my($char_id)=@_;
561     my($char,$cdp);
562     $char=pack("U",$char_id);
563     foreach (@CDP){
564         if($cdp=&get_char_attribute($char,$_)){
565             last;
566         }
567     }
568     if($cdp){
569         return "{\\fontencoding{OT1}\\fontfamily{cdp}\\selectfont\\char".($cdp|0x8080)."}";
570     }else{
571         return undef;
572     }
573 }