Peaceful mind Where there is a will, there is a way!

26Jun/090

FPDF中的编码

最近在用FPDF生成pdf时,用UTF-8编码的日文或者繁体文字始终都是乱码。查了相关资料后,才发现FPDF本身并不支持UTF-8,除此之外,FPDF对中,日,韩支持的扩展类中使用的是CID字体,和我们window中用到的字体的都不同。因此当你使用支持中文的扩展类时,生成pdf时对日文肯定是不支持的。而TCPDF据说是支持UTF-8,但使用后发现对中文的支持很烂,还要手工转换字体,其方式和UFPDF是一样的。而我们很难找到一种同时对中,日,韩都支持的字体。用msgothic也只是对日文和繁体支持的比较好而已,对简体中文用华文中宋等字体显示更好一些,因此我的结论是,用FPDF生成pdf时,如果文件包含中文,日文,韩文等内容时,生成的pdf肯定有乱码或者空白。除非我们确切的知道文件中哪些地方显示中文,哪些地方显示日文,那我们就可以在开始的时用addfont添加这些字体,然后在输出的时候用setfont指定要输出的内容采取哪种字体。

此外,在解决乱码问题时容易遇到的以下问题:
现象一:当修改页面字符集为UTF-8,页面出现空白,不显示任何内容
都是字符集charset惹的祸,理由在于用charset指定为UTF-8之前,已经有非UTF-8编码文字的输出。比如一般html页面都是把title标签放在meta标签前面,因此80%的可能是title内容的编码和UTF-8引起的,最好的解决方法就是把title用UTF-8编码后再输出,或者在meta之后指定title。

现象二:页面报js错误,但仔细查看源代码后,发现没有任何问题。
同样是编码不一致导致的。这时要仔细查看页面是否引用了非UTF-8编码的文件,一个典型的情况就是外部js文件中的中文(包含注释等)引起的,解决方法就是把中文去掉,或者全部改为英文即可。

Tagged as: No Comments
3Jun/090

FPDF实现中文换行

关于fpdf对中文的支持,这里就不多讲了,已经有达人写了一个pdf的子类PDF_chinese实现了对中文的支持。我们重点考虑的是中文换行,提到换行,就不得不提ln和multicell和cell方法,ln是显式换行,multicell和cell最大的差别就是cell有一个是否换行的参数,而multicell没有,详细见手册。其实,如果对于要生成的pdf文档,只有一个字段的内容需要换行时,并且该字段是最右边的那个字段(当然你可以调整),那么使用multicell是大致可以得到想要的结果的。对于多个字段需要换行时,该方法就无能为力了。在官方的script库中,我们可以找到这个一段代码table with multicell,该方法是专门为有多个需要换行的字段设计的。但该方法仅提供了对英文字符换行的支持,中文换行仍然存在问题,解决方法如下:
1.首先将属性和方法加到基类的适当处。
2.修改Nblines方法,该方法是用来计算内容在宽度固定的条件,需要几行来显示该数据才不至于撑破单元格。并且我们在使用中文换行时,出现的现象是一致的,就是每个中文内容字段在一个cell中显示2行就不再显示。仔细查看代码:

 1 function NbLines($w,$txt)
 2 {
 3     //Computes the number of lines a MultiCell of width w will take
 4     $cw=&$this->CurrentFont['cw'];
 5     if($w==0)
 6         $w=$this->w-$this->rMargin-$this->x;
 7     $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
 8     $s=str_replace("\r",'',$txt);
 9     $nb=strlen($s);
10     if($nb>0 and $s[$nb-1]=="\n")
11         $nb--;
12     $sep=-1;
13     $i=0;
14     $j=0;
15     $l=0;
16     $nl=1;
17     while($i<$nb)
18     {
19         $c=$s[$i];
20         if($c=="\n")
21         {
22             $i++;
23             $sep=-1;
24             $j=$i;
25             $l=0;
26             $nl++;
27             continue;
28         }
29         if($c==' ')
30             $sep=$i;
31         $l+=$cw[$c];
32         if($l>$wmax)
33         {
34             if($sep==-1)
35             {
36                 if($i==$j)
37                     $i++;
38             }
39             else
40                 $i=$sep+1;
41             $sep=-1;
42             $j=$i;
43             $l=0;
44             $nl++;
45         }
46         else
47             $i++;
48     }
49     return $nl;
50 }

发现31行存在问题,由于这里的cw就是我们在chinese.php中定义的$GB_widths数组。而$GB_widths中并没有对中文的判断,因此每次遇到中文时,都没有进行累加操作。因此需改变为如下的代码:
if(!$cw[$c]) $l+=500; else $l+$cw[$c];
也就是说,我们把一个中文字看作一个占据一个空间的字母/数字代替,也就解决了中文不能换行的问题
3.如果要生成pdf文档颜色交替显示,需要修改Rows方法,添加一个参数fill,并修改其中的
$this->Rect($x,$y,$w,$h);为 if($fill) $this->sect($x,$y,$w,$h,"FD"); else $this->Rect($x,$y,$w,$h);

Tagged as: No Comments