##// END OF EJS Templates
missing rfpdf in the repository......
Jean-Philippe Lang -
r47:5e9e01bf7ff6
parent child
Show More
@@ -0,0 +1,13
1 1.00 Added view template functionality
2 1.10 Added Chinese support
3 1.11 Added Japanese support
4 1.12 Added Korean support
5 1.13 Updated to fpdf.rb 1.53d.
6 Added makefont and fpdf_eps.
7 Handle \n at the beginning of a string in MultiCell.
8 Tried to fix clipping issue in MultiCell - still needs some work.
9 1.14 2006-09-26
10 * Added support for @options_for_rfpdf hash for configuration:
11 * Added :filename option in this hash
12 If you're using the same settings for @options_for_rfpdf often, you might want to
13 put your assignment in a before_filter (perhaps overriding :filename, etc in your actions).
@@ -0,0 +1,20
1 Copyright (c) 2006 4ssoM LLC <www.4ssoM.com>
2
3 Permission is hereby granted, free of charge, to any person obtaining
4 a copy of this software and associated documentation files (the
5 "Software"), to deal in the Software without restriction, including
6 without limitation the rights to use, copy, modify, merge, publish,
7 distribute, sublicense, and/or sell copies of the Software, and to
8 permit persons to whom the Software is furnished to do so, subject to
9 the following conditions:
10
11 The above copyright notice and this permission notice shall be
12 included in all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOa AND
17 NONINFRINGEMENT. IN NO EVENT SaALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. No newline at end of file
@@ -0,0 +1,99
1 = RFPDF Template Plugin
2
3 A template plugin allowing the inclusion of ERB-enabled RFPDF template files.
4
5 == Example .rb method Usage
6
7 In the controller, something like:
8
9 def mypdf
10 pdf = FPDF.new()
11
12 #
13 # Chinese
14 #
15 pdf.extend(PDF_Chinese)
16 pdf.AddPage
17 pdf.AddBig5Font
18 pdf.SetFont('Big5','',18)
19 pdf.Write(5, '²{®É®ð·Å 18 C Àã«× 83 %')
20 icBig5 = Iconv.new('Big5', 'UTF-8')
21 pdf.Write(15, icBig5.iconv("宋体 should be working"))
22 send_data pdf.Output, :filename => "something.pdf", :type => "application/pdf"
23 end
24
25 == Example .rfdf Usage
26
27 In the controller, something like:
28
29 def mypdf
30 @options_for_rfpdf ||= {}
31 @options_for_rfpdf[:file_name] = "nice_looking.pdf"
32 end
33
34 In the layout (make sure this is the only item in the layout):
35 <%= @content_for_layout %>
36
37 In the view (mypdf.rfpdf):
38
39 <%
40 pdf = FPDF.new()
41 #
42 # Chinese
43 #
44 pdf.extend(PDF_Chinese)
45 pdf.AddPage
46 pdf.AddBig5Font
47 pdf.SetFont('Big5','',18)
48 pdf.Write(5, '²{®É®ð·Å 18 C Àã«× 83 %')
49 icBig5 = Iconv.new('Big5', 'UTF-8')
50 pdf.Write(15, icBig5.iconv("宋体 should be working"))
51
52 #
53 # Japanese
54 #
55 pdf.extend(PDF_Japanese)
56 pdf.AddSJISFont();
57 pdf.AddPage();
58 pdf.SetFont('SJIS','',18);
59 pdf.Write(5,'9ÉñåéÇÃåˆäJÉeÉXÉgÇåoǃPHP 3.0ÇÕ1998îN6åéÇ…åˆéÆÇ…ÉäÉäÅ[ÉXÇ≥ÇÍNjǵÇΩÅB');
60 icSJIS = Iconv.new('SJIS', 'UTF-8')
61 pdf.Write(15, icSJIS.iconv("これはテキストである should be working"))
62
63 #
64 # Korean
65 #
66 pdf.extend(PDF_Korean)
67 pdf.AddUHCFont();
68 pdf.AddPage();
69 pdf.SetFont('UHC','',18);
70 pdf.Write(5,'PHP 3.0Àº 1998³â 6¿ù¿¡ °ø½ÄÀûÀ¸·Î ¸±¸®ÁîµÇ¾ú´Ù. °ø°³ÀûÀÎ Å×½ºÆ® ÀÌÈľà 9°³¿ù¸¸À̾ú´Ù.');
71 icUHC = Iconv.new('UHC', 'UTF-8')
72 pdf.Write(15, icUHC.iconv("이것은 원본 이다"))
73
74 #
75 # English
76 #
77 pdf.AddPage();
78 pdf.SetFont('Arial', '', 10)
79 pdf.Write(5, "should be working")
80 %>
81 <%= pdf.Output() %>
82
83
84 == Configuring
85
86 You can configure Rfpdf by using an @options_for_rfpdf hash in your controllers.
87
88 Here are a few options:
89
90 :filename (default: action_name.pdf)
91 Filename of PDF to generate
92
93 Note: If you're using the same settings for @options_for_rfpdf often, you might want to
94 put your assignment in a before_filter (perhaps overriding :filename, etc in your actions).
95
96 == Problems
97
98 Layouts and partials are currently not supported; just need
99 to wrap the PDF generation differently.
@@ -0,0 +1,3
1 require 'rfpdf'
2
3 ActionView::Base::register_template_handler 'rfpdf', RFPDF::View No newline at end of file
@@ -0,0 +1,31
1 # Copyright (c) 2006 4ssoM LLC <www.4ssoM.com>
2 #
3 # The MIT License
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
11 #
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
14 #
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 # THE SOFTWARE.
22
23 $LOAD_PATH.unshift(File.dirname(__FILE__))
24
25 require 'rfpdf/errors'
26 require 'rfpdf/view'
27 require 'rfpdf/fpdf'
28 require 'rfpdf/rfpdf'
29 require 'rfpdf/chinese'
30 require 'rfpdf/japanese'
31 require 'rfpdf/korean'
@@ -0,0 +1,99
1 # Translation of the bookmark class from the PHP FPDF script from Olivier Plathey
2 # Translated by Sylvain Lafleur and ?? with the help of Brian Ollenberger
3 #
4 # First added in 1.53b
5 #
6 # Usage is as follows:
7 #
8 # require 'fpdf'
9 # require 'bookmark'
10 # pdf = FPDF.new
11 # pdf.extend(PDF_Bookmark)
12 #
13 # This allows it to be combined with other extensions, such as the Chinese
14 # module.
15
16 module PDF_Bookmark
17 def PDF_Bookmark.extend_object(o)
18 o.instance_eval('@outlines,@OutlineRoot=[],0')
19 super(o)
20 end
21
22 def Bookmark(txt,level=0,y=0)
23 y=self.GetY() if y==-1
24 @outlines.push({'t'=>txt,'l'=>level,'y'=>y,'p'=>self.PageNo()})
25 end
26
27 def putbookmarks
28 @nb=@outlines.size
29 return if @nb==0
30 lru=[]
31 level=0
32 @outlines.each_index do |i|
33 o=@outlines[i]
34 if o['l']>0
35 parent=lru[o['l']-1]
36 # Set parent and last pointers
37 @outlines[i]['parent']=parent
38 @outlines[parent]['last']=i
39 if o['l']>level
40 # Level increasing: set first pointer
41 @outlines[parent]['first']=i
42 end
43 else
44 @outlines[i]['parent']=@nb
45 end
46 if o['l']<=level and i>0
47 # Set prev and next pointers
48 prev=lru[o['l']]
49 @outlines[prev]['next']=i
50 @outlines[i]['prev']=prev
51 end
52 lru[o['l']]=i
53 level=o['l']
54 end
55 # Outline items
56 n=@n+1
57 @outlines.each_index do |i|
58 o=@outlines[i]
59 newobj
60 out('<</Title '+(textstring(o['t'])))
61 out('/Parent '+(n+o['parent']).to_s+' 0 R')
62 if o['prev']
63 out('/Prev '+(n+o['prev']).to_s+' 0 R')
64 end
65 if o['next']
66 out('/Next '+(n+o['next']).to_s+' 0 R')
67 end
68 if o['first']
69 out('/First '+(n+o['first']).to_s+' 0 R')
70 end
71 if o['last']
72 out('/Last '+(n+o['last']).to_s+' 0 R')
73 end
74 out(sprintf('/Dest [%d 0 R /XYZ 0 %.2f
75 null]',1+2*o['p'],(@h-o['y'])*@k))
76 out('/Count 0>>')
77 out('endobj')
78 end
79 # Outline root
80 newobj
81 @OutlineRoot=@n
82 out('<</Type /Outlines /First '+n.to_s+' 0 R')
83 out('/Last '+(n+lru[0]).to_s+' 0 R>>')
84 out('endobj')
85 end
86
87 def putresources
88 super
89 putbookmarks
90 end
91
92 def putcatalog
93 super
94 if not @outlines.empty?
95 out('/Outlines '+@OutlineRoot.to_s+' 0 R')
96 out('/PageMode /UseOutlines')
97 end
98 end
99 end
@@ -0,0 +1,473
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,'end'=>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,'end'=>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(@CurrentFont['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=@CurrentFont['cw']
130 nb=s.length
131 i=0
132 while(i<nb)
133 c=s[i]
134 if(c<128)
135 l+=cw[c.chr]
136 i+=1
137 else
138 l+=1000
139 i+=2
140 end
141 end
142 return l*@FontSize/1000
143 end
144
145 def MultiCell(w,h,txt,border=0,align='L',fill=0)
146 if(@CurrentFont['type']=='Type0')
147 MBMultiCell(w,h,txt,border,align,fill)
148 else
149 super(w,h,txt,border,align,fill)
150 end
151 end
152
153 def MBMultiCell(w,h,txt,border=0,align='L',fill=0)
154 #Multi-byte version of MultiCell()
155 cw=@CurrentFont['cw']
156 if(w==0)
157 w=@w-@rMargin-@x
158 end
159 wmax=(w-2*@cMargin)*1000/@FontSize
160 s=txt.gsub("\r",'')
161 nb=s.length
162 if(nb>0 and s[nb-1]=="\n")
163 nb-=1
164 end
165 b=0
166 if(border)
167 if(border==1)
168 border='LTRB'
169 b='LRT'
170 b2='LR'
171 else
172 b2=''
173 if(border.index('L').nil?)
174 b2+='L'
175 end
176 if(border.index('R').nil?)
177 b2+='R'
178 end
179 b=border.index('T').nil? ? b2+'T' : b2
180 end
181 end
182 sep=-1
183 i=0
184 j=0
185 l=0
186 nl=1
187 while(i<nb)
188 #Get next character
189 c=s[i]
190 #Check if ASCII or MB
191 ascii=(c<128)
192 if(c=="\n")
193 #Explicit line break
194 Cell(w,h,s[j,i-j],b,2,align,fill)
195 i+=1
196 sep=-1
197 j=i
198 l=0
199 nl+=1
200 if(border and nl==2)
201 b=b2
202 end
203 next
204 end
205 if(!ascii)
206 sep=i
207 ls=l
208 elsif(c==' ')
209 sep=i
210 ls=l
211 end
212 l+=ascii ? cw[c.chr] : 1000
213 if(l>wmax)
214 #Automatic line break
215 if(sep==-1 or i==j)
216 if(i==j)
217 i+=ascii ? 1 : 2
218 end
219 Cell(w,h,s[j,i-j],b,2,align,fill)
220 else
221 Cell(w,h,s[j,sep-j],b,2,align,fill)
222 i=(s[sep]==' ') ? sep+1 : sep
223 end
224 sep=-1
225 j=i
226 l=0
227 # nl+=1
228 if(border and nl==2)
229 b=b2
230 end
231 else
232 i+=ascii ? 1 : 2
233 end
234 end
235 #Last chunk
236 if(border and not border.index('B').nil?)
237 b+='B'
238 end
239 Cell(w,h,s[j,i-j],b,2,align,fill)
240 @x=@lMargin
241 end
242
243 def Write(h,txt,link='')
244 if(@CurrentFont['type']=='Type0')
245 MBWrite(h,txt,link)
246 else
247 super(h,txt,link)
248 end
249 end
250
251 def MBWrite(h,txt,link)
252 #Multi-byte version of Write()
253 cw=@CurrentFont['cw']
254 w=@w-@rMargin-@x
255 wmax=(w-2*@cMargin)*1000/@FontSize
256 s=txt.gsub("\r",'')
257 nb=s.length
258 sep=-1
259 i=0
260 j=0
261 l=0
262 nl=1
263 while(i<nb)
264 #Get next character
265 c=s[i]
266 #Check if ASCII or MB
267 ascii=(c<128)
268 if(c=="\n")
269 #Explicit line break
270 Cell(w,h,s[j,i-j],0,2,'',0,link)
271 i+=1
272 sep=-1
273 j=i
274 l=0
275 if(nl==1)
276 @x=@lMargin
277 w=@w-@rMargin-@x
278 wmax=(w-2*@cMargin)*1000/@FontSize
279 end
280 nl+=1
281 next
282 end
283 if(!ascii or c==' ')
284 sep=i
285 end
286 l+=ascii ? cw[c.chr] : 1000
287 if(l>wmax)
288 #Automatic line break
289 if(sep==-1 or i==j)
290 if(@x>@lMargin)
291 #Move to next line
292 @x=@lMargin
293 @y+=h
294 w=@w-@rMargin-@x
295 wmax=(w-2*@cMargin)*1000/@FontSize
296 i+=1
297 nl+=1
298 next
299 end
300 if(i==j)
301 i+=ascii ? 1 : 2
302 end
303 Cell(w,h,s[j,i-j],0,2,'',0,link)
304 else
305 Cell(w,h,s[j,sep-j],0,2,'',0,link)
306 i=(s[sep]==' ') ? sep+1 : sep
307 end
308 sep=-1
309 j=i
310 l=0
311 if(nl==1)
312 @x=@lMargin
313 w=@w-@rMargin-@x
314 wmax=(w-2*@cMargin)*1000/@FontSize
315 end
316 nl+=1
317 else
318 i+=ascii ? 1 : 2
319 end
320 end
321 #Last chunk
322 if(i!=j)
323 Cell(l/1000*@FontSize,h,s[j,i-j],0,0,'',0,link)
324 end
325 end
326
327 private
328
329 def putfonts()
330 nf=@n
331 @diffs.each do |diff|
332 #Encodings
333 newobj()
334 out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['+diff+']>>')
335 out('endobj')
336 end
337 # mqr=get_magic_quotes_runtime()
338 # set_magic_quotes_runtime(0)
339 @FontFiles.each_pair do |file, info|
340 #Font file embedding
341 newobj()
342 @FontFiles[file]['n']=@n
343 if(defined('FPDF_FONTPATH'))
344 file=FPDF_FONTPATH+file
345 end
346 size=filesize(file)
347 if(!size)
348 Error('Font file not found')
349 end
350 out('<</Length '+size)
351 if(file[-2]=='.z')
352 out('/Filter /FlateDecode')
353 end
354 out('/Length1 '+info['length1'])
355 unless info['length2'].nil?
356 out('/Length2 '+info['length2']+' /Length3 0')
357 end
358 out('>>')
359 f=fopen(file,'rb')
360 putstream(fread(f,size))
361 fclose(f)
362 out('endobj')
363 end
364 #
365 # set_magic_quotes_runtime(mqr)
366 #
367 @fonts.each_pair do |k, font|
368 #Font objects
369 newobj()
370 @fonts[k]['n']=@n
371 out('<</Type /Font')
372 if(font['type']=='Type0')
373 putType0(font)
374 else
375 name=font['name']
376 out('/BaseFont /'+name)
377 if(font['type']=='core')
378 #Standard font
379 out('/Subtype /Type1')
380 if(name!='Symbol' and name!='ZapfDingbats')
381 out('/Encoding /WinAnsiEncoding')
382 end
383 else
384 #Additional font
385 out('/Subtype /'+font['type'])
386 out('/FirstChar 32')
387 out('/LastChar 255')
388 out('/Widths '+(@n+1)+' 0 R')
389 out('/FontDescriptor '+(@n+2)+' 0 R')
390 if(font['enc'])
391 if !font['diff'].nil?
392 out('/Encoding '+(nf+font['diff'])+' 0 R')
393 else
394 out('/Encoding /WinAnsiEncoding')
395 end
396 end
397 end
398 out('>>')
399 out('endobj')
400 if(font['type']!='core')
401 #Widths
402 newobj()
403 cw=font['cw']
404 s='['
405 32.upto(255) do |i|
406 s+=cw[i.chr]+' '
407 end
408 out(s+']')
409 out('endobj')
410 #Descriptor
411 newobj()
412 s='<</Type /FontDescriptor /FontName /'+name
413 font['desc'].each_pair do |k, v|
414 s+=' /'+k+' '+v
415 end
416 file=font['file']
417 if(file)
418 s+=' /FontFile'+(font['type']=='Type1' ? '' : '2')+' '+@FontFiles[file]['n']+' 0 R'
419 end
420 out(s+'>>')
421 out('endobj')
422 end
423 end
424 end
425 end
426
427 def putType0(font)
428 #Type0
429 out('/Subtype /Type0')
430 out('/BaseFont /'+font['name']+'-'+font['CMap'])
431 out('/Encoding /'+font['CMap'])
432 out('/DescendantFonts ['+(@n+1).to_s+' 0 R]')
433 out('>>')
434 out('endobj')
435 #CIDFont
436 newobj()
437 out('<</Type /Font')
438 out('/Subtype /CIDFontType0')
439 out('/BaseFont /'+font['name'])
440 out('/CIDSystemInfo <</Registry '+textstring('Adobe')+' /Ordering '+textstring(font['registry']['ordering'])+' /Supplement '+font['registry']['supplement'].to_s+'>>')
441 out('/FontDescriptor '+(@n+1).to_s+' 0 R')
442 if(font['CMap']=='ETen-B5-H')
443 w='13648 13742 500'
444 elsif(font['CMap']=='GBK-EUC-H')
445 w='814 907 500 7716 [500]'
446 else
447 # ActionController::Base::logger.debug font['cw'].keys.sort.join(' ').to_s
448 # ActionController::Base::logger.debug font['cw'].values.join(' ').to_s
449 w='1 ['
450 font['cw'].keys.sort.each {|key|
451 w+=font['cw'][key].to_s + " "
452 # ActionController::Base::logger.debug key.to_s
453 # ActionController::Base::logger.debug font['cw'][key].to_s
454 }
455 w +=']'
456 end
457 out('/W ['+w+']>>')
458 out('endobj')
459 #Font descriptor
460 newobj()
461 out('<</Type /FontDescriptor')
462 out('/FontName /'+font['name'])
463 out('/Flags 6')
464 out('/FontBBox [0 -200 1000 900]')
465 out('/ItalicAngle 0')
466 out('/Ascent 800')
467 out('/Descent -200')
468 out('/CapHeight 800')
469 out('/StemV 50')
470 out('>>')
471 out('endobj')
472 end
473 end
@@ -0,0 +1,4
1 module RFPDF
2 class GenerationError < StandardError #:nodoc:
3 end
4 end No newline at end of file
This diff has been collapsed as it changes many lines, (1550 lines changed) Show them Hide them
@@ -0,0 +1,1550
1 # Ruby FPDF 1.53d
2 # FPDF 1.53 by Olivier Plathey ported to Ruby by Brian Ollenberger
3 # Copyright 2005 Brian Ollenberger
4 # Please retain this entire copyright notice. If you distribute any
5 # modifications, place an additional comment here that clearly indicates
6 # that it was modified. You may (but are not send any useful modifications that you make
7 # back to me at http://zeropluszero.com/software/fpdf/
8
9 # Bug fixes, examples, external fonts, JPEG support, and upgrade to version
10 # 1.53 contributed by Kim Shrier.
11 #
12 # Bookmark support contributed by Sylvain Lafleur.
13 #
14 # EPS support contributed by Thiago Jackiw, ported from the PHP version by Valentin Schmidt.
15 #
16 # Bookmarks contributed by Sylvain Lafleur.
17 #
18 # 1.53 contributed by Ed Moss
19 # Handle '\n' at the beginning of a string
20 # Bookmarks contributed by Sylvain Lafleur.
21
22 require 'date'
23 require 'zlib'
24
25 class FPDF
26 FPDF_VERSION = '1.53d'
27
28 Charwidths = {
29 'courier'=>[600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600],
30
31 'courierB'=>[600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600],
32
33 'courierI'=>[600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600],
34
35 'courierBI'=>[600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600],
36
37 'helvetica'=>[278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 350, 556, 350, 222, 556, 333, 1000, 556, 556, 333, 1000, 667, 333, 1000, 350, 611, 350, 350, 222, 222, 333, 333, 350, 556, 1000, 333, 1000, 500, 333, 944, 350, 500, 667, 278, 333, 556, 556, 556, 556, 260, 556, 333, 737, 370, 556, 584, 333, 737, 333, 400, 584, 333, 333, 333, 556, 537, 278, 333, 333, 365, 556, 834, 834, 834, 611, 667, 667, 667, 667, 667, 667, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 584, 611, 556, 556, 556, 556, 500, 556, 500],
38
39 'helveticaB'=>[278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 350, 556, 350, 278, 556, 500, 1000, 556, 556, 333, 1000, 667, 333, 1000, 350, 611, 350, 350, 278, 278, 500, 500, 350, 556, 1000, 333, 1000, 556, 333, 944, 350, 500, 667, 278, 333, 556, 556, 556, 556, 280, 556, 333, 737, 370, 556, 584, 333, 737, 333, 400, 584, 333, 333, 333, 611, 556, 278, 333, 333, 365, 556, 834, 834, 834, 611, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 584, 611, 611, 611, 611, 611, 556, 611, 556],
40
41 'helveticaI'=>[278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 350, 556, 350, 222, 556, 333, 1000, 556, 556, 333, 1000, 667, 333, 1000, 350, 611, 350, 350, 222, 222, 333, 333, 350, 556, 1000, 333, 1000, 500, 333, 944, 350, 500, 667, 278, 333, 556, 556, 556, 556, 260, 556, 333, 737, 370, 556, 584, 333, 737, 333, 400, 584, 333, 333, 333, 556, 537, 278, 333, 333, 365, 556, 834, 834, 834, 611, 667, 667, 667, 667, 667, 667, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 584, 611, 556, 556, 556, 556, 500, 556, 500],
42
43 'helveticaBI'=>[278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 350, 556, 350, 278, 556, 500, 1000, 556, 556, 333, 1000, 667, 333, 1000, 350, 611, 350, 350, 278, 278, 500, 500, 350, 556, 1000, 333, 1000, 556, 333, 944, 350, 500, 667, 278, 333, 556, 556, 556, 556, 280, 556, 333, 737, 370, 556, 584, 333, 737, 333, 400, 584, 333, 333, 333, 611, 556, 278, 333, 333, 365, 556, 834, 834, 834, 611, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 584, 611, 611, 611, 611, 611, 556, 611, 556],
44
45 'times'=>[250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 333, 408, 500, 500, 833, 778, 180, 333, 333, 500, 564, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 278, 564, 564, 564, 444, 921, 722, 667, 667, 722, 611, 556, 722, 722, 333, 389, 722, 611, 889, 722, 722, 556, 722, 667, 556, 611, 722, 722, 944, 722, 722, 611, 333, 278, 333, 469, 500, 333, 444, 500, 444, 500, 444, 333, 500, 500, 278, 278, 500, 278, 778, 500, 500, 500, 500, 333, 389, 278, 500, 500, 722, 500, 500, 444, 480, 200, 480, 541, 350, 500, 350, 333, 500, 444, 1000, 500, 500, 333, 1000, 556, 333, 889, 350, 611, 350, 350, 333, 333, 444, 444, 350, 500, 1000, 333, 980, 389, 333, 722, 350, 444, 722, 250, 333, 500, 500, 500, 500, 200, 500, 333, 760, 276, 500, 564, 333, 760, 333, 400, 564, 300, 300, 333, 500, 453, 250, 333, 300, 310, 500, 750, 750, 750, 444, 722, 722, 722, 722, 722, 722, 889, 667, 611, 611, 611, 611, 333, 333, 333, 333, 722, 722, 722, 722, 722, 722, 722, 564, 722, 722, 722, 722, 722, 722, 556, 500, 444, 444, 444, 444, 444, 444, 667, 444, 444, 444, 444, 444, 278, 278, 278, 278, 500, 500, 500, 500, 500, 500, 500, 564, 500, 500, 500, 500, 500, 500, 500, 500],
46
47 'timesB'=>[250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 333, 555, 500, 500, 1000, 833, 278, 333, 333, 500, 570, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 570, 570, 570, 500, 930, 722, 667, 722, 722, 667, 611, 778, 778, 389, 500, 778, 667, 944, 722, 778, 611, 778, 722, 556, 667, 722, 722, 1000, 722, 722, 667, 333, 278, 333, 581, 500, 333, 500, 556, 444, 556, 444, 333, 500, 556, 278, 333, 556, 278, 833, 556, 500, 556, 556, 444, 389, 333, 556, 500, 722, 500, 500, 444, 394, 220, 394, 520, 350, 500, 350, 333, 500, 500, 1000, 500, 500, 333, 1000, 556, 333, 1000, 350, 667, 350, 350, 333, 333, 500, 500, 350, 500, 1000, 333, 1000, 389, 333, 722, 350, 444, 722, 250, 333, 500, 500, 500, 500, 220, 500, 333, 747, 300, 500, 570, 333, 747, 333, 400, 570, 300, 300, 333, 556, 540, 250, 333, 300, 330, 500, 750, 750, 750, 500, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 389, 389, 389, 389, 722, 722, 778, 778, 778, 778, 778, 570, 778, 722, 722, 722, 722, 722, 611, 556, 500, 500, 500, 500, 500, 500, 722, 444, 444, 444, 444, 444, 278, 278, 278, 278, 500, 556, 500, 500, 500, 500, 500, 570, 500, 556, 556, 556, 556, 500, 556, 500],
48
49 'timesI'=>[250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 333, 420, 500, 500, 833, 778, 214, 333, 333, 500, 675, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 675, 675, 675, 500, 920, 611, 611, 667, 722, 611, 611, 722, 722, 333, 444, 667, 556, 833, 667, 722, 611, 722, 611, 500, 556, 722, 611, 833, 611, 556, 556, 389, 278, 389, 422, 500, 333, 500, 500, 444, 500, 444, 278, 500, 500, 278, 278, 444, 278, 722, 500, 500, 500, 500, 389, 389, 278, 500, 444, 667, 444, 444, 389, 400, 275, 400, 541, 350, 500, 350, 333, 500, 556, 889, 500, 500, 333, 1000, 500, 333, 944, 350, 556, 350, 350, 333, 333, 556, 556, 350, 500, 889, 333, 980, 389, 333, 667, 350, 389, 556, 250, 389, 500, 500, 500, 500, 275, 500, 333, 760, 276, 500, 675, 333, 760, 333, 400, 675, 300, 300, 333, 500, 523, 250, 333, 300, 310, 500, 750, 750, 750, 500, 611, 611, 611, 611, 611, 611, 889, 667, 611, 611, 611, 611, 333, 333, 333, 333, 722, 667, 722, 722, 722, 722, 722, 675, 722, 722, 722, 722, 722, 556, 611, 500, 500, 500, 500, 500, 500, 500, 667, 444, 444, 444, 444, 444, 278, 278, 278, 278, 500, 500, 500, 500, 500, 500, 500, 675, 500, 500, 500, 500, 500, 444, 500, 444],
50
51 'timesBI'=>[250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 389, 555, 500, 500, 833, 778, 278, 333, 333, 500, 570, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 570, 570, 570, 500, 832, 667, 667, 667, 722, 667, 667, 722, 778, 389, 500, 667, 611, 889, 722, 722, 611, 722, 667, 556, 611, 722, 667, 889, 667, 611, 611, 333, 278, 333, 570, 500, 333, 500, 500, 444, 500, 444, 333, 500, 556, 278, 278, 500, 278, 778, 556, 500, 500, 500, 389, 389, 278, 556, 444, 667, 500, 444, 389, 348, 220, 348, 570, 350, 500, 350, 333, 500, 500, 1000, 500, 500, 333, 1000, 556, 333, 944, 350, 611, 350, 350, 333, 333, 500, 500, 350, 500, 1000, 333, 1000, 389, 333, 722, 350, 389, 611, 250, 389, 500, 500, 500, 500, 220, 500, 333, 747, 266, 500, 606, 333, 747, 333, 400, 570, 300, 300, 333, 576, 500, 250, 333, 300, 300, 500, 750, 750, 750, 500, 667, 667, 667, 667, 667, 667, 944, 667, 667, 667, 667, 667, 389, 389, 389, 389, 722, 722, 722, 722, 722, 722, 722, 570, 722, 722, 722, 722, 722, 611, 611, 500, 500, 500, 500, 500, 500, 500, 722, 444, 444, 444, 444, 444, 278, 278, 278, 278, 500, 556, 500, 500, 500, 500, 500, 570, 500, 556, 556, 556, 556, 444, 500, 444],
52
53 'symbol'=>[250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 333, 713, 500, 549, 833, 778, 439, 333, 333, 500, 549, 250, 549, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 278, 549, 549, 549, 444, 549, 722, 667, 722, 612, 611, 763, 603, 722, 333, 631, 722, 686, 889, 722, 722, 768, 741, 556, 592, 611, 690, 439, 768, 645, 795, 611, 333, 863, 333, 658, 500, 500, 631, 549, 549, 494, 439, 521, 411, 603, 329, 603, 549, 549, 576, 521, 549, 549, 521, 549, 603, 439, 576, 713, 686, 493, 686, 494, 480, 200, 480, 549, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 750, 620, 247, 549, 167, 713, 500, 753, 753, 753, 753, 1042, 987, 603, 987, 603, 400, 549, 411, 549, 549, 713, 494, 460, 549, 549, 549, 549, 1000, 603, 1000, 658, 823, 686, 795, 987, 768, 768, 823, 768, 768, 713, 713, 713, 713, 713, 713, 713, 768, 713, 790, 790, 890, 823, 549, 250, 713, 603, 603, 1042, 987, 603, 987, 603, 494, 329, 790, 790, 786, 713, 384, 384, 384, 384, 384, 384, 494, 494, 494, 494, 0, 329, 274, 686, 686, 686, 384, 384, 384, 384, 384, 384, 494, 494, 494, 0],
54
55 'zapfdingbats'=>[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 278, 974, 961, 974, 980, 719, 789, 790, 791, 690, 960, 939, 549, 855, 911, 933, 911, 945, 974, 755, 846, 762, 761, 571, 677, 763, 760, 759, 754, 494, 552, 537, 577, 692, 786, 788, 788, 790, 793, 794, 816, 823, 789, 841, 823, 833, 816, 831, 923, 744, 723, 749, 790, 792, 695, 776, 768, 792, 759, 707, 708, 682, 701, 826, 815, 789, 789, 707, 687, 696, 689, 786, 787, 713, 791, 785, 791, 873, 761, 762, 762, 759, 759, 892, 892, 788, 784, 438, 138, 277, 415, 392, 392, 668, 668, 0, 390, 390, 317, 317, 276, 276, 509, 509, 410, 410, 234, 234, 334, 334, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 732, 544, 544, 910, 667, 760, 760, 776, 595, 694, 626, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 894, 838, 1016, 458, 748, 924, 748, 918, 927, 928, 928, 834, 873, 828, 924, 924, 917, 930, 931, 463, 883, 836, 836, 867, 867, 696, 696, 874, 0, 874, 760, 946, 771, 865, 771, 888, 967, 888, 831, 873, 927, 970, 918, 0]
56 }
57
58 def initialize(orientation='P', unit='mm', format='A4')
59 # Initialization of properties
60 @page=0
61 @n=2
62 @buffer=''
63 @pages=[]
64 @OrientationChanges=[]
65 @state=0
66 @fonts={}
67 @FontFiles={}
68 @diffs=[]
69 @images={}
70 @links=[]
71 @PageLinks={}
72 @InFooter=false
73 @FontFamily=''
74 @FontStyle=''
75 @FontSizePt=12
76 @underline= false
77 @DrawColor='0 G'
78 @FillColor='0 g'
79 @TextColor='0 g'
80 @ColorFlag=false
81 @ws=0
82 @offsets=[]
83
84 # Standard fonts
85 @CoreFonts={}
86 @CoreFonts['courier']='Courier'
87 @CoreFonts['courierB']='Courier-Bold'
88 @CoreFonts['courierI']='Courier-Oblique'
89 @CoreFonts['courierBI']='Courier-BoldOblique'
90 @CoreFonts['helvetica']='Helvetica'
91 @CoreFonts['helveticaB']='Helvetica-Bold'
92 @CoreFonts['helveticaI']='Helvetica-Oblique'
93 @CoreFonts['helveticaBI']='Helvetica-BoldOblique'
94 @CoreFonts['times']='Times-Roman'
95 @CoreFonts['timesB']='Times-Bold'
96 @CoreFonts['timesI']='Times-Italic'
97 @CoreFonts['timesBI']='Times-BoldItalic'
98 @CoreFonts['symbol']='Symbol'
99 @CoreFonts['zapfdingbats']='ZapfDingbats'
100
101 # Scale factor
102 if unit=='pt'
103 @k=1
104 elsif unit=='mm'
105 @k=72/25.4
106 elsif unit=='cm'
107 @k=72/2.54;
108 elsif unit=='in'
109 @k=72
110 else
111 raise 'Incorrect unit: '+unit
112 end
113
114 # Page format
115 if format.is_a? String
116 format.downcase!
117 if format=='a3'
118 format=[841.89,1190.55]
119 elsif format=='a4'
120 format=[595.28,841.89]
121 elsif format=='a5'
122 format=[420.94,595.28]
123 elsif format=='letter'
124 format=[612,792]
125 elsif format=='legal'
126 format=[612,1008]
127 else
128 raise 'Unknown page format: '+format
129 end
130 @fwPt,@fhPt=format
131 else
132 @fwPt=format[0]*@k
133 @fhPt=format[1]*@k
134 end
135 @fw=@fwPt/@k;
136 @fh=@fhPt/@k;
137
138 # Page orientation
139 orientation.downcase!
140 if orientation=='p' or orientation=='portrait'
141 @DefOrientation='P'
142 @wPt=@fwPt
143 @hPt=@fhPt
144 elsif orientation=='l' or orientation=='landscape'
145 @DefOrientation='L'
146 @wPt=@fhPt
147 @hPt=@fwPt
148 else
149 raise 'Incorrect orientation: '+orientation
150 end
151 @CurOrientation=@DefOrientation
152 @w=@wPt/@k
153 @h=@hPt/@k
154
155 # Page margins (1 cm)
156 margin=28.35/@k
157 SetMargins(margin,margin)
158 # Interior cell margin (1 mm)
159 @cMargin=margin/10
160 # Line width (0.2 mm)
161 @LineWidth=0.567/@k
162 # Automatic page break
163 SetAutoPageBreak(true,2*margin)
164 # Full width display mode
165 SetDisplayMode('fullwidth')
166 # Enable compression
167 SetCompression(true)
168 # Set default PDF version number
169 @PDFVersion='1.3'
170 end
171
172 def SetMargins(left, top, right=-1)
173 # Set left, top and right margins
174 @lMargin=left
175 @tMargin=top
176 right=left if right==-1
177 @rMargin=right
178 end
179
180 def SetLeftMargin(margin)
181 # Set left margin
182 @lMargin=margin
183 @x=margin if @page>0 and @x<margin
184 end
185
186 def SetTopMargin(margin)
187 # Set top margin
188 @tMargin=margin
189 end
190
191 def SetRightMargin(margin)
192 #Set right margin
193 @rMargin=margin
194 end
195
196 def SetAutoPageBreak(auto, margin=0)
197 # Set auto page break mode and triggering margin
198 @AutoPageBreak=auto
199 @bMargin=margin
200 @PageBreakTrigger=@h-margin
201 end
202
203 def SetDisplayMode(zoom, layout='continuous')
204 # Set display mode in viewer
205 if zoom=='fullpage' or zoom=='fullwidth' or zoom=='real' or
206 zoom=='default' or not zoom.kind_of? String
207
208 @ZoomMode=zoom;
209 elsif zoom=='zoom'
210 @ZoomMode=layout
211 else
212 raise 'Incorrect zoom display mode: '+zoom
213 end
214 if layout=='single' or layout=='continuous' or layout=='two' or
215 layout=='default'
216
217 @LayoutMode=layout
218 elsif zoom!='zoom'
219 raise 'Incorrect layout display mode: '+layout
220 end
221 end
222
223 def SetCompression(compress)
224 # Set page compression
225 @compress = compress
226 end
227
228 def SetTitle(title)
229 # Title of document
230 @title=title
231 end
232
233 def SetSubject(subject)
234 # Subject of document
235 @subject=subject
236 end
237
238 def SetAuthor(author)
239 # Author of document
240 @author=author
241 end
242
243 def SetKeywords(keywords)
244 # Keywords of document
245 @keywords=keywords
246 end
247
248 def SetCreator(creator)
249 # Creator of document
250 @creator=creator
251 end
252
253 def AliasNbPages(aliasnb='{nb}')
254 # Define an alias for total number of pages
255 @AliasNbPages=aliasnb
256 end
257
258 def Error(msg)
259 raise 'FPDF error: '+msg
260 end
261
262 def Open
263 # Begin document
264 @state=1
265 end
266
267 def Close
268 # Terminate document
269 return if @state==3
270 self.AddPage if @page==0
271 # Page footer
272 @InFooter=true
273 self.Footer
274 @InFooter=false
275 # Close page
276 endpage
277 # Close document
278 enddoc
279 end
280
281 def AddPage(orientation='')
282 # Start a new page
283 self.Open if @state==0
284 family=@FontFamily
285 style=@FontStyle+(@underline ? 'U' : '')
286 size=@FontSizePt
287 lw=@LineWidth
288 dc=@DrawColor
289 fc=@FillColor
290 tc=@TextColor
291 cf=@ColorFlag
292 if @page>0
293 # Page footer
294 @InFooter=true
295 self.Footer
296 @InFooter=false
297 # Close page
298 endpage
299 end
300 # Start new page
301 beginpage(orientation)
302 # Set line cap style to square
303 out('2 J')
304 # Set line width
305 @LineWidth=lw
306 out(sprintf('%.2f w',lw*@k))
307 # Set font
308 SetFont(family,style,size) if family
309 # Set colors
310 @DrawColor=dc
311 out(dc) if dc!='0 G'
312 @FillColor=fc
313 out(fc) if fc!='0 g'
314 @TextColor=tc
315 @ColorFlag=cf
316 # Page header
317 self.Header
318 # Restore line width
319 if @LineWidth!=lw
320 @LineWidth=lw
321 out(sprintf('%.2f w',lw*@k))
322 end
323 # Restore font
324 self.SetFont(family,style,size) if family
325 # Restore colors
326 if @DrawColor!=dc
327 @DrawColor=dc
328 out(dc)
329 end
330 if @FillColor!=fc
331 @FillColor=fc
332 out(fc)
333 end
334 @TextColor=tc
335 @ColorFlag=cf
336 end
337
338 def Header
339 # To be implemented in your inherited class
340 end
341
342 def Footer
343 # To be implemented in your inherited class
344 end
345
346 def PageNo
347 # Get current page number
348 @page
349 end
350
351 def SetDrawColor(r,g=-1,b=-1)
352 # Set color for all stroking operations
353 if (r==0 and g==0 and b==0) or g==-1
354 @DrawColor=sprintf('%.3f G',r/255.0)
355 else
356 @DrawColor=sprintf('%.3f %.3f %.3f RG',r/255.0,g/255.0,b/255.0)
357 end
358 out(@DrawColor) if(@page>0)
359 end
360
361 def SetFillColor(r,g=-1,b=-1)
362 # Set color for all filling operations
363 if (r==0 and g==0 and b==0) or g==-1
364 @FillColor=sprintf('%.3f g',r/255.0)
365 else
366 @FillColor=sprintf('%.3f %.3f %.3f rg',r/255.0,g/255.0,b/255.0)
367 end
368 @ColorFlag=(@FillColor!=@TextColor)
369 out(@FillColor) if(@page>0)
370 end
371
372 def SetTextColor(r,g=-1,b=-1)
373 # Set color for text
374 if (r==0 and g==0 and b==0) or g==-1
375 @TextColor=sprintf('%.3f g',r/255.0)
376 else
377 @TextColor=sprintf('%.3f %.3f %.3f rg',r/255.0,g/255.0,b/255.0)
378 end
379 @ColorFlag=(@FillColor!=@TextColor)
380 end
381
382 def GetStringWidth(s)
383 # Get width of a string in the current font
384 cw=@CurrentFont['cw']
385 w=0
386 s.each_byte do |c|
387 w=w+cw[c]
388 end
389 w*@FontSize/1000.0
390 end
391
392 def SetLineWidth(width)
393 # Set line width
394 @LineWidth=width
395 out(sprintf('%.2f w',width*@k)) if @page>0
396 end
397
398 def Line(x1, y1, x2, y2)
399 # Draw a line
400 out(sprintf('%.2f %.2f m %.2f %.2f l S',
401 x1*@k,(@h-y1)*@k,x2*@k,(@h-y2)*@k))
402 end
403
404 def Rect(x, y, w, h, style='')
405 # Draw a rectangle
406 if style=='F'
407 op='f'
408 elsif style=='FD' or style=='DF'
409 op='B'
410 else
411 op='S'
412 end
413 out(sprintf('%.2f %.2f %.2f %.2f re %s', x*@k,(@h-y)*@k,w*@k,-h*@k,op))
414 end
415
416 def AddFont(family, style='', file='')
417 # Add a TrueType or Type1 font
418 family = family.downcase
419 family = 'helvetica' if family == 'arial'
420
421 style = style.upcase
422 style = 'BI' if style == 'IB'
423
424 fontkey = family + style
425
426 if @fonts.has_key?(fontkey)
427 self.Error("Font already added: #{family} #{style}")
428 end
429
430 file = family.gsub(' ', '') + style.downcase + '.rb' if file == ''
431
432 if self.class.const_defined? 'FPDF_FONTPATH'
433 if FPDF_FONTPATH[-1,1] == '/'
434 file = FPDF_FONTPATH + file
435 else
436 file = FPDF_FONTPATH + '/' + file
437 end
438 end
439
440 # Changed from "require file" to fix bug reported by Hans Allis.
441 load file
442
443 if FontDef.desc.nil?
444 self.Error("Could not include font definition file #{file}")
445 end
446
447 i = @fonts.length + 1
448
449 @fonts[fontkey] = {'i' => i,
450 'type' => FontDef.type,
451 'name' => FontDef.name,
452 'desc' => FontDef.desc,
453 'up' => FontDef.up,
454 'ut' => FontDef.ut,
455 'cw' => FontDef.cw,
456 'enc' => FontDef.enc,
457 'file' => FontDef.file
458 }
459
460 if FontDef.diff
461 # Search existing encodings
462 unless @diffs.include?(FontDef.diff)
463 @diffs.push(FontDef.diff)
464 @fonts[fontkey]['diff'] = @diffs.length - 1
465 end
466 end
467
468 if FontDef.file
469 if FontDef.type == 'TrueType'
470 @FontFiles[FontDef.file] = {'length1' => FontDef.originalsize}
471 else
472 @FontFiles[FontDef.file] = {'length1' => FontDef.size1, 'length2' => FontDef.size2}
473 end
474 end
475
476 return self
477 end
478
479 def SetFont(family, style='', size=0)
480 # Select a font; size given in points
481 family.downcase!
482 family=@FontFamily if family==''
483 if family=='arial'
484 family='helvetica'
485 elsif family=='symbol' or family=='zapfdingbats'
486 style=''
487 end
488 style.upcase!
489 unless style.index('U').nil?
490 @underline=true
491 style.gsub!('U','')
492 else
493 @underline=false;
494 end
495 style='BI' if style=='IB'
496 size=@FontSizePt if size==0
497 # Test if font is already selected
498 return if @FontFamily==family and
499 @FontStyle==style and @FontSizePt==size
500 # Test if used for the first time
501 fontkey=family+style
502 unless @fonts.has_key?(fontkey)
503 if @CoreFonts.has_key?(fontkey)
504 unless Charwidths.has_key?(fontkey)
505 raise 'Font unavailable'
506 end
507 @fonts[fontkey]={
508 'i'=>@fonts.size,
509 'type'=>'core',
510 'name'=>@CoreFonts[fontkey],
511 'up'=>-100,
512 'ut'=>50,
513 'cw'=>Charwidths[fontkey]}
514 else
515 raise 'Font unavailable'
516 end
517 end
518
519 #Select it
520 @FontFamily=family
521 @FontStyle=style;
522 @FontSizePt=size
523 @FontSize=size/@k;
524 @CurrentFont=@fonts[fontkey]
525 if @page>0
526 out(sprintf('BT /F%d %.2f Tf ET', @CurrentFont['i'], @FontSizePt))
527 end
528 end
529
530 def SetFontSize(size)
531 # Set font size in points
532 return if @FontSizePt==size
533 @FontSizePt=size
534 @FontSize=size/@k
535 if @page>0
536 out(sprintf('BT /F%d %.2f Tf ET',@CurrentFont['i'],@FontSizePt))
537 end
538 end
539
540 def AddLink
541 # Create a new internal link
542 @links.push([0, 0])
543 @links.size
544 end
545
546 def SetLink(link, y=0, page=-1)
547 # Set destination of internal link
548 y=@y if y==-1
549 page=@page if page==-1
550 @links[link]=[page, y]
551 end
552
553 def Link(x, y, w, h, link)
554 # Put a link on the page
555 @PageLinks[@page]=Array.new unless @PageLinks.has_key?(@Page)
556 @PageLinks[@page].push([x*@k,@hPt-y*@k,w*@k,h*@k,link])
557 end
558
559 def Text(x, y, txt)
560 # Output a string
561 txt.gsub!(')', '\\)')
562 txt.gsub!('(', '\\(')
563 txt.gsub!('\\', '\\\\')
564 s=sprintf('BT %.2f %.2f Td (%s) Tj ET',x*@k,(@h-y)*@k,txt);
565 s=s+' '+dounderline(x,y,txt) if @underline and txt!=''
566 s='q '+@TextColor+' '+s+' Q' if @ColorFlag
567 out(s)
568 end
569
570 def AcceptPageBreak
571 # Accept automatic page break or not
572 @AutoPageBreak
573 end
574
575 def Cell(w,h=0,txt='',border=0,ln=0,align='',fill=0,link='')
576 # Output a cell
577 if @y+h>@PageBreakTrigger and !@InFooter and self.AcceptPageBreak
578 # Automatic page break
579 x=@x
580 ws=@ws
581 if ws>0
582 @ws=0
583 out('0 Tw')
584 end
585 self.AddPage(@CurOrientation)
586 @x=x
587 if ws>0
588 @ws=ws
589 out(sprintf('%.3f Tw',ws*@k))
590 end
591 end
592 w=@w-@rMargin-@x if w==0
593 s=''
594 if fill==1 or border==1
595 if fill==1
596 op=(border==1) ? 'B' : 'f'
597 else
598 op='S'
599 end
600 s=sprintf('%.2f %.2f %.2f %.2f re %s ',@x*@k,(@h-@y)*@k,w*@k,-h*@k,op)
601 end
602 if border.is_a? String
603 x=@x
604 y=@y
605 unless border.index('L').nil?
606 s=s+sprintf('%.2f %.2f m %.2f %.2f l S ',
607 x*@k,(@h-y)*@k,x*@k,(@h-(y+h))*@k)
608 end
609 unless border.index('T').nil?
610 s=s+sprintf('%.2f %.2f m %.2f %.2f l S ',
611 x*@k,(@h-y)*@k,(x+w)*@k,(@h-y)*@k)
612 end
613 unless border.index('R').nil?
614 s=s+sprintf('%.2f %.2f m %.2f %.2f l S ',
615 (x+w)*@k,(@h-y)*@k,(x+w)*@k,(@h-(y+h))*@k)
616 end
617 unless border.index('B').nil?
618 s=s+sprintf('%.2f %.2f m %.2f %.2f l S ',
619 x*@k,(@h-(y+h))*@k,(x+w)*@k,(@h-(y+h))*@k)
620 end
621 end
622 if txt!=''
623 if align=='R'
624 dx=w-@cMargin-self.GetStringWidth(txt)
625 elsif align=='C'
626 dx=(w-self.GetStringWidth(txt))/2
627 else
628 dx=@cMargin
629 end
630 txt = txt.gsub(')', '\\)')
631 txt.gsub!('(', '\\(')
632 txt.gsub!('\\', '\\\\')
633 if @ColorFlag
634 s=s+'q '+@TextColor+' '
635 end
636 s=s+sprintf('BT %.2f %.2f Td (%s) Tj ET',
637 (@x+dx)*@k,(@h-(@y+0.5*h+0.3*@FontSize))*@k,txt)
638 s=s+' '+dounderline(@x+dx,@y+0.5*h+0.3*@FontSize,txt) if @underline
639 s=s+' Q' if @ColorFlag
640 if link and link != ''
641 Link(@x+dx,@y+0.5*h-0.5*@FontSize,GetStringWidth(txt),@FontSize,link)
642 end
643 end
644 out(s) if s
645 @lasth=h
646 if ln>0
647 # Go to next line
648 @y=@y+h
649 @x=@lMargin if ln==1
650 else
651 @x=@x+w
652 end
653 end
654
655 def MultiCell(w,h,txt,border=0,align='J',fill=0)
656 # Output text with automatic or explicit line breaks
657 cw=@CurrentFont['cw']
658 w=@w-@rMargin-@x if w==0
659 wmax=(w-2*@cMargin)*1000/@FontSize
660 s=txt.gsub('\r','')
661 nb=s.length
662 nb=nb-1 if nb>0 and s[nb-1].chr=='\n'
663 b=0
664 if border!=0
665 if border==1
666 border='LTRB'
667 b='LRT'
668 b2='LR'
669 else
670 b2=''
671 b2='L' unless border.index('L').nil?
672 b2=b2+'R' unless border.index('R').nil?
673 b=(not border.index('T').nil?) ? (b2+'T') : b2
674 end
675 end
676 sep=-1
677 i=0
678 j=0
679 l=0
680 ns=0
681 nl=1
682 while i<nb
683 # Get next character
684 c=s[i].chr
685 if c=="\n"
686 # Explicit line break
687 if @ws>0
688 @ws=0
689 out('0 Tw')
690 end
691 #Ed Moss
692 # Don't let i go negative
693 end_i = i == 0 ? 0 : i - 1
694 # Changed from s[j..i] to fix bug reported by Hans Allis.
695 self.Cell(w,h,s[j..end_i],b,2,align,fill)
696 #
697 i=i+1
698 sep=-1
699 j=i
700 l=0
701 ns=0
702 nl=nl+1
703 b=b2 if border and nl==2
704 else
705 if c==' '
706 sep=i
707 ls=l
708 ns=ns+1
709 end
710 l=l+cw[c[0]]
711 if l>wmax
712 # Automatic line break
713 if sep==-1
714 i=i+1 if i==j
715 if @ws>0
716 @ws=0
717 out('0 Tw')
718 end
719 self.Cell(w,h,s[j..i],b,2,align,fill)
720 #Ed Moss
721 # Added so that it wouldn't print the last character of the string if it got close
722 #FIXME 2006-07-18 Level=0 - but it still puts out an extra new line
723 i += 1
724 #
725 else
726 if align=='J'
727 @ws=(ns>1) ? (wmax-ls)/1000.0*@FontSize/(ns-1) : 0
728 out(sprintf('%.3f Tw',@ws*@k))
729 end
730 self.Cell(w,h,s[j..sep],b,2,align,fill)
731 i=sep+1
732 end
733 sep=-1
734 j=i
735 l=0
736 ns=0
737 nl=nl+1
738 b=b2 if border and nl==2
739 else
740 i=i+1
741 end
742 end
743 end
744
745 # Last chunk
746 if @ws>0
747 @ws=0
748 out('0 Tw')
749 end
750 b=b+'B' if border!=0 and not border.index('B').nil?
751 self.Cell(w,h,s[j..i],b,2,align,fill)
752 @x=@lMargin
753 end
754
755 def Write(h,txt,link='')
756 # Output text in flowing mode
757 cw=@CurrentFont['cw']
758 w=@w-@rMargin-@x
759 wmax=(w-2*@cMargin)*1000/@FontSize
760 s=txt.gsub("\r",'')
761 nb=s.length
762 sep=-1
763 i=0
764 j=0
765 l=0
766 nl=1
767 while i<nb
768 # Get next character
769 c=s[i]
770 if c=="\n"[0]
771 # Explicit line break
772 self.Cell(w,h,s[j,i-j],0,2,'',0,link)
773 i=i+1
774 sep=-1
775 j=i
776 l=0
777 if nl==1
778 @x=@lMargin
779 w=@w-@rMargin-@x
780 wmax=(w-2*@cMargin)*1000/@FontSize
781 end
782 nl=nl+1
783 next
784 end
785 if c==' '[0]
786 sep=i
787 ls=l
788 end
789 l=l+cw[c];
790 if l>wmax
791 # Automatic line break
792 if sep==-1
793 if @x>@lMargin
794 # Move to next line
795 @x=@lMargin
796 @y=@y+h
797 w=@w-@rMargin-@x
798 wmax=(w-2*@cMargin)*1000/@FontSize
799 i=i+1
800 nl=nl+1
801 next
802 end
803 i=i+1 if i==j
804 self.Cell(w,h,s[j,i-j],0,2,'',0,link)
805 else
806 self.Cell(w,h,s[j,sep-j],0,2,'',0,link)
807 i=sep+1
808 end
809 sep=-1
810 j=i
811 l=0
812 if nl==1
813 @x=@lMargin
814 w=@w-@rMargin-@x
815 wmax=(w-2*@cMargin)*1000/@FontSize
816 end
817 nl=nl+1
818 else
819 i=i+1
820 end
821 end
822 # Last chunk
823 self.Cell(l/1000.0*@FontSize,h,s[j,i],0,0,'',0,link) if i!=j
824 end
825
826 def Image(file,x,y,w=0,h=0,type='',link='')
827 # Put an image on the page
828 unless @images.has_key?(file)
829 # First use of image, get info
830 if type==''
831 pos=file.rindex('.')
832 if pos.nil?
833 self.Error('Image file has no extension and no type was '+
834 'specified: '+file)
835 end
836 type=file[pos+1..-1]
837 end
838 type.downcase!
839 if type=='jpg' or type=='jpeg'
840 info=parsejpg(file)
841 elsif type=='png'
842 info=parsepng(file)
843 else
844 self.Error('Unsupported image file type: '+type)
845 end
846 info['i']=@images.length+1
847 @images[file]=info
848 else
849 info=@images[file]
850 end
851 #Ed Moss
852 if(w==0 && h==0)
853 #Put image at 72 dpi
854 w=info['w']/@k;
855 h=info['h']/@k;
856 end
857 #
858 # Automatic width or height calculation
859 w=h*info['w']/info['h'] if w==0
860 h=w*info['h']/info['w'] if h==0
861 out(sprintf('q %.2f 0 0 %.2f %.2f %.2f cm /I%d Do Q',
862 w*@k,h*@k,x*@k,(@h-(y+h))*@k,info['i']))
863 Link(x,y,w,h,link) if link and link != ''
864 end
865
866 def Ln(h='')
867 # Line feed; default value is last cell height
868 @x=@lMargin
869 if h.kind_of?(String)
870 @y=@y+@lasth
871 else
872 @y=@y+h
873 end
874 end
875
876 def GetX
877 # Get x position
878 @x
879 end
880
881 def SetX(x)
882 # Set x position
883 if x>=0
884 @x=x
885 else
886 @x=@w+x
887 end
888 end
889
890 def GetY
891 # Get y position
892 @y
893 end
894
895 def SetY(y)
896 # Set y position and reset x
897 @x=@lMargin
898 if y>=0
899 @y=y
900 else
901 @y=@h+y
902 end
903 end
904
905 def SetXY(x,y)
906 # Set x and y positions
907 SetY(y)
908 SetX(x)
909 end
910
911 def Output(file=nil)
912 # Output PDF to file or return as a string
913
914 # Finish document if necessary
915 self.Close if(@state<3)
916
917 if file.nil?
918 # Return as a string
919 return @buffer
920 else
921 # Save file locally
922 open(file,'wb') do |f|
923 f.write(@buffer)
924 end
925 end
926 end
927
928 private
929
930 def putpages
931 nb=@page
932 unless @AliasNbPages.nil? or @AliasNbPages==''
933 # Replace number of pages
934 1.upto(nb) do |n|
935 @pages[n].gsub!(@AliasNbPages,nb.to_s)
936 end
937 end
938 if @DefOrientation=='P'
939 wPt=@fwPt
940 hPt=@fhPt
941 else
942 wPt=@fhPt
943 hPt=@fwPt
944 end
945 filter=(@compress) ? '/Filter /FlateDecode ' : ''
946 1.upto(nb) do |n|
947 # Page
948 newobj
949 out('<</Type /Page')
950 out('/Parent 1 0 R')
951 unless @OrientationChanges[n].nil?
952 out(sprintf('/MediaBox [0 0 %.2f %.2f]',hPt,wPt))
953 end
954 out('/Resources 2 0 R')
955 if @PageLinks[n]
956 # Links
957 annots='/Annots ['
958 @PageLinks[n].each do |pl|
959 rect=sprintf('%.2f %.2f %.2f %.2f',
960 pl[0],pl[1],pl[0]+pl[2],pl[1]-pl[3])
961 annots=annots+'<</Type /Annot /Subtype /Link /Rect ['+rect+
962 '] /Border [0 0 0] '
963 if pl[4].kind_of?(String)
964 annots=annots+'/A <</S /URI /URI '+textstring(pl[4])+
965 '>>>>'
966 else
967 l=@links[pl[4]]
968 h=@OrientationChanges[l[0]].nil? ? hPt : wPt
969 annots=annots+sprintf(
970 '/Dest [%d 0 R /XYZ 0 %.2f null]>>',
971 1+2*l[0],h-l[1]*@k)
972 end
973 end
974 out(annots+']')
975 end
976 out('/Contents '+(@n+1).to_s+' 0 R>>')
977 out('endobj')
978 # Page content
979 p=(@compress) ? Zlib::Deflate.deflate(@pages[n]) : @pages[n]
980 newobj
981 out('<<'+filter+'/Length '+p.length.to_s+'>>')
982 putstream(p)
983 out('endobj')
984 end
985 # Pages root
986 @offsets[1]=@buffer.length
987 out('1 0 obj')
988 out('<</Type /Pages')
989 kids='/Kids ['
990 nb.times do |i|
991 kids=kids+(3+2*i).to_s+' 0 R '
992 end
993 out(kids+']')
994 out('/Count '+nb.to_s)
995 out(sprintf('/MediaBox [0 0 %.2f %.2f]',wPt,hPt))
996 out('>>')
997 out('endobj')
998 end
999
1000 def putfonts
1001 nf=@n
1002 @diffs.each do |diff|
1003 # Encodings
1004 newobj
1005 out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences '+
1006 '['+diff+']>>')
1007 out('endobj')
1008 end
1009
1010 @FontFiles.each do |file, info|
1011 # Font file embedding
1012 newobj
1013 @FontFiles[file]['n'] = @n
1014
1015 if self.class.const_defined? 'FPDF_FONTPATH' then
1016 if FPDF_FONTPATH[-1,1] == '/' then
1017 file = FPDF_FONTPATH + file
1018 else
1019 file = FPDF_FONTPATH + '/' + file
1020 end
1021 end
1022
1023 size = File.size(file)
1024 unless File.exists?(file)
1025 Error('Font file not found')
1026 end
1027
1028 out('<</Length ' + size.to_s)
1029
1030 if file[-2, 2] == '.z' then
1031 out('/Filter /FlateDecode')
1032 end
1033 out('/Length1 ' + info['length1'])
1034 out('/Length2 ' + info['length2'] + ' /Length3 0') if info['length2']
1035 out('>>')
1036 open(file, 'rb') do |f|
1037 putstream(f.read())
1038 end
1039 out('endobj')
1040 end
1041
1042 file = 0
1043 @fonts.each do |k, font|
1044 # Font objects
1045 @fonts[k]['n']=@n+1
1046 type=font['type']
1047 name=font['name']
1048 if type=='core'
1049 # Standard font
1050 newobj
1051 out('<</Type /Font')
1052 out('/BaseFont /'+name)
1053 out('/Subtype /Type1')
1054 if name!='Symbol' and name!='ZapfDingbats'
1055 out('/Encoding /WinAnsiEncoding')
1056 end
1057 out('>>')
1058 out('endobj')
1059 elsif type=='Type1' or type=='TrueType'
1060 # Additional Type1 or TrueType font
1061 newobj
1062 out('<</Type /Font')
1063 out('/BaseFont /'+name)
1064 out('/Subtype /'+type)
1065 out('/FirstChar 32 /LastChar 255')
1066 out('/Widths '+(@n+1).to_s+' 0 R')
1067 out('/FontDescriptor '+(@n+2).to_s+' 0 R')
1068 if font['enc'] and font['enc'] != ''
1069 unless font['diff'].nil?
1070 out('/Encoding '+(nf+font['diff']).to_s+' 0 R')
1071 else
1072 out('/Encoding /WinAnsiEncoding')
1073 end
1074 end
1075 out('>>')
1076 out('endobj')
1077 # Widths
1078 newobj
1079 cw=font['cw']
1080 s='['
1081 32.upto(255) do |i|
1082 s << cw[i].to_s+' '
1083 end
1084 out(s+']')
1085 out('endobj')
1086 # Descriptor
1087 newobj
1088 s='<</Type /FontDescriptor /FontName /'+name
1089 font['desc'].each do |k, v|
1090 s << ' /'+k+' '+v
1091 end
1092 file=font['file']
1093 if file
1094 s << ' /FontFile'+(type=='Type1' ? '' : '2')+' '+
1095 @FontFiles[file]['n'].to_s+' 0 R'
1096 end
1097 out(s+'>>')
1098 out('endobj')
1099 else
1100 # Allow for additional types
1101 mtd='put'+type.downcase
1102 unless self.respond_to?(mtd)
1103 self.Error('Unsupported font type: '+type)
1104 end
1105 self.send(mtd, font)
1106 end
1107 end
1108 end
1109
1110 def putimages
1111 filter=(@compress) ? '/Filter /FlateDecode ' : ''
1112 @images.each do |file, info|
1113 newobj
1114 @images[file]['n']=@n
1115 out('<</Type /XObject')
1116 out('/Subtype /Image')
1117 out('/Width '+info['w'].to_s)
1118 out('/Height '+info['h'].to_s)
1119 if info['cs']=='Indexed'
1120 out("/ColorSpace [/Indexed /DeviceRGB #{info['pal'].length/3-1} #{(@n+1)} 0 R]")
1121 else
1122 out('/ColorSpace /'+info['cs'])
1123 if info['cs']=='DeviceCMYK'
1124 out('/Decode [1 0 1 0 1 0 1 0]')
1125 end
1126 end
1127 out('/BitsPerComponent '+info['bpc'].to_s)
1128 out('/Filter /'+info['f']) if info['f']
1129 unless info['parms'].nil?
1130 out(info['parms'])
1131 end
1132 if info['trns'] and info['trns'].kind_of?(Array)
1133 trns=''
1134 info['trns'].length.times do |i|
1135 trns=trns+info['trns'][i].to_s+' '+info['trns'][i].to_s+' '
1136 end
1137 out('/Mask ['+trns+']')
1138 end
1139 out('/Length '+info['data'].length.to_s+'>>')
1140 putstream(info['data'])
1141 @images[file]['data']=nil
1142 out('endobj')
1143 # Palette
1144 if info['cs']=='Indexed'
1145 newobj
1146 pal=(@compress) ? Zlib::Deflate.deflate(info['pal']) : info['pal']
1147 out('<<'+filter+'/Length '+pal.length.to_s+'>>')
1148 putstream(pal)
1149 out('endobj')
1150 end
1151 end
1152 end
1153
1154 def putxobjectdict
1155 @images.each_value do |image|
1156 out('/I'+image['i'].to_s+' '+image['n'].to_s+' 0 R')
1157 end
1158 end
1159
1160 def putresourcedict
1161 out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]')
1162 out('/Font <<')
1163 @fonts.each_value do |font|
1164 out('/F'+font['i'].to_s+' '+font['n'].to_s+' 0 R')
1165 end
1166 out('>>')
1167 out('/XObject <<')
1168 putxobjectdict
1169 out('>>')
1170 end
1171
1172 def putresources
1173 putfonts
1174 putimages
1175 # Resource dictionary
1176 @offsets[2]=@buffer.length
1177 out('2 0 obj')
1178 out('<<')
1179 putresourcedict
1180 out('>>')
1181 out('endobj')
1182 end
1183
1184 def putinfo
1185 out('/Producer '+textstring('Ruby FPDF '+FPDF_VERSION));
1186 unless @title.nil?
1187 out('/Title '+textstring(@title))
1188 end
1189 unless @subject.nil?
1190 out('/Subject '+textstring(@subject))
1191 end
1192 unless @author.nil?
1193 out('/Author '+textstring(@author))
1194 end
1195 unless @keywords.nil?
1196 out('/Keywords '+textstring(@keywords))
1197 end
1198 unless @creator.nil?
1199 out('/Creator '+textstring(@creator))
1200 end
1201 out('/CreationDate '+textstring('D: '+DateTime.now.to_s))
1202 end
1203
1204 def putcatalog
1205 out('/Type /Catalog')
1206 out('/Pages 1 0 R')
1207 if @ZoomMode=='fullpage'
1208 out('/OpenAction [3 0 R /Fit]')
1209 elsif @ZoomMode=='fullwidth'
1210 out('/OpenAction [3 0 R /FitH null]')
1211 elsif @ZoomMode=='real'
1212 out('/OpenAction [3 0 R /XYZ null null 1]')
1213 elsif not @ZoomMode.kind_of?(String)
1214 out('/OpenAction [3 0 R /XYZ null null '+(@ZoomMode/100)+']')
1215 end
1216
1217 if @LayoutMode=='single'
1218 out('/PageLayout /SinglePage')
1219 elsif @LayoutMode=='continuous'
1220 out('/PageLayout /OneColumn')
1221 elsif @LayoutMode=='two'
1222 out('/PageLayout /TwoColumnLeft')
1223 end
1224 end
1225
1226 def putheader
1227 out('%PDF-'+@PDFVersion)
1228 end
1229
1230 def puttrailer
1231 out('/Size '+(@n+1).to_s)
1232 out('/Root '+@n.to_s+' 0 R')
1233 out('/Info '+(@n-1).to_s+' 0 R')
1234 end
1235
1236 def enddoc
1237 putheader
1238 putpages
1239 putresources
1240 # Info
1241 newobj
1242 out('<<')
1243 putinfo
1244 out('>>')
1245 out('endobj')
1246 # Catalog
1247 newobj
1248 out('<<')
1249 putcatalog
1250 out('>>')
1251 out('endobj')
1252 # Cross-ref
1253 o=@buffer.length
1254 out('xref')
1255 out('0 '+(@n+1).to_s)
1256 out('0000000000 65535 f ')
1257 1.upto(@n) do |i|
1258 out(sprintf('%010d 00000 n ',@offsets[i]))
1259 end
1260 # Trailer
1261 out('trailer')
1262 out('<<')
1263 puttrailer
1264 out('>>')
1265 out('startxref')
1266 out(o)
1267 out('%%EOF')
1268 state=3
1269 end
1270
1271 def beginpage(orientation)
1272 @page=@page+1
1273 @pages[@page]=''
1274 @state=2
1275 @x=@lMargin
1276 @y=@tMargin
1277 @lasth=0
1278 @FontFamily=''
1279 # Page orientation
1280 if orientation==''
1281 orientation=@DefOrientation
1282 else
1283 orientation=orientation[0].chr.upcase
1284 if orientation!=@DefOrientation
1285 @OrientationChanges[@page]=true
1286 end
1287 end
1288 if orientation!=@CurOrientation
1289 # Change orientation
1290 if orientation=='P'
1291 @wPt=@fwPt
1292 @hPt=@fhPt
1293 @w=@fw
1294 @h=@fh
1295 else
1296 @wPt=@fhPt
1297 @hPt=@fwPt
1298 @w=@fh
1299 @h=@fw
1300 end
1301 @PageBreakTrigger=@h-@bMargin
1302 @CurOrientation=orientation
1303 end
1304 end
1305
1306 def endpage
1307 # End of page contents
1308 @state=1
1309 end
1310
1311 def newobj
1312 # Begin a new object
1313 @n=@n+1
1314 @offsets[@n]=@buffer.length
1315 out(@n.to_s+' 0 obj')
1316 end
1317
1318 def dounderline(x,y,txt)
1319 # Underline text
1320 up=@CurrentFont['up']
1321 ut=@CurrentFont['ut']
1322 w=GetStringWidth(txt)+@ws*txt.count(' ')
1323 sprintf('%.2f %.2f %.2f %.2f re f',
1324 x*@k,(@h-(y-up/1000.0*@FontSize))*@k,w*@k,-ut/1000.0*@FontSizePt)
1325 end
1326
1327 def parsejpg(file)
1328 # Extract info from a JPEG file
1329 a=extractjpginfo(file)
1330 raise "Missing or incorrect JPEG file: #{file}" if a.nil?
1331
1332 if a['channels'].nil? || a['channels']==3 then
1333 colspace='DeviceRGB'
1334 elsif a['channels']==4 then
1335 colspace='DeviceCMYK'
1336 else
1337 colspace='DeviceGray'
1338 end
1339 bpc= a['bits'] ? a['bits'].to_i : 8
1340
1341 # Read whole file
1342 data = nil
1343 open(file, 'rb') do |f|
1344 data = f.read
1345 end
1346 return {'w'=>a['width'],'h'=>a['height'],'cs'=>colspace,'bpc'=>bpc,'f'=>'DCTDecode','data'=>data}
1347 end
1348
1349 def parsepng(file)
1350 # Extract info from a PNG file
1351 f=open(file,'rb')
1352 # Check signature
1353 unless f.read(8)==137.chr+'PNG'+13.chr+10.chr+26.chr+10.chr
1354 self.Error('Not a PNG file: '+file)
1355 end
1356 # Read header chunk
1357 f.read(4)
1358 if f.read(4)!='IHDR'
1359 self.Error('Incorrect PNG file: '+file)
1360 end
1361 w=freadint(f)
1362 h=freadint(f)
1363 bpc=f.read(1)[0]
1364 if bpc>8
1365 self.Error('16-bit depth not supported: '+file)
1366 end
1367 ct=f.read(1)[0]
1368 if ct==0
1369 colspace='DeviceGray'
1370 elsif ct==2
1371 colspace='DeviceRGB'
1372 elsif ct==3
1373 colspace='Indexed'
1374 else
1375 self.Error('Alpha channel not supported: '+file)
1376 end
1377 if f.read(1)[0]!=0
1378 self.Error('Unknown compression method: '+file)
1379 end
1380 if f.read(1)[0]!=0
1381 self.Error('Unknown filter method: '+file)
1382 end
1383 if f.read(1)[0]!=0
1384 self.Error('Interlacing not supported: '+file)
1385 end
1386 f.read(4)
1387 parms='/DecodeParms <</Predictor 15 /Colors '+(ct==2 ? '3' : '1')+
1388 ' /BitsPerComponent '+bpc.to_s+' /Columns '+w.to_s+'>>'
1389 # Scan chunks looking for palette, transparency and image data
1390 pal=''
1391 trns=''
1392 data=''
1393 begin
1394 n=freadint(f)
1395 type=f.read(4)
1396 if type=='PLTE'
1397 # Read palette
1398 pal=f.read(n)
1399 f.read(4)
1400 elsif type=='tRNS'
1401 # Read transparency info
1402 t=f.read(n)
1403 if ct==0
1404 trns=[t[1]]
1405 elsif ct==2
1406 trns=[t[1],t[3],t[5]]
1407 else
1408 pos=t.index(0)
1409 trns=[pos] unless pos.nil?
1410 end
1411 f.read(4)
1412 elsif type=='IDAT'
1413 # Read image data block
1414 data << f.read(n)
1415 f.read(4)
1416 elsif type=='IEND'
1417 break
1418 else
1419 f.read(n+4)
1420 end
1421 end while n
1422 if colspace=='Indexed' and pal==''
1423 self.Error('Missing palette in '+file)
1424 end
1425 f.close
1426 {'w'=>w,'h'=>h,'cs'=>colspace,'bpc'=>bpc,'f'=>'FlateDecode',
1427 'parms'=>parms,'pal'=>pal,'trns'=>trns,'data'=>data}
1428 end
1429
1430 def freadint(f)
1431 # Read a 4-byte integer from file
1432 a = f.read(4).unpack('N')
1433 return a[0]
1434 end
1435
1436 def freadshort(f)
1437 a = f.read(2).unpack('n')
1438 return a[0]
1439 end
1440
1441 def freadbyte(f)
1442 a = f.read(1).unpack('C')
1443 return a[0]
1444 end
1445
1446 def textstring(s)
1447 # Format a text string
1448 '('+escape(s)+')'
1449 end
1450
1451 def escape(s)
1452 # Add \ before \, ( and )
1453 s.gsub('\\','\\\\').gsub('(','\\(').gsub(')','\\)')
1454 end
1455
1456 def putstream(s)
1457 out('stream')
1458 out(s)
1459 out('endstream')
1460 end
1461
1462 def out(s)
1463 # Add a line to the document
1464 if @state==2
1465 @pages[@page]=@pages[@page]+s+"\n"
1466 else
1467 @buffer=@buffer+s.to_s+"\n"
1468 end
1469 end
1470
1471 # jpeg marker codes
1472
1473 M_SOF0 = 0xc0
1474 M_SOF1 = 0xc1
1475 M_SOF2 = 0xc2
1476 M_SOF3 = 0xc3
1477
1478 M_SOF5 = 0xc5
1479 M_SOF6 = 0xc6
1480 M_SOF7 = 0xc7
1481
1482 M_SOF9 = 0xc9
1483 M_SOF10 = 0xca
1484 M_SOF11 = 0xcb
1485
1486 M_SOF13 = 0xcd
1487 M_SOF14 = 0xce
1488 M_SOF15 = 0xcf
1489
1490 M_SOI = 0xd8
1491 M_EOI = 0xd9
1492 M_SOS = 0xda
1493
1494 def extractjpginfo(file)
1495 result = nil
1496
1497 open(file, "rb") do |f|
1498 marker = jpegnextmarker(f)
1499
1500 if marker != M_SOI
1501 return nil
1502 end
1503
1504 while true
1505 marker = jpegnextmarker(f)
1506
1507 case marker
1508 when M_SOF0, M_SOF1, M_SOF2, M_SOF3,
1509 M_SOF5, M_SOF6, M_SOF7, M_SOF9,
1510 M_SOF10, M_SOF11, M_SOF13, M_SOF14,
1511 M_SOF15 then
1512
1513 length = freadshort(f)
1514
1515 if result.nil?
1516 result = {}
1517
1518 result['bits'] = freadbyte(f)
1519 result['height'] = freadshort(f)
1520 result['width'] = freadshort(f)
1521 result['channels'] = freadbyte(f)
1522
1523 f.seek(length - 8, IO::SEEK_CUR)
1524 else
1525 f.seek(length - 2, IO::SEEK_CUR)
1526 end
1527 when M_SOS, M_EOI then
1528 return result
1529 else
1530 length = freadshort(f)
1531 f.seek(length - 2, IO::SEEK_CUR)
1532 end
1533 end
1534 end
1535 end
1536
1537 def jpegnextmarker(f)
1538 while true
1539 # look for 0xff
1540 while (c = freadbyte(f)) != 0xff
1541 end
1542
1543 c = freadbyte(f)
1544
1545 if c != 0
1546 return c
1547 end
1548 end
1549 end
1550 end
@@ -0,0 +1,139
1 # Information
2 #
3 # PDF_EPS class from Valentin Schmidt ported to ruby by Thiago Jackiw (tjackiw@gmail.com)
4 # working for Mingle LLC (www.mingle.com)
5 # Release Date: July 13th, 2006
6 #
7 # Description
8 #
9 # This script allows to embed vector-based Adobe Illustrator (AI) or AI-compatible EPS files.
10 # Only vector drawing is supported, not text or bitmap. Although the script was successfully
11 # tested with various AI format versions, best results are probably achieved with files that
12 # were exported in the AI3 format (tested with Illustrator CS2, Freehand MX and Photoshop CS2).
13 #
14 # ImageEps(string file, float x, float y [, float w [, float h [, string link [, boolean useBoundingBox]]]])
15 #
16 # Same parameters as for regular FPDF::Image() method, with an additional one:
17 #
18 # useBoundingBox: specifies whether to position the bounding box (true) or the complete canvas (false)
19 # at location (x,y). Default value is true.
20 #
21 # First added to the Ruby FPDF distribution in 1.53c
22 #
23 # Usage is as follows:
24 #
25 # require 'fpdf'
26 # require 'fpdf_eps'
27 # pdf = FPDF.new
28 # pdf.extend(PDF_EPS)
29 # pdf.ImageEps(...)
30 #
31 # This allows it to be combined with other extensions, such as the bookmark
32 # module.
33
34 module PDF_EPS
35 def ImageEps(file, x, y, w=0, h=0, link='', use_bounding_box=true)
36 data = nil
37 if File.exists?(file)
38 File.open(file, 'rb') do |f|
39 data = f.read()
40 end
41 else
42 Error('EPS file not found: '+file)
43 end
44
45 # Find BoundingBox param
46 regs = data.scan(/%%BoundingBox: [^\r\n]*/m)
47 regs << regs[0].gsub(/%%BoundingBox: /, '')
48 if regs.size > 1
49 tmp = regs[1].to_s.split(' ')
50 @x1 = tmp[0].to_i
51 @y1 = tmp[1].to_i
52 @x2 = tmp[2].to_i
53 @y2 = tmp[3].to_i
54 else
55 Error('No BoundingBox found in EPS file: '+file)
56 end
57 f_start = data.index('%%EndSetup')
58 f_start = data.index('%%EndProlog') if f_start === false
59 f_start = data.index('%%BoundingBox') if f_start === false
60
61 data = data.slice(f_start, data.length)
62
63 f_end = data.index('%%PageTrailer')
64 f_end = data.index('showpage') if f_end === false
65 data = data.slice(0, f_end) if f_end
66
67 # save the current graphic state
68 out('q')
69
70 k = @k
71
72 # Translate
73 if use_bounding_box
74 dx = x*k-@x1
75 dy = @hPt-@y2-y*k
76 else
77 dx = x*k
78 dy = -y*k
79 end
80 tm = [1,0,0,1,dx,dy]
81 out(sprintf('%.3f %.3f %.3f %.3f %.3f %.3f cm',
82 tm[0], tm[1], tm[2], tm[3], tm[4], tm[5]))
83
84 if w > 0
85 scale_x = w/((@x2-@x1)/k)
86 if h > 0
87 scale_y = h/((@y2-@y1)/k)
88 else
89 scale_y = scale_x
90 h = (@y2-@y1)/k * scale_y
91 end
92 else
93 if h > 0
94 scale_y = $h/((@y2-@y1)/$k)
95 scale_x = scale_y
96 w = (@x2-@x1)/k * scale_x
97 else
98 w = (@x2-@x1)/k
99 h = (@y2-@y1)/k
100 end
101 end
102
103 if !scale_x.nil?
104 # Scale
105 tm = [scale_x,0,0,scale_y,0,@hPt*(1-scale_y)]
106 out(sprintf('%.3f %.3f %.3f %.3f %.3f %.3f cm',
107 tm[0], tm[1], tm[2], tm[3], tm[4], tm[5]))
108 end
109
110 data.split(/\r\n|[\r\n]/).each do |line|
111 next if line == '' || line[0,1] == '%'
112 len = line.length
113 # next if (len > 2 && line[len-2,len] != ' ')
114 cmd = line[len-2,len].strip
115 case cmd
116 when 'm', 'l', 'v', 'y', 'c', 'k', 'K', 'g', 'G', 's', 'S', 'J', 'j', 'w', 'M', 'd':
117 out(line)
118
119 when 'L':
120 line[len-1,len]='l'
121 out(line)
122
123 when 'C':
124 line[len-1,len]='c'
125 out(line)
126
127 when 'f', 'F':
128 out('f*')
129
130 when 'b', 'B':
131 out(cmd + '*')
132 end
133 end
134
135 # restore previous graphic state
136 out('Q')
137 Link(x,y,w,h,link) if link
138 end
139 end
@@ -0,0 +1,468
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(@CurrentFont['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=@CurrentFont['cw']
100 nb=s.length
101 i=0
102 while(i<nb)
103 o=s[i]
104 if(o<128)
105 #ASCII
106 l+=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*@FontSize/1000
119 end
120
121 def MultiCell(w,h,txt,border=0,align='L',fill=0)
122 if(@CurrentFont['type']=='Type0')
123 SJISMultiCell(w,h,txt,border,align,fill)
124 else
125 super(w,h,txt,border,align,fill)
126 end
127 end
128
129 def SJISMultiCell(w,h,txt,border=0,align='L',fill=0)
130 #Output text with automatic or explicit line breaks
131 cw=@CurrentFont['cw']
132 if(w==0)
133 w=@w-@rMargin-@x
134 end
135 wmax=(w-2*@cMargin)*1000/@FontSize
136 s=txt.gsub("\r",'')
137 nb=s.length
138 if(nb>0 and s[nb-1]=="\n")
139 nb-=1
140 end
141 b=0
142 if(border)
143 if(border==1)
144 border='LTRB'
145 b='LRT'
146 b2='LR'
147 else
148 b2=''
149 if(border.index('L').nil?)
150 b2+='L'
151 end
152 if(border.index('R').nil?)
153 b2+='R'
154 end
155 b=border.index('T').nil? ? b2+'T' : b2
156 end
157 end
158 sep=-1
159 i=0
160 j=0
161 l=0
162 nl=1
163 while(i<nb)
164 #Get next character
165 c=s[i]
166 o=ord(c)
167 if(o==10)
168 #Explicit line break
169 Cell(w,h,s[j,i-j],b,2,align,fill)
170 i+=1
171 sep=-1
172 j=i
173 l=0
174 nl+=1
175 if(border and nl==2)
176 b=b2
177 end
178 next
179 end
180 if(o<128)
181 #ASCII
182 l+=cw[c.chr]
183 n=1
184 if(o==32)
185 sep=i
186 end
187 elsif(o>=161 and o<=223)
188 #Half-width katakana
189 l+=500
190 n=1
191 sep=i
192 else
193 #Full-width character
194 l+=1000
195 n=2
196 sep=i
197 end
198 if(l>wmax)
199 #Automatic line break
200 if(sep==-1 or i==j)
201 if(i==j)
202 i+=n
203 end
204 Cell(w,h,s[j,i-j],b,2,align,fill)
205 else
206 Cell(w,h,s[j,sep-j],b,2,align,fill)
207 i=(s[sep]==' ') ? sep+1 : sep
208 end
209 sep=-1
210 j=i
211 l=0
212 nl+=1
213 if(border and nl==2)
214 b=b2
215 end
216 else
217 i+=n
218 if(o>=128)
219 sep=i
220 end
221 end
222 end
223 #Last chunk
224 if(border and not border.index('B').nil?)
225 b+='B'
226 end
227 Cell(w,h,s[j,i-j],b,2,align,fill)
228 @x=@lMargin
229 end
230
231 def Write(h,txt,link='')
232 if(@CurrentFont['type']=='Type0')
233 SJISWrite(h,txt,link)
234 else
235 super(h,txt,link)
236 end
237 end
238
239 def SJISWrite(h,txt,link)
240 #SJIS version of Write()
241 cw=@CurrentFont['cw']
242 w=@w-@rMargin-@x
243 wmax=(w-2*@cMargin)*1000/@FontSize
244 s=txt.gsub("\r",'')
245 nb=s.length
246 sep=-1
247 i=0
248 j=0
249 l=0
250 nl=1
251 while(i<nb)
252 #Get next character
253 c=s[i]
254 o=c
255 if(o==10)
256 #Explicit line break
257 Cell(w,h,s[j,i-j],0,2,'',0,link)
258 i+=1
259 sep=-1
260 j=i
261 l=0
262 if(nl==1)
263 #Go to left margin
264 @x=@lMargin
265 w=@w-@rMargin-@x
266 wmax=(w-2*@cMargin)*1000/@FontSize
267 end
268 nl+=1
269 next
270 end
271 if(o<128)
272 #ASCII
273 l+=cw[c.chr]
274 n=1
275 if(o==32)
276 sep=i
277 end
278 elsif(o>=161 and o<=223)
279 #Half-width katakana
280 l+=500
281 n=1
282 sep=i
283 else
284 #Full-width character
285 l+=1000
286 n=2
287 sep=i
288 end
289 if(l>wmax)
290 #Automatic line break
291 if(sep==-1 or i==j)
292 if(@x>@lMargin)
293 #Move to next line
294 @x=@lMargin
295 @y+=h
296 w=@w-@rMargin-@x
297 wmax=(w-2*@cMargin)*1000/@FontSize
298 i+=n
299 nl+=1
300 next
301 end
302 if(i==j)
303 i+=n
304 end
305 Cell(w,h,s[j,i-j],0,2,'',0,link)
306 else
307 Cell(w,h,s[j,sep-j],0,2,'',0,link)
308 i=(s[sep]==' ') ? sep+1 : sep
309 end
310 sep=-1
311 j=i
312 l=0
313 if(nl==1)
314 @x=@lMargin
315 w=@w-@rMargin-@x
316 wmax=(w-2*@cMargin)*1000/@FontSize
317 end
318 nl+=1
319 else
320 i+=n
321 if(o>=128)
322 sep=i
323 end
324 end
325 end
326 #Last chunk
327 if(i!=j)
328 Cell(l/1000*@FontSize,h,s[j,i-j],0,0,'',0,link)
329 end
330 end
331
332 private
333
334 def putfonts()
335 nf=@n
336 @diffs.each do |diff|
337 #Encodings
338 newobj()
339 out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['+diff+']>>')
340 out('endobj')
341 end
342 # mqr=get_magic_quotes_runtime()
343 # set_magic_quotes_runtime(0)
344 @FontFiles.each_pair do |file, info|
345 #Font file embedding
346 newobj()
347 @FontFiles[file]['n']=@n
348 if(defined('FPDF_FONTPATH'))
349 file=FPDF_FONTPATH+file
350 end
351 size=filesize(file)
352 if(!size)
353 Error('Font file not found')
354 end
355 out('<</Length '+size)
356 if(file[-2]=='.z')
357 out('/Filter /FlateDecode')
358 end
359 out('/Length1 '+info['length1'])
360 unless info['length2'].nil?
361 out('/Length2 '+info['length2']+' /Length3 0')
362 end
363 out('>>')
364 f=fopen(file,'rb')
365 putstream(fread(f,size))
366 fclose(f)
367 out('endobj')
368 end
369 # set_magic_quotes_runtime(mqr)
370 @fonts.each_pair do |k, font|
371 #Font objects
372 newobj()
373 @fonts[k]['n']=@n
374 out('<</Type /Font')
375 if(font['type']=='Type0')
376 putType0(font)
377 else
378 name=font['name']
379 out('/BaseFont /'+name)
380 if(font['type']=='core')
381 #Standard font
382 out('/Subtype /Type1')
383 if(name!='Symbol' and name!='ZapfDingbats')
384 out('/Encoding /WinAnsiEncoding')
385 end
386 else
387 #Additional font
388 out('/Subtype /'+font['type'])
389 out('/FirstChar 32')
390 out('/LastChar 255')
391 out('/Widths '+(@n+1)+' 0 R')
392 out('/FontDescriptor '+(@n+2)+' 0 R')
393 if(font['enc'])
394 if !font['diff'].nil?
395 out('/Encoding '+(nf+font['diff'])+' 0 R')
396 else
397 out('/Encoding /WinAnsiEncoding')
398 end
399 end
400 end
401 out('>>')
402 out('endobj')
403 if(font['type']!='core')
404 #Widths
405 newobj()
406 cw=font['cw']
407 s='['
408 32.upto(255) do |i|
409 s+=cw[i.chr]+' '
410 end
411 out(s+']')
412 out('endobj')
413 #Descriptor
414 newobj()
415 s='<</Type /FontDescriptor /FontName /'+name
416 font['desc'].each_pair do |k, v|
417 s+=' /'+k+' '+v
418 end
419 file=font['file']
420 if(file)
421 s+=' /FontFile'+(font['type']=='Type1' ? '' : '2')+' '+@FontFiles[file]['n']+' 0 R'
422 end
423 out(s+'>>')
424 out('endobj')
425 end
426 end
427 end
428 end
429
430 def putType0(font)
431 #Type0
432 out('/Subtype /Type0')
433 out('/BaseFont /'+font['name']+'-'+font['CMap'])
434 out('/Encoding /'+font['CMap'])
435 out('/DescendantFonts ['+(@n+1).to_s+' 0 R]')
436 out('>>')
437 out('endobj')
438 #CIDFont
439 newobj()
440 out('<</Type /Font')
441 out('/Subtype /CIDFontType0')
442 out('/BaseFont /'+font['name'])
443 out('/CIDSystemInfo <</Registry (Adobe) /Ordering ('+font['registry']['ordering']+') /Supplement '+font['registry']['supplement'].to_s+'>>')
444 out('/FontDescriptor '+(@n+1).to_s+' 0 R')
445 w='/W [1 ['
446 font['cw'].keys.sort.each {|key|
447 w+=font['cw'][key].to_s + " "
448 # ActionController::Base::logger.debug key.to_s
449 # ActionController::Base::logger.debug font['cw'][key].to_s
450 }
451 out(w+'] 231 325 500 631 [500] 326 389 500]')
452 out('>>')
453 out('endobj')
454 #Font descriptor
455 newobj()
456 out('<</Type /FontDescriptor')
457 out('/FontName /'+font['name'])
458 out('/Flags 6')
459 out('/FontBBox [0 -200 1000 900]')
460 out('/ItalicAngle 0')
461 out('/Ascent 800')
462 out('/Descent -200')
463 out('/CapHeight 800')
464 out('/StemV 60')
465 out('>>')
466 out('endobj')
467 end
468 end
@@ -0,0 +1,436
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 korean.php
25 #
26 # Korean PDF support.
27 #
28 # Usage is as follows:
29 #
30 # require 'fpdf'
31 # require 'chinese'
32 # pdf = FPDF.new
33 # pdf.extend(PDF_Korean)
34 #
35 # This allows it to be combined with other extensions, such as the bookmark
36 # module.
37
38 module PDF_Korean
39
40 UHC_widths={' ' => 333, '!' => 416, '"' => 416, '#' => 833, '$' => 625, '%' => 916, '&' => 833, '\'' => 250,
41 '(' => 500, ')' => 500, '*' => 500, '+' => 833, ',' => 291, '-' => 833, '.' => 291, '/' => 375, '0' => 625, '1' => 625,
42 '2' => 625, '3' => 625, '4' => 625, '5' => 625, '6' => 625, '7' => 625, '8' => 625, '9' => 625, ':' => 333, ';' => 333,
43 '<' => 833, '=' => 833, '>' => 916, '?' => 500, '@' => 1000, 'A' => 791, 'B' => 708, 'C' => 708, 'D' => 750, 'E' => 708,
44 'F' => 666, 'G' => 750, 'H' => 791, 'I' => 375, 'J' => 500, 'K' => 791, 'L' => 666, 'M' => 916, 'N' => 791, 'O' => 750,
45 'P' => 666, 'Q' => 750, 'R' => 708, 'S' => 666, 'T' => 791, 'U' => 791, 'V' => 750, 'W' => 1000, 'X' => 708, 'Y' => 708,
46 'Z' => 666, '[' => 500, '\\' => 375, ']' => 500, '^' => 500, '_' => 500, '`' => 333, 'a' => 541, 'b' => 583, 'c' => 541,
47 'd' => 583, 'e' => 583, 'f' => 375, 'g' => 583, 'h' => 583, 'i' => 291, 'j' => 333, 'k' => 583, 'l' => 291, 'm' => 875,
48 'n' => 583, 'o' => 583, 'p' => 583, 'q' => 583, 'r' => 458, 's' => 541, 't' => 375, 'u' => 583, 'v' => 583, 'w' => 833,
49 'x' => 625, 'y' => 625, 'z' => 500, '{' => 583, '|' => 583, '}' => 583, '~' => 750}
50
51 def AddCIDFont(family,style,name,cw,cMap,registry)
52 fontkey=family.downcase+style.upcase
53 unless @fonts[fontkey].nil?
54 Error("Font already added: family style")
55 end
56 i=@fonts.length+1
57 name=name.gsub(' ','')
58 @fonts[fontkey]={'i'=>i,'type'=>'Type0','name'=>name,'up'=>-130,'ut'=>40,'cw'=>cw,
59 'CMap'=>cMap,'registry'=>registry}
60 end
61
62 def AddCIDFonts(family,name,cw,cMap,registry)
63 AddCIDFont(family,'',name,cw,cMap,registry)
64 AddCIDFont(family,'B',name+',Bold',cw,cMap,registry)
65 AddCIDFont(family,'I',name+',Italic',cw,cMap,registry)
66 AddCIDFont(family,'BI',name+',BoldItalic',cw,cMap,registry)
67 end
68
69 def AddUHCFont(family='UHC',name='HYSMyeongJoStd-Medium-Acro')
70 #Add UHC font with proportional Latin
71 cw=UHC_widths
72 cMap='KSCms-UHC-H'
73 registry={'ordering'=>'Korea1','supplement'=>1}
74 AddCIDFonts(family,name,cw,cMap,registry)
75 end
76
77 def AddUHChwFont(family='UHC-hw',name='HYSMyeongJoStd-Medium-Acro')
78 #Add UHC font with half-witdh Latin
79 32.upto(126) do |i|
80 cw[i.chr]=500
81 end
82 cMap='KSCms-UHC-HW-H'
83 registry={'ordering'=>'Korea1','supplement'=>1}
84 AddCIDFonts(family,name,cw,cMap,registry)
85 end
86
87 def GetStringWidth(s)
88 if(@CurrentFont['type']=='Type0')
89 return GetMBStringWidth(s)
90 else
91 return super(s)
92 end
93 end
94
95 def GetMBStringWidth(s)
96 #Multi-byte version of GetStringWidth()
97 l=0
98 cw=@CurrentFont['cw']
99 nb=s.length
100 i=0
101 while(i<nb)
102 c=s[i]
103 if(c<128)
104 l+=cw[c.chr]
105 i+=1
106 else
107 l+=1000
108 i+=2
109 end
110 end
111 return l*@FontSize/1000
112 end
113
114 def MultiCell(w,h,txt,border=0,align='L',fill=0)
115 if(@CurrentFont['type']=='Type0')
116 MBMultiCell(w,h,txt,border,align,fill)
117 else
118 super(w,h,txt,border,align,fill)
119 end
120 end
121
122 def MBMultiCell(w,h,txt,border=0,align='L',fill=0)
123 #Multi-byte version of MultiCell()
124 cw=@CurrentFont['cw']
125 if(w==0)
126 w=@w-@rMargin-@x
127 end
128 wmax=(w-2*@cMargin)*1000/@FontSize
129 s=txt.gsub("\r",'')
130 nb=s.length
131 if(nb>0 and s[nb-1]=="\n")
132 nb-=1
133 end
134 b=0
135 if(border)
136 if(border==1)
137 border='LTRB'
138 b='LRT'
139 b2='LR'
140 else
141 b2=''
142 if(border.index('L').nil?)
143 b2+='L'
144 end
145 if(border.index('R').nil?)
146 b2+='R'
147 end
148 b=border.index('T').nil? ? b2+'T' : b2
149 end
150 end
151 sep=-1
152 i=0
153 j=0
154 l=0
155 nl=1
156 while(i<nb)
157 #Get next character
158 c=s[i]
159 #Check if ASCII or MB
160 ascii=(c<128)
161 if(c=="\n")
162 #Explicit line break
163 Cell(w,h,s[j,i-j],b,2,align,fill)
164 i+=1
165 sep=-1
166 j=i
167 l=0
168 nl+=1
169 if(border and nl==2)
170 b=b2
171 end
172 next
173 end
174 if(!ascii)
175 sep=i
176 ls=l
177 elsif(c==' ')
178 sep=i
179 ls=l
180 end
181 l+=ascii ? cw[c.chr] : 1000
182 if(l>wmax)
183 #Automatic line break
184 if(sep==-1 or i==j)
185 if(i==j)
186 i+=ascii ? 1 : 2
187 end
188 Cell(w,h,s[j,i-j],b,2,align,fill)
189 else
190 Cell(w,h,s[j,sep-j],b,2,align,fill)
191 i=(s[sep]==' ') ? sep+1 : sep
192 end
193 sep=-1
194 j=i
195 l=0
196 nl+=1
197 if(border and nl==2)
198 b=b2
199 end
200 else
201 i+=ascii ? 1 : 2
202 end
203 end
204 #Last chunk
205 if(border and not border.index('B').nil?)
206 b+='B'
207 end
208 Cell(w,h,s[j,i-j],b,2,align,fill)
209 @x=@lMargin
210 end
211
212 def Write(h,txt,link='')
213 if(@CurrentFont['type']=='Type0')
214 MBWrite(h,txt,link)
215 else
216 super(h,txt,link)
217 end
218 end
219
220 def MBWrite(h,txt,link)
221 #Multi-byte version of Write()
222 cw=@CurrentFont['cw']
223 w=@w-@rMargin-@x
224 wmax=(w-2*@cMargin)*1000/@FontSize
225 s=txt.gsub("\r",'')
226 nb=s.length
227 sep=-1
228 i=0
229 j=0
230 l=0
231 nl=1
232 while(i<nb)
233 #Get next character
234 c=s[i]
235 #Check if ASCII or MB
236 ascii=(c<128)
237 if(c=="\n")
238 #Explicit line break
239 Cell(w,h,s[j,i-j],0,2,'',0,link)
240 i+=1
241 sep=-1
242 j=i
243 l=0
244 if(nl==1)
245 @x=@lMargin
246 w=@w-@rMargin-@x
247 wmax=(w-2*@cMargin)*1000/@FontSize
248 end
249 nl+=1
250 next
251 end
252 if(!ascii or c==' ')
253 sep=i
254 end
255 l+=ascii ? cw[c.chr] : 1000
256 if(l>wmax)
257 #Automatic line break
258 if(sep==-1 or i==j)
259 if(@x>@lMargin)
260 #Move to next line
261 @x=@lMargin
262 @y+=h
263 w=@w-@rMargin-@x
264 wmax=(w-2*@cMargin)*1000/@FontSize
265 i+=1
266 nl+=1
267 next
268 end
269 if(i==j)
270 i+=ascii ? 1 : 2
271 end
272 Cell(w,h,s[j,i-j],0,2,'',0,link)
273 else
274 Cell(w,h,s[j,sep-j],0,2,'',0,link)
275 i=(s[sep]==' ') ? sep+1 : sep
276 end
277 sep=-1
278 j=i
279 l=0
280 if(nl==1)
281 @x=@lMargin
282 w=@w-@rMargin-@x
283 wmax=(w-2*@cMargin)*1000/@FontSize
284 end
285 nl+=1
286 else
287 i+=ascii ? 1 : 2
288 end
289 end
290 #Last chunk
291 if(i!=j)
292 Cell(l/1000*@FontSize,h,s[j,i-j],0,0,'',0,link)
293 end
294 end
295
296 private
297
298 def putfonts()
299 nf=@n
300 @diffs.each do |diff|
301 #Encodings
302 newobj()
303 out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['+diff+']>>')
304 out('endobj')
305 end
306 # mqr=get_magic_quotes_runtime()
307 # set_magic_quotes_runtime(0)
308 @FontFiles.each_pair do |file, info|
309 #Font file embedding
310 newobj()
311 @FontFiles[file]['n']=@n
312 if(defined('FPDF_FONTPATH'))
313 file=FPDF_FONTPATH+file
314 end
315 size=filesize(file)
316 if(!size)
317 Error('Font file not found')
318 end
319 out('<</Length '+size)
320 if(file[-2]=='.z')
321 out('/Filter /FlateDecode')
322 end
323 out('/Length1 '+info['length1'])
324 if(not info['length2'].nil?)
325 out('/Length2 '+info['length2']+' /Length3 0')
326 end
327 out('>>')
328 f=fopen(file,'rb')
329 putstream(fread(f,size))
330 fclose(f)
331 out('endobj')
332 end
333 # set_magic_quotes_runtime(mqr)
334 @fonts.each_pair do |k, font|
335 #Font objects
336 newobj()
337 @fonts[k]['n']=@n
338 out('<</Type /Font')
339 if(font['type']=='Type0')
340 putType0(font)
341 else
342 name=font['name']
343 out('/BaseFont /'+name)
344 if(font['type']=='core')
345 #Standard font
346 out('/Subtype /Type1')
347 if(name!='Symbol' and name!='ZapfDingbats')
348 out('/Encoding /WinAnsiEncoding')
349 end
350 else
351 #Additional font
352 out('/Subtype /'+font['type'])
353 out('/FirstChar 32')
354 out('/LastChar 255')
355 out('/Widths '+(@n+1)+' 0 R')
356 out('/FontDescriptor '+(@n+2)+' 0 R')
357 if(font['enc'])
358 if(not font['diff'].nil?)
359 out('/Encoding '+(nf+font['diff'])+' 0 R')
360 else
361 out('/Encoding /WinAnsiEncoding')
362 end
363 end
364 end
365 out('>>')
366 out('endobj')
367 if(font['type']!='core')
368 #Widths
369 newobj()
370 cw=font['cw']
371 s='['
372 32.upto(255) do |i|
373 s+=cw[i.chr]+' '
374 end
375 out(s+']')
376 out('endobj')
377 #Descriptor
378 newobj()
379 s='<</Type /FontDescriptor /FontName /'+name
380 font['desc'].each_pair do |k, v|
381 s+=' /'+k+' '+v
382 end
383 file=font['file']
384 if(file)
385 s+=' /FontFile'+(font['type']=='Type1' ? '' : '2')+' '+@FontFiles[file]['n']+' 0 R'
386 end
387 out(s+'>>')
388 out('endobj')
389 end
390 end
391 end
392 end
393
394 def putType0(font)
395 #Type0
396 out('/Subtype /Type0')
397 out('/BaseFont /'+font['name']+'-'+font['CMap'])
398 out('/Encoding /'+font['CMap'])
399 out('/DescendantFonts ['+(@n+1).to_s+' 0 R]')
400 out('>>')
401 out('endobj')
402 #CIDFont
403 newobj()
404 out('<</Type /Font')
405 out('/Subtype /CIDFontType0')
406 out('/BaseFont /'+font['name'])
407 out('/CIDSystemInfo <</Registry (Adobe) /Ordering ('+font['registry']['ordering']+') /Supplement '+font['registry']['supplement'].to_s+'>>')
408 out('/FontDescriptor '+(@n+1).to_s+' 0 R')
409 if(font['CMap']=='KSCms-UHC-HW-H')
410 w='8094 8190 500'
411 else
412 w='1 ['
413 font['cw'].keys.sort.each {|key|
414 w+=font['cw'][key].to_s + " "
415 # ActionController::Base::logger.debug key.to_s
416 # ActionController::Base::logger.debug font['cw'][key].to_s
417 }
418 w +=']'
419 end
420 out('/W ['+w+']>>')
421 out('endobj')
422 #Font descriptor
423 newobj()
424 out('<</Type /FontDescriptor')
425 out('/FontName /'+font['name'])
426 out('/Flags 6')
427 out('/FontBBox [0 -200 1000 900]')
428 out('/ItalicAngle 0')
429 out('/Ascent 800')
430 out('/Descent -200')
431 out('/CapHeight 800')
432 out('/StemV 50')
433 out('>>')
434 out('endobj')
435 end
436 end
This diff has been collapsed as it changes many lines, (1787 lines changed) Show them Hide them
@@ -0,0 +1,1787
1 #!/usr/bin/env ruby
2 #
3 # Utility to generate font definition files
4 # Version: 1.1
5 # Date: 2006-07-19
6 #
7 # Changelog:
8 # Version 1.1 - Brian Ollenberger
9 # - Fixed a very small bug in MakeFont for generating FontDef.diff.
10
11 Charencodings = {
12 # Central Europe
13 'cp1250' => [
14 '.notdef', '.notdef', '.notdef', '.notdef',
15 '.notdef', '.notdef', '.notdef', '.notdef',
16 '.notdef', '.notdef', '.notdef', '.notdef',
17 '.notdef', '.notdef', '.notdef', '.notdef',
18 '.notdef', '.notdef', '.notdef', '.notdef',
19 '.notdef', '.notdef', '.notdef', '.notdef',
20 '.notdef', '.notdef', '.notdef', '.notdef',
21 '.notdef', '.notdef', '.notdef', '.notdef',
22 'space', 'exclam', 'quotedbl', 'numbersign',
23 'dollar', 'percent', 'ampersand', 'quotesingle',
24 'parenleft', 'parenright', 'asterisk', 'plus',
25 'comma', 'hyphen', 'period', 'slash',
26 'zero', 'one', 'two', 'three',
27 'four', 'five', 'six', 'seven',
28 'eight', 'nine', 'colon', 'semicolon',
29 'less', 'equal', 'greater', 'question',
30 'at', 'A', 'B', 'C',
31 'D', 'E', 'F', 'G',
32 'H', 'I', 'J', 'K',
33 'L', 'M', 'N', 'O',
34 'P', 'Q', 'R', 'S',
35 'T', 'U', 'V', 'W',
36 'X', 'Y', 'Z', 'bracketleft',
37 'backslash', 'bracketright', 'asciicircum', 'underscore',
38 'grave', 'a', 'b', 'c',
39 'd', 'e', 'f', 'g',
40 'h', 'i', 'j', 'k',
41 'l', 'm', 'n', 'o',
42 'p', 'q', 'r', 's',
43 't', 'u', 'v', 'w',
44 'x', 'y', 'z', 'braceleft',
45 'bar', 'braceright', 'asciitilde', '.notdef',
46 'Euro', '.notdef', 'quotesinglbase', '.notdef',
47 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl',
48 '.notdef', 'perthousand', 'Scaron', 'guilsinglleft',
49 'Sacute', 'Tcaron', 'Zcaron', 'Zacute',
50 '.notdef', 'quoteleft', 'quoteright', 'quotedblleft',
51 'quotedblright', 'bullet', 'endash', 'emdash',
52 '.notdef', 'trademark', 'scaron', 'guilsinglright',
53 'sacute', 'tcaron', 'zcaron', 'zacute',
54 'space', 'caron', 'breve', 'Lslash',
55 'currency', 'Aogonek', 'brokenbar', 'section',
56 'dieresis', 'copyright', 'Scedilla', 'guillemotleft',
57 'logicalnot', 'hyphen', 'registered', 'Zdotaccent',
58 'degree', 'plusminus', 'ogonek', 'lslash',
59 'acute', 'mu', 'paragraph', 'periodcentered',
60 'cedilla', 'aogonek', 'scedilla', 'guillemotright',
61 'Lcaron', 'hungarumlaut', 'lcaron', 'zdotaccent',
62 'Racute', 'Aacute', 'Acircumflex', 'Abreve',
63 'Adieresis', 'Lacute', 'Cacute', 'Ccedilla',
64 'Ccaron', 'Eacute', 'Eogonek', 'Edieresis',
65 'Ecaron', 'Iacute', 'Icircumflex', 'Dcaron',
66 'Dcroat', 'Nacute', 'Ncaron', 'Oacute',
67 'Ocircumflex', 'Ohungarumlaut', 'Odieresis', 'multiply',
68 'Rcaron', 'Uring', 'Uacute', 'Uhungarumlaut',
69 'Udieresis', 'Yacute', 'Tcommaaccent', 'germandbls',
70 'racute', 'aacute', 'acircumflex', 'abreve',
71 'adieresis', 'lacute', 'cacute', 'ccedilla',
72 'ccaron', 'eacute', 'eogonek', 'edieresis',
73 'ecaron', 'iacute', 'icircumflex', 'dcaron',
74 'dcroat', 'nacute', 'ncaron', 'oacute',
75 'ocircumflex', 'ohungarumlaut', 'odieresis', 'divide',
76 'rcaron', 'uring', 'uacute', 'uhungarumlaut',
77 'udieresis', 'yacute', 'tcommaaccent', 'dotaccent'
78 ],
79 # Cyrillic
80 'cp1251' => [
81 '.notdef', '.notdef', '.notdef', '.notdef',
82 '.notdef', '.notdef', '.notdef', '.notdef',
83 '.notdef', '.notdef', '.notdef', '.notdef',
84 '.notdef', '.notdef', '.notdef', '.notdef',
85 '.notdef', '.notdef', '.notdef', '.notdef',
86 '.notdef', '.notdef', '.notdef', '.notdef',
87 '.notdef', '.notdef', '.notdef', '.notdef',
88 '.notdef', '.notdef', '.notdef', '.notdef',
89 'space', 'exclam', 'quotedbl', 'numbersign',
90 'dollar', 'percent', 'ampersand', 'quotesingle',
91 'parenleft', 'parenright', 'asterisk', 'plus',
92 'comma', 'hyphen', 'period', 'slash',
93 'zero', 'one', 'two', 'three',
94 'four', 'five', 'six', 'seven',
95 'eight', 'nine', 'colon', 'semicolon',
96 'less', 'equal', 'greater', 'question',
97 'at', 'A', 'B', 'C',
98 'D', 'E', 'F', 'G',
99 'H', 'I', 'J', 'K',
100 'L', 'M', 'N', 'O',
101 'P', 'Q', 'R', 'S',
102 'T', 'U', 'V', 'W',
103 'X', 'Y', 'Z', 'bracketleft',
104 'backslash', 'bracketright', 'asciicircum', 'underscore',
105 'grave', 'a', 'b', 'c',
106 'd', 'e', 'f', 'g',
107 'h', 'i', 'j', 'k',
108 'l', 'm', 'n', 'o',
109 'p', 'q', 'r', 's',
110 't', 'u', 'v', 'w',
111 'x', 'y', 'z', 'braceleft',
112 'bar', 'braceright', 'asciitilde', '.notdef',
113 'afii10051', 'afii10052', 'quotesinglbase', 'afii10100',
114 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl',
115 'Euro', 'perthousand', 'afii10058', 'guilsinglleft',
116 'afii10059', 'afii10061', 'afii10060', 'afii10145',
117 'afii10099', 'quoteleft', 'quoteright', 'quotedblleft',
118 'quotedblright', 'bullet', 'endash', 'emdash',
119 '.notdef', 'trademark', 'afii10106', 'guilsinglright',
120 'afii10107', 'afii10109', 'afii10108', 'afii10193',
121 'space', 'afii10062', 'afii10110', 'afii10057',
122 'currency', 'afii10050', 'brokenbar', 'section',
123 'afii10023', 'copyright', 'afii10053', 'guillemotleft',
124 'logicalnot', 'hyphen', 'registered', 'afii10056',
125 'degree', 'plusminus', 'afii10055', 'afii10103',
126 'afii10098', 'mu', 'paragraph', 'periodcentered',
127 'afii10071', 'afii61352', 'afii10101', 'guillemotright',
128 'afii10105', 'afii10054', 'afii10102', 'afii10104',
129 'afii10017', 'afii10018', 'afii10019', 'afii10020',
130 'afii10021', 'afii10022', 'afii10024', 'afii10025',
131 'afii10026', 'afii10027', 'afii10028', 'afii10029',
132 'afii10030', 'afii10031', 'afii10032', 'afii10033',
133 'afii10034', 'afii10035', 'afii10036', 'afii10037',
134 'afii10038', 'afii10039', 'afii10040', 'afii10041',
135 'afii10042', 'afii10043', 'afii10044', 'afii10045',
136 'afii10046', 'afii10047', 'afii10048', 'afii10049',
137 'afii10065', 'afii10066', 'afii10067', 'afii10068',
138 'afii10069', 'afii10070', 'afii10072', 'afii10073',
139 'afii10074', 'afii10075', 'afii10076', 'afii10077',
140 'afii10078', 'afii10079', 'afii10080', 'afii10081',
141 'afii10082', 'afii10083', 'afii10084', 'afii10085',
142 'afii10086', 'afii10087', 'afii10088', 'afii10089',
143 'afii10090', 'afii10091', 'afii10092', 'afii10093',
144 'afii10094', 'afii10095', 'afii10096', 'afii10097'
145 ],
146 # Western Europe
147 'cp1252' => [
148 '.notdef', '.notdef', '.notdef', '.notdef',
149 '.notdef', '.notdef', '.notdef', '.notdef',
150 '.notdef', '.notdef', '.notdef', '.notdef',
151 '.notdef', '.notdef', '.notdef', '.notdef',
152 '.notdef', '.notdef', '.notdef', '.notdef',
153 '.notdef', '.notdef', '.notdef', '.notdef',
154 '.notdef', '.notdef', '.notdef', '.notdef',
155 '.notdef', '.notdef', '.notdef', '.notdef',
156 'space', 'exclam', 'quotedbl', 'numbersign',
157 'dollar', 'percent', 'ampersand', 'quotesingle',
158 'parenleft', 'parenright', 'asterisk', 'plus',
159 'comma', 'hyphen', 'period', 'slash',
160 'zero', 'one', 'two', 'three',
161 'four', 'five', 'six', 'seven',
162 'eight', 'nine', 'colon', 'semicolon',
163 'less', 'equal', 'greater', 'question',
164 'at', 'A', 'B', 'C',
165 'D', 'E', 'F', 'G',
166 'H', 'I', 'J', 'K',
167 'L', 'M', 'N', 'O',
168 'P', 'Q', 'R', 'S',
169 'T', 'U', 'V', 'W',
170 'X', 'Y', 'Z', 'bracketleft',
171 'backslash', 'bracketright', 'asciicircum', 'underscore',
172 'grave', 'a', 'b', 'c',
173 'd', 'e', 'f', 'g',
174 'h', 'i', 'j', 'k',
175 'l', 'm', 'n', 'o',
176 'p', 'q', 'r', 's',
177 't', 'u', 'v', 'w',
178 'x', 'y', 'z', 'braceleft',
179 'bar', 'braceright', 'asciitilde', '.notdef',
180 'Euro', '.notdef', 'quotesinglbase', 'florin',
181 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl',
182 'circumflex', 'perthousand', 'Scaron', 'guilsinglleft',
183 'OE', '.notdef', 'Zcaron', '.notdef',
184 '.notdef', 'quoteleft', 'quoteright', 'quotedblleft',
185 'quotedblright', 'bullet', 'endash', 'emdash',
186 'tilde', 'trademark', 'scaron', 'guilsinglright',
187 'oe', '.notdef', 'zcaron', 'Ydieresis',
188 'space', 'exclamdown', 'cent', 'sterling',
189 'currency', 'yen', 'brokenbar', 'section',
190 'dieresis', 'copyright', 'ordfeminine', 'guillemotleft',
191 'logicalnot', 'hyphen', 'registered', 'macron',
192 'degree', 'plusminus', 'twosuperior', 'threesuperior',
193 'acute', 'mu', 'paragraph', 'periodcentered',
194 'cedilla', 'onesuperior', 'ordmasculine', 'guillemotright',
195 'onequarter', 'onehalf', 'threequarters', 'questiondown',
196 'Agrave', 'Aacute', 'Acircumflex', 'Atilde',
197 'Adieresis', 'Aring', 'AE', 'Ccedilla',
198 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis',
199 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis',
200 'Eth', 'Ntilde', 'Ograve', 'Oacute',
201 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply',
202 'Oslash', 'Ugrave', 'Uacute', 'Ucircumflex',
203 'Udieresis', 'Yacute', 'Thorn', 'germandbls',
204 'agrave', 'aacute', 'acircumflex', 'atilde',
205 'adieresis', 'aring', 'ae', 'ccedilla',
206 'egrave', 'eacute', 'ecircumflex', 'edieresis',
207 'igrave', 'iacute', 'icircumflex', 'idieresis',
208 'eth', 'ntilde', 'ograve', 'oacute',
209 'ocircumflex', 'otilde', 'odieresis', 'divide',
210 'oslash', 'ugrave', 'uacute', 'ucircumflex',
211 'udieresis', 'yacute', 'thorn', 'ydieresis'
212 ],
213 # Greek
214 'cp1253' => [
215 '.notdef', '.notdef', '.notdef', '.notdef',
216 '.notdef', '.notdef', '.notdef', '.notdef',
217 '.notdef', '.notdef', '.notdef', '.notdef',
218 '.notdef', '.notdef', '.notdef', '.notdef',
219 '.notdef', '.notdef', '.notdef', '.notdef',
220 '.notdef', '.notdef', '.notdef', '.notdef',
221 '.notdef', '.notdef', '.notdef', '.notdef',
222 '.notdef', '.notdef', '.notdef', '.notdef',
223 'space', 'exclam', 'quotedbl', 'numbersign',
224 'dollar', 'percent', 'ampersand', 'quotesingle',
225 'parenleft', 'parenright', 'asterisk', 'plus',
226 'comma', 'hyphen', 'period', 'slash',
227 'zero', 'one', 'two', 'three',
228 'four', 'five', 'six', 'seven',
229 'eight', 'nine', 'colon', 'semicolon',
230 'less', 'equal', 'greater', 'question',
231 'at', 'A', 'B', 'C',
232 'D', 'E', 'F', 'G',
233 'H', 'I', 'J', 'K',
234 'L', 'M', 'N', 'O',
235 'P', 'Q', 'R', 'S',
236 'T', 'U', 'V', 'W',
237 'X', 'Y', 'Z', 'bracketleft',
238 'backslash', 'bracketright', 'asciicircum', 'underscore',
239 'grave', 'a', 'b', 'c',
240 'd', 'e', 'f', 'g',
241 'h', 'i', 'j', 'k',
242 'l', 'm', 'n', 'o',
243 'p', 'q', 'r', 's',
244 't', 'u', 'v', 'w',
245 'x', 'y', 'z', 'braceleft',
246 'bar', 'braceright', 'asciitilde', '.notdef',
247 'Euro', '.notdef', 'quotesinglbase', 'florin',
248 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl',
249 '.notdef', 'perthousand', '.notdef', 'guilsinglleft',
250 '.notdef', '.notdef', '.notdef', '.notdef',
251 '.notdef', 'quoteleft', 'quoteright', 'quotedblleft',
252 'quotedblright', 'bullet', 'endash', 'emdash',
253 '.notdef', 'trademark', '.notdef', 'guilsinglright',
254 '.notdef', '.notdef', '.notdef', '.notdef',
255 'space', 'dieresistonos', 'Alphatonos', 'sterling',
256 'currency', 'yen', 'brokenbar', 'section',
257 'dieresis', 'copyright', '.notdef', 'guillemotleft',
258 'logicalnot', 'hyphen', 'registered', 'afii00208',
259 'degree', 'plusminus', 'twosuperior', 'threesuperior',
260 'tonos', 'mu', 'paragraph', 'periodcentered',
261 'Epsilontonos', 'Etatonos', 'Iotatonos', 'guillemotright',
262 'Omicrontonos', 'onehalf', 'Upsilontonos', 'Omegatonos',
263 'iotadieresistonos','Alpha', 'Beta', 'Gamma',
264 'Delta', 'Epsilon', 'Zeta', 'Eta',
265 'Theta', 'Iota', 'Kappa', 'Lambda',
266 'Mu', 'Nu', 'Xi', 'Omicron',
267 'Pi', 'Rho', '.notdef', 'Sigma',
268 'Tau', 'Upsilon', 'Phi', 'Chi',
269 'Psi', 'Omega', 'Iotadieresis', 'Upsilondieresis',
270 'alphatonos', 'epsilontonos', 'etatonos', 'iotatonos',
271 'upsilondieresistonos','alpha', 'beta', 'gamma',
272 'delta', 'epsilon', 'zeta', 'eta',
273 'theta', 'iota', 'kappa', 'lambda',
274 'mu', 'nu', 'xi', 'omicron',
275 'pi', 'rho', 'sigma1', 'sigma',
276 'tau', 'upsilon', 'phi', 'chi',
277 'psi', 'omega', 'iotadieresis', 'upsilondieresis',
278 'omicrontonos', 'upsilontonos', 'omegatonos', '.notdef'
279 ],
280 # Turkish
281 'cp1254' => [
282 '.notdef', '.notdef', '.notdef', '.notdef',
283 '.notdef', '.notdef', '.notdef', '.notdef',
284 '.notdef', '.notdef', '.notdef', '.notdef',
285 '.notdef', '.notdef', '.notdef', '.notdef',
286 '.notdef', '.notdef', '.notdef', '.notdef',
287 '.notdef', '.notdef', '.notdef', '.notdef',
288 '.notdef', '.notdef', '.notdef', '.notdef',
289 '.notdef', '.notdef', '.notdef', '.notdef',
290 'space', 'exclam', 'quotedbl', 'numbersign',
291 'dollar', 'percent', 'ampersand', 'quotesingle',
292 'parenleft', 'parenright', 'asterisk', 'plus',
293 'comma', 'hyphen', 'period', 'slash',
294 'zero', 'one', 'two', 'three',
295 'four', 'five', 'six', 'seven',
296 'eight', 'nine', 'colon', 'semicolon',
297 'less', 'equal', 'greater', 'question',
298 'at', 'A', 'B', 'C',
299 'D', 'E', 'F', 'G',
300 'H', 'I', 'J', 'K',
301 'L', 'M', 'N', 'O',
302 'P', 'Q', 'R', 'S',
303 'T', 'U', 'V', 'W',
304 'X', 'Y', 'Z', 'bracketleft',
305 'backslash', 'bracketright', 'asciicircum', 'underscore',
306 'grave', 'a', 'b', 'c',
307 'd', 'e', 'f', 'g',
308 'h', 'i', 'j', 'k',
309 'l', 'm', 'n', 'o',
310 'p', 'q', 'r', 's',
311 't', 'u', 'v', 'w',
312 'x', 'y', 'z', 'braceleft',
313 'bar', 'braceright', 'asciitilde', '.notdef',
314 'Euro', '.notdef', 'quotesinglbase', 'florin',
315 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl',
316 'circumflex', 'perthousand', 'Scaron', 'guilsinglleft',
317 'OE', '.notdef', '.notdef', '.notdef',
318 '.notdef', 'quoteleft', 'quoteright', 'quotedblleft',
319 'quotedblright', 'bullet', 'endash', 'emdash',
320 'tilde', 'trademark', 'scaron', 'guilsinglright',
321 'oe', '.notdef', '.notdef', 'Ydieresis',
322 'space', 'exclamdown', 'cent', 'sterling',
323 'currency', 'yen', 'brokenbar', 'section',
324 'dieresis', 'copyright', 'ordfeminine', 'guillemotleft',
325 'logicalnot', 'hyphen', 'registered', 'macron',
326 'degree', 'plusminus', 'twosuperior', 'threesuperior',
327 'acute', 'mu', 'paragraph', 'periodcentered',
328 'cedilla', 'onesuperior', 'ordmasculine', 'guillemotright',
329 'onequarter', 'onehalf', 'threequarters', 'questiondown',
330 'Agrave', 'Aacute', 'Acircumflex', 'Atilde',
331 'Adieresis', 'Aring', 'AE', 'Ccedilla',
332 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis',
333 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis',
334 'Gbreve', 'Ntilde', 'Ograve', 'Oacute',
335 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply',
336 'Oslash', 'Ugrave', 'Uacute', 'Ucircumflex',
337 'Udieresis', 'Idotaccent', 'Scedilla', 'germandbls',
338 'agrave', 'aacute', 'acircumflex', 'atilde',
339 'adieresis', 'aring', 'ae', 'ccedilla',
340 'egrave', 'eacute', 'ecircumflex', 'edieresis',
341 'igrave', 'iacute', 'icircumflex', 'idieresis',
342 'gbreve', 'ntilde', 'ograve', 'oacute',
343 'ocircumflex', 'otilde', 'odieresis', 'divide',
344 'oslash', 'ugrave', 'uacute', 'ucircumflex',
345 'udieresis', 'dotlessi', 'scedilla', 'ydieresis'
346 ],
347 # Hebrew
348 'cp1255' => [
349 '.notdef', '.notdef', '.notdef', '.notdef',
350 '.notdef', '.notdef', '.notdef', '.notdef',
351 '.notdef', '.notdef', '.notdef', '.notdef',
352 '.notdef', '.notdef', '.notdef', '.notdef',
353 '.notdef', '.notdef', '.notdef', '.notdef',
354 '.notdef', '.notdef', '.notdef', '.notdef',
355 '.notdef', '.notdef', '.notdef', '.notdef',
356 '.notdef', '.notdef', '.notdef', '.notdef',
357 'space', 'exclam', 'quotedbl', 'numbersign',
358 'dollar', 'percent', 'ampersand', 'quotesingle',
359 'parenleft', 'parenright', 'asterisk', 'plus',
360 'comma', 'hyphen', 'period', 'slash',
361 'zero', 'one', 'two', 'three',
362 'four', 'five', 'six', 'seven',
363 'eight', 'nine', 'colon', 'semicolon',
364 'less', 'equal', 'greater', 'question',
365 'at', 'A', 'B', 'C',
366 'D', 'E', 'F', 'G',
367 'H', 'I', 'J', 'K',
368 'L', 'M', 'N', 'O',
369 'P', 'Q', 'R', 'S',
370 'T', 'U', 'V', 'W',
371 'X', 'Y', 'Z', 'bracketleft',
372 'backslash', 'bracketright', 'asciicircum', 'underscore',
373 'grave', 'a', 'b', 'c',
374 'd', 'e', 'f', 'g',
375 'h', 'i', 'j', 'k',
376 'l', 'm', 'n', 'o',
377 'p', 'q', 'r', 's',
378 't', 'u', 'v', 'w',
379 'x', 'y', 'z', 'braceleft',
380 'bar', 'braceright', 'asciitilde', '.notdef',
381 'Euro', '.notdef', 'quotesinglbase', 'florin',
382 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl',
383 'circumflex', 'perthousand', '.notdef', 'guilsinglleft',
384 '.notdef', '.notdef', '.notdef', '.notdef',
385 '.notdef', 'quoteleft', 'quoteright', 'quotedblleft',
386 'quotedblright', 'bullet', 'endash', 'emdash',
387 'tilde', 'trademark', '.notdef', 'guilsinglright',
388 '.notdef', '.notdef', '.notdef', '.notdef',
389 'space', 'exclamdown', 'cent', 'sterling',
390 'afii57636', 'yen', 'brokenbar', 'section',
391 'dieresis', 'copyright', 'multiply', 'guillemotleft',
392 'logicalnot', 'sfthyphen', 'registered', 'macron',
393 'degree', 'plusminus', 'twosuperior', 'threesuperior',
394 'acute', 'mu', 'paragraph', 'middot',
395 'cedilla', 'onesuperior', 'divide', 'guillemotright',
396 'onequarter', 'onehalf', 'threequarters', 'questiondown',
397 'afii57799', 'afii57801', 'afii57800', 'afii57802',
398 'afii57793', 'afii57794', 'afii57795', 'afii57798',
399 'afii57797', 'afii57806', '.notdef', 'afii57796',
400 'afii57807', 'afii57839', 'afii57645', 'afii57841',
401 'afii57842', 'afii57804', 'afii57803', 'afii57658',
402 'afii57716', 'afii57717', 'afii57718', 'gereshhebrew',
403 'gershayimhebrew','.notdef', '.notdef', '.notdef',
404 '.notdef', '.notdef', '.notdef', '.notdef',
405 'afii57664', 'afii57665', 'afii57666', 'afii57667',
406 'afii57668', 'afii57669', 'afii57670', 'afii57671',
407 'afii57672', 'afii57673', 'afii57674', 'afii57675',
408 'afii57676', 'afii57677', 'afii57678', 'afii57679',
409 'afii57680', 'afii57681', 'afii57682', 'afii57683',
410 'afii57684', 'afii57685', 'afii57686', 'afii57687',
411 'afii57688', 'afii57689', 'afii57690', '.notdef',
412 '.notdef', 'afii299', 'afii300', '.notdef'
413 ],
414 # Baltic
415 'cp1257' => [
416 '.notdef', '.notdef', '.notdef', '.notdef',
417 '.notdef', '.notdef', '.notdef', '.notdef',
418 '.notdef', '.notdef', '.notdef', '.notdef',
419 '.notdef', '.notdef', '.notdef', '.notdef',
420 '.notdef', '.notdef', '.notdef', '.notdef',
421 '.notdef', '.notdef', '.notdef', '.notdef',
422 '.notdef', '.notdef', '.notdef', '.notdef',
423 '.notdef', '.notdef', '.notdef', '.notdef',
424 'space', 'exclam', 'quotedbl', 'numbersign',
425 'dollar', 'percent', 'ampersand', 'quotesingle',
426 'parenleft', 'parenright', 'asterisk', 'plus',
427 'comma', 'hyphen', 'period', 'slash',
428 'zero', 'one', 'two', 'three',
429 'four', 'five', 'six', 'seven',
430 'eight', 'nine', 'colon', 'semicolon',
431 'less', 'equal', 'greater', 'question',
432 'at', 'A', 'B', 'C',
433 'D', 'E', 'F', 'G',
434 'H', 'I', 'J', 'K',
435 'L', 'M', 'N', 'O',
436 'P', 'Q', 'R', 'S',
437 'T', 'U', 'V', 'W',
438 'X', 'Y', 'Z', 'bracketleft',
439 'backslash', 'bracketright', 'asciicircum', 'underscore',
440 'grave', 'a', 'b', 'c',
441 'd', 'e', 'f', 'g',
442 'h', 'i', 'j', 'k',
443 'l', 'm', 'n', 'o',
444 'p', 'q', 'r', 's',
445 't', 'u', 'v', 'w',
446 'x', 'y', 'z', 'braceleft',
447 'bar', 'braceright', 'asciitilde', '.notdef',
448 'Euro', '.notdef', 'quotesinglbase', '.notdef',
449 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl',
450 '.notdef', 'perthousand', '.notdef', 'guilsinglleft',
451 '.notdef', 'dieresis', 'caron', 'cedilla',
452 '.notdef', 'quoteleft', 'quoteright', 'quotedblleft',
453 'quotedblright', 'bullet', 'endash', 'emdash',
454 '.notdef', 'trademark', '.notdef', 'guilsinglright',
455 '.notdef', 'macron', 'ogonek', '.notdef',
456 'space', '.notdef', 'cent', 'sterling',
457 'currency', '.notdef', 'brokenbar', 'section',
458 'Oslash', 'copyright', 'Rcommaaccent', 'guillemotleft',
459 'logicalnot', 'hyphen', 'registered', 'AE',
460 'degree', 'plusminus', 'twosuperior', 'threesuperior',
461 'acute', 'mu', 'paragraph', 'periodcentered',
462 'oslash', 'onesuperior', 'rcommaaccent', 'guillemotright',
463 'onequarter', 'onehalf', 'threequarters', 'ae',
464 'Aogonek', 'Iogonek', 'Amacron', 'Cacute',
465 'Adieresis', 'Aring', 'Eogonek', 'Emacron',
466 'Ccaron', 'Eacute', 'Zacute', 'Edotaccent',
467 'Gcommaaccent', 'Kcommaaccent', 'Imacron', 'Lcommaaccent',
468 'Scaron', 'Nacute', 'Ncommaaccent', 'Oacute',
469 'Omacron', 'Otilde', 'Odieresis', 'multiply',
470 'Uogonek', 'Lslash', 'Sacute', 'Umacron',
471 'Udieresis', 'Zdotaccent', 'Zcaron', 'germandbls',
472 'aogonek', 'iogonek', 'amacron', 'cacute',
473 'adieresis', 'aring', 'eogonek', 'emacron',
474 'ccaron', 'eacute', 'zacute', 'edotaccent',
475 'gcommaaccent', 'kcommaaccent', 'imacron', 'lcommaaccent',
476 'scaron', 'nacute', 'ncommaaccent', 'oacute',
477 'omacron', 'otilde', 'odieresis', 'divide',
478 'uogonek', 'lslash', 'sacute', 'umacron',
479 'udieresis', 'zdotaccent', 'zcaron', 'dotaccent'
480 ],
481 # Vietnamese
482 'cp1258' => [
483 '.notdef', '.notdef', '.notdef', '.notdef',
484 '.notdef', '.notdef', '.notdef', '.notdef',
485 '.notdef', '.notdef', '.notdef', '.notdef',
486 '.notdef', '.notdef', '.notdef', '.notdef',
487 '.notdef', '.notdef', '.notdef', '.notdef',
488 '.notdef', '.notdef', '.notdef', '.notdef',
489 '.notdef', '.notdef', '.notdef', '.notdef',
490 '.notdef', '.notdef', '.notdef', '.notdef',
491 'space', 'exclam', 'quotedbl', 'numbersign',
492 'dollar', 'percent', 'ampersand', 'quotesingle',
493 'parenleft', 'parenright', 'asterisk', 'plus',
494 'comma', 'hyphen', 'period', 'slash',
495 'zero', 'one', 'two', 'three',
496 'four', 'five', 'six', 'seven',
497 'eight', 'nine', 'colon', 'semicolon',
498 'less', 'equal', 'greater', 'question',
499 'at', 'A', 'B', 'C',
500 'D', 'E', 'F', 'G',
501 'H', 'I', 'J', 'K',
502 'L', 'M', 'N', 'O',
503 'P', 'Q', 'R', 'S',
504 'T', 'U', 'V', 'W',
505 'X', 'Y', 'Z', 'bracketleft',
506 'backslash', 'bracketright', 'asciicircum', 'underscore',
507 'grave', 'a', 'b', 'c',
508 'd', 'e', 'f', 'g',
509 'h', 'i', 'j', 'k',
510 'l', 'm', 'n', 'o',
511 'p', 'q', 'r', 's',
512 't', 'u', 'v', 'w',
513 'x', 'y', 'z', 'braceleft',
514 'bar', 'braceright', 'asciitilde', '.notdef',
515 'Euro', '.notdef', 'quotesinglbase', 'florin',
516 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl',
517 'circumflex', 'perthousand', '.notdef', 'guilsinglleft',
518 'OE', '.notdef', '.notdef', '.notdef',
519 '.notdef', 'quoteleft', 'quoteright', 'quotedblleft',
520 'quotedblright', 'bullet', 'endash', 'emdash',
521 'tilde', 'trademark', '.notdef', 'guilsinglright',
522 'oe', '.notdef', '.notdef', 'Ydieresis',
523 'space', 'exclamdown', 'cent', 'sterling',
524 'currency', 'yen', 'brokenbar', 'section',
525 'dieresis', 'copyright', 'ordfeminine', 'guillemotleft',
526 'logicalnot', 'hyphen', 'registered', 'macron',
527 'degree', 'plusminus', 'twosuperior', 'threesuperior',
528 'acute', 'mu', 'paragraph', 'periodcentered',
529 'cedilla', 'onesuperior', 'ordmasculine', 'guillemotright',
530 'onequarter', 'onehalf', 'threequarters', 'questiondown',
531 'Agrave', 'Aacute', 'Acircumflex', 'Abreve',
532 'Adieresis', 'Aring', 'AE', 'Ccedilla',
533 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis',
534 'gravecomb', 'Iacute', 'Icircumflex', 'Idieresis',
535 'Dcroat', 'Ntilde', 'hookabovecomb', 'Oacute',
536 'Ocircumflex', 'Ohorn', 'Odieresis', 'multiply',
537 'Oslash', 'Ugrave', 'Uacute', 'Ucircumflex',
538 'Udieresis', 'Uhorn', 'tildecomb', 'germandbls',
539 'agrave', 'aacute', 'acircumflex', 'abreve',
540 'adieresis', 'aring', 'ae', 'ccedilla',
541 'egrave', 'eacute', 'ecircumflex', 'edieresis',
542 'acutecomb', 'iacute', 'icircumflex', 'idieresis',
543 'dcroat', 'ntilde', 'dotbelowcomb', 'oacute',
544 'ocircumflex', 'ohorn', 'odieresis', 'divide',
545 'oslash', 'ugrave', 'uacute', 'ucircumflex',
546 'udieresis', 'uhorn', 'dong', 'ydieresis'
547 ],
548 # Thai
549 'cp874' => [
550 '.notdef', '.notdef', '.notdef', '.notdef',
551 '.notdef', '.notdef', '.notdef', '.notdef',
552 '.notdef', '.notdef', '.notdef', '.notdef',
553 '.notdef', '.notdef', '.notdef', '.notdef',
554 '.notdef', '.notdef', '.notdef', '.notdef',
555 '.notdef', '.notdef', '.notdef', '.notdef',
556 '.notdef', '.notdef', '.notdef', '.notdef',
557 '.notdef', '.notdef', '.notdef', '.notdef',
558 'space', 'exclam', 'quotedbl', 'numbersign',
559 'dollar', 'percent', 'ampersand', 'quotesingle',
560 'parenleft', 'parenright', 'asterisk', 'plus',
561 'comma', 'hyphen', 'period', 'slash',
562 'zero', 'one', 'two', 'three',
563 'four', 'five', 'six', 'seven',
564 'eight', 'nine', 'colon', 'semicolon',
565 'less', 'equal', 'greater', 'question',
566 'at', 'A', 'B', 'C',
567 'D', 'E', 'F', 'G',
568 'H', 'I', 'J', 'K',
569 'L', 'M', 'N', 'O',
570 'P', 'Q', 'R', 'S',
571 'T', 'U', 'V', 'W',
572 'X', 'Y', 'Z', 'bracketleft',
573 'backslash', 'bracketright', 'asciicircum', 'underscore',
574 'grave', 'a', 'b', 'c',
575 'd', 'e', 'f', 'g',
576 'h', 'i', 'j', 'k',
577 'l', 'm', 'n', 'o',
578 'p', 'q', 'r', 's',
579 't', 'u', 'v', 'w',
580 'x', 'y', 'z', 'braceleft',
581 'bar', 'braceright', 'asciitilde', '.notdef',
582 'Euro', '.notdef', '.notdef', '.notdef',
583 '.notdef', 'ellipsis', '.notdef', '.notdef',
584 '.notdef', '.notdef', '.notdef', '.notdef',
585 '.notdef', '.notdef', '.notdef', '.notdef',
586 '.notdef', 'quoteleft', 'quoteright', 'quotedblleft',
587 'quotedblright', 'bullet', 'endash', 'emdash',
588 '.notdef', '.notdef', '.notdef', '.notdef',
589 '.notdef', '.notdef', '.notdef', '.notdef',
590 'space', 'kokaithai', 'khokhaithai', 'khokhuatthai',
591 'khokhwaithai', 'khokhonthai', 'khorakhangthai', 'ngonguthai',
592 'chochanthai', 'chochingthai', 'chochangthai', 'sosothai',
593 'chochoethai', 'yoyingthai', 'dochadathai', 'topatakthai',
594 'thothanthai', 'thonangmonthothai', 'thophuthaothai', 'nonenthai',
595 'dodekthai', 'totaothai', 'thothungthai', 'thothahanthai',
596 'thothongthai', 'nonuthai', 'bobaimaithai', 'poplathai',
597 'phophungthai', 'fofathai', 'phophanthai', 'fofanthai',
598 'phosamphaothai', 'momathai', 'yoyakthai', 'roruathai',
599 'ruthai', 'lolingthai', 'luthai', 'wowaenthai',
600 'sosalathai', 'sorusithai', 'sosuathai', 'hohipthai',
601 'lochulathai', 'oangthai', 'honokhukthai', 'paiyannoithai',
602 'saraathai', 'maihanakatthai', 'saraaathai', 'saraamthai',
603 'saraithai', 'saraiithai', 'sarauethai', 'saraueethai',
604 'sarauthai', 'sarauuthai', 'phinthuthai', '.notdef',
605 '.notdef', '.notdef', '.notdef', 'bahtthai',
606 'saraethai', 'saraaethai', 'saraothai', 'saraaimaimuanthai',
607 'saraaimaimalaithai', 'lakkhangyaothai', 'maiyamokthai', 'maitaikhuthai',
608 'maiekthai', 'maithothai', 'maitrithai', 'maichattawathai',
609 'thanthakhatthai', 'nikhahitthai', 'yamakkanthai', 'fongmanthai',
610 'zerothai', 'onethai', 'twothai', 'threethai',
611 'fourthai', 'fivethai', 'sixthai', 'seventhai',
612 'eightthai', 'ninethai', 'angkhankhuthai', 'khomutthai',
613 '.notdef', '.notdef', '.notdef', '.notdef'
614 ],
615 # Western Europe
616 'ISO-8859-1' => [
617 '.notdef', '.notdef', '.notdef', '.notdef',
618 '.notdef', '.notdef', '.notdef', '.notdef',
619 '.notdef', '.notdef', '.notdef', '.notdef',
620 '.notdef', '.notdef', '.notdef', '.notdef',
621 '.notdef', '.notdef', '.notdef', '.notdef',
622 '.notdef', '.notdef', '.notdef', '.notdef',
623 '.notdef', '.notdef', '.notdef', '.notdef',
624 '.notdef', '.notdef', '.notdef', '.notdef',
625 'space', 'exclam', 'quotedbl', 'numbersign',
626 'dollar', 'percent', 'ampersand', 'quotesingle',
627 'parenleft', 'parenright', 'asterisk', 'plus',
628 'comma', 'hyphen', 'period', 'slash',
629 'zero', 'one', 'two', 'three',
630 'four', 'five', 'six', 'seven',
631 'eight', 'nine', 'colon', 'semicolon',
632 'less', 'equal', 'greater', 'question',
633 'at', 'A', 'B', 'C',
634 'D', 'E', 'F', 'G',
635 'H', 'I', 'J', 'K',
636 'L', 'M', 'N', 'O',
637 'P', 'Q', 'R', 'S',
638 'T', 'U', 'V', 'W',
639 'X', 'Y', 'Z', 'bracketleft',
640 'backslash', 'bracketright', 'asciicircum', 'underscore',
641 'grave', 'a', 'b', 'c',
642 'd', 'e', 'f', 'g',
643 'h', 'i', 'j', 'k',
644 'l', 'm', 'n', 'o',
645 'p', 'q', 'r', 's',
646 't', 'u', 'v', 'w',
647 'x', 'y', 'z', 'braceleft',
648 'bar', 'braceright', 'asciitilde', '.notdef',
649 '.notdef', '.notdef', '.notdef', '.notdef',
650 '.notdef', '.notdef', '.notdef', '.notdef',
651 '.notdef', '.notdef', '.notdef', '.notdef',
652 '.notdef', '.notdef', '.notdef', '.notdef',
653 '.notdef', '.notdef', '.notdef', '.notdef',
654 '.notdef', '.notdef', '.notdef', '.notdef',
655 '.notdef', '.notdef', '.notdef', '.notdef',
656 '.notdef', '.notdef', '.notdef', '.notdef',
657 'space', 'exclamdown', 'cent', 'sterling',
658 'currency', 'yen', 'brokenbar', 'section',
659 'dieresis', 'copyright', 'ordfeminine', 'guillemotleft',
660 'logicalnot', 'hyphen', 'registered', 'macron',
661 'degree', 'plusminus', 'twosuperior', 'threesuperior',
662 'acute', 'mu', 'paragraph', 'periodcentered',
663 'cedilla', 'onesuperior', 'ordmasculine', 'guillemotright',
664 'onequarter', 'onehalf', 'threequarters', 'questiondown',
665 'Agrave', 'Aacute', 'Acircumflex', 'Atilde',
666 'Adieresis', 'Aring', 'AE', 'Ccedilla',
667 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis',
668 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis',
669 'Eth', 'Ntilde', 'Ograve', 'Oacute',
670 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply',
671 'Oslash', 'Ugrave', 'Uacute', 'Ucircumflex',
672 'Udieresis', 'Yacute', 'Thorn', 'germandbls',
673 'agrave', 'aacute', 'acircumflex', 'atilde',
674 'adieresis', 'aring', 'ae', 'ccedilla',
675 'egrave', 'eacute', 'ecircumflex', 'edieresis',
676 'igrave', 'iacute', 'icircumflex', 'idieresis',
677 'eth', 'ntilde', 'ograve', 'oacute',
678 'ocircumflex', 'otilde', 'odieresis', 'divide',
679 'oslash', 'ugrave', 'uacute', 'ucircumflex',
680 'udieresis', 'yacute', 'thorn', 'ydieresis'
681 ],
682 # Central Europe
683 'ISO-8859-2' => [
684 '.notdef', '.notdef', '.notdef', '.notdef',
685 '.notdef', '.notdef', '.notdef', '.notdef',
686 '.notdef', '.notdef', '.notdef', '.notdef',
687 '.notdef', '.notdef', '.notdef', '.notdef',
688 '.notdef', '.notdef', '.notdef', '.notdef',
689 '.notdef', '.notdef', '.notdef', '.notdef',
690 '.notdef', '.notdef', '.notdef', '.notdef',
691 '.notdef', '.notdef', '.notdef', '.notdef',
692 'space', 'exclam', 'quotedbl', 'numbersign',
693 'dollar', 'percent', 'ampersand', 'quotesingle',
694 'parenleft', 'parenright', 'asterisk', 'plus',
695 'comma', 'hyphen', 'period', 'slash',
696 'zero', 'one', 'two', 'three',
697 'four', 'five', 'six', 'seven',
698 'eight', 'nine', 'colon', 'semicolon',
699 'less', 'equal', 'greater', 'question',
700 'at', 'A', 'B', 'C',
701 'D', 'E', 'F', 'G',
702 'H', 'I', 'J', 'K',
703 'L', 'M', 'N', 'O',
704 'P', 'Q', 'R', 'S',
705 'T', 'U', 'V', 'W',
706 'X', 'Y', 'Z', 'bracketleft',
707 'backslash', 'bracketright', 'asciicircum', 'underscore',
708 'grave', 'a', 'b', 'c',
709 'd', 'e', 'f', 'g',
710 'h', 'i', 'j', 'k',
711 'l', 'm', 'n', 'o',
712 'p', 'q', 'r', 's',
713 't', 'u', 'v', 'w',
714 'x', 'y', 'z', 'braceleft',
715 'bar', 'braceright', 'asciitilde', '.notdef',
716 '.notdef', '.notdef', '.notdef', '.notdef',
717 '.notdef', '.notdef', '.notdef', '.notdef',
718 '.notdef', '.notdef', '.notdef', '.notdef',
719 '.notdef', '.notdef', '.notdef', '.notdef',
720 '.notdef', '.notdef', '.notdef', '.notdef',
721 '.notdef', '.notdef', '.notdef', '.notdef',
722 '.notdef', '.notdef', '.notdef', '.notdef',
723 '.notdef', '.notdef', '.notdef', '.notdef',
724 'space', 'Aogonek', 'breve', 'Lslash',
725 'currency', 'Lcaron', 'Sacute', 'section',
726 'dieresis', 'Scaron', 'Scedilla', 'Tcaron',
727 'Zacute', 'hyphen', 'Zcaron', 'Zdotaccent',
728 'degree', 'aogonek', 'ogonek', 'lslash',
729 'acute', 'lcaron', 'sacute', 'caron',
730 'cedilla', 'scaron', 'scedilla', 'tcaron',
731 'zacute', 'hungarumlaut', 'zcaron', 'zdotaccent',
732 'Racute', 'Aacute', 'Acircumflex', 'Abreve',
733 'Adieresis', 'Lacute', 'Cacute', 'Ccedilla',
734 'Ccaron', 'Eacute', 'Eogonek', 'Edieresis',
735 'Ecaron', 'Iacute', 'Icircumflex', 'Dcaron',
736 'Dcroat', 'Nacute', 'Ncaron', 'Oacute',
737 'Ocircumflex', 'Ohungarumlaut', 'Odieresis', 'multiply',
738 'Rcaron', 'Uring', 'Uacute', 'Uhungarumlaut',
739 'Udieresis', 'Yacute', 'Tcommaaccent', 'germandbls',
740 'racute', 'aacute', 'acircumflex', 'abreve',
741 'adieresis', 'lacute', 'cacute', 'ccedilla',
742 'ccaron', 'eacute', 'eogonek', 'edieresis',
743 'ecaron', 'iacute', 'icircumflex', 'dcaron',
744 'dcroat', 'nacute', 'ncaron', 'oacute',
745 'ocircumflex', 'ohungarumlaut', 'odieresis', 'divide',
746 'rcaron', 'uring', 'uacute', 'uhungarumlaut',
747 'udieresis', 'yacute', 'tcommaaccent', 'dotaccent'
748 ],
749 # Baltic
750 'ISO-8859-4' => [
751 '.notdef', '.notdef', '.notdef', '.notdef',
752 '.notdef', '.notdef', '.notdef', '.notdef',
753 '.notdef', '.notdef', '.notdef', '.notdef',
754 '.notdef', '.notdef', '.notdef', '.notdef',
755 '.notdef', '.notdef', '.notdef', '.notdef',
756 '.notdef', '.notdef', '.notdef', '.notdef',
757 '.notdef', '.notdef', '.notdef', '.notdef',
758 '.notdef', '.notdef', '.notdef', '.notdef',
759 'space', 'exclam', 'quotedbl', 'numbersign',
760 'dollar', 'percent', 'ampersand', 'quotesingle',
761 'parenleft', 'parenright', 'asterisk', 'plus',
762 'comma', 'hyphen', 'period', 'slash',
763 'zero', 'one', 'two', 'three',
764 'four', 'five', 'six', 'seven',
765 'eight', 'nine', 'colon', 'semicolon',
766 'less', 'equal', 'greater', 'question',
767 'at', 'A', 'B', 'C',
768 'D', 'E', 'F', 'G',
769 'H', 'I', 'J', 'K',
770 'L', 'M', 'N', 'O',
771 'P', 'Q', 'R', 'S',
772 'T', 'U', 'V', 'W',
773 'X', 'Y', 'Z', 'bracketleft',
774 'backslash', 'bracketright', 'asciicircum', 'underscore',
775 'grave', 'a', 'b', 'c',
776 'd', 'e', 'f', 'g',
777 'h', 'i', 'j', 'k',
778 'l', 'm', 'n', 'o',
779 'p', 'q', 'r', 's',
780 't', 'u', 'v', 'w',
781 'x', 'y', 'z', 'braceleft',
782 'bar', 'braceright', 'asciitilde', '.notdef',
783 '.notdef', '.notdef', '.notdef', '.notdef',
784 '.notdef', '.notdef', '.notdef', '.notdef',
785 '.notdef', '.notdef', '.notdef', '.notdef',
786 '.notdef', '.notdef', '.notdef', '.notdef',
787 '.notdef', '.notdef', '.notdef', '.notdef',
788 '.notdef', '.notdef', '.notdef', '.notdef',
789 '.notdef', '.notdef', '.notdef', '.notdef',
790 '.notdef', '.notdef', '.notdef', '.notdef',
791 'space', 'Aogonek', 'kgreenlandic', 'Rcommaaccent',
792 'currency', 'Itilde', 'Lcommaaccent', 'section',
793 'dieresis', 'Scaron', 'Emacron', 'Gcommaaccent',
794 'Tbar', 'hyphen', 'Zcaron', 'macron',
795 'degree', 'aogonek', 'ogonek', 'rcommaaccent',
796 'acute', 'itilde', 'lcommaaccent', 'caron',
797 'cedilla', 'scaron', 'emacron', 'gcommaaccent',
798 'tbar', 'Eng', 'zcaron', 'eng',
799 'Amacron', 'Aacute', 'Acircumflex', 'Atilde',
800 'Adieresis', 'Aring', 'AE', 'Iogonek',
801 'Ccaron', 'Eacute', 'Eogonek', 'Edieresis',
802 'Edotaccent', 'Iacute', 'Icircumflex', 'Imacron',
803 'Dcroat', 'Ncommaaccent', 'Omacron', 'Kcommaaccent',
804 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply',
805 'Oslash', 'Uogonek', 'Uacute', 'Ucircumflex',
806 'Udieresis', 'Utilde', 'Umacron', 'germandbls',
807 'amacron', 'aacute', 'acircumflex', 'atilde',
808 'adieresis', 'aring', 'ae', 'iogonek',
809 'ccaron', 'eacute', 'eogonek', 'edieresis',
810 'edotaccent', 'iacute', 'icircumflex', 'imacron',
811 'dcroat', 'ncommaaccent', 'omacron', 'kcommaaccent',
812 'ocircumflex', 'otilde', 'odieresis', 'divide',
813 'oslash', 'uogonek', 'uacute', 'ucircumflex',
814 'udieresis', 'utilde', 'umacron', 'dotaccent'
815 ],
816 # Cyrillic
817 'ISO-8859-5' => [
818 '.notdef', '.notdef', '.notdef', '.notdef',
819 '.notdef', '.notdef', '.notdef', '.notdef',
820 '.notdef', '.notdef', '.notdef', '.notdef',
821 '.notdef', '.notdef', '.notdef', '.notdef',
822 '.notdef', '.notdef', '.notdef', '.notdef',
823 '.notdef', '.notdef', '.notdef', '.notdef',
824 '.notdef', '.notdef', '.notdef', '.notdef',
825 '.notdef', '.notdef', '.notdef', '.notdef',
826 'space', 'exclam', 'quotedbl', 'numbersign',
827 'dollar', 'percent', 'ampersand', 'quotesingle',
828 'parenleft', 'parenright', 'asterisk', 'plus',
829 'comma', 'hyphen', 'period', 'slash',
830 'zero', 'one', 'two', 'three',
831 'four', 'five', 'six', 'seven',
832 'eight', 'nine', 'colon', 'semicolon',
833 'less', 'equal', 'greater', 'question',
834 'at', 'A', 'B', 'C',
835 'D', 'E', 'F', 'G',
836 'H', 'I', 'J', 'K',
837 'L', 'M', 'N', 'O',
838 'P', 'Q', 'R', 'S',
839 'T', 'U', 'V', 'W',
840 'X', 'Y', 'Z', 'bracketleft',
841 'backslash', 'bracketright', 'asciicircum', 'underscore',
842 'grave', 'a', 'b', 'c',
843 'd', 'e', 'f', 'g',
844 'h', 'i', 'j', 'k',
845 'l', 'm', 'n', 'o',
846 'p', 'q', 'r', 's',
847 't', 'u', 'v', 'w',
848 'x', 'y', 'z', 'braceleft',
849 'bar', 'braceright', 'asciitilde', '.notdef',
850 '.notdef', '.notdef', '.notdef', '.notdef',
851 '.notdef', '.notdef', '.notdef', '.notdef',
852 '.notdef', '.notdef', '.notdef', '.notdef',
853 '.notdef', '.notdef', '.notdef', '.notdef',
854 '.notdef', '.notdef', '.notdef', '.notdef',
855 '.notdef', '.notdef', '.notdef', '.notdef',
856 '.notdef', '.notdef', '.notdef', '.notdef',
857 '.notdef', '.notdef', '.notdef', '.notdef',
858 'space', 'afii10023', 'afii10051', 'afii10052',
859 'afii10053', 'afii10054', 'afii10055', 'afii10056',
860 'afii10057', 'afii10058', 'afii10059', 'afii10060',
861 'afii10061', 'hyphen', 'afii10062', 'afii10145',
862 'afii10017', 'afii10018', 'afii10019', 'afii10020',
863 'afii10021', 'afii10022', 'afii10024', 'afii10025',
864 'afii10026', 'afii10027', 'afii10028', 'afii10029',
865 'afii10030', 'afii10031', 'afii10032', 'afii10033',
866 'afii10034', 'afii10035', 'afii10036', 'afii10037',
867 'afii10038', 'afii10039', 'afii10040', 'afii10041',
868 'afii10042', 'afii10043', 'afii10044', 'afii10045',
869 'afii10046', 'afii10047', 'afii10048', 'afii10049',
870 'afii10065', 'afii10066', 'afii10067', 'afii10068',
871 'afii10069', 'afii10070', 'afii10072', 'afii10073',
872 'afii10074', 'afii10075', 'afii10076', 'afii10077',
873 'afii10078', 'afii10079', 'afii10080', 'afii10081',
874 'afii10082', 'afii10083', 'afii10084', 'afii10085',
875 'afii10086', 'afii10087', 'afii10088', 'afii10089',
876 'afii10090', 'afii10091', 'afii10092', 'afii10093',
877 'afii10094', 'afii10095', 'afii10096', 'afii10097',
878 'afii61352', 'afii10071', 'afii10099', 'afii10100',
879 'afii10101', 'afii10102', 'afii10103', 'afii10104',
880 'afii10105', 'afii10106', 'afii10107', 'afii10108',
881 'afii10109', 'section', 'afii10110', 'afii10193'
882 ],
883 # Greek
884 'ISO-8859-7' => [
885 '.notdef', '.notdef', '.notdef', '.notdef',
886 '.notdef', '.notdef', '.notdef', '.notdef',
887 '.notdef', '.notdef', '.notdef', '.notdef',
888 '.notdef', '.notdef', '.notdef', '.notdef',
889 '.notdef', '.notdef', '.notdef', '.notdef',
890 '.notdef', '.notdef', '.notdef', '.notdef',
891 '.notdef', '.notdef', '.notdef', '.notdef',
892 '.notdef', '.notdef', '.notdef', '.notdef',
893 'space', 'exclam', 'quotedbl', 'numbersign',
894 'dollar', 'percent', 'ampersand', 'quotesingle',
895 'parenleft', 'parenright', 'asterisk', 'plus',
896 'comma', 'hyphen', 'period', 'slash',
897 'zero', 'one', 'two', 'three',
898 'four', 'five', 'six', 'seven',
899 'eight', 'nine', 'colon', 'semicolon',
900 'less', 'equal', 'greater', 'question',
901 'at', 'A', 'B', 'C',
902 'D', 'E', 'F', 'G',
903 'H', 'I', 'J', 'K',
904 'L', 'M', 'N', 'O',
905 'P', 'Q', 'R', 'S',
906 'T', 'U', 'V', 'W',
907 'X', 'Y', 'Z', 'bracketleft',
908 'backslash', 'bracketright', 'asciicircum', 'underscore',
909 'grave', 'a', 'b', 'c',
910 'd', 'e', 'f', 'g',
911 'h', 'i', 'j', 'k',
912 'l', 'm', 'n', 'o',
913 'p', 'q', 'r', 's',
914 't', 'u', 'v', 'w',
915 'x', 'y', 'z', 'braceleft',
916 'bar', 'braceright', 'asciitilde', '.notdef',
917 '.notdef', '.notdef', '.notdef', '.notdef',
918 '.notdef', '.notdef', '.notdef', '.notdef',
919 '.notdef', '.notdef', '.notdef', '.notdef',
920 '.notdef', '.notdef', '.notdef', '.notdef',
921 '.notdef', '.notdef', '.notdef', '.notdef',
922 '.notdef', '.notdef', '.notdef', '.notdef',
923 '.notdef', '.notdef', '.notdef', '.notdef',
924 '.notdef', '.notdef', '.notdef', '.notdef',
925 'space', 'quoteleft', 'quoteright', 'sterling',
926 '.notdef', '.notdef', 'brokenbar', 'section',
927 'dieresis', 'copyright', '.notdef', 'guillemotleft',
928 'logicalnot', 'hyphen', '.notdef', 'afii00208',
929 'degree', 'plusminus', 'twosuperior', 'threesuperior',
930 'tonos', 'dieresistonos', 'Alphatonos', 'periodcentered',
931 'Epsilontonos', 'Etatonos', 'Iotatonos', 'guillemotright',
932 'Omicrontonos', 'onehalf', 'Upsilontonos', 'Omegatonos',
933 'iotadieresistonos','Alpha', 'Beta', 'Gamma',
934 'Delta', 'Epsilon', 'Zeta', 'Eta',
935 'Theta', 'Iota', 'Kappa', 'Lambda',
936 'Mu', 'Nu', 'Xi', 'Omicron',
937 'Pi', 'Rho', '.notdef', 'Sigma',
938 'Tau', 'Upsilon', 'Phi', 'Chi',
939 'Psi', 'Omega', 'Iotadieresis', 'Upsilondieresis',
940 'alphatonos', 'epsilontonos', 'etatonos', 'iotatonos',
941 'upsilondieresistonos','alpha', 'beta', 'gamma',
942 'delta', 'epsilon', 'zeta', 'eta',
943 'theta', 'iota', 'kappa', 'lambda',
944 'mu', 'nu', 'xi', 'omicron',
945 'pi', 'rho', 'sigma1', 'sigma',
946 'tau', 'upsilon', 'phi', 'chi',
947 'psi', 'omega', 'iotadieresis', 'upsilondieresis',
948 'omicrontonos', 'upsilontonos', 'omegatonos', '.notdef'
949 ],
950 # Turkish
951 'ISO-8859-9' => [
952 '.notdef', '.notdef', '.notdef', '.notdef',
953 '.notdef', '.notdef', '.notdef', '.notdef',
954 '.notdef', '.notdef', '.notdef', '.notdef',
955 '.notdef', '.notdef', '.notdef', '.notdef',
956 '.notdef', '.notdef', '.notdef', '.notdef',
957 '.notdef', '.notdef', '.notdef', '.notdef',
958 '.notdef', '.notdef', '.notdef', '.notdef',
959 '.notdef', '.notdef', '.notdef', '.notdef',
960 'space', 'exclam', 'quotedbl', 'numbersign',
961 'dollar', 'percent', 'ampersand', 'quotesingle',
962 'parenleft', 'parenright', 'asterisk', 'plus',
963 'comma', 'hyphen', 'period', 'slash',
964 'zero', 'one', 'two', 'three',
965 'four', 'five', 'six', 'seven',
966 'eight', 'nine', 'colon', 'semicolon',
967 'less', 'equal', 'greater', 'question',
968 'at', 'A', 'B', 'C',
969 'D', 'E', 'F', 'G',
970 'H', 'I', 'J', 'K',
971 'L', 'M', 'N', 'O',
972 'P', 'Q', 'R', 'S',
973 'T', 'U', 'V', 'W',
974 'X', 'Y', 'Z', 'bracketleft',
975 'backslash', 'bracketright', 'asciicircum', 'underscore',
976 'grave', 'a', 'b', 'c',
977 'd', 'e', 'f', 'g',
978 'h', 'i', 'j', 'k',
979 'l', 'm', 'n', 'o',
980 'p', 'q', 'r', 's',
981 't', 'u', 'v', 'w',
982 'x', 'y', 'z', 'braceleft',
983 'bar', 'braceright', 'asciitilde', '.notdef',
984 '.notdef', '.notdef', '.notdef', '.notdef',
985 '.notdef', '.notdef', '.notdef', '.notdef',
986 '.notdef', '.notdef', '.notdef', '.notdef',
987 '.notdef', '.notdef', '.notdef', '.notdef',
988 '.notdef', '.notdef', '.notdef', '.notdef',
989 '.notdef', '.notdef', '.notdef', '.notdef',
990 '.notdef', '.notdef', '.notdef', '.notdef',
991 '.notdef', '.notdef', '.notdef', '.notdef',
992 'space', 'exclamdown', 'cent', 'sterling',
993 'currency', 'yen', 'brokenbar', 'section',
994 'dieresis', 'copyright', 'ordfeminine', 'guillemotleft',
995 'logicalnot', 'hyphen', 'registered', 'macron',
996 'degree', 'plusminus', 'twosuperior', 'threesuperior',
997 'acute', 'mu', 'paragraph', 'periodcentered',
998 'cedilla', 'onesuperior', 'ordmasculine', 'guillemotright',
999 'onequarter', 'onehalf', 'threequarters', 'questiondown',
1000 'Agrave', 'Aacute', 'Acircumflex', 'Atilde',
1001 'Adieresis', 'Aring', 'AE', 'Ccedilla',
1002 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis',
1003 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis',
1004 'Gbreve', 'Ntilde', 'Ograve', 'Oacute',
1005 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply',
1006 'Oslash', 'Ugrave', 'Uacute', 'Ucircumflex',
1007 'Udieresis', 'Idotaccent', 'Scedilla', 'germandbls',
1008 'agrave', 'aacute', 'acircumflex', 'atilde',
1009 'adieresis', 'aring', 'ae', 'ccedilla',
1010 'egrave', 'eacute', 'ecircumflex', 'edieresis',
1011 'igrave', 'iacute', 'icircumflex', 'idieresis',
1012 'gbreve', 'ntilde', 'ograve', 'oacute',
1013 'ocircumflex', 'otilde', 'odieresis', 'divide',
1014 'oslash', 'ugrave', 'uacute', 'ucircumflex',
1015 'udieresis', 'dotlessi', 'scedilla', 'ydieresis'
1016 ],
1017 # Thai
1018 'ISO-8859-11' => [
1019 '.notdef', '.notdef', '.notdef', '.notdef',
1020 '.notdef', '.notdef', '.notdef', '.notdef',
1021 '.notdef', '.notdef', '.notdef', '.notdef',
1022 '.notdef', '.notdef', '.notdef', '.notdef',
1023 '.notdef', '.notdef', '.notdef', '.notdef',
1024 '.notdef', '.notdef', '.notdef', '.notdef',
1025 '.notdef', '.notdef', '.notdef', '.notdef',
1026 '.notdef', '.notdef', '.notdef', '.notdef',
1027 'space', 'exclam', 'quotedbl', 'numbersign',
1028 'dollar', 'percent', 'ampersand', 'quotesingle',
1029 'parenleft', 'parenright', 'asterisk', 'plus',
1030 'comma', 'hyphen', 'period', 'slash',
1031 'zero', 'one', 'two', 'three',
1032 'four', 'five', 'six', 'seven',
1033 'eight', 'nine', 'colon', 'semicolon',
1034 'less', 'equal', 'greater', 'question',
1035 'at', 'A', 'B', 'C',
1036 'D', 'E', 'F', 'G',
1037 'H', 'I', 'J', 'K',
1038 'L', 'M', 'N', 'O',
1039 'P', 'Q', 'R', 'S',
1040 'T', 'U', 'V', 'W',
1041 'X', 'Y', 'Z', 'bracketleft',
1042 'backslash', 'bracketright', 'asciicircum', 'underscore',
1043 'grave', 'a', 'b', 'c',
1044 'd', 'e', 'f', 'g',
1045 'h', 'i', 'j', 'k',
1046 'l', 'm', 'n', 'o',
1047 'p', 'q', 'r', 's',
1048 't', 'u', 'v', 'w',
1049 'x', 'y', 'z', 'braceleft',
1050 'bar', 'braceright', 'asciitilde', '.notdef',
1051 '.notdef', '.notdef', '.notdef', '.notdef',
1052 '.notdef', '.notdef', '.notdef', '.notdef',
1053 '.notdef', '.notdef', '.notdef', '.notdef',
1054 '.notdef', '.notdef', '.notdef', '.notdef',
1055 '.notdef', '.notdef', '.notdef', '.notdef',
1056 '.notdef', '.notdef', '.notdef', '.notdef',
1057 '.notdef', '.notdef', '.notdef', '.notdef',
1058 '.notdef', '.notdef', '.notdef', '.notdef',
1059 'space', 'kokaithai', 'khokhaithai', 'khokhuatthai',
1060 'khokhwaithai', 'khokhonthai', 'khorakhangthai', 'ngonguthai',
1061 'chochanthai', 'chochingthai', 'chochangthai', 'sosothai',
1062 'chochoethai', 'yoyingthai', 'dochadathai', 'topatakthai',
1063 'thothanthai', 'thonangmonthothai','thophuthaothai', 'nonenthai',
1064 'dodekthai', 'totaothai', 'thothungthai', 'thothahanthai',
1065 'thothongthai', 'nonuthai', 'bobaimaithai', 'poplathai',
1066 'phophungthai', 'fofathai', 'phophanthai', 'fofanthai',
1067 'phosamphaothai', 'momathai', 'yoyakthai', 'roruathai',
1068 'ruthai', 'lolingthai', 'luthai', 'wowaenthai',
1069 'sosalathai', 'sorusithai', 'sosuathai', 'hohipthai',
1070 'lochulathai', 'oangthai', 'honokhukthai', 'paiyannoithai',
1071 'saraathai', 'maihanakatthai', 'saraaathai', 'saraamthai',
1072 'saraithai', 'saraiithai', 'sarauethai', 'saraueethai',
1073 'sarauthai', 'sarauuthai', 'phinthuthai', '.notdef',
1074 '.notdef', '.notdef', '.notdef', 'bahtthai',
1075 'saraethai', 'saraaethai', 'saraothai', 'saraaimaimuanthai',
1076 'saraaimaimalaithai','lakkhangyaothai','maiyamokthai', 'maitaikhuthai',
1077 'maiekthai', 'maithothai', 'maitrithai', 'maichattawathai',
1078 'thanthakhatthai','nikhahitthai', 'yamakkanthai', 'fongmanthai',
1079 'zerothai', 'onethai', 'twothai', 'threethai',
1080 'fourthai', 'fivethai', 'sixthai', 'seventhai',
1081 'eightthai', 'ninethai', 'angkhankhuthai', 'khomutthai',
1082 '.notdef', '.notdef', '.notdef', '.notdef'
1083 ],
1084 # Western Europe
1085 'ISO-8859-15' => [
1086 '.notdef', '.notdef', '.notdef', '.notdef',
1087 '.notdef', '.notdef', '.notdef', '.notdef',
1088 '.notdef', '.notdef', '.notdef', '.notdef',
1089 '.notdef', '.notdef', '.notdef', '.notdef',
1090 '.notdef', '.notdef', '.notdef', '.notdef',
1091 '.notdef', '.notdef', '.notdef', '.notdef',
1092 '.notdef', '.notdef', '.notdef', '.notdef',
1093 '.notdef', '.notdef', '.notdef', '.notdef',
1094 'space', 'exclam', 'quotedbl', 'numbersign',
1095 'dollar', 'percent', 'ampersand', 'quotesingle',
1096 'parenleft', 'parenright', 'asterisk', 'plus',
1097 'comma', 'hyphen', 'period', 'slash',
1098 'zero', 'one', 'two', 'three',
1099 'four', 'five', 'six', 'seven',
1100 'eight', 'nine', 'colon', 'semicolon',
1101 'less', 'equal', 'greater', 'question',
1102 'at', 'A', 'B', 'C',
1103 'D', 'E', 'F', 'G',
1104 'H', 'I', 'J', 'K',
1105 'L', 'M', 'N', 'O',
1106 'P', 'Q', 'R', 'S',
1107 'T', 'U', 'V', 'W',
1108 'X', 'Y', 'Z', 'bracketleft',
1109 'backslash', 'bracketright', 'asciicircum', 'underscore',
1110 'grave', 'a', 'b', 'c',
1111 'd', 'e', 'f', 'g',
1112 'h', 'i', 'j', 'k',
1113 'l', 'm', 'n', 'o',
1114 'p', 'q', 'r', 's',
1115 't', 'u', 'v', 'w',
1116 'x', 'y', 'z', 'braceleft',
1117 'bar', 'braceright', 'asciitilde', '.notdef',
1118 '.notdef', '.notdef', '.notdef', '.notdef',
1119 '.notdef', '.notdef', '.notdef', '.notdef',
1120 '.notdef', '.notdef', '.notdef', '.notdef',
1121 '.notdef', '.notdef', '.notdef', '.notdef',
1122 '.notdef', '.notdef', '.notdef', '.notdef',
1123 '.notdef', '.notdef', '.notdef', '.notdef',
1124 '.notdef', '.notdef', '.notdef', '.notdef',
1125 '.notdef', '.notdef', '.notdef', '.notdef',
1126 'space', 'exclamdown', 'cent', 'sterling',
1127 'Euro', 'yen', 'Scaron', 'section',
1128 'scaron', 'copyright', 'ordfeminine', 'guillemotleft',
1129 'logicalnot', 'hyphen', 'registered', 'macron',
1130 'degree', 'plusminus', 'twosuperior', 'threesuperior',
1131 'Zcaron', 'mu', 'paragraph', 'periodcentered',
1132 'zcaron', 'onesuperior', 'ordmasculine', 'guillemotright',
1133 'OE', 'oe', 'Ydieresis', 'questiondown',
1134 'Agrave', 'Aacute', 'Acircumflex', 'Atilde',
1135 'Adieresis', 'Aring', 'AE', 'Ccedilla',
1136 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis',
1137 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis',
1138 'Eth', 'Ntilde', 'Ograve', 'Oacute',
1139 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply',
1140 'Oslash', 'Ugrave', 'Uacute', 'Ucircumflex',
1141 'Udieresis', 'Yacute', 'Thorn', 'germandbls',
1142 'agrave', 'aacute', 'acircumflex', 'atilde',
1143 'adieresis', 'aring', 'ae', 'ccedilla',
1144 'egrave', 'eacute', 'ecircumflex', 'edieresis',
1145 'igrave', 'iacute', 'icircumflex', 'idieresis',
1146 'eth', 'ntilde', 'ograve', 'oacute',
1147 'ocircumflex', 'otilde', 'odieresis', 'divide',
1148 'oslash', 'ugrave', 'uacute', 'ucircumflex',
1149 'udieresis', 'yacute', 'thorn', 'ydieresis'
1150 ],
1151 # Central Europe
1152 'ISO-8859-16' => [
1153 '.notdef', '.notdef', '.notdef', '.notdef',
1154 '.notdef', '.notdef', '.notdef', '.notdef',
1155 '.notdef', '.notdef', '.notdef', '.notdef',
1156 '.notdef', '.notdef', '.notdef', '.notdef',
1157 '.notdef', '.notdef', '.notdef', '.notdef',
1158 '.notdef', '.notdef', '.notdef', '.notdef',
1159 '.notdef', '.notdef', '.notdef', '.notdef',
1160 '.notdef', '.notdef', '.notdef', '.notdef',
1161 'space', 'exclam', 'quotedbl', 'numbersign',
1162 'dollar', 'percent', 'ampersand', 'quotesingle',
1163 'parenleft', 'parenright', 'asterisk', 'plus',
1164 'comma', 'hyphen', 'period', 'slash',
1165 'zero', 'one', 'two', 'three',
1166 'four', 'five', 'six', 'seven',
1167 'eight', 'nine', 'colon', 'semicolon',
1168 'less', 'equal', 'greater', 'question',
1169 'at', 'A', 'B', 'C',
1170 'D', 'E', 'F', 'G',
1171 'H', 'I', 'J', 'K',
1172 'L', 'M', 'N', 'O',
1173 'P', 'Q', 'R', 'S',
1174 'T', 'U', 'V', 'W',
1175 'X', 'Y', 'Z', 'bracketleft',
1176 'backslash', 'bracketright', 'asciicircum', 'underscore',
1177 'grave', 'a', 'b', 'c',
1178 'd', 'e', 'f', 'g',
1179 'h', 'i', 'j', 'k',
1180 'l', 'm', 'n', 'o',
1181 'p', 'q', 'r', 's',
1182 't', 'u', 'v', 'w',
1183 'x', 'y', 'z', 'braceleft',
1184 'bar', 'braceright', 'asciitilde', '.notdef',
1185 '.notdef', '.notdef', '.notdef', '.notdef',
1186 '.notdef', '.notdef', '.notdef', '.notdef',
1187 '.notdef', '.notdef', '.notdef', '.notdef',
1188 '.notdef', '.notdef', '.notdef', '.notdef',
1189 '.notdef', '.notdef', '.notdef', '.notdef',
1190 '.notdef', '.notdef', '.notdef', '.notdef',
1191 '.notdef', '.notdef', '.notdef', '.notdef',
1192 '.notdef', '.notdef', '.notdef', '.notdef',
1193 'space', 'Aogonek', 'aogonek', 'Lslash',
1194 'Euro', 'quotedblbase', 'Scaron', 'section',
1195 'scaron', 'copyright', 'Scommaaccent', 'guillemotleft',
1196 'Zacute', 'hyphen', 'zacute', 'Zdotaccent',
1197 'degree', 'plusminus', 'Ccaron', 'lslash',
1198 'Zcaron', 'quotedblright', 'paragraph', 'periodcentered',
1199 'zcaron', 'ccaron', 'scommaaccent', 'guillemotright',
1200 'OE', 'oe', 'Ydieresis', 'zdotaccent',
1201 'Agrave', 'Aacute', 'Acircumflex', 'Abreve',
1202 'Adieresis', 'Cacute', 'AE', 'Ccedilla',
1203 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis',
1204 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis',
1205 'Dcroat', 'Nacute', 'Ograve', 'Oacute',
1206 'Ocircumflex', 'Ohungarumlaut', 'Odieresis', 'Sacute',
1207 'Uhungarumlaut', 'Ugrave', 'Uacute', 'Ucircumflex',
1208 'Udieresis', 'Eogonek', 'Tcommaaccent', 'germandbls',
1209 'agrave', 'aacute', 'acircumflex', 'abreve',
1210 'adieresis', 'cacute', 'ae', 'ccedilla',
1211 'egrave', 'eacute', 'ecircumflex', 'edieresis',
1212 'igrave', 'iacute', 'icircumflex', 'idieresis',
1213 'dcroat', 'nacute', 'ograve', 'oacute',
1214 'ocircumflex', 'ohungarumlaut', 'odieresis', 'sacute',
1215 'uhungarumlaut', 'ugrave', 'uacute', 'ucircumflex',
1216 'udieresis', 'eogonek', 'tcommaaccent', 'ydieresis'
1217 ],
1218 # Russian
1219 'KOI8-R' => [
1220 '.notdef', '.notdef', '.notdef', '.notdef',
1221 '.notdef', '.notdef', '.notdef', '.notdef',
1222 '.notdef', '.notdef', '.notdef', '.notdef',
1223 '.notdef', '.notdef', '.notdef', '.notdef',
1224 '.notdef', '.notdef', '.notdef', '.notdef',
1225 '.notdef', '.notdef', '.notdef', '.notdef',
1226 '.notdef', '.notdef', '.notdef', '.notdef',
1227 '.notdef', '.notdef', '.notdef', '.notdef',
1228 'space', 'exclam', 'quotedbl', 'numbersign',
1229 'dollar', 'percent', 'ampersand', 'quotesingle',
1230 'parenleft', 'parenright', 'asterisk', 'plus',
1231 'comma', 'hyphen', 'period', 'slash',
1232 'zero', 'one', 'two', 'three',
1233 'four', 'five', 'six', 'seven',
1234 'eight', 'nine', 'colon', 'semicolon',
1235 'less', 'equal', 'greater', 'question',
1236 'at', 'A', 'B', 'C',
1237 'D', 'E', 'F', 'G',
1238 'H', 'I', 'J', 'K',
1239 'L', 'M', 'N', 'O',
1240 'P', 'Q', 'R', 'S',
1241 'T', 'U', 'V', 'W',
1242 'X', 'Y', 'Z', 'bracketleft',
1243 'backslash', 'bracketright', 'asciicircum', 'underscore',
1244 'grave', 'a', 'b', 'c',
1245 'd', 'e', 'f', 'g',
1246 'h', 'i', 'j', 'k',
1247 'l', 'm', 'n', 'o',
1248 'p', 'q', 'r', 's',
1249 't', 'u', 'v', 'w',
1250 'x', 'y', 'z', 'braceleft',
1251 'bar', 'braceright', 'asciitilde', '.notdef',
1252 'SF100000', 'SF110000', 'SF010000', 'SF030000',
1253 'SF020000', 'SF040000', 'SF080000', 'SF090000',
1254 'SF060000', 'SF070000', 'SF050000', 'upblock',
1255 'dnblock', 'block', 'lfblock', 'rtblock',
1256 'ltshade', 'shade', 'dkshade', 'integraltp',
1257 'filledbox', 'periodcentered', 'radical', 'approxequal',
1258 'lessequal', 'greaterequal', 'space', 'integralbt',
1259 'degree', 'twosuperior', 'periodcentered', 'divide',
1260 'SF430000', 'SF240000', 'SF510000', 'afii10071',
1261 'SF520000', 'SF390000', 'SF220000', 'SF210000',
1262 'SF250000', 'SF500000', 'SF490000', 'SF380000',
1263 'SF280000', 'SF270000', 'SF260000', 'SF360000',
1264 'SF370000', 'SF420000', 'SF190000', 'afii10023',
1265 'SF200000', 'SF230000', 'SF470000', 'SF480000',
1266 'SF410000', 'SF450000', 'SF460000', 'SF400000',
1267 'SF540000', 'SF530000', 'SF440000', 'copyright',
1268 'afii10096', 'afii10065', 'afii10066', 'afii10088',
1269 'afii10069', 'afii10070', 'afii10086', 'afii10068',
1270 'afii10087', 'afii10074', 'afii10075', 'afii10076',
1271 'afii10077', 'afii10078', 'afii10079', 'afii10080',
1272 'afii10081', 'afii10097', 'afii10082', 'afii10083',
1273 'afii10084', 'afii10085', 'afii10072', 'afii10067',
1274 'afii10094', 'afii10093', 'afii10073', 'afii10090',
1275 'afii10095', 'afii10091', 'afii10089', 'afii10092',
1276 'afii10048', 'afii10017', 'afii10018', 'afii10040',
1277 'afii10021', 'afii10022', 'afii10038', 'afii10020',
1278 'afii10039', 'afii10026', 'afii10027', 'afii10028',
1279 'afii10029', 'afii10030', 'afii10031', 'afii10032',
1280 'afii10033', 'afii10049', 'afii10034', 'afii10035',
1281 'afii10036', 'afii10037', 'afii10024', 'afii10019',
1282 'afii10046', 'afii10045', 'afii10025', 'afii10042',
1283 'afii10047', 'afii10043', 'afii10041', 'afii10044'
1284 ],
1285 # Ukrainian
1286 'KOI8-U' => [
1287 '.notdef', '.notdef', '.notdef', '.notdef',
1288 '.notdef', '.notdef', '.notdef', '.notdef',
1289 '.notdef', '.notdef', '.notdef', '.notdef',
1290 '.notdef', '.notdef', '.notdef', '.notdef',
1291 '.notdef', '.notdef', '.notdef', '.notdef',
1292 '.notdef', '.notdef', '.notdef', '.notdef',
1293 '.notdef', '.notdef', '.notdef', '.notdef',
1294 '.notdef', '.notdef', '.notdef', '.notdef',
1295 'space', 'exclam', 'quotedbl', 'numbersign',
1296 'dollar', 'percent', 'ampersand', 'quotesingle',
1297 'parenleft', 'parenright', 'asterisk', 'plus',
1298 'comma', 'hyphen', 'period', 'slash',
1299 'zero', 'one', 'two', 'three',
1300 'four', 'five', 'six', 'seven',
1301 'eight', 'nine', 'colon', 'semicolon',
1302 'less', 'equal', 'greater', 'question',
1303 'at', 'A', 'B', 'C',
1304 'D', 'E', 'F', 'G',
1305 'H', 'I', 'J', 'K',
1306 'L', 'M', 'N', 'O',
1307 'P', 'Q', 'R', 'S',
1308 'T', 'U', 'V', 'W',
1309 'X', 'Y', 'Z', 'bracketleft',
1310 'backslash', 'bracketright', 'asciicircum', 'underscore',
1311 'grave', 'a', 'b', 'c',
1312 'd', 'e', 'f', 'g',
1313 'h', 'i', 'j', 'k',
1314 'l', 'm', 'n', 'o',
1315 'p', 'q', 'r', 's',
1316 't', 'u', 'v', 'w',
1317 'x', 'y', 'z', 'braceleft',
1318 'bar', 'braceright', 'asciitilde', '.notdef',
1319 'SF100000', 'SF110000', 'SF010000', 'SF030000',
1320 'SF020000', 'SF040000', 'SF080000', 'SF090000',
1321 'SF060000', 'SF070000', 'SF050000', 'upblock',
1322 'dnblock', 'block', 'lfblock', 'rtblock',
1323 'ltshade', 'shade', 'dkshade', 'integraltp',
1324 'filledbox', 'bullet', 'radical', 'approxequal',
1325 'lessequal', 'greaterequal', 'space', 'integralbt',
1326 'degree', 'twosuperior', 'periodcentered', 'divide',
1327 'SF430000', 'SF240000', 'SF510000', 'afii10071',
1328 'afii10101', 'SF390000', 'afii10103', 'afii10104',
1329 'SF250000', 'SF500000', 'SF490000', 'SF380000',
1330 'SF280000', 'afii10098', 'SF260000', 'SF360000',
1331 'SF370000', 'SF420000', 'SF190000', 'afii10023',
1332 'afii10053', 'SF230000', 'afii10055', 'afii10056',
1333 'SF410000', 'SF450000', 'SF460000', 'SF400000',
1334 'SF540000', 'afii10050', 'SF440000', 'copyright',
1335 'afii10096', 'afii10065', 'afii10066', 'afii10088',
1336 'afii10069', 'afii10070', 'afii10086', 'afii10068',
1337 'afii10087', 'afii10074', 'afii10075', 'afii10076',
1338 'afii10077', 'afii10078', 'afii10079', 'afii10080',
1339 'afii10081', 'afii10097', 'afii10082', 'afii10083',
1340 'afii10084', 'afii10085', 'afii10072', 'afii10067',
1341 'afii10094', 'afii10093', 'afii10073', 'afii10090',
1342 'afii10095', 'afii10091', 'afii10089', 'afii10092',
1343 'afii10048', 'afii10017', 'afii10018', 'afii10040',
1344 'afii10021', 'afii10022', 'afii10038', 'afii10020',
1345 'afii10039', 'afii10026', 'afii10027', 'afii10028',
1346 'afii10029', 'afii10030', 'afii10031', 'afii10032',
1347 'afii10033', 'afii10049', 'afii10034', 'afii10035',
1348 'afii10036', 'afii10037', 'afii10024', 'afii10019',
1349 'afii10046', 'afii10045', 'afii10025', 'afii10042',
1350 'afii10047', 'afii10043', 'afii10041', 'afii10044'
1351 ]
1352 }
1353
1354 def ReadAFM(file, map)
1355
1356 # Read a font metric file
1357 a = IO.readlines(file)
1358
1359 raise "File no found: #{file}" if a.size == 0
1360
1361 widths = {}
1362 fm = {}
1363 fix = { 'Edot' => 'Edotaccent', 'edot' => 'edotaccent',
1364 'Idot' => 'Idotaccent',
1365 'Zdot' => 'Zdotaccent', 'zdot' => 'zdotaccent',
1366 'Odblacute' => 'Ohungarumlaut', 'odblacute' => 'ohungarumlaut',
1367 'Udblacute' => 'Uhungarumlaut', 'udblacute' => 'uhungarumlaut',
1368 'Gcedilla' => 'Gcommaaccent', 'gcedilla' => 'gcommaaccent',
1369 'Kcedilla' => 'Kcommaaccent', 'kcedilla' => 'kcommaaccent',
1370 'Lcedilla' => 'Lcommaaccent', 'lcedilla' => 'lcommaaccent',
1371 'Ncedilla' => 'Ncommaaccent', 'ncedilla' => 'ncommaaccent',
1372 'Rcedilla' => 'Rcommaaccent', 'rcedilla' => 'rcommaaccent',
1373 'Scedilla' => 'Scommaaccent',' scedilla' => 'scommaaccent',
1374 'Tcedilla' => 'Tcommaaccent',' tcedilla' => 'tcommaaccent',
1375 'Dslash' => 'Dcroat', 'dslash' => 'dcroat',
1376 'Dmacron' => 'Dcroat', 'dmacron' => 'dcroat',
1377 'combininggraveaccent' => 'gravecomb',
1378 'combininghookabove' => 'hookabovecomb',
1379 'combiningtildeaccent' => 'tildecomb',
1380 'combiningacuteaccent' => 'acutecomb',
1381 'combiningdotbelow' => 'dotbelowcomb',
1382 'dongsign' => 'dong'
1383 }
1384
1385 a.each do |line|
1386
1387 e = line.rstrip.split(' ')
1388 next if e.size < 2
1389
1390 code = e[0]
1391 param = e[1]
1392
1393 if code == 'C' then
1394
1395 # Character metrics
1396 cc = e[1].to_i
1397 w = e[4]
1398 gn = e[7]
1399
1400 gn = 'Euro' if gn[-4, 4] == '20AC'
1401
1402 if fix[gn] then
1403
1404 # Fix incorrect glyph name
1405 0.upto(map.size - 1) do |i|
1406 if map[i] == fix[gn] then
1407 map[i] = gn
1408 end
1409 end
1410 end
1411
1412 if map.size == 0 then
1413 # Symbolic font: use built-in encoding
1414 widths[cc] = w
1415 else
1416 widths[gn] = w
1417 fm['CapXHeight'] = e[13].to_i if gn == 'X'
1418 end
1419
1420 fm['MissingWidth'] = w if gn == '.notdef'
1421
1422 elsif code == 'FontName' then
1423 fm['FontName'] = param
1424 elsif code == 'Weight' then
1425 fm['Weight'] = param
1426 elsif code == 'ItalicAngle' then
1427 fm['ItalicAngle'] = param.to_f
1428 elsif code == 'Ascender' then
1429 fm['Ascender'] = param.to_i
1430 elsif code == 'Descender' then
1431 fm['Descender'] = param.to_i
1432 elsif code == 'UnderlineThickness' then
1433 fm['UnderlineThickness'] = param.to_i
1434 elsif code == 'UnderlinePosition' then
1435 fm['UnderlinePosition'] = param.to_i
1436 elsif code == 'IsFixedPitch' then
1437 fm['IsFixedPitch'] = (param == 'true')
1438 elsif code == 'FontBBox' then
1439 fm['FontBBox'] = "[#{e[1]},#{e[2]},#{e[3]},#{e[4]}]"
1440 elsif code == 'CapHeight' then
1441 fm['CapHeight'] = param.to_i
1442 elsif code == 'StdVW' then
1443 fm['StdVW'] = param.to_i
1444 end
1445 end
1446
1447 raise 'FontName not found' unless fm['FontName']
1448
1449 if map.size > 0 then
1450 widths['.notdef'] = 600 unless widths['.notdef']
1451
1452 if (widths['Delta'] == nil) && widths['increment'] then
1453 widths['Delta'] = widths['increment']
1454 end
1455
1456 # Order widths according to map
1457 0.upto(255) do |i|
1458 if widths[map[i]] == nil
1459 puts "Warning: character #{map[i]} is missing"
1460 widths[i] = widths['.notdef']
1461 else
1462 widths[i] = widths[map[i]]
1463 end
1464 end
1465 end
1466
1467 fm['Widths'] = widths
1468
1469 return fm
1470 end
1471
1472 def MakeFontDescriptor(fm, symbolic)
1473
1474 # Ascent
1475 asc = fm['Ascender'] ? fm['Ascender'] : 1000
1476 fd = "{\n 'Ascent' => '#{asc}'"
1477
1478 # Descent
1479 desc = fm['Descender'] ? fm['Descender'] : -200
1480 fd += ", 'Descent' => '#{desc}'"
1481
1482 # CapHeight
1483 if fm['CapHeight'] then
1484 ch = fm['CapHeight']
1485 elsif fm['CapXHeight']
1486 ch = fm['CapXHeight']
1487 else
1488 ch = asc
1489 end
1490 fd += ", 'CapHeight' => '#{ch}'"
1491
1492 # Flags
1493 flags = 0
1494
1495 if fm['IsFixedPitch'] then
1496 flags += 1 << 0
1497 end
1498
1499 if symbolic then
1500 flags += 1 << 2
1501 else
1502 flags += 1 << 5
1503 end
1504
1505 if fm['ItalicAngle'] && (fm['ItalicAngle'] != 0) then
1506 flags += 1 << 6
1507 end
1508
1509 fd += ",\n 'Flags' => '#{flags}'"
1510
1511 # FontBBox
1512 if fm['FontBBox'] then
1513 fbb = fm['FontBBox'].gsub(/,/, ' ')
1514 else
1515 fbb = "[0 #{desc - 100} 1000 #{asc + 100}]"
1516 end
1517
1518 fd += ", 'FontBBox' => '#{fbb}'"
1519
1520 # ItalicAngle
1521 ia = fm['ItalicAngle'] ? fm['ItalicAngle'] : 0
1522 fd += ",\n 'ItalicAngle' => '#{ia}'"
1523
1524 # StemV
1525 if fm['StdVW'] then
1526 stemv = fm['StdVW']
1527 elsif fm['Weight'] && (/bold|black/i =~ fm['Weight'])
1528 stemv = 120
1529 else
1530 stemv = 70
1531 end
1532
1533 fd += ", 'StemV' => '#{stemv}'"
1534
1535 # MissingWidth
1536 if fm['MissingWidth'] then
1537 fd += ", 'MissingWidth' => '#{fm['MissingWidth']}'"
1538 end
1539
1540 fd += "\n }"
1541 return fd
1542 end
1543
1544 def MakeWidthArray(fm)
1545
1546 # Make character width array
1547 s = " [\n "
1548
1549 cw = fm['Widths']
1550
1551 0.upto(255) do |i|
1552 s += "%5d" % cw[i]
1553 s += "," if i != 255
1554 s += "\n " if (i % 8) == 7
1555 end
1556
1557 s += ']'
1558
1559 return s
1560 end
1561
1562 def MakeFontEncoding(map)
1563
1564 # Build differences from reference encoding
1565 ref = Charencodings['cp1252']
1566 s = ''
1567 last = 0
1568 32.upto(255) do |i|
1569 if map[i] != ref[i] then
1570 if i != last + 1 then
1571 s += i.to_s + ' '
1572 end
1573 last = i
1574 s += '/' + map[i] + ' '
1575 end
1576 end
1577 return s.rstrip
1578 end
1579
1580 def ReadShort(f)
1581 a = f.read(2).unpack('n')
1582 return a[0]
1583 end
1584
1585 def ReadLong(f)
1586 a = f.read(4).unpack('N')
1587 return a[0]
1588 end
1589
1590 def CheckTTF(file)
1591
1592 rl = false
1593 pp = false
1594 e = false
1595
1596 # Check if font license allows embedding
1597 File.open(file, 'rb') do |f|
1598
1599 # Extract number of tables
1600 f.seek(4, IO::SEEK_CUR)
1601 nb = ReadShort(f)
1602 f.seek(6, IO::SEEK_CUR)
1603
1604 # Seek OS/2 table
1605 found = false
1606 0.upto(nb - 1) do |i|
1607 if f.read(4) == 'OS/2' then
1608 found = true
1609 break
1610 end
1611
1612 f.seek(12, IO::SEEK_CUR)
1613 end
1614
1615 if ! found then
1616 return
1617 end
1618
1619 f.seek(4, IO::SEEK_CUR)
1620 offset = ReadLong(f)
1621 f.seek(offset, IO::SEEK_SET)
1622
1623 # Extract fsType flags
1624 f.seek(8, IO::SEEK_CUR)
1625 fsType = ReadShort(f)
1626
1627 rl = (fsType & 0x02) != 0
1628 pp = (fsType & 0x04) != 0
1629 e = (fsType & 0x08) != 0
1630 end
1631
1632 if rl && ( ! pp) && ( ! e) then
1633 puts 'Warning: font license does not allow embedding'
1634 end
1635 end
1636
1637 #
1638 # fontfile: path to TTF file (or empty string if not to be embedded)
1639 # afmfile: path to AFM file
1640 # enc: font encoding (or empty string for symbolic fonts)
1641 # patch: optional patch for encoding
1642 # type : font type if $fontfile is empty
1643 #
1644 def MakeFont(fontfile, afmfile, enc = 'cp1252', patch = {}, type = 'TrueType')
1645 # Generate a font definition file
1646 if (enc != nil) && (enc != '') then
1647 map = Charencodings[enc]
1648 patch.each { |cc, gn| map[cc] = gn }
1649 else
1650 map = []
1651 end
1652
1653 raise "Error: AFM file not found: #{afmfile}" unless File.exists?(afmfile)
1654
1655 fm = ReadAFM(afmfile, map)
1656
1657 if (enc != nil) && (enc != '') then
1658 diff = MakeFontEncoding(map)
1659 else
1660 diff = ''
1661 end
1662
1663 fd = MakeFontDescriptor(fm, (map.size == 0))
1664
1665 # Find font type
1666 if fontfile then
1667 ext = File.extname(fontfile).downcase.sub(/^\./, '')
1668
1669 if ext == 'ttf' then
1670 type = 'TrueType'
1671 elsif ext == 'pfb'
1672 type = 'Type1'
1673 else
1674 raise "Error: unrecognized font file extension: #{ext}"
1675 end
1676 else
1677 raise "Error: incorrect font type: #{type}" if (type != 'TrueType') && (type != 'Type1')
1678 end
1679 printf "type = #{type}\n"
1680 # Start generation
1681 s = "# #{fm['FontName']} font definition\n\n"
1682 s += "module FontDef\n"
1683 s += " def FontDef.type\n '#{type}'\n end\n"
1684 s += " def FontDef.name\n '#{fm['FontName']}'\n end\n"
1685 s += " def FontDef.desc\n #{fd}\n end\n"
1686
1687 if fm['UnderlinePosition'] == nil then
1688 fm['UnderlinePosition'] = -100
1689 end
1690
1691 if fm['UnderlineThickness'] == nil then
1692 fm['UnderlineThickness'] = 50
1693 end
1694
1695 s += " def FontDef.up\n #{fm['UnderlinePosition']}\n end\n"
1696 s += " def FontDef.ut\n #{fm['UnderlineThickness']}\n end\n"
1697
1698 w = MakeWidthArray(fm)
1699 s += " def FontDef.cw\n#{w}\n end\n"
1700
1701 s += " def FontDef.enc\n '#{enc}'\n end\n"
1702 s += " def FontDef.diff\n #{(diff == nil) || (diff == '') ? 'nil' : '\'' + diff '\''}\n end\n"
1703
1704 basename = File.basename(afmfile, '.*')
1705
1706 if fontfile then
1707 # Embedded font
1708 if ! File.exist?(fontfile) then
1709 raise "Error: font file not found: #{fontfile}"
1710 end
1711
1712 if type == 'TrueType' then
1713 CheckTTF(fontfile)
1714 end
1715
1716 file = ''
1717 File.open(fontfile, 'rb') do |f|
1718 file = f.read()
1719 end
1720
1721 if type == 'Type1' then
1722 # Find first two sections and discard third one
1723 header = file[0] == 128
1724 file = file[6, file.length - 6] if header
1725
1726 pos = file.index('eexec')
1727 raise 'Error: font file does not seem to be valid Type1' if pos == nil
1728
1729 size1 = pos + 6
1730
1731 file = file[0, size1] + file[size1 + 6, file.length - (size1 + 6)] if header && file[size1] == 128
1732
1733 pos = file.index('00000000')
1734 raise 'Error: font file does not seem to be valid Type1' if pos == nil
1735
1736 size2 = pos - size1
1737 file = file[0, size1 + size2]
1738 end
1739
1740 if require 'zlib' then
1741 File.open(basename + '.z', 'wb') { |f| f.write(Zlib::Deflate.deflate(file)) }
1742 s += " def FontDef.file\n '#{basename}.z'\n end\n"
1743 puts "Font file compressed ('#{basename}.z')"
1744 else
1745 s += " def FontDef.file\n '#{File.basename(fontfile)}'\n end\n"
1746 puts 'Notice: font file could not be compressed (zlib not available)'
1747 end
1748
1749 if type == 'Type1' then
1750 s += " def FontDef.size1\n '#{size1}'\n end\n"
1751 s += " def FontDef.size2\n '#{size2}'\n end\n"
1752 else
1753 s += " def FontDef.originalsize\n '#{File.size(fontfile)}'\n end\n"
1754 end
1755
1756 else
1757 # Not embedded font
1758 s += " def FontDef.file\n ''\n end\n"
1759 end
1760
1761 s += "end\n"
1762 File.open(basename + '.rb', 'w') { |file| file.write(s)}
1763 puts "Font definition file generated (#{basename}.rb)"
1764 end
1765
1766
1767 if $0 == __FILE__ then
1768 if ARGV.length >= 3 then
1769 enc = ARGV[2]
1770 else
1771 enc = 'cp1252'
1772 end
1773
1774 if ARGV.length >= 4 then
1775 patch = ARGV[3]
1776 else
1777 patch = {}
1778 end
1779
1780 if ARGV.length >= 5 then
1781 type = ARGV[4]
1782 else
1783 type = 'TrueType'
1784 end
1785
1786 MakeFont(ARGV[0], ARGV[1], enc, patch, type)
1787 end
@@ -0,0 +1,346
1 module RFPDF
2 COLOR_PALETTE = {
3 :black => [0x00, 0x00, 0x00],
4 :white => [0xff, 0xff, 0xff],
5 }.freeze
6
7 # Draw a line from (<tt>x1, y1</tt>) to (<tt>x2, y2</tt>).
8 #
9 # Options are:
10 # * <tt>:line_color</tt> - Default value is <tt>COLOR_PALETTE[:black]</tt>.
11 # * <tt>:line_width</tt> - Default value is <tt>0.5</tt>.
12 #
13 # Example:
14 #
15 # draw_line(x1, y1, x1, y1+h, :line_color => ReportHelper::COLOR_PALETTE[:dark_blue], :line_width => 1)
16 #
17 def draw_line(x1, y1, x2, y2, options = {})
18 options[:line_color] ||= COLOR_PALETTE[:black]
19 options[:line_width] ||= 0.5
20 set_draw_color(options[:line_color])
21 SetLineWidth(options[:line_width])
22 Line(x1, y1, x2, y2)
23 end
24
25 # Draw a string of <tt>text</tt> at (<tt>x, y</tt>).
26 #
27 # Options are:
28 # * <tt>:font_color</tt> - Default value is <tt>COLOR_PALETTE[:black]</tt>.
29 # * <tt>:font_size</tt> - Default value is <tt>10</tt>.
30 # * <tt>:font_style</tt> - Default value is nothing or <tt>''</tt>.
31 #
32 # Example:
33 #
34 # draw_text(x, y, header_left, :font_size => 10)
35 #
36 def draw_text(x, y, text, options = {})
37 options[:font_color] ||= COLOR_PALETTE[:black]
38 options[:font_size] ||= 10
39 options[:font_style] ||= ''
40 set_text_color(options[:font_color])
41 SetFont('Arial', options[:font_style], options[:font_size])
42 SetXY(x, y)
43 Write(options[:font_size] + 4, text)
44 end
45
46 # Draw a block of <tt>text</tt> at (<tt>x, y</tt>) bounded by <tt>left_margin</tt> and <tt>right_margin</tt>. Both
47 # margins are measured from their corresponding edge.
48 #
49 # Options are:
50 # * <tt>:font_color</tt> - Default value is <tt>COLOR_PALETTE[:black]</tt>.
51 # * <tt>:font_size</tt> - Default value is <tt>10</tt>.
52 # * <tt>:font_style</tt> - Default value is nothing or <tt>''</tt>.
53 #
54 # Example:
55 #
56 # draw_text_block(left_margin, 85, "question", left_margin, 280,
57 # :font_color => ReportHelper::COLOR_PALETTE[:dark_blue],
58 # :font_size => 12,
59 # :font_style => 'I')
60 #
61 def draw_text_block(x, y, text, left_margin, right_margin, options = {})
62 options[:font_color] ||= COLOR_PALETTE[:black]
63 options[:font_size] ||= 10
64 options[:font_style] ||= ''
65 set_text_color(options[:font_color])
66 SetFont('Arial', options[:font_style], options[:font_size])
67 SetXY(x, y)
68 SetLeftMargin(left_margin)
69 SetRightMargin(right_margin)
70 Write(options[:font_size] + 4, text)
71 SetMargins(0,0,0)
72 end
73
74 # Draw a box at (<tt>x, y</tt>), <tt>w</tt> wide and <tt>h</tt> high.
75 #
76 # Options are:
77 # * <tt>:border</tt> - Draw a border, 0 = no, 1 = yes? Default value is <tt>1</tt>.
78 # * <tt>:border_color</tt> - Default value is <tt>COLOR_PALETTE[:black]</tt>.
79 # * <tt>:border_width</tt> - Default value is <tt>0.5</tt>.
80 # * <tt>:fill</tt> - Fill the box, 0 = no, 1 = yes? Default value is <tt>1</tt>.
81 # * <tt>:fill_color</tt> - Default value is nothing or <tt>COLOR_PALETTE[:white]</tt>.
82 #
83 # Example:
84 #
85 # draw_box(x, y - 1, 38, 22)
86 #
87 def draw_box(x, y, w, h, options = {})
88 options[:border] ||= 1
89 options[:border_color] ||= COLOR_PALETTE[:black]
90 options[:border_width] ||= 0.5
91 options[:fill] ||= 1
92 options[:fill_color] ||= COLOR_PALETTE[:white]
93 SetLineWidth(options[:border_width])
94 set_draw_color(options[:border_color])
95 set_fill_color(options[:fill_color])
96 fd = ""
97 fd = "D" if options[:border] == 1
98 fd += "F" if options[:fill] == 1
99 Rect(x, y, w, h, fd)
100 end
101
102 # Draw a string of <tt>text</tt> at (<tt>x, y</tt>) in a box <tt>w</tt> wide and <tt>h</tt> high.
103 #
104 # Options are:
105 # * <tt>:align</tt> - Vertical alignment 'C' = center, 'L' = left, 'R' = right. Default value is <tt>'C'</tt>.
106 # * <tt>:border</tt> - Draw a border, 0 = no, 1 = yes? Default value is <tt>0</tt>.
107 # * <tt>:border_color</tt> - Default value is <tt>COLOR_PALETTE[:black]</tt>.
108 # * <tt>:border_width</tt> - Default value is <tt>0.5</tt>.
109 # * <tt>:fill</tt> - Fill the box, 0 = no, 1 = yes? Default value is <tt>1</tt>.
110 # * <tt>:fill_color</tt> - Default value is nothing or <tt>COLOR_PALETTE[:white]</tt>.
111 # * <tt>:font_color</tt> - Default value is <tt>COLOR_PALETTE[:black]</tt>.
112 # * <tt>:font_size</tt> - Default value is nothing or <tt>8</tt>.
113 # * <tt>:font_style</tt> - 'B' = bold, 'I' = italic, 'U' = underline. Default value is nothing <tt>''</tt>.
114 # * <tt>:padding</tt> - Default value is nothing or <tt>2</tt>.
115 # * <tt>:valign</tt> - 'M' = middle, 'T' = top, 'B' = bottom. Default value is nothing or <tt>'M'</tt>.
116 #
117 # Example:
118 #
119 # draw_text_box(x, y - 1, 38, 22,
120 # "your_score_title",
121 # :fill => 0,
122 # :font_color => ReportHelper::COLOR_PALETTE[:blue],
123 # :font_line_spacing => 0,
124 # :font_style => "B",
125 # :valign => "M")
126 #
127 def draw_text_box(x, y, w, h, text, options = {})
128 options[:align] ||= 'C'
129 options[:border] ||= 0
130 options[:border_color] ||= COLOR_PALETTE[:black]
131 options[:border_width] ||= 0.5
132 options[:fill] ||= 1
133 options[:fill_color] ||= COLOR_PALETTE[:white]
134 options[:font_color] ||= COLOR_PALETTE[:black]
135 options[:font_size] ||= 8
136 options[:font_line_spacing] ||= options[:font_size] * 0.3
137 options[:font_style] ||= ''
138 options[:padding] ||= 2
139 options[:valign] ||= "M"
140 if options[:fill] == 1 or options[:border] == 1
141 draw_box(x, y, w, h, options)
142 end
143 SetMargins(0,0,0)
144 set_text_color(options[:font_color])
145 font_size = options[:font_size]
146 SetFont('Arial', options[:font_style], font_size)
147 font_size += options[:font_line_spacing]
148 case options[:valign]
149 when "B"
150 y -= options[:padding]
151 text = "\n" + text if text["\n"].nil?
152 when "T"
153 y += options[:padding]
154 end
155 SetXY(x, y)
156 if GetStringWidth(text) > w or not text["\n"].nil? or options[:valign] == "T"
157 font_size += options[:font_size] * 0.1
158 #TODO 2006-07-21 Level=1 - this is assuming a 2 line text
159 SetXY(x, y + ((h - (font_size * 2)) / 2)) if options[:valign] == "M"
160 MultiCell(w, font_size, text, 0, options[:align])
161 else
162 Cell(w, h, text, 0, 0, options[:align])
163 end
164 end
165
166 # Draw a string of <tt>text</tt> at (<tt>x, y</tt>) as a title.
167 #
168 # Options are:
169 # * <tt>:font_color</tt> - Default value is <tt>COLOR_PALETTE[:black]</tt>.
170 # * <tt>:font_size</tt> - Default value is <tt>18</tt>.
171 # * <tt>:font_style</tt> - Default value is nothing or <tt>''</tt>.
172 #
173 # Example:
174 #
175 # draw_title(left_margin, 60,
176 # "title:",
177 # :font_color => ReportHelper::COLOR_PALETTE[:dark_blue])
178 #
179 def draw_title(x, y, title, options = {})
180 options[:font_color] ||= COLOR_PALETTE[:black]
181 options[:font_size] ||= 18
182 options[:font_style] ||= ''
183 set_text_color(options[:font_color])
184 SetFont('Arial', options[:font_style], options[:font_size])
185 SetXY(x, y)
186 Write(options[:font_size] + 2, title)
187 end
188
189 # Set the draw color. Default value is <tt>COLOR_PALETTE[:black]</tt>.
190 #
191 # Example:
192 #
193 # set_draw_color(ReportHelper::COLOR_PALETTE[:dark_blue])
194 #
195 def set_draw_color(color = COLOR_PALETTE[:black])
196 SetDrawColor(color[0], color[1], color[2])
197 end
198
199 # Set the fill color. Default value is <tt>COLOR_PALETTE[:white]</tt>.
200 #
201 # Example:
202 #
203 # set_fill_color(ReportHelper::COLOR_PALETTE[:dark_blue])
204 #
205 def set_fill_color(color = COLOR_PALETTE[:white])
206 SetFillColor(color[0], color[1], color[2])
207 end
208
209 # Set the text color. Default value is <tt>COLOR_PALETTE[:white]</tt>.
210 #
211 # Example:
212 #
213 # set_text_color(ReportHelper::COLOR_PALETTE[:dark_blue])
214 #
215 def set_text_color(color = COLOR_PALETTE[:black])
216 SetTextColor(color[0], color[1], color[2])
217 end
218
219 # Write a string containing html characters. Default value is <tt>COLOR_PALETTE[:white]</tt>.
220 #
221 # Options are:
222 # * <tt>:height</tt> - Line height. Default value is <tt>20</tt>.
223 #
224 # Example:
225 #
226 # write_html(html, :height => 12)
227 #
228 def write_html(html, options = {})
229 options[:height] ||= 20
230 #HTML parser
231 @href = nil
232 @style = {}
233 html.gsub!("\n",' ')
234 re = %r{ ( <!--.*?--> |
235 < (?:
236 [^<>"] +
237 |
238 " (?: \\. | [^\\"]+ ) * "
239 ) *
240 >
241 ) }xm
242
243 html.split(re).each do |value|
244 if "<" == value[0,1]
245 #Tag
246 if (value[1, 1] == '/')
247 close_tag(value[2..-2], options)
248 else
249 tag = value[1..-2]
250 open_tag(tag, options)
251 end
252 else
253 #Text
254 if @href
255 put_link(@href,value)
256 else
257 Write(options[:height], value)
258 end
259 end
260 end
261 end
262
263 def open_tag(tag, options = {}) #:nodoc:
264 #Opening tag
265 tag = tag.to_s.upcase
266 set_style(tag, true) if tag == 'B' or tag == 'I' or tag == 'U'
267 @href = options['HREF'] if tag == 'A'
268 Ln(options[:height]) if tag == 'BR'
269 end
270
271 def close_tag(tag, options = {}) #:nodoc:
272 #Closing tag
273 tag = tag.to_s.upcase
274 set_style(tag, false) if tag == 'B' or tag == 'I' or tag == 'U'
275 @href = '' if $tag == 'A'
276 end
277
278 def set_style(tag, enable = true) #:nodoc:
279 #Modify style and select corresponding font
280 style = ""
281 @style[tag] = enable
282 ['B','I','U'].each do |s|
283 style += s if not @style[s].nil? and @style[s]
284 end
285 SetFont('', style)
286 end
287
288 def put_link(url, txt) #:nodoc:
289 #Put a hyperlink
290 SetTextColor(0,0,255)
291 set_style('U',true)
292 Write(5, txt, url)
293 set_style('U',false)
294 SetTextColor(0)
295 end
296 end
297
298 # class FPDF
299 # alias_method :set_margins , :SetMargins
300 # alias_method :set_left_margin , :SetLeftMargin
301 # alias_method :set_top_margin , :SetTopMargin
302 # alias_method :set_right_margin , :SetRightMargin
303 # alias_method :set_auto_pagebreak , :SetAutoPageBreak
304 # alias_method :set_display_mode , :SetDisplayMode
305 # alias_method :set_compression , :SetCompression
306 # alias_method :set_title , :SetTitle
307 # alias_method :set_subject , :SetSubject
308 # alias_method :set_author , :SetAuthor
309 # alias_method :set_keywords , :SetKeywords
310 # alias_method :set_creator , :SetCreator
311 # alias_method :set_draw_color , :SetDrawColor
312 # alias_method :set_fill_color , :SetFillColor
313 # alias_method :set_text_color , :SetTextColor
314 # alias_method :set_line_width , :SetLineWidth
315 # alias_method :set_font , :SetFont
316 # alias_method :set_font_size , :SetFontSize
317 # alias_method :set_link , :SetLink
318 # alias_method :set_y , :SetY
319 # alias_method :set_xy , :SetXY
320 # alias_method :get_string_width , :GetStringWidth
321 # alias_method :get_x , :GetX
322 # alias_method :set_x , :SetX
323 # alias_method :get_y , :GetY
324 # alias_method :accept_pagev_break , :AcceptPageBreak
325 # alias_method :add_font , :AddFont
326 # alias_method :add_link , :AddLink
327 # alias_method :add_page , :AddPage
328 # alias_method :alias_nb_pages , :AliasNbPages
329 # alias_method :cell , :Cell
330 # alias_method :close , :Close
331 # alias_method :error , :Error
332 # alias_method :footer , :Footer
333 # alias_method :header , :Header
334 # alias_method :image , :Image
335 # alias_method :line , :Line
336 # alias_method :link , :Link
337 # alias_method :ln , :Ln
338 # alias_method :multi_cell , :MultiCell
339 # alias_method :open , :Open
340 # alias_method :Open , :open
341 # alias_method :output , :Output
342 # alias_method :page_no , :PageNo
343 # alias_method :rect , :Rect
344 # alias_method :text , :Text
345 # alias_method :write , :Write
346 # end
@@ -0,0 +1,75
1 # Copyright (c) 2006 4ssoM LLC <www.4ssoM.com>
2 #
3 # The MIT License
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
11 #
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
14 #
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 # THE SOFTWARE.
22 #
23 # Thanks go out to Bruce Williams of codefluency who created RTex. This
24 # template handler is modification of his work.
25 #
26 # Example Registration
27 #
28 # ActionView::Base::register_template_handler 'rfpdf', RFpdfView
29
30 module RFPDF
31
32 class View
33
34 def initialize(action_view)
35 @action_view = action_view
36 # Override with @options_for_rfpdf Hash in your controller
37 @options = {
38 # Run through latex first? (for table of contents, etc)
39 :pre_process => false,
40 # Debugging mode; raises exception
41 :debug => false,
42 # Filename of pdf to generate
43 :file_name => "#{@action_view.controller.action_name}.pdf",
44 # Temporary Directory
45 :temp_dir => "#{File.expand_path(RAILS_ROOT)}/tmp"
46 }.merge(@action_view.controller.instance_eval{ @options_for_rfpdf } || {}).with_indifferent_access
47 end
48
49 def render(template, local_assigns = {})
50 @pdf_name = "Default.pdf" if @pdf_name.nil?
51 unless @action_view.controller.headers["Content-Type"] == 'application/pdf'
52 @generate = true
53 @action_view.controller.headers["Content-Type"] = 'application/pdf'
54 @action_view.controller.headers["Content-disposition:"] = "inline; filename=\"#{@options[:file_name]}\""
55 end
56 assigns = @action_view.assigns.dup
57
58 if content_for_layout = @action_view.instance_variable_get("@content_for_layout")
59 assigns['content_for_layout'] = content_for_layout
60 end
61
62 result = @action_view.instance_eval do
63 assigns.each do |key,val|
64 instance_variable_set "@#{key}", val
65 end
66 local_assigns.each do |key,val|
67 class << self; self; end.send(:define_method,key){ val }
68 end
69 ERB.new(template).result(binding)
70 end
71 end
72
73 end
74
75 end No newline at end of file
@@ -0,0 +1,1
1 #!/usr/bin/env ruby No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now