首页 > 开发 > PHP > 正文

用PHP创建PDF中文文档

2024-05-04 22:55:05
字体:
来源:转载
供稿:网友


收集最实用的网页特效代码!

我使用的是fpdf(www.fpdf.org),下载了fpdf类库后,还要使用下面的中文类库才能支持中文,但只能使用一种中文字体(华文仿宋)。为此我烦恼了很长时间,现在终于搞定了,将truetype字体转化为pt1字体使用:

下面是在fpdf上找的一个中文类库:
<?php
require(''fpdf.php'');

$big5_widths=array('' ''=>250,''!''=>250,''"''=>408,''#''=>668,''$''=>490,''%''=>875,''&''=>698,''''''=>250,
''(''=>240,'')''=>240,''*''=>417,''+''=>667,'',''=>250,''-''=>313,''.''=>250,''/''=>520,''0''=>500,''1''=>500,
''2''=>500,''3''=>500,''4''=>500,''5''=>500,''6''=>500,''7''=>500,''8''=>500,''9''=>500,'':''=>250,'';''=>250,
''<''=>667,''=''=>667,''>''=>667,''?''=>396,''@''=>921,''a''=>677,''b''=>615,''c''=>719,''d''=>760,''e''=>625,
''f''=>552,''g''=>771,''h''=>802,''i''=>354,''j''=>354,''k''=>781,''l''=>604,''m''=>927,''n''=>750,''o''=>823,
''p''=>563,''q''=>823,''r''=>729,''s''=>542,''t''=>698,''u''=>771,''v''=>729,''w''=>948,''x''=>771,''y''=>677,
''z''=>635,''[''=>344,''''=>520,'']''=>344,''^''=>469,''_''=>500,''`''=>250,''a''=>469,''b''=>521,''c''=>427,
''d''=>521,''e''=>438,''f''=>271,''g''=>469,''h''=>531,''i''=>250,''j''=>250,''k''=>458,''l''=>240,''m''=>802,
''n''=>531,''o''=>500,''p''=>521,''q''=>521,''r''=>365,''s''=>333,''t''=>292,''u''=>521,''v''=>458,''w''=>677,
''x''=>479,''y''=>458,''z''=>427,''{''=>480,''|''=>496,''}''=>480,''~''=>667);

$gb_widths=array('' ''=>207,''!''=>270,''"''=>342,''#''=>467,''$''=>462,''%''=>797,''&''=>710,''''''=>239,
''(''=>374,'')''=>374,''*''=>423,''+''=>605,'',''=>238,''-''=>375,''.''=>238,''/''=>334,''0''=>462,''1''=>462,
''2''=>462,''3''=>462,''4''=>462,''5''=>462,''6''=>462,''7''=>462,''8''=>462,''9''=>462,'':''=>238,'';''=>238,
''<''=>605,''=''=>605,''>''=>605,''?''=>344,''@''=>748,''a''=>684,''b''=>560,''c''=>695,''d''=>739,''e''=>563,
''f''=>511,''g''=>729,''h''=>793,''i''=>318,''j''=>312,''k''=>666,''l''=>526,''m''=>896,''n''=>758,''o''=>772,
''p''=>544,''q''=>772,''r''=>628,''s''=>465,''t''=>607,''u''=>753,''v''=>711,''w''=>972,''x''=>647,''y''=>620,
''z''=>607,''[''=>374,''''=>333,'']''=>374,''^''=>606,''_''=>500,''`''=>239,''a''=>417,''b''=>503,''c''=>427,
''d''=>529,''e''=>415,''f''=>264,''g''=>444,''h''=>518,''i''=>241,''j''=>230,''k''=>495,''l''=>228,''m''=>793,
''n''=>527,''o''=>524,''p''=>524,''q''=>504,''r''=>338,''s''=>336,''t''=>277,''u''=>517,''v''=>450,''w''=>652,
''x''=>466,''y''=>452,''z''=>407,''{''=>370,''|''=>258,''}''=>370,''~''=>605);

class pdf_chinese extends fpdf
{
function addcidfont($family,$style,$name,$cw,$cmap,$registry)
{
$i=count($this->fonts)+1;
$fontkey=strtolower($family).strtoupper($style);
$this->fonts[$fontkey]=array(''i''=>$i,''type''=>''type0'',''name''=>$name,''up''=>-120,''ut''=>40,''cw''=>$cw,''cmap''=>$cmap,''registry''=>$registry);
}

function addbig5font($family=''big5'')
{
$cw=$globals[''big5_widths''];
$name=''msungstd-light-acro'';
$cmap=''etenms-b5-h'';
$registry=array(''ordering''=>''cns1'',''supplement''=>0);
$this->addcidfont($family,'''',$name,$cw,$cmap,$registry);
$this->addcidfont($family,''b'',$name.'',bold'',$cw,$cmap,$registry);
$this->addcidfont($family,''i'',$name.'',italic'',$cw,$cmap,$registry);
$this->addcidfont($family,''bi'',$name.'',bolditalic'',$cw,$cmap,$registry);
}

function addgbfont($family=''gb'')
{
$cw=$globals[''gb_widths''];
$name=''stsongstd-light-acro'';
$cmap=''gbkp-euc-h'';
$registry=array(''ordering''=>''gb1'',''supplement''=>2);
$this->addcidfont($family,'''',$name,$cw,$cmap,$registry);
$this->addcidfont($family,''b'',$name.'',bold'',$cw,$cmap,$registry);
$this->addcidfont($family,''i'',$name.'',italic'',$cw,$cmap,$registry);
$this->addcidfont($family,''bi'',$name.'',bolditalic'',$cw,$cmap,$registry);
}

function getstringwidth($s)
{
if($this->currentfont[''type'']==''type0'')
return $this->getmbstringwidth($s);
else
return parent::getstringwidth($s);
}

function getmbstringwidth($s)
{
//multi-byte version of getstringwidth()
$l=0;
$cw=&$this->currentfont[''cw''];
$nb=strlen($s);
$i=0;
while($i<$nb)
{
$c=$s[$i];
if(ord($c)<128)
{
$l+=$cw[$c];
$i++;
}
else
{
$l+=1000;
$i+=2;
}
}
return $l*$this->fontsize/1000;
}

function multicell($w,$h,$txt,$border=0,$align=''l'',$fill=0)
{
if($this->currentfont[''type'']==''type0'')
$this->mbmulticell($w,$h,$txt,$border,$align,$fill);
else
parent::multicell($w,$h,$txt,$border,$align,$fill);
}

function mbmulticell($w,$h,$txt,$border=0,$align=''l'',$fill=0)
{
//multi-byte version of multicell()
$cw=&$this->currentfont[''cw''];
if($w==0)
$w=$this->w-$this->rmargin-$this->x;
$wmax=($w-2*$this->cmargin)*1000/$this->fontsize;
$s=str_replace("/r",'''',$txt);
$nb=strlen($s);
if($nb>0 and $s[$nb-1]=="/n"
$nb--;
$b=0;
if($border)
{
if($border==1)
{
$border=''ltrb'';
$b=''lrt'';
$b2=''lr'';
}
else
{
$b2='''';
if(is_int(strpos($border,''l'')))
$b2.=''l'';
if(is_int(strpos($border,''r'')))
$b2.=''r'';
$b=is_int(strpos($border,''t'')) ? $b2.''t'' : $b2;
}
}
$sep=-1;
$i=0;
$j=0;
$l=0;
$ns=0;
$nl=1;
while($i<$nb)
{
//get next character
$c=$s[$i];
//check if ascii or mb
$ascii=(ord($c)<128);
if($c=="/n"
{
//explicit line break
if($this->ws>0)
{
$this->ws=0;
$this->_out(''0 tw'');
}
$this->cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
$i++;
$sep=-1;
$j=$i;
$l=0;
$ns=0;
$nl++;
if($border and $nl==2)
$b=$b2;
continue;
}
if(!$ascii)
{
$sep=$i;
$ls=$l;
}
elseif($c=='' '')
{
$sep=$i;
$ls=$l;
$ns++;
}
$l+=$ascii ? $cw[$c] : 1000;
if($l>$wmax)
{
//automatic line break
if($sep==-1 or $i==$j)
{
if($i==$j)
$i+=$ascii ? 1 : 2;
if($this->ws>0)
{
$this->ws=0;
$this->_out(''0 tw'');
}
$this->cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
}
else
{
if($align==''j'')
{
if($s[$sep]=='' '')
$ns--;
if($s[$i-1]=='' '')
{
$ns--;
$ls-=$cw['' ''];
}
$this->ws=($ns>0) ? ($wmax-$ls)/1000*$this->fontsize/$ns : 0;
$this->_out(sprintf(''%.3f tw'',$this->ws*$this->k));
}
$this->cell($w,$h,substr($s,$j,$sep-$j),$b,2,$align,$fill);
$i=($s[$sep]=='' '') ? $sep+1 : $sep;
}
$sep=-1;
$j=$i;
$l=0;
$ns=0;
$nl++;
if($border and $nl==2)
$b=$b2;
}
else
$i+=$ascii ? 1 : 2;
}
//last chunk
if($this->ws>0)
{
$this->ws=0;
$this->_out(''0 tw'');
}
if($border and is_int(strpos($border,''b'')))
$b.=''b'';
$this->cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
$this->x=$this->lmargin;
}

function write($h,$txt,$link='''')
{
if($this->currentfont[''type'']==''type0'')
$this->mbwrite($h,$txt,$link);
else
parent::write($h,$txt,$link);
}

function mbwrite($h,$txt,$link)
{
//multi-byte version of write()
$cw=&$this->currentfont[''cw''];
$w=$this->w-$this->rmargin-$this->x;
$wmax=($w-2*$this->cmargin)*1000/$this->fontsize;
$s=str_replace("/r",'''',$txt);
$nb=strlen($s);
$sep=-1;
$i=0;
$j=0;
$l=0;
$nl=1;
while($i<$nb)
{
//get next character
$c=$s[$i];
//check if ascii or mb
$ascii=(ord($c)<128);
if($c=="/n"
{
//explicit line break
$this->cell($w,$h,substr($s,$j,$i-$j),0,2,'''',0,$link);
$i++;
$sep=-1;
$j=$i;
$l=0;
if($nl==1)
{
$this->x=$this->lmargin;
$w=$this->w-$this->rmargin-$this->x;
$wmax=($w-2*$this->cmargin)*1000/$this->fontsize;
}
$nl++;
continue;
}
if(!$ascii or $c=='' '')
$sep=$i;
$l+=$ascii ? $cw[$c] : 1000;
if($l>$wmax)
{
//automatic line break
if($sep==-1 or $i==$j)
{
if($this->x>$this->lmargin)
{
//move to next line
$this->x=$this->lmargin;
$this->y+=$h;
$w=$this->w-$this->rmargin-$this->x;
$wmax=($w-2*$this->cmargin)*1000/$this->fontsize;
$i++;
$nl++;
continue;
}
if($i==$j)
$i+=$ascii ? 1 : 2;
$this->cell($w,$h,substr($s,$j,$i-$j),0,2,'''',0,$link);
}
else
{
$this->cell($w,$h,substr($s,$j,$sep-$j),0,2,'''',0,$link);
$i=($s[$sep]=='' '') ? $sep+1 : $sep;
}
$sep=-1;
$j=$i;
$l=0;
if($nl==1)
{
$this->x=$this->lmargin;
$w=$this->w-$this->rmargin-$this->x;
$wmax=($w-2*$this->cmargin)*1000/$this->fontsize;
}
$nl++;
}
else
$i+=$ascii ? 1 : 2;
}
//last chunk
if($i!=$j)
$this->cell($l/1000*$this->fontsize,$h,substr($s,$j,$i-$j),0,0,'''',0,$link);
}

function _putfonts()
{
$nf=$this->n;
foreach($this->diffs as $diff)
{
//encodings
$this->_newobj();
$this->_out(''<</type /encoding /baseencoding /winansiencoding /differences [''.$diff.'']>>'');
$this->_out(''endobj'');
}
$mqr=get_magic_quotes_runtime();
set_magic_quotes_runtime(0);
foreach($this->fontfiles as $file=>$info)
{
//font file embedding
$this->_newobj();
$this->fontfiles[$file][''n'']=$this->n;
if(defined(''fpdf_fontpath''))
$file=fpdf_fontpath.$file;
$size=filesize($file);
if(!$size)
$this->error(''font file not found'');
$this->_out(''<</length ''.$size);
if(substr($file,-2)==''.z'')
$this->_out(''/filter /flatedecode'');
$this->_out(''/length1 ''.$info[''length1'']);
if(isset($info[''length2'']))
$this->_out(''/length2 ''.$info[''length2''].'' /length3 0'');
$this->_out(''>>'');
$f=fopen($file,''rb'');
$this->_putstream(fread($f,$size));
fclose($f);
$this->_out(''endobj'');
}
set_magic_quotes_runtime($mqr);
foreach($this->fonts as $k=>$font)
{
//font objects
$this->_newobj();
$this->fonts[$k][''n'']=$this->n;
$this->_out(''<</type /font'');
if($font[''type'']==''type0'')
$this->_puttype0($font);
else
{
$name=$font[''name''];
$this->_out(''/basefont /''.$name);
if($font[''type'']==''core'')
{
//standard font
$this->_out(''/subtype /type1'');
if($name!=''symbol'' and $name!=''zapfdingbats'')
$this->_out(''/encoding /winansiencoding'');
}
else
{
//additional font
$this->_out(''/subtype /''.$font[''type'']);
$this->_out(''/firstchar 32'');
$this->_out(''/lastchar 255'');
$this->_out(''/widths ''.($this->n+1).'' 0 r'');
$this->_out(''/fontdescriptor ''.($this->n+2).'' 0 r'');
if($font[''enc''])
{
if(isset($font[''diff'']))
$this->_out(''/encoding ''.($nf+$font[''diff'']).'' 0 r'');
else
$this->_out(''/encoding /winansiencoding'');
}
}
$this->_out(''>>'');
$this->_out(''endobj'');
if($font[''type'']!=''core'')
{
//widths
$this->_newobj();
$cw=&$font[''cw''];
$s=''['';
for($i=32;$i<=255;$i++)
$s.=$cw[chr($i)].'' '';
$this->_out($s.'']'');
$this->_out(''endobj'');
//descriptor
$this->_newobj();
$s=''<</type /fontdescriptor /fontname /''.$name;
foreach($font[''desc''] as $k=>$v)
$s.='' /''.$k.'' ''.$v;
$file=$font[''file''];
if($file)
$s.='' /fontfile''.($font[''type'']==''type1'' ? '''' : ''2'').'' ''.$this->fontfiles[$file][''n''].'' 0 r'';
$this->_out($s.''>>'');
$this->_out(''endobj'');
}
}
}
}

function _puttype0($font)
{
//type0
$this->_out(''/subtype /type0'');
$this->_out(''/basefont /''.$font[''name''].''-''.$font[''cmap'']);
$this->_out(''/encoding /''.$font[''cmap'']);
$this->_out(''/descendantfonts [''.($this->n+1).'' 0 r]'');
$this->_out(''>>'');
$this->_out(''endobj'');
//cidfont
$this->_newobj();
$this->_out(''<</type /font'');
$this->_out(''/subtype /cidfonttype0'');
$this->_out(''/basefont /''.$font[''name'']);
$this->_out(''/cidsysteminfo <</registry (adobe) /ordering (''.$font[''registry''][''ordering''].'') /supplement ''.$font[''registry''][''supplement''].''>>'');
$this->_out(''/fontdescriptor ''.($this->n+1).'' 0 r'');
$w=''/w [1 ['';
foreach($font[''cw''] as $w)
$w.=$w.'' '';
$this->_out($w.'']]'');
$this->_out(''>>'');
$this->_out(''endobj'');
//font descriptor
$this->_newobj();
$this->_out(''<</type /fontdescriptor'');
$this->_out(''/fontname /''.$font[''name'']);
$this->_out(''/flags 6'');
$this->_out(''/fontbbox [0 0 1000 1000]'');
$this->_out(''/italicangle 0'');
$this->_out(''/ascent 1000'');
$this->_out(''/descent 0'');
$this->_out(''/capheight 1000'');
$this->_out(''/stemv 10'');
$this->_out(''>>'');
$this->_out(''endobj'');
}
}
?>

将以上代码存为chinese.php即可引用。但用它只能得到一种字体。为了支持所有中文字体,可用ttf2pt1程序将truetype字体转化pt1字体,一个一个地转(具体方法在fpdf的教程中有详细说明)。为了支持其他中文字体,养分要修改上面的chinese.php,如下:

1: replace the following line in the addgbfont() method:

function addgbfont($family=''gb'',$name=''stsongstd-light-acro'')
{
$cw=$globals[''gb_widths''];
// $name=''stsongstd-light-acro'';
$cmap=''gbkp-euc-h'';
........

2: this is a sample.

<?php
require(''chinese.php'');

$pdf=new pdf_chinese();
$pdf->addgbfont(''simsun'',''宋体'');
$pdf->addgbfont(''simhei'',''黑体'');
$pdf->addgbfont(''simkai'',''楷体_gb2312'');
$pdf->addgbfont(''sinfang'',''仿宋_gb2312'''');
$pdf->open();
$pdf->addpage();
$pdf->setfont(''simsun'','''',20);
$pdf->write(10,''简体中文汉字‘);
$pdf->setfont(''simhei'','''',20);
$pdf->write(10,''简体中文汉字’);
$pdf->setfont(''simkai'','''',20);
$pdf->write(10,''简体中文汉字‘);
$pdf->setfont(''sinfang'','''',20);
$pdf->write(10,''简体中文汉字’);
$pdf->output();
?>

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表