OSDN Git Service

11df9ffb0ea604f0082ed59c20bbd10a60147f5c
[redminele/redmine.git] / vendor / plugins / rfpdf / lib / fpdf / korean.rb
1 # Copyright (c) 2006 4ssoM LLC <www.4ssoM.com>\r
2 # 1.12 contributed by Ed Moss.\r
3 #\r
4 # The MIT License\r
5 #\r
6 # Permission is hereby granted, free of charge, to any person obtaining a copy\r
7 # of this software and associated documentation files (the "Software"), to deal\r
8 # in the Software without restriction, including without limitation the rights\r
9 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
10 # copies of the Software, and to permit persons to whom the Software is\r
11 # furnished to do so, subject to the following conditions:\r
12 #\r
13 # The above copyright notice and this permission notice shall be included in\r
14 # all copies or substantial portions of the Software.\r
15 #\r
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\r
19 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
22 # THE SOFTWARE.\r
23 #\r
24 # This is direct port of korean.php\r
25 #\r
26 # Korean PDF support.\r
27 #\r
28 # Usage is as follows:\r
29 #\r
30 # require 'fpdf'\r
31 # require 'chinese'\r
32 # pdf = FPDF.new\r
33 # pdf.extend(PDF_Korean)\r
34 #\r
35 # This allows it to be combined with other extensions, such as the bookmark\r
36 # module.\r
37 \r
38 module PDF_Korean\r
39 \r
40 UHC_widths={' ' => 333, '!' => 416, '"' => 416, '#' => 833, '$' => 625, '%' => 916, '&' => 833, '\'' => 250, \r
41         '(' => 500, ')' => 500, '*' => 500, '+' => 833, ',' => 291, '-' => 833, '.' => 291, '/' => 375, '0' => 625, '1' => 625, \r
42         '2' => 625, '3' => 625, '4' => 625, '5' => 625, '6' => 625, '7' => 625, '8' => 625, '9' => 625, ':' => 333, ';' => 333, \r
43         '<' => 833, '=' => 833, '>' => 916, '?' => 500, '@' => 1000, 'A' => 791, 'B' => 708, 'C' => 708, 'D' => 750, 'E' => 708, \r
44         'F' => 666, 'G' => 750, 'H' => 791, 'I' => 375, 'J' => 500, 'K' => 791, 'L' => 666, 'M' => 916, 'N' => 791, 'O' => 750, \r
45         'P' => 666, 'Q' => 750, 'R' => 708, 'S' => 666, 'T' => 791, 'U' => 791, 'V' => 750, 'W' => 1000, 'X' => 708, 'Y' => 708, \r
46         'Z' => 666, '[' => 500, '\\' => 375, ']' => 500, '^' => 500, '_' => 500, '`' => 333, 'a' => 541, 'b' => 583, 'c' => 541, \r
47         'd' => 583, 'e' => 583, 'f' => 375, 'g' => 583, 'h' => 583, 'i' => 291, 'j' => 333, 'k' => 583, 'l' => 291, 'm' => 875, \r
48         'n' => 583, 'o' => 583, 'p' => 583, 'q' => 583, 'r' => 458, 's' => 541, 't' => 375, 'u' => 583, 'v' => 583, 'w' => 833, \r
49         'x' => 625, 'y' => 625, 'z' => 500, '{' => 583, '|' => 583, '}' => 583, '~' => 750}\r
50 \r
51   def AddCIDFont(family,style,name,cw,cMap,registry)\r
52     fontkey=family.downcase+style.upcase\r
53     unless @fonts[fontkey].nil?\r
54                 Error("Font already added: family style")\r
55     end\r
56         i=@fonts.length+1\r
57         name=name.gsub(' ','')\r
58         @fonts[fontkey]={'i'=>i,'type'=>'Type0','name'=>name,'up'=>-130,'ut'=>40,'cw'=>cw,\r
59           'CMap'=>cMap,'registry'=>registry}\r
60   end\r
61 \r
62   def AddCIDFonts(family,name,cw,cMap,registry)\r
63         AddCIDFont(family,'',name,cw,cMap,registry)\r
64         AddCIDFont(family,'B',name+',Bold',cw,cMap,registry)\r
65         AddCIDFont(family,'I',name+',Italic',cw,cMap,registry)\r
66         AddCIDFont(family,'BI',name+',BoldItalic',cw,cMap,registry)\r
67   end\r
68 \r
69   def AddUHCFont(family='UHC',name='HYSMyeongJoStd-Medium-Acro')\r
70         #Add UHC font with proportional Latin\r
71         cw=UHC_widths\r
72         cMap='KSCms-UHC-H'\r
73         registry={'ordering'=>'Korea1','supplement'=>1}\r
74         AddCIDFonts(family,name,cw,cMap,registry)\r
75   end\r
76 \r
77   def AddUHChwFont(family='UHC-hw',name='HYSMyeongJoStd-Medium-Acro')\r
78         #Add UHC font with half-witdh Latin\r
79     32.upto(126) do |i|\r
80                 cw[i.chr]=500\r
81     end\r
82         cMap='KSCms-UHC-HW-H'\r
83         registry={'ordering'=>'Korea1','supplement'=>1}\r
84         AddCIDFonts(family,name,cw,cMap,registry)\r
85   end\r
86 \r
87   def GetStringWidth(s)\r
88         if(@current_font['type']=='Type0')\r
89                 return GetMBStringWidth(s)\r
90         else\r
91                 return super(s)\r
92     end\r
93   end\r
94 \r
95   def GetMBStringWidth(s)\r
96         #Multi-byte version of GetStringWidth()\r
97         l=0\r
98         cw=@current_font['cw']\r
99         nb=s.length\r
100         i=0\r
101         while(i<nb)\r
102                 c = s[i].is_a?(String) ? s[i].ord : s[i]\r
103                 if(c<128)\r
104                         l+=cw[c.chr] if cw[c.chr]\r
105                         i+=1\r
106                 else\r
107                         l+=1000\r
108                         i+=2\r
109                 end\r
110         end\r
111         return l*@font_size/1000\r
112   end\r
113 \r
114   def MultiCell(w,h,txt,border=0,align='L',fill=0)\r
115         if(@current_font['type']=='Type0')\r
116                 MBMultiCell(w,h,txt,border,align,fill)\r
117         else\r
118                 super(w,h,txt,border,align,fill)\r
119     end\r
120   end\r
121 \r
122   def MBMultiCell(w,h,txt,border=0,align='L',fill=0)\r
123         #Multi-byte version of MultiCell()\r
124         cw=@current_font['cw']\r
125         if(w==0)\r
126                 w=@w-@r_margin-@x\r
127     end\r
128         wmax=(w-2*@c_margin)*1000/@font_size\r
129         s=txt.gsub("\r",'')\r
130         nb=s.length\r
131         if(nb>0 and s[nb-1]=="\n")\r
132                 nb-=1\r
133     end\r
134         b=0\r
135         if(border)\r
136                 if(border==1)\r
137                         border='LTRB'\r
138                         b='LRT'\r
139                         b2='LR'\r
140                 else\r
141                         b2=''\r
142                         b2='L' unless border.to_s.index('L').nil?\r
143                         b2=b2+'R' unless border.to_s.index('R').nil?\r
144                         b=(border.to_s.index('T')) ? (b2+'T') : b2\r
145                 end\r
146         end\r
147         sep=-1\r
148         i=0\r
149         j=0\r
150         l=0\r
151         nl=1\r
152         while(i<nb)\r
153                 #Get next character\r
154                 c = s[i].is_a?(String) ? s[i].ord : s[i]\r
155                 #Check if ASCII or MB\r
156                 ascii=(c<128)\r
157                 if(c.chr=="\n")\r
158                         #Explicit line break\r
159                         Cell(w,h,s[j,i-j],b,2,align,fill)\r
160                         i+=1\r
161                         sep=-1\r
162                         j=i\r
163                         l=0\r
164                         nl+=1\r
165                         if(border and nl==2)\r
166                                 b=b2\r
167         end\r
168                         next\r
169                 end\r
170                 if(!ascii)\r
171                         sep=i\r
172                         ls=l\r
173                 elsif(c.chr==' ')\r
174                         sep=i\r
175                         ls=l\r
176                 end\r
177                 l+=(ascii ? cw[c.chr] : 1000) || 0\r
178                 if(l>wmax)\r
179                         #Automatic line break\r
180                         if(sep==-1 or i==j)\r
181                                 if(i==j)\r
182                                         i+=ascii ? 1 : 2\r
183           end\r
184                                 Cell(w,h,s[j,i-j],b,2,align,fill)\r
185                         else\r
186                                 Cell(w,h,s[j,sep-j],b,2,align,fill)\r
187                                 i=(s[sep].chr==' ') ? sep+1 : sep\r
188                         end\r
189                         sep=-1\r
190                         j=i\r
191                         l=0\r
192                         nl+=1\r
193                         if(border and nl==2)\r
194                                 b=b2\r
195         end\r
196                 else\r
197                         i+=ascii ? 1 : 2\r
198       end\r
199         end\r
200         #Last chunk\r
201         if(border and not border.to_s.index('B').nil?)\r
202                 b+='B'\r
203     end\r
204         Cell(w,h,s[j,i-j],b,2,align,fill)\r
205         @x=@l_margin\r
206   end\r
207 \r
208   def Write(h,txt,link='')\r
209         if(@current_font['type']=='Type0')\r
210                 MBWrite(h,txt,link)\r
211         else\r
212                 super(h,txt,link)\r
213     end\r
214   end\r
215 \r
216   def MBWrite(h,txt,link)\r
217         #Multi-byte version of Write()\r
218         cw=@current_font['cw']\r
219         w=@w-@r_margin-@x\r
220         wmax=(w-2*@c_margin)*1000/@font_size\r
221         s=txt.gsub("\r",'')\r
222         nb=s.length\r
223         sep=-1\r
224         i=0\r
225         j=0\r
226         l=0\r
227         nl=1\r
228         while(i<nb)\r
229                 #Get next character\r
230                 c = s[i].is_a?(String) ? s[i].ord : s[i]\r
231                 #Check if ASCII or MB\r
232                 ascii=(c<128)\r
233                 if(c.chr=="\n")\r
234                         #Explicit line break\r
235                         Cell(w,h,s[j,i-j],0,2,'',0,link)\r
236                         i+=1\r
237                         sep=-1\r
238                         j=i\r
239                         l=0\r
240                         if(nl==1)\r
241                                 @x=@l_margin\r
242                                 w=@w-@r_margin-@x\r
243                                 wmax=(w-2*@c_margin)*1000/@font_size\r
244                         end\r
245                         nl+=1\r
246                         next\r
247                 end\r
248                 if(!ascii or c.chr==' ')\r
249                         sep=i\r
250       end\r
251                 l+=(ascii ? cw[c.chr] : 1000) || 0\r
252                 if(l>wmax)\r
253                         #Automatic line break\r
254                         if(sep==-1 or i==j)\r
255                                 if(@x>@l_margin)\r
256                                         #Move to next line\r
257                                         @x=@l_margin\r
258                                         @y+=h\r
259                                         w=@w-@r_margin-@x\r
260                                         wmax=(w-2*@c_margin)*1000/@font_size\r
261                                         i+=1\r
262                                         nl+=1\r
263                                         next\r
264                                 end\r
265                                 if(i==j)\r
266                                         i+=ascii ? 1 : 2\r
267           end\r
268                                 Cell(w,h,s[j,i-j],0,2,'',0,link)\r
269                         else\r
270                                 Cell(w,h,s[j,sep-j],0,2,'',0,link)\r
271                                 i=(s[sep].chr==' ') ? sep+1 : sep\r
272                         end\r
273                         sep=-1\r
274                         j=i\r
275                         l=0\r
276                         if(nl==1)\r
277                                 @x=@l_margin\r
278                                 w=@w-@r_margin-@x\r
279                                 wmax=(w-2*@c_margin)*1000/@font_size\r
280                         end\r
281                         nl+=1\r
282                 else\r
283                         i+=ascii ? 1 : 2\r
284       end\r
285         end\r
286         #Last chunk\r
287         if(i!=j)\r
288                 Cell(l/1000*@font_size,h,s[j,i-j],0,0,'',0,link)\r
289     end\r
290   end\r
291 \r
292 private\r
293 \r
294   def putfonts()\r
295         nf=@n\r
296     @diffs.each do |diff|\r
297                 #Encodings\r
298                 newobj()\r
299                 out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['+diff+']>>')\r
300                 out('endobj')\r
301         end\r
302         # mqr=get_magic_quotes_runtime()\r
303         # set_magic_quotes_runtime(0)\r
304     @font_files.each_pair do |file, info|\r
305                 #Font file embedding\r
306                 newobj()\r
307                 @font_files[file]['n']=@n\r
308                 if(defined('FPDF_FONTPATH'))\r
309                         file=FPDF_FONTPATH+file\r
310       end\r
311                 size=filesize(file)\r
312                 if(!size)\r
313                         Error('Font file not found')\r
314       end\r
315                 out('<</Length '+size)\r
316                 if(file[-2]=='.z')\r
317                         out('/Filter /FlateDecode')\r
318       end\r
319                 out('/Length1 '+info['length1'])\r
320                 if(not info['length2'].nil?)\r
321                         out('/Length2 '+info['length2']+' /Length3 0')\r
322       end\r
323                 out('>>')\r
324                 f=fopen(file,'rb')\r
325                 putstream(fread(f,size))\r
326                 fclose(f)\r
327                 out('endobj')\r
328         end\r
329         # set_magic_quotes_runtime(mqr)\r
330     @fonts.each_pair do |k, font|\r
331                 #Font objects\r
332                 newobj()\r
333                 @fonts[k]['n']=@n\r
334                 out('<</Type /Font')\r
335                 if(font['type']=='Type0')\r
336                         putType0(font)\r
337                 else\r
338                         name=font['name']\r
339                         out('/BaseFont /'+name)\r
340                         if(font['type']=='core')\r
341                                 #Standard font\r
342                                 out('/Subtype /Type1')\r
343                                 if(name!='Symbol' and name!='ZapfDingbats')\r
344                                         out('/Encoding /WinAnsiEncoding')\r
345                                 end\r
346                         else\r
347                                 #Additional font\r
348                                 out('/Subtype /'+font['type'])\r
349                                 out('/FirstChar 32')\r
350                                 out('/LastChar 255')\r
351                                 out('/Widths '+(@n+1)+' 0 R')\r
352                                 out('/FontDescriptor '+(@n+2)+' 0 R')\r
353                                 if(font['enc'])\r
354                                         if(not font['diff'].nil?)\r
355                                                 out('/Encoding '+(nf+font['diff'])+' 0 R')\r
356                                         else\r
357                                                 out('/Encoding /WinAnsiEncoding')\r
358             end\r
359                                 end\r
360                         end\r
361                         out('>>')\r
362                         out('endobj')\r
363                         if(font['type']!='core')\r
364                                 #Widths\r
365                                 newobj()\r
366                                 cw=font['cw']\r
367                                 s='['\r
368           32.upto(255) do |i|\r
369                                         s+=cw[i.chr]+' '\r
370           end\r
371                                 out(s+']')\r
372                                 out('endobj')\r
373                                 #Descriptor\r
374                                 newobj()\r
375                                 s='<</Type /FontDescriptor /FontName /'+name\r
376                                 font['desc'].each_pair do |k, v|                                \r
377                                         s+=' /'+k+' '+v\r
378           end\r
379                                 file=font['file']\r
380                                 if(file)\r
381                                         s+=' /FontFile'+(font['type']=='Type1' ? '' : '2')+' '+@font_files[file]['n']+' 0 R'\r
382           end\r
383                                 out(s+'>>')\r
384                                 out('endobj')\r
385                         end\r
386                 end\r
387         end\r
388   end\r
389   \r
390   def putType0(font)\r
391         #Type0\r
392         out('/Subtype /Type0')\r
393         out('/BaseFont /'+font['name']+'-'+font['CMap'])\r
394         out('/Encoding /'+font['CMap'])\r
395         out('/DescendantFonts ['+(@n+1).to_s+' 0 R]')\r
396         out('>>')\r
397         out('endobj')\r
398         #CIDFont\r
399         newobj()\r
400         out('<</Type /Font')\r
401         out('/Subtype /CIDFontType0')\r
402         out('/BaseFont /'+font['name'])\r
403         out('/CIDSystemInfo <</Registry (Adobe) /Ordering ('+font['registry']['ordering']+') /Supplement '+font['registry']['supplement'].to_s+'>>')\r
404         out('/FontDescriptor '+(@n+1).to_s+' 0 R')\r
405         if(font['CMap']=='KSCms-UHC-HW-H')\r
406                 w='8094 8190 500'\r
407         else\r
408                 w='1 ['\r
409                 font['cw'].keys.sort.each {|key|\r
410                   w+=font['cw'][key].to_s + " "\r
411   # ActionController::Base::logger.debug key.to_s\r
412   # ActionController::Base::logger.debug font['cw'][key].to_s\r
413                 }\r
414                 w +=']'\r
415     end\r
416         out('/W ['+w+']>>')\r
417         out('endobj')\r
418         #Font descriptor\r
419         newobj()\r
420         out('<</Type /FontDescriptor')\r
421         out('/FontName /'+font['name'])\r
422         out('/Flags 6')\r
423         out('/FontBBox [0 -200 1000 900]')\r
424         out('/ItalicAngle 0')\r
425         out('/Ascent 800')\r
426         out('/Descent -200')\r
427         out('/CapHeight 800')\r
428         out('/StemV 50')\r
429         out('>>')\r
430         out('endobj')\r
431   end\r
432 end\r