Mercurial > hg > soundsoftware-site
comparison .svn/pristine/4b/4b4de4b924745eb31dbf2319917091a84bc1704f.svn-base @ 909:cbb26bc654de redmine-1.3
Update to Redmine 1.3-stable branch (Redmine SVN rev 8964)
author | Chris Cannam |
---|---|
date | Fri, 24 Feb 2012 19:09:32 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
908:c6c2cbd0afee | 909:cbb26bc654de |
---|---|
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 chinese.php | |
25 # | |
26 # Chinese PDF support. | |
27 # | |
28 # Usage is as follows: | |
29 # | |
30 # require 'fpdf' | |
31 # require 'chinese' | |
32 # pdf = FPDF.new | |
33 # pdf.extend(PDF_Chinese) | |
34 # | |
35 # This allows it to be combined with other extensions, such as the bookmark | |
36 # module. | |
37 | |
38 module PDF_Chinese | |
39 | |
40 Big5_widths={' '=>250,'!'=>250,'"'=>408,'#'=>668,'$'=>490,'%'=>875,'&'=>698,'\''=>250, | |
41 '('=>240,')'=>240,'*'=>417,'+'=>667,','=>250,'-'=>313,'.'=>250,'/'=>520,'0'=>500,'1'=>500, | |
42 '2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>250,';'=>250, | |
43 '<'=>667,'='=>667,'>'=>667,'?'=>396,'@'=>921,'A'=>677,'B'=>615,'C'=>719,'D'=>760,'E'=>625, | |
44 'F'=>552,'G'=>771,'H'=>802,'I'=>354,'J'=>354,'K'=>781,'L'=>604,'M'=>927,'N'=>750,'O'=>823, | |
45 'P'=>563,'Q'=>823,'R'=>729,'S'=>542,'T'=>698,'U'=>771,'V'=>729,'W'=>948,'X'=>771,'Y'=>677, | |
46 'Z'=>635,'['=>344,'\\'=>520,']'=>344,'^'=>469,'_'=>500,'`'=>250,'a'=>469,'b'=>521,'c'=>427, | |
47 'd'=>521,'e'=>438,'f'=>271,'g'=>469,'h'=>531,'i'=>250,'j'=>250,'k'=>458,'l'=>240,'m'=>802, | |
48 'n'=>531,'o'=>500,'p'=>521,'q'=>521,'r'=>365,'s'=>333,'t'=>292,'u'=>521,'v'=>458,'w'=>677, | |
49 'x'=>479,'y'=>458,'z'=>427,'{'=>480,'|'=>496,'}'=>480,'~'=>667} | |
50 | |
51 GB_widths={' '=>207,'!'=>270,'"'=>342,'#'=>467,'$'=>462,'%'=>797,'&'=>710,'\''=>239, | |
52 '('=>374,')'=>374,'*'=>423,'+'=>605,','=>238,'-'=>375,'.'=>238,'/'=>334,'0'=>462,'1'=>462, | |
53 '2'=>462,'3'=>462,'4'=>462,'5'=>462,'6'=>462,'7'=>462,'8'=>462,'9'=>462,':'=>238,';'=>238, | |
54 '<'=>605,'='=>605,'>'=>605,'?'=>344,'@'=>748,'A'=>684,'B'=>560,'C'=>695,'D'=>739,'E'=>563, | |
55 'F'=>511,'G'=>729,'H'=>793,'I'=>318,'J'=>312,'K'=>666,'L'=>526,'M'=>896,'N'=>758,'O'=>772, | |
56 'P'=>544,'Q'=>772,'R'=>628,'S'=>465,'T'=>607,'U'=>753,'V'=>711,'W'=>972,'X'=>647,'Y'=>620, | |
57 'Z'=>607,'['=>374,'\\'=>333,']'=>374,'^'=>606,'_'=>500,'`'=>239,'a'=>417,'b'=>503,'c'=>427, | |
58 'd'=>529,'e'=>415,'f'=>264,'g'=>444,'h'=>518,'i'=>241,'j'=>230,'k'=>495,'l'=>228,'m'=>793, | |
59 'n'=>527,'o'=>524,'p'=>524,'q'=>504,'r'=>338,'s'=>336,'t'=>277,'u'=>517,'v'=>450,'w'=>652, | |
60 'x'=>466,'y'=>452,'z'=>407,'{'=>370,'|'=>258,'}'=>370,'~'=>605} | |
61 | |
62 def AddCIDFont(family,style,name,cw,cMap,registry) | |
63 #ActionController::Base::logger.debug registry.to_a.join(":").to_s | |
64 fontkey=family.downcase+style.upcase | |
65 unless @fonts[fontkey].nil? | |
66 Error("Font already added: family style") | |
67 end | |
68 i=@fonts.length+1 | |
69 name=name.gsub(' ','') | |
70 @fonts[fontkey]={'i'=>i,'type'=>'Type0','name'=>name,'up'=>-130,'ut'=>40,'cw'=>cw, 'CMap'=>cMap,'registry'=>registry} | |
71 end | |
72 | |
73 def AddCIDFonts(family,name,cw,cMap,registry) | |
74 AddCIDFont(family,'',name,cw,cMap,registry) | |
75 AddCIDFont(family,'B',name+',Bold',cw,cMap,registry) | |
76 AddCIDFont(family,'I',name+',Italic',cw,cMap,registry) | |
77 AddCIDFont(family,'BI',name+',BoldItalic',cw,cMap,registry) | |
78 end | |
79 | |
80 def AddBig5Font(family='Big5',name='MSungStd-Light-Acro') | |
81 #Add Big5 font with proportional Latin | |
82 cw=Big5_widths | |
83 cMap='ETenms-B5-H' | |
84 registry={'ordering'=>'CNS1','supplement'=>0} | |
85 #ActionController::Base::logger.debug registry.to_a.join(":").to_s | |
86 AddCIDFonts(family,name,cw,cMap,registry) | |
87 end | |
88 | |
89 def AddBig5hwFont(family='Big5-hw',name='MSungStd-Light-Acro') | |
90 #Add Big5 font with half-witdh Latin | |
91 cw = {} | |
92 32.upto(126) do |i| | |
93 cw[i.chr]=500 | |
94 end | |
95 cMap='ETen-B5-H' | |
96 registry={'ordering'=>'CNS1','supplement'=>0} | |
97 AddCIDFonts(family,name,cw,cMap,registry) | |
98 end | |
99 | |
100 def AddGBFont(family='GB',name='STSongStd-Light-Acro') | |
101 #Add GB font with proportional Latin | |
102 cw=GB_widths | |
103 cMap='GBKp-EUC-H' | |
104 registry={'ordering'=>'GB1','supplement'=>2} | |
105 AddCIDFonts(family,name,cw,cMap,registry) | |
106 end | |
107 | |
108 def AddGBhwFont(family='GB-hw',name='STSongStd-Light-Acro') | |
109 #Add GB font with half-width Latin | |
110 32.upto(126) do |i| | |
111 cw[i.chr]=500 | |
112 end | |
113 cMap='GBK-EUC-H' | |
114 registry={'ordering'=>'GB1','supplement'=>2} | |
115 AddCIDFonts(family,name,cw,cMap,registry) | |
116 end | |
117 | |
118 def GetStringWidth(s) | |
119 if(@current_font['type']=='Type0') | |
120 return GetMBStringWidth(s) | |
121 else | |
122 return super(s) | |
123 end | |
124 end | |
125 | |
126 def GetMBStringWidth(s) | |
127 #Multi-byte version of GetStringWidth() | |
128 l=0 | |
129 cw=@current_font['cw'] | |
130 nb=s.length | |
131 i=0 | |
132 while(i<nb) | |
133 c = s[i].is_a?(String) ? s[i].ord : s[i] | |
134 if(c<128) | |
135 l+=cw[c.chr] if cw[c.chr] | |
136 i+=1 | |
137 else | |
138 l+=1000 | |
139 i+=2 | |
140 end | |
141 end | |
142 return l*@font_size/1000 | |
143 end | |
144 | |
145 def MultiCell(w,h,txt,border=0,align='L',fill=0,ln=1) | |
146 if(@current_font['type']=='Type0') | |
147 MBMultiCell(w,h,txt,border,align,fill,ln) | |
148 else | |
149 super(w,h,txt,border,align,fill,ln) | |
150 end | |
151 end | |
152 | |
153 def MBMultiCell(w,h,txt,border=0,align='L',fill=0,ln=1) | |
154 | |
155 # save current position | |
156 prevx = @x; | |
157 prevy = @y; | |
158 | |
159 #Multi-byte version of MultiCell() | |
160 cw=@current_font['cw'] | |
161 if(w==0) | |
162 w=@w-@r_margin-@x | |
163 end | |
164 wmax=(w-2*@c_margin)*1000/@font_size | |
165 s=txt.gsub("\r",'') | |
166 nb=s.length | |
167 if(nb>0 and s[nb-1]=="\n") | |
168 nb-=1 | |
169 end | |
170 b=0 | |
171 if(border) | |
172 if(border==1) | |
173 border='LTRB' | |
174 b='LRT' | |
175 b2='LR' | |
176 else | |
177 b2='' | |
178 b2='L' unless border.to_s.index('L').nil? | |
179 b2=b2+'R' unless border.to_s.index('R').nil? | |
180 b=(border.to_s.index('T')) ? (b2+'T') : b2 | |
181 end | |
182 end | |
183 sep=-1 | |
184 i=0 | |
185 j=0 | |
186 l=0 | |
187 nl=1 | |
188 while(i<nb) | |
189 #Get next character | |
190 c = s[i].is_a?(String) ? s[i].ord : s[i] | |
191 #Check if ASCII or MB | |
192 ascii=(c<128) | |
193 if(c.chr=="\n") | |
194 #Explicit line break | |
195 Cell(w,h,s[j,i-j],b,2,align,fill) | |
196 i+=1 | |
197 sep=-1 | |
198 j=i | |
199 l=0 | |
200 nl+=1 | |
201 if(border and nl==2) | |
202 b=b2 | |
203 end | |
204 next | |
205 end | |
206 if(!ascii) | |
207 sep=i | |
208 ls=l | |
209 elsif(c.chr==' ') | |
210 sep=i | |
211 ls=l | |
212 end | |
213 l+=(ascii ? cw[c.chr] : 1000) || 0 | |
214 if(l>wmax) | |
215 #Automatic line break | |
216 if(sep==-1 or i==j) | |
217 if(i==j) | |
218 i+=ascii ? 1 : 2 | |
219 end | |
220 Cell(w,h,s[j,i-j],b,2,align,fill) | |
221 else | |
222 Cell(w,h,s[j,sep-j],b,2,align,fill) | |
223 i=(s[sep].chr==' ') ? sep+1 : sep | |
224 end | |
225 sep=-1 | |
226 j=i | |
227 l=0 | |
228 nl+=1 | |
229 if(border and nl==2) | |
230 b=b2 | |
231 end | |
232 else | |
233 i+=ascii ? 1 : 2 | |
234 end | |
235 end | |
236 #Last chunk | |
237 if(border and not border.to_s.index('B').nil?) | |
238 b+='B' | |
239 end | |
240 Cell(w,h,s[j,i-j],b,2,align,fill) | |
241 | |
242 # move cursor to specified position | |
243 if (ln == 1) | |
244 # go to the beginning of the next line | |
245 @x=@l_margin | |
246 elsif (ln == 0) | |
247 # go to the top-right of the cell | |
248 @y = prevy; | |
249 @x = prevx + w; | |
250 elsif (ln == 2) | |
251 # go to the bottom-left of the cell | |
252 @x = prevx; | |
253 end | |
254 end | |
255 | |
256 def Write(h,txt,link='',fill=0) | |
257 if(@current_font['type']=='Type0') | |
258 MBWrite(h,txt,link,fill) | |
259 else | |
260 super(h,txt,link,fill) | |
261 end | |
262 end | |
263 | |
264 def MBWrite(h,txt,link,fill=0) | |
265 #Multi-byte version of Write() | |
266 cw=@current_font['cw'] | |
267 w=@w-@r_margin-@x | |
268 wmax=(w-2*@c_margin)*1000/@font_size | |
269 s=txt.gsub("\r",'') | |
270 nb=s.length | |
271 sep=-1 | |
272 i=0 | |
273 j=0 | |
274 l=0 | |
275 nl=1 | |
276 while(i<nb) | |
277 #Get next character | |
278 c = s[i].is_a?(String) ? s[i].ord : s[i] | |
279 #Check if ASCII or MB | |
280 ascii=(c<128) | |
281 if(c.chr=="\n") | |
282 #Explicit line break | |
283 Cell(w,h,s[j,i-j],0,2,'',fill,link) | |
284 i+=1 | |
285 sep=-1 | |
286 j=i | |
287 l=0 | |
288 if(nl==1) | |
289 @x=@l_margin | |
290 w=@w-@r_margin-@x | |
291 wmax=(w-2*@c_margin)*1000/@font_size | |
292 end | |
293 nl+=1 | |
294 next | |
295 end | |
296 if(!ascii or c.chr==' ') | |
297 sep=i | |
298 end | |
299 l+=(ascii ? cw[c.chr] : 1000) || 0 | |
300 if(l>wmax) | |
301 #Automatic line break | |
302 if(sep==-1 or i==j) | |
303 if(@x>@l_margin) | |
304 #Move to next line | |
305 @x=@l_margin | |
306 @y+=h | |
307 w=@w-@r_margin-@x | |
308 wmax=(w-2*@c_margin)*1000/@font_size | |
309 i+=1 | |
310 nl+=1 | |
311 next | |
312 end | |
313 if(i==j) | |
314 i+=ascii ? 1 : 2 | |
315 end | |
316 Cell(w,h,s[j,i-j],0,2,'',fill,link) | |
317 else | |
318 Cell(w,h,s[j,sep-j],0,2,'',fill,link) | |
319 i=(s[sep].chr==' ') ? sep+1 : sep | |
320 end | |
321 sep=-1 | |
322 j=i | |
323 l=0 | |
324 if(nl==1) | |
325 @x=@l_margin | |
326 w=@w-@r_margin-@x | |
327 wmax=(w-2*@c_margin)*1000/@font_size | |
328 end | |
329 nl+=1 | |
330 else | |
331 i+=ascii ? 1 : 2 | |
332 end | |
333 end | |
334 #Last chunk | |
335 if(i!=j) | |
336 Cell(l*@font_size/1000.0,h,s[j,i-j],0,0,'',fill,link) | |
337 end | |
338 end | |
339 | |
340 private | |
341 | |
342 def putfonts() | |
343 nf=@n | |
344 @diffs.each do |diff| | |
345 #Encodings | |
346 newobj() | |
347 out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['+diff+']>>') | |
348 out('endobj') | |
349 end | |
350 # mqr=get_magic_quotes_runtime() | |
351 # set_magic_quotes_runtime(0) | |
352 @font_files.each_pair do |file, info| | |
353 #Font file embedding | |
354 newobj() | |
355 @font_files[file]['n']=@n | |
356 if(defined('FPDF_FONTPATH')) | |
357 file=FPDF_FONTPATH+file | |
358 end | |
359 size=filesize(file) | |
360 if(!size) | |
361 Error('Font file not found') | |
362 end | |
363 out('<</Length '+size) | |
364 if(file[-2]=='.z') | |
365 out('/Filter /FlateDecode') | |
366 end | |
367 out('/Length1 '+info['length1']) | |
368 unless info['length2'].nil? | |
369 out('/Length2 '+info['length2']+' /Length3 0') | |
370 end | |
371 out('>>') | |
372 f=fopen(file,'rb') | |
373 putstream(fread(f,size)) | |
374 fclose(f) | |
375 out('endobj') | |
376 end | |
377 # | |
378 # set_magic_quotes_runtime(mqr) | |
379 # | |
380 @fonts.each_pair do |k, font| | |
381 #Font objects | |
382 newobj() | |
383 @fonts[k]['n']=@n | |
384 out('<</Type /Font') | |
385 if(font['type']=='Type0') | |
386 putType0(font) | |
387 else | |
388 name=font['name'] | |
389 out('/BaseFont /'+name) | |
390 if(font['type']=='core') | |
391 #Standard font | |
392 out('/Subtype /Type1') | |
393 if(name!='Symbol' and name!='ZapfDingbats') | |
394 out('/Encoding /WinAnsiEncoding') | |
395 end | |
396 else | |
397 #Additional font | |
398 out('/Subtype /'+font['type']) | |
399 out('/FirstChar 32') | |
400 out('/LastChar 255') | |
401 out('/Widths '+(@n+1)+' 0 R') | |
402 out('/FontDescriptor '+(@n+2)+' 0 R') | |
403 if(font['enc']) | |
404 if !font['diff'].nil? | |
405 out('/Encoding '+(nf+font['diff'])+' 0 R') | |
406 else | |
407 out('/Encoding /WinAnsiEncoding') | |
408 end | |
409 end | |
410 end | |
411 out('>>') | |
412 out('endobj') | |
413 if(font['type']!='core') | |
414 #Widths | |
415 newobj() | |
416 cw=font['cw'] | |
417 s='[' | |
418 32.upto(255) do |i| | |
419 s+=cw[i.chr]+' ' | |
420 end | |
421 out(s+']') | |
422 out('endobj') | |
423 #Descriptor | |
424 newobj() | |
425 s='<</Type /FontDescriptor /FontName /'+name | |
426 font['desc'].each_pair do |k, v| | |
427 s+=' /'+k+' '+v | |
428 end | |
429 file=font['file'] | |
430 if(file) | |
431 s+=' /FontFile'+(font['type']=='Type1' ? '' : '2')+' '+@font_files[file]['n']+' 0 R' | |
432 end | |
433 out(s+'>>') | |
434 out('endobj') | |
435 end | |
436 end | |
437 end | |
438 end | |
439 | |
440 def putType0(font) | |
441 #Type0 | |
442 out('/Subtype /Type0') | |
443 out('/BaseFont /'+font['name']+'-'+font['CMap']) | |
444 out('/Encoding /'+font['CMap']) | |
445 out('/DescendantFonts ['+(@n+1).to_s+' 0 R]') | |
446 out('>>') | |
447 out('endobj') | |
448 #CIDFont | |
449 newobj() | |
450 out('<</Type /Font') | |
451 out('/Subtype /CIDFontType0') | |
452 out('/BaseFont /'+font['name']) | |
453 out('/CIDSystemInfo <</Registry '+textstring('Adobe')+' /Ordering '+textstring(font['registry']['ordering'])+' /Supplement '+font['registry']['supplement'].to_s+'>>') | |
454 out('/FontDescriptor '+(@n+1).to_s+' 0 R') | |
455 if(font['CMap']=='ETen-B5-H') | |
456 w='13648 13742 500' | |
457 elsif(font['CMap']=='GBK-EUC-H') | |
458 w='814 907 500 7716 [500]' | |
459 else | |
460 # ActionController::Base::logger.debug font['cw'].keys.sort.join(' ').to_s | |
461 # ActionController::Base::logger.debug font['cw'].values.join(' ').to_s | |
462 w='1 [' | |
463 font['cw'].keys.sort.each {|key| | |
464 w+=font['cw'][key].to_s + " " | |
465 # ActionController::Base::logger.debug key.to_s | |
466 # ActionController::Base::logger.debug font['cw'][key].to_s | |
467 } | |
468 w +=']' | |
469 end | |
470 out('/W ['+w+']>>') | |
471 out('endobj') | |
472 #Font descriptor | |
473 newobj() | |
474 out('<</Type /FontDescriptor') | |
475 out('/FontName /'+font['name']) | |
476 out('/Flags 6') | |
477 out('/FontBBox [0 -200 1000 900]') | |
478 out('/ItalicAngle 0') | |
479 out('/Ascent 800') | |
480 out('/Descent -200') | |
481 out('/CapHeight 800') | |
482 out('/StemV 50') | |
483 out('>>') | |
484 out('endobj') | |
485 end | |
486 end |