Chris@441: # Copyright (c) 2006 4ssoM LLC Chris@441: # 1.12 contributed by Ed Moss. Chris@441: # Chris@441: # The MIT License Chris@441: # Chris@441: # Permission is hereby granted, free of charge, to any person obtaining a copy Chris@441: # of this software and associated documentation files (the "Software"), to deal Chris@441: # in the Software without restriction, including without limitation the rights Chris@441: # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell Chris@441: # copies of the Software, and to permit persons to whom the Software is Chris@441: # furnished to do so, subject to the following conditions: Chris@441: # Chris@441: # The above copyright notice and this permission notice shall be included in Chris@441: # all copies or substantial portions of the Software. Chris@441: # Chris@441: # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR Chris@441: # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, Chris@441: # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE Chris@441: # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER Chris@441: # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, Chris@441: # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN Chris@441: # THE SOFTWARE. Chris@441: # Chris@441: # This is direct port of chinese.php Chris@441: # Chris@441: # Chinese PDF support. Chris@441: # Chris@441: # Usage is as follows: Chris@441: # Chris@441: # require 'fpdf' Chris@441: # require 'chinese' Chris@441: # pdf = FPDF.new Chris@441: # pdf.extend(PDF_Chinese) Chris@441: # Chris@441: # This allows it to be combined with other extensions, such as the bookmark Chris@441: # module. Chris@441: Chris@441: module PDF_Chinese Chris@441: Chris@441: Big5_widths={' '=>250,'!'=>250,'"'=>408,'#'=>668,'$'=>490,'%'=>875,'&'=>698,'\''=>250, Chris@441: '('=>240,')'=>240,'*'=>417,'+'=>667,','=>250,'-'=>313,'.'=>250,'/'=>520,'0'=>500,'1'=>500, Chris@441: '2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>250,';'=>250, Chris@441: '<'=>667,'='=>667,'>'=>667,'?'=>396,'@'=>921,'A'=>677,'B'=>615,'C'=>719,'D'=>760,'E'=>625, Chris@441: 'F'=>552,'G'=>771,'H'=>802,'I'=>354,'J'=>354,'K'=>781,'L'=>604,'M'=>927,'N'=>750,'O'=>823, Chris@441: 'P'=>563,'Q'=>823,'R'=>729,'S'=>542,'T'=>698,'U'=>771,'V'=>729,'W'=>948,'X'=>771,'Y'=>677, Chris@441: 'Z'=>635,'['=>344,'\\'=>520,']'=>344,'^'=>469,'_'=>500,'`'=>250,'a'=>469,'b'=>521,'c'=>427, Chris@441: 'd'=>521,'e'=>438,'f'=>271,'g'=>469,'h'=>531,'i'=>250,'j'=>250,'k'=>458,'l'=>240,'m'=>802, Chris@441: 'n'=>531,'o'=>500,'p'=>521,'q'=>521,'r'=>365,'s'=>333,'t'=>292,'u'=>521,'v'=>458,'w'=>677, Chris@441: 'x'=>479,'y'=>458,'z'=>427,'{'=>480,'|'=>496,'}'=>480,'~'=>667} Chris@441: Chris@441: GB_widths={' '=>207,'!'=>270,'"'=>342,'#'=>467,'$'=>462,'%'=>797,'&'=>710,'\''=>239, Chris@441: '('=>374,')'=>374,'*'=>423,'+'=>605,','=>238,'-'=>375,'.'=>238,'/'=>334,'0'=>462,'1'=>462, Chris@441: '2'=>462,'3'=>462,'4'=>462,'5'=>462,'6'=>462,'7'=>462,'8'=>462,'9'=>462,':'=>238,';'=>238, Chris@441: '<'=>605,'='=>605,'>'=>605,'?'=>344,'@'=>748,'A'=>684,'B'=>560,'C'=>695,'D'=>739,'E'=>563, Chris@441: 'F'=>511,'G'=>729,'H'=>793,'I'=>318,'J'=>312,'K'=>666,'L'=>526,'M'=>896,'N'=>758,'O'=>772, Chris@441: 'P'=>544,'Q'=>772,'R'=>628,'S'=>465,'T'=>607,'U'=>753,'V'=>711,'W'=>972,'X'=>647,'Y'=>620, Chris@441: 'Z'=>607,'['=>374,'\\'=>333,']'=>374,'^'=>606,'_'=>500,'`'=>239,'a'=>417,'b'=>503,'c'=>427, Chris@441: 'd'=>529,'e'=>415,'f'=>264,'g'=>444,'h'=>518,'i'=>241,'j'=>230,'k'=>495,'l'=>228,'m'=>793, Chris@441: 'n'=>527,'o'=>524,'p'=>524,'q'=>504,'r'=>338,'s'=>336,'t'=>277,'u'=>517,'v'=>450,'w'=>652, Chris@441: 'x'=>466,'y'=>452,'z'=>407,'{'=>370,'|'=>258,'}'=>370,'~'=>605} Chris@441: Chris@441: def AddCIDFont(family,style,name,cw,cMap,registry) Chris@441: #ActionController::Base::logger.debug registry.to_a.join(":").to_s Chris@441: fontkey=family.downcase+style.upcase Chris@441: unless @fonts[fontkey].nil? Chris@441: Error("Font already added: family style") Chris@441: end Chris@441: i=@fonts.length+1 Chris@441: name=name.gsub(' ','') Chris@441: @fonts[fontkey]={'i'=>i,'type'=>'Type0','name'=>name,'up'=>-130,'ut'=>40,'cw'=>cw, 'CMap'=>cMap,'registry'=>registry} Chris@441: end Chris@441: Chris@441: def AddCIDFonts(family,name,cw,cMap,registry) Chris@441: AddCIDFont(family,'',name,cw,cMap,registry) Chris@441: AddCIDFont(family,'B',name+',Bold',cw,cMap,registry) Chris@441: AddCIDFont(family,'I',name+',Italic',cw,cMap,registry) Chris@441: AddCIDFont(family,'BI',name+',BoldItalic',cw,cMap,registry) Chris@441: end Chris@441: Chris@441: def AddBig5Font(family='Big5',name='MSungStd-Light-Acro') Chris@441: #Add Big5 font with proportional Latin Chris@441: cw=Big5_widths Chris@441: cMap='ETenms-B5-H' Chris@441: registry={'ordering'=>'CNS1','supplement'=>0} Chris@441: #ActionController::Base::logger.debug registry.to_a.join(":").to_s Chris@441: AddCIDFonts(family,name,cw,cMap,registry) Chris@441: end Chris@441: Chris@441: def AddBig5hwFont(family='Big5-hw',name='MSungStd-Light-Acro') Chris@441: #Add Big5 font with half-witdh Latin Chris@441: cw = {} Chris@441: 32.upto(126) do |i| Chris@441: cw[i.chr]=500 Chris@441: end Chris@441: cMap='ETen-B5-H' Chris@441: registry={'ordering'=>'CNS1','supplement'=>0} Chris@441: AddCIDFonts(family,name,cw,cMap,registry) Chris@441: end Chris@441: Chris@441: def AddGBFont(family='GB',name='STSongStd-Light-Acro') Chris@441: #Add GB font with proportional Latin Chris@441: cw=GB_widths Chris@441: cMap='GBKp-EUC-H' Chris@441: registry={'ordering'=>'GB1','supplement'=>2} Chris@441: AddCIDFonts(family,name,cw,cMap,registry) Chris@441: end Chris@441: Chris@441: def AddGBhwFont(family='GB-hw',name='STSongStd-Light-Acro') Chris@441: #Add GB font with half-width Latin Chris@441: 32.upto(126) do |i| Chris@441: cw[i.chr]=500 Chris@441: end Chris@441: cMap='GBK-EUC-H' Chris@441: registry={'ordering'=>'GB1','supplement'=>2} Chris@441: AddCIDFonts(family,name,cw,cMap,registry) Chris@441: end Chris@441: Chris@441: def GetStringWidth(s) Chris@441: if(@current_font['type']=='Type0') Chris@441: return GetMBStringWidth(s) Chris@441: else Chris@441: return super(s) Chris@441: end Chris@441: end Chris@441: Chris@441: def GetMBStringWidth(s) Chris@441: #Multi-byte version of GetStringWidth() Chris@441: l=0 Chris@441: cw=@current_font['cw'] Chris@441: nb=s.length Chris@441: i=0 Chris@441: while(i0 and s[nb-1]=="\n") Chris@441: nb-=1 Chris@441: end Chris@441: b=0 Chris@441: if(border) Chris@441: if(border==1) Chris@441: border='LTRB' Chris@441: b='LRT' Chris@441: b2='LR' Chris@441: else Chris@441: b2='' Chris@441: b2='L' unless border.to_s.index('L').nil? Chris@441: b2=b2+'R' unless border.to_s.index('R').nil? Chris@441: b=(border.to_s.index('T')) ? (b2+'T') : b2 Chris@441: end Chris@441: end Chris@441: sep=-1 Chris@441: i=0 Chris@441: j=0 Chris@441: l=0 Chris@441: nl=1 Chris@441: while(iwmax) Chris@441: #Automatic line break Chris@441: if(sep==-1 or i==j) Chris@441: if(i==j) Chris@441: i+=ascii ? 1 : 2 Chris@441: end Chris@441: Cell(w,h,s[j,i-j],b,2,align,fill) Chris@441: else Chris@441: Cell(w,h,s[j,sep-j],b,2,align,fill) Chris@441: i=(s[sep].chr==' ') ? sep+1 : sep Chris@441: end Chris@441: sep=-1 Chris@441: j=i Chris@441: l=0 Chris@441: nl+=1 Chris@441: if(border and nl==2) Chris@441: b=b2 Chris@441: end Chris@441: else Chris@441: i+=ascii ? 1 : 2 Chris@441: end Chris@441: end Chris@441: #Last chunk Chris@441: if(border and not border.to_s.index('B').nil?) Chris@441: b+='B' Chris@441: end Chris@441: Cell(w,h,s[j,i-j],b,2,align,fill) Chris@441: @x=@l_margin Chris@441: end Chris@441: Chris@507: def Write(h,txt,link='',fill=0) Chris@441: if(@current_font['type']=='Type0') Chris@441: MBWrite(h,txt,link) Chris@441: else Chris@441: super(h,txt,link) Chris@441: end Chris@441: end Chris@441: Chris@441: def MBWrite(h,txt,link) Chris@441: #Multi-byte version of Write() Chris@441: cw=@current_font['cw'] Chris@441: w=@w-@r_margin-@x Chris@441: wmax=(w-2*@c_margin)*1000/@font_size Chris@441: s=txt.gsub("\r",'') Chris@441: nb=s.length Chris@441: sep=-1 Chris@441: i=0 Chris@441: j=0 Chris@441: l=0 Chris@441: nl=1 Chris@441: while(iwmax) Chris@441: #Automatic line break Chris@441: if(sep==-1 or i==j) Chris@441: if(@x>@l_margin) Chris@441: #Move to next line Chris@441: @x=@l_margin Chris@441: @y+=h Chris@441: w=@w-@r_margin-@x Chris@441: wmax=(w-2*@c_margin)*1000/@font_size Chris@441: i+=1 Chris@441: nl+=1 Chris@441: next Chris@441: end Chris@441: if(i==j) Chris@441: i+=ascii ? 1 : 2 Chris@441: end Chris@441: Cell(w,h,s[j,i-j],0,2,'',0,link) Chris@441: else Chris@441: Cell(w,h,s[j,sep-j],0,2,'',0,link) Chris@441: i=(s[sep].chr==' ') ? sep+1 : sep Chris@441: end Chris@441: sep=-1 Chris@441: j=i Chris@441: l=0 Chris@441: if(nl==1) Chris@441: @x=@l_margin Chris@441: w=@w-@r_margin-@x Chris@441: wmax=(w-2*@c_margin)*1000/@font_size Chris@441: end Chris@441: nl+=1 Chris@441: else Chris@441: i+=ascii ? 1 : 2 Chris@441: end Chris@441: end Chris@441: #Last chunk Chris@441: if(i!=j) Chris@441: Cell(l/1000*@font_size,h,s[j,i-j],0,0,'',0,link) Chris@441: end Chris@441: end Chris@441: Chris@441: private Chris@441: Chris@441: def putfonts() Chris@441: nf=@n Chris@441: @diffs.each do |diff| Chris@441: #Encodings Chris@441: newobj() Chris@441: out('<>') Chris@441: out('endobj') Chris@441: end Chris@441: # mqr=get_magic_quotes_runtime() Chris@441: # set_magic_quotes_runtime(0) Chris@441: @font_files.each_pair do |file, info| Chris@441: #Font file embedding Chris@441: newobj() Chris@441: @font_files[file]['n']=@n Chris@441: if(defined('FPDF_FONTPATH')) Chris@441: file=FPDF_FONTPATH+file Chris@441: end Chris@441: size=filesize(file) Chris@441: if(!size) Chris@441: Error('Font file not found') Chris@441: end Chris@441: out('<>') Chris@441: f=fopen(file,'rb') Chris@441: putstream(fread(f,size)) Chris@441: fclose(f) Chris@441: out('endobj') Chris@441: end Chris@441: # Chris@441: # set_magic_quotes_runtime(mqr) Chris@441: # Chris@441: @fonts.each_pair do |k, font| Chris@441: #Font objects Chris@441: newobj() Chris@441: @fonts[k]['n']=@n Chris@441: out('<>') Chris@441: out('endobj') Chris@441: if(font['type']!='core') Chris@441: #Widths Chris@441: newobj() Chris@441: cw=font['cw'] Chris@441: s='[' Chris@441: 32.upto(255) do |i| Chris@441: s+=cw[i.chr]+' ' Chris@441: end Chris@441: out(s+']') Chris@441: out('endobj') Chris@441: #Descriptor Chris@441: newobj() Chris@441: s='<>') Chris@441: out('endobj') Chris@441: end Chris@441: end Chris@441: end Chris@441: end Chris@441: Chris@441: def putType0(font) Chris@441: #Type0 Chris@441: out('/Subtype /Type0') Chris@441: out('/BaseFont /'+font['name']+'-'+font['CMap']) Chris@441: out('/Encoding /'+font['CMap']) Chris@441: out('/DescendantFonts ['+(@n+1).to_s+' 0 R]') Chris@441: out('>>') Chris@441: out('endobj') Chris@441: #CIDFont Chris@441: newobj() Chris@441: out('<>') Chris@441: out('/FontDescriptor '+(@n+1).to_s+' 0 R') Chris@441: if(font['CMap']=='ETen-B5-H') Chris@441: w='13648 13742 500' Chris@441: elsif(font['CMap']=='GBK-EUC-H') Chris@441: w='814 907 500 7716 [500]' Chris@441: else Chris@441: # ActionController::Base::logger.debug font['cw'].keys.sort.join(' ').to_s Chris@441: # ActionController::Base::logger.debug font['cw'].values.join(' ').to_s Chris@441: w='1 [' Chris@441: font['cw'].keys.sort.each {|key| Chris@441: w+=font['cw'][key].to_s + " " Chris@441: # ActionController::Base::logger.debug key.to_s Chris@441: # ActionController::Base::logger.debug font['cw'][key].to_s Chris@441: } Chris@441: w +=']' Chris@441: end Chris@441: out('/W ['+w+']>>') Chris@441: out('endobj') Chris@441: #Font descriptor Chris@441: newobj() Chris@441: out('<>') Chris@441: out('endobj') Chris@441: end Chris@441: end