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