Blog: UFPDF: Quick and dirty fix for page numbering

Views:
7635

UFPDF [http://acko.net/node/56] is a Unicode/UTF-8 extension for FPDF [http://www.fpdf.org/] by Steven Wittens. It is quite outdated right now, but if for some reasons you're stuck with it, you might not like the fact, that one quite important function is broken.

In FPDF you can use AliasNbPages [http://www.fpdf.org/en/doc/aliasnbpages.htm] method, to specify a 'total pages' alias - a short string that will be replaced with total number of pages in document when PDF is generated. So if you for example do:

$this->Cell(0,10,'Page '.$this->PageNo().'/{nb}',0,0,'C');   //{nb} is a default AliasNbPages

and your document has 12 pages, {nb} will be replaced with 12 on each page.

Unfortunately in UFPDF this does not work. UFPDF is replacing and adding some UTF-8 enabled methods to core FPDF class, which on its side does most of the generating PDF work. (BTW: you can safely replace fpdf.php that is in UFPDF download, with the newest version from FPDF site without breaking anything) Substituting AliasNbPages for number of pages is also handled by FPDF by means of simple str_replace [http://www.php.net/manual/en/function.str-replace.php]. That's where it fails:

function _putpages()
{
	$nb=$this->page;
	if(!empty($this->AliasNbPages))
	{
		//Replace number of pages
		for($n=1;$n<=$nb;$n++)
			$this->pages[$n]=str_replace($this->AliasNbPages,$nb,$this->pages[$n]);
	}
...
}

All content generated by UFPDF is already UTF-8/Unicode encoded at this moment, so str_replace just can't find the alias and replace it. I've spend some time trying to find out a nice fix for this using mb_string [http://www.php.net/manual/en/book.mbstring.php] or other encoding conversion functions, but ultimately I've come up with this:

function _putpages()
{
	$nb=$this->page;
	if(!empty($this->AliasNbPages))
	{
		//Replace number of pages
		
		$nb = (string)$nb;
		$nbs = '';
		for($i = 0;$i < strlen($nb); $i++) {
			$nbs .= "\0".$nb[$i];
		}
		
		$alias = $this->AliasNbPages;
		$aliass = '';
		for($i = 0;$i < strlen($alias); $i++) {
			$aliass .= "\0".$alias[$i];
		}
		
		for($n=1;$n<=$nb;$n++)
			$this->pages[$n]=str_replace($aliass,$nbs,$this->pages[$n]);
	}
...
}

What it does is it adds additional \0 character (essentially a byte with value 0) in front of each character in AliasNbPages. It does the same to the number of pages string. Then it just replaces one with the other.

It's ugly as hell, but it works. One limitation is, you should only use characters from ASCII set to define AliasNbPages (default {nb} works well).