PageRenderTime 48ms CodeModel.GetById 6ms app.highlight 35ms RepoModel.GetById 1ms app.codeStats 0ms

/libs/PdfNFePHP.class.php

https://github.com/trsanabio/nfephp
PHP | 855 lines | 562 code | 21 blank | 272 comment | 103 complexity | f4fbb77b898033deb5c51449b71b00cf MD5 | raw file
  1<?php
  2/**
  3 * Este arquivo é parte do projeto NFePHP - Nota Fiscal eletrônica em PHP.
  4 *
  5 * Este programa é um software livre: você pode redistribuir e/ou modificá-lo
  6 * sob os termos da Licença Pública Geral GNU como é publicada pela Fundação
  7 * para o Software Livre, na versão 3 da licença, ou qualquer versão posterior.
  8 * e/ou
  9 * sob os termos da Licença Pública Geral Menor GNU (LGPL) como é publicada pela
 10 * Fundação para o Software Livre, na versão 3 da licença, ou qualquer versão posterior.
 11 *
 12 * Este programa é distribuído na esperança que será útil, mas SEM NENHUMA
 13 * GARANTIA; nem mesmo a garantia explícita definida por qualquer VALOR COMERCIAL
 14 * ou de ADEQUAÇÃO PARA UM PROPÓSITO EM PARTICULAR,
 15 * veja a Licença Pública Geral GNU para mais detalhes.
 16 *
 17 * Você deve ter recebido uma cópia da Licença Publica GNU e da
 18 * Licença Pública Geral Menor GNU (LGPL) junto com este programa.
 19 * Caso contrário consulte
 20 * <http://www.fsfla.org/svnwiki/trad/GPLv3>
 21 * ou
 22 * <http://www.fsfla.org/svnwiki/trad/LGPLv3>.
 23 *
 24 * @package     NFePHP
 25 * @name        PdfNFePHP.class.php
 26 * @version     1.0.4
 27 * @license     http://www.gnu.org/licenses/gpl.html GNU/GPL v.3
 28 * @license     http://www.gnu.org/licenses/lgpl.html GNU/LGPL v.3
 29 * @copyright   2009-2011 &copy; NFePHP
 30 * @link        http://www.nfephp.org/
 31 * @author      Roberto L. Machado <linux.rlm at gmail dot com>
 32 * 
 33 * Esta classe contêm todas as funções necessárias para a criação dos arquivos
 34 * PDF usando o FPDF padrão sem a necessidade de modificação ou de outras classes 
 35 * auxiliares
 36 * 
 37 */
 38require_once('FPDF/fpdf.php');
 39
 40class PdfNFePHP extends FPDF {
 41    
 42    private $T128;                                             // tabela de codigos 128
 43    private $ABCset="";                                        // conjunto de caracteres legiveis em 128
 44    private $Aset="";                                          // grupo A do conjunto de de caracteres legiveis
 45    private $Bset="";                                          // grupo B do conjunto de caracteres legiveis
 46    private $Cset="";                                          // grupo C do conjunto de caracteres legiveis
 47    private $SetFrom;                                          // converter de 
 48    private $SetTo;                                            // converter para
 49    private $JStart = array("A"=>103, "B"=>104, "C"=>105);     // Caracteres de seleção do grupo 128
 50    private $JSwap = array("A"=>101, "B"=>100, "C"=>99);       // Caracteres de troca de grupo
 51
 52    function __construct($orientation='P',$unit='mm',$format='A4') {
 53       //passar parametros para a classe principal 
 54       parent::FPDF($orientation,$unit,$format);
 55       // composição dos caracteres do barcode 128
 56       $this->T128[] = array(2, 1, 2, 2, 2, 2);           //0 : [ ]
 57       $this->T128[] = array(2, 2, 2, 1, 2, 2);           //1 : [!]
 58       $this->T128[] = array(2, 2, 2, 2, 2, 1);           //2 : ["]
 59       $this->T128[] = array(1, 2, 1, 2, 2, 3);           //3 : [#]
 60       $this->T128[] = array(1, 2, 1, 3, 2, 2);           //4 : [$]
 61       $this->T128[] = array(1, 3, 1, 2, 2, 2);           //5 : [%]
 62       $this->T128[] = array(1, 2, 2, 2, 1, 3);           //6 : [&]
 63       $this->T128[] = array(1, 2, 2, 3, 1, 2);           //7 : [']
 64       $this->T128[] = array(1, 3, 2, 2, 1, 2);           //8 : [(]
 65       $this->T128[] = array(2, 2, 1, 2, 1, 3);           //9 : [)]
 66       $this->T128[] = array(2, 2, 1, 3, 1, 2);           //10 : [*]
 67       $this->T128[] = array(2, 3, 1, 2, 1, 2);           //11 : [+]
 68       $this->T128[] = array(1, 1, 2, 2, 3, 2);           //12 : [,]
 69       $this->T128[] = array(1, 2, 2, 1, 3, 2);           //13 : [-]
 70       $this->T128[] = array(1, 2, 2, 2, 3, 1);           //14 : [.]
 71       $this->T128[] = array(1, 1, 3, 2, 2, 2);           //15 : [/]
 72       $this->T128[] = array(1, 2, 3, 1, 2, 2);           //16 : [0]
 73       $this->T128[] = array(1, 2, 3, 2, 2, 1);           //17 : [1]
 74       $this->T128[] = array(2, 2, 3, 2, 1, 1);           //18 : [2]
 75       $this->T128[] = array(2, 2, 1, 1, 3, 2);           //19 : [3]
 76       $this->T128[] = array(2, 2, 1, 2, 3, 1);           //20 : [4]
 77       $this->T128[] = array(2, 1, 3, 2, 1, 2);           //21 : [5]
 78       $this->T128[] = array(2, 2, 3, 1, 1, 2);           //22 : [6]
 79       $this->T128[] = array(3, 1, 2, 1, 3, 1);           //23 : [7]
 80       $this->T128[] = array(3, 1, 1, 2, 2, 2);           //24 : [8]
 81       $this->T128[] = array(3, 2, 1, 1, 2, 2);           //25 : [9]
 82       $this->T128[] = array(3, 2, 1, 2, 2, 1);           //26 : [:]
 83       $this->T128[] = array(3, 1, 2, 2, 1, 2);           //27 : [;]
 84       $this->T128[] = array(3, 2, 2, 1, 1, 2);           //28 : [<]
 85       $this->T128[] = array(3, 2, 2, 2, 1, 1);           //29 : [=]
 86       $this->T128[] = array(2, 1, 2, 1, 2, 3);           //30 : [>]
 87       $this->T128[] = array(2, 1, 2, 3, 2, 1);           //31 : [?]
 88       $this->T128[] = array(2, 3, 2, 1, 2, 1);           //32 : [@]
 89       $this->T128[] = array(1, 1, 1, 3, 2, 3);           //33 : [A]
 90       $this->T128[] = array(1, 3, 1, 1, 2, 3);           //34 : [B]
 91       $this->T128[] = array(1, 3, 1, 3, 2, 1);           //35 : [C]
 92       $this->T128[] = array(1, 1, 2, 3, 1, 3);           //36 : [D]
 93       $this->T128[] = array(1, 3, 2, 1, 1, 3);           //37 : [E]
 94       $this->T128[] = array(1, 3, 2, 3, 1, 1);           //38 : [F]
 95       $this->T128[] = array(2, 1, 1, 3, 1, 3);           //39 : [G]
 96       $this->T128[] = array(2, 3, 1, 1, 1, 3);           //40 : [H]
 97       $this->T128[] = array(2, 3, 1, 3, 1, 1);           //41 : [I]
 98       $this->T128[] = array(1, 1, 2, 1, 3, 3);           //42 : [J]
 99       $this->T128[] = array(1, 1, 2, 3, 3, 1);           //43 : [K]
100       $this->T128[] = array(1, 3, 2, 1, 3, 1);           //44 : [L]
101       $this->T128[] = array(1, 1, 3, 1, 2, 3);           //45 : [M]
102       $this->T128[] = array(1, 1, 3, 3, 2, 1);           //46 : [N]
103       $this->T128[] = array(1, 3, 3, 1, 2, 1);           //47 : [O]
104       $this->T128[] = array(3, 1, 3, 1, 2, 1);           //48 : [P]
105       $this->T128[] = array(2, 1, 1, 3, 3, 1);           //49 : [Q]
106       $this->T128[] = array(2, 3, 1, 1, 3, 1);           //50 : [R]
107       $this->T128[] = array(2, 1, 3, 1, 1, 3);           //51 : [S]
108       $this->T128[] = array(2, 1, 3, 3, 1, 1);           //52 : [T]
109       $this->T128[] = array(2, 1, 3, 1, 3, 1);           //53 : [U]
110       $this->T128[] = array(3, 1, 1, 1, 2, 3);           //54 : [V]
111       $this->T128[] = array(3, 1, 1, 3, 2, 1);           //55 : [W]
112       $this->T128[] = array(3, 3, 1, 1, 2, 1);           //56 : [X]
113       $this->T128[] = array(3, 1, 2, 1, 1, 3);           //57 : [Y]
114       $this->T128[] = array(3, 1, 2, 3, 1, 1);           //58 : [Z]
115       $this->T128[] = array(3, 3, 2, 1, 1, 1);           //59 : [[]
116       $this->T128[] = array(3, 1, 4, 1, 1, 1);           //60 : [\]
117       $this->T128[] = array(2, 2, 1, 4, 1, 1);           //61 : []]
118       $this->T128[] = array(4, 3, 1, 1, 1, 1);           //62 : [^]
119       $this->T128[] = array(1, 1, 1, 2, 2, 4);           //63 : [_]
120       $this->T128[] = array(1, 1, 1, 4, 2, 2);           //64 : [`]
121       $this->T128[] = array(1, 2, 1, 1, 2, 4);           //65 : [a]
122       $this->T128[] = array(1, 2, 1, 4, 2, 1);           //66 : [b]
123       $this->T128[] = array(1, 4, 1, 1, 2, 2);           //67 : [c]
124       $this->T128[] = array(1, 4, 1, 2, 2, 1);           //68 : [d]
125       $this->T128[] = array(1, 1, 2, 2, 1, 4);           //69 : [e]
126       $this->T128[] = array(1, 1, 2, 4, 1, 2);           //70 : [f]
127       $this->T128[] = array(1, 2, 2, 1, 1, 4);           //71 : [g]
128       $this->T128[] = array(1, 2, 2, 4, 1, 1);           //72 : [h]
129       $this->T128[] = array(1, 4, 2, 1, 1, 2);           //73 : [i]
130       $this->T128[] = array(1, 4, 2, 2, 1, 1);           //74 : [j]
131       $this->T128[] = array(2, 4, 1, 2, 1, 1);           //75 : [k]
132       $this->T128[] = array(2, 2, 1, 1, 1, 4);           //76 : [l]
133       $this->T128[] = array(4, 1, 3, 1, 1, 1);           //77 : [m]
134       $this->T128[] = array(2, 4, 1, 1, 1, 2);           //78 : [n]
135       $this->T128[] = array(1, 3, 4, 1, 1, 1);           //79 : [o]
136       $this->T128[] = array(1, 1, 1, 2, 4, 2);           //80 : [p]
137       $this->T128[] = array(1, 2, 1, 1, 4, 2);           //81 : [q]
138       $this->T128[] = array(1, 2, 1, 2, 4, 1);           //82 : [r]
139       $this->T128[] = array(1, 1, 4, 2, 1, 2);           //83 : [s]
140       $this->T128[] = array(1, 2, 4, 1, 1, 2);           //84 : [t]
141       $this->T128[] = array(1, 2, 4, 2, 1, 1);           //85 : [u]
142       $this->T128[] = array(4, 1, 1, 2, 1, 2);           //86 : [v]
143       $this->T128[] = array(4, 2, 1, 1, 1, 2);           //87 : [w]
144       $this->T128[] = array(4, 2, 1, 2, 1, 1);           //88 : [x]
145       $this->T128[] = array(2, 1, 2, 1, 4, 1);           //89 : [y]
146       $this->T128[] = array(2, 1, 4, 1, 2, 1);           //90 : [z]
147       $this->T128[] = array(4, 1, 2, 1, 2, 1);           //91 : [{]
148       $this->T128[] = array(1, 1, 1, 1, 4, 3);           //92 : [|]
149       $this->T128[] = array(1, 1, 1, 3, 4, 1);           //93 : [}]
150       $this->T128[] = array(1, 3, 1, 1, 4, 1);           //94 : [~]
151       $this->T128[] = array(1, 1, 4, 1, 1, 3);           //95 : [DEL]
152       $this->T128[] = array(1, 1, 4, 3, 1, 1);           //96 : [FNC3]
153       $this->T128[] = array(4, 1, 1, 1, 1, 3);           //97 : [FNC2]
154       $this->T128[] = array(4, 1, 1, 3, 1, 1);           //98 : [SHIFT]
155       $this->T128[] = array(1, 1, 3, 1, 4, 1);           //99 : [Cswap]
156       $this->T128[] = array(1, 1, 4, 1, 3, 1);           //100 : [Bswap]
157       $this->T128[] = array(3, 1, 1, 1, 4, 1);           //101 : [Aswap]
158       $this->T128[] = array(4, 1, 1, 1, 3, 1);           //102 : [FNC1]
159       $this->T128[] = array(2, 1, 1, 4, 1, 2);           //103 : [Astart]
160       $this->T128[] = array(2, 1, 1, 2, 1, 4);           //104 : [Bstart]
161       $this->T128[] = array(2, 1, 1, 2, 3, 2);           //105 : [Cstart]
162       $this->T128[] = array(2, 3, 3, 1, 1, 1);           //106 : [STOP]
163       $this->T128[] = array(2, 1);                       //107 : [END BAR]
164       for ($i = 32; $i <= 95; $i++) {   // conjunto de caracteres
165              $this->ABCset .= chr($i);
166       }
167       $this->Aset = $this->ABCset;
168       $this->Bset = $this->ABCset;
169       for ($i = 0; $i <= 31; $i++) {
170              $this->ABCset .= chr($i);
171              $this->Aset .= chr($i);
172       }
173       for ($i = 96; $i <= 126; $i++) {
174              $this->ABCset .= chr($i);
175              $this->Bset .= chr($i);
176       }
177       $this->Cset="0123456789";
178       for ($i=0; $i<96; $i++) {  // convertendo grupos A & B  
179              @$this->SetFrom["A"] .= chr($i);
180              @$this->SetFrom["B"] .= chr($i + 32);
181              @$this->SetTo["A"] .= chr(($i < 32) ? $i+64 : $i-32);
182              @$this->SetTo["B"] .= chr($i);
183       }
184    }//fim __construct
185
186    /**
187     * Code128
188     * Imprime barcode 128
189     * @package     FPDF
190     * @name        Code128
191     * @version     1.0
192     * @author      Roland Gautier
193     */
194    public function Code128($x,$y,$code,$w,$h) {
195       $Aguid=""; 
196       $Bguid="";
197       $Cguid="";
198       for ($i=0; $i < strlen($code); $i++) {
199            $needle=substr($code,$i,1);
200            $Aguid .= ((strpos($this->Aset,$needle)===FALSE) ? "N" : "O"); 
201            $Bguid .= ((strpos($this->Bset,$needle)===FALSE) ? "N" : "O"); 
202              $Cguid .= ((strpos($this->Cset,$needle)===FALSE) ? "N" : "O");
203       }
204       $SminiC = "OOOO";
205       $IminiC = 4;
206       $crypt = "";
207       while ($code > "") {
208              $i = strpos($Cguid,$SminiC);
209              if ($i!==FALSE) {
210                     $Aguid [$i] = "N";
211                     $Bguid [$i] = "N";
212              }
213              if (substr($Cguid,0,$IminiC) == $SminiC) { 
214                     $crypt .= chr(($crypt > "") ? $this->JSwap["C"] : $this->JStart["C"]);
215                     $made = strpos($Cguid,"N");
216                     if ($made === FALSE) $made = strlen($Cguid);
217                     if (fmod($made,2)==1) $made--;
218                     for ($i=0; $i < $made; $i += 2) $crypt .= chr(strval(substr($code,$i,2)));
219                     $jeu = "C";
220              } else {
221                     $madeA = strpos($Aguid,"N");
222                     if ($madeA === FALSE) $madeA = strlen($Aguid);
223                     $madeB = strpos($Bguid,"N");
224                     if ($madeB === FALSE) $madeB = strlen($Bguid);
225                     $made = (($madeA < $madeB) ? $madeB : $madeA );
226                     $jeu = (($madeA < $madeB) ? "B" : "A" );
227                     $jeuguid = $jeu . "guid";
228                     $crypt .= chr(($crypt > "") ? $this->JSwap["$jeu"] : $this->JStart["$jeu"]);
229                     $crypt .= strtr(substr($code, 0,$made), $this->SetFrom[$jeu], $this->SetTo[$jeu]);
230              }
231              $code = substr($code,$made);
232              $Aguid = substr($Aguid,$made);
233              $Bguid = substr($Bguid,$made);
234              $Cguid = substr($Cguid,$made);
235       }
236       $check=ord($crypt[0]);
237       for ($i=0; $i<strlen($crypt); $i++) {
238              $check += (ord($crypt[$i]) * $i);
239       }
240       $check %= 103;
241       $crypt .= chr($check) . chr(106) . chr(107);
242       $i = (strlen($crypt) * 11) - 8;
243       $modul = $w/$i;
244       for ($i=0; $i<strlen($crypt); $i++) {
245              $c = $this->T128[ord($crypt[$i])];
246              for ($j=0; $j<count($c); $j++) {
247                     $this->Rect($x,$y,$c[$j]*$modul,$h,"F");
248                     $x += ($c[$j++]+$c[$j])*$modul;
249              }
250       }
251    } //fim Code128
252
253    /** 
254     * Rotate
255     * Rotaciona para impressão paisagem (landscape)
256     * @package     FPDF
257     * @name        Rotate
258     * @version     1.0
259     * @author      Oliver
260     * @param number $angle 
261     * @param number $x
262     * @param number $y
263     */
264    public function Rotate($angle,$x=-1,$y=-1) {
265        if($x==-1){
266            $x=$this->x;
267        }
268        if($y==-1){
269            $y=$this->y;
270       }
271       if( isset( $this->angle ) && $this->angle != 0){
272            $this->_out('Q');
273       }
274        $this->angle=$angle;
275        if($angle!=0){
276            $angle*=M_PI/180;
277            $c=cos($angle);
278            $s=sin($angle);
279            $cx=$x*$this->k;
280            $cy=($this->h-$y)*$this->k;
281            $this->_out(sprintf('q %.5F %.5F %.5F %.5F %.2F %.2F cm 1 0 0 1 %.2F %.2F cm',$c,$s,-$s,$c,$cx,$cy,-$cx,-$cy));
282        }
283    } //fim função rotate
284
285    /**
286     * RoundedRect
287     * Desenha um retangulo com cantos arredondados
288     * @package     FPDF
289     * @name        RoundedRect
290     * @version     1.0
291     * @author      Maxime Delorme & Christophe Prugnaud
292     * @param number $x
293     * @param number $y
294     * @param number $w
295     * @param number $h
296     * @param number $r
297     * @param string $corners
298     * @param string $style 
299     */
300    public function RoundedRect($x, $y, $w, $h, $r, $corners = '1234', $style = '') {
301        $k = $this->k;
302        $hp = $this->h;
303        if($style=='F'){
304            $op='f';
305        } elseif($style=='FD' || $style=='DF') {
306            $op='B';
307        } else {
308            $op='S';
309        }    
310        $MyArc = 4/3 * (sqrt(2) - 1);
311        $this->_out(sprintf('%.2F %.2F m',($x+$r)*$k,($hp-$y)*$k ));
312        $xc = $x+$w-$r;
313        $yc = $y+$r;
314        $this->_out(sprintf('%.2F %.2F l', $xc*$k,($hp-$y)*$k ));
315        if (strpos($corners, '2')===false){
316            $this->_out(sprintf('%.2F %.2F l', ($x+$w)*$k,($hp-$y)*$k ));
317        } else {
318            $this->_arc($xc + $r*$MyArc, $yc - $r, $xc + $r, $yc - $r*$MyArc, $xc + $r, $yc);
319        }    
320        $xc = $x+$w-$r;
321        $yc = $y+$h-$r;
322        $this->_out(sprintf('%.2F %.2F l',($x+$w)*$k,($hp-$yc)*$k));
323        if (strpos($corners, '3')===false){
324            $this->_out(sprintf('%.2F %.2F l',($x+$w)*$k,($hp-($y+$h))*$k));
325        } else {
326            $this->_arc($xc + $r, $yc + $r*$MyArc, $xc + $r*$MyArc, $yc + $r, $xc, $yc + $r);
327        }    
328        $xc = $x+$r;
329        $yc = $y+$h-$r;
330        $this->_out(sprintf('%.2F %.2F l',$xc*$k,($hp-($y+$h))*$k));
331        if (strpos($corners, '4')===false){
332            $this->_out(sprintf('%.2F %.2F l',($x)*$k,($hp-($y+$h))*$k));
333        } else {
334            $this->_arc($xc - $r*$MyArc, $yc + $r, $xc - $r, $yc + $r*$MyArc, $xc - $r, $yc);
335        }    
336        $xc = $x+$r ;
337        $yc = $y+$r;
338        $this->_out(sprintf('%.2F %.2F l',($x)*$k,($hp-$yc)*$k ));
339        if (strpos($corners, '1')===false){
340            $this->_out(sprintf('%.2F %.2F l',($x)*$k,($hp-$y)*$k ));
341            $this->_out(sprintf('%.2F %.2F l',($x+$r)*$k,($hp-$y)*$k ));
342        }else{
343            $this->_arc($xc - $r, $yc - $r*$MyArc, $xc - $r*$MyArc, $yc - $r, $xc, $yc - $r);
344        }    
345        $this->_out($op);
346    }//fim RoundedRect
347    
348    /**
349     * _arc
350     * Desenha o arco para arredondar o canto do retangulo
351     * @package     FPDF
352     * @name        _arc
353     * @version     1.0
354     * @author      Maxime Delorme & Christophe Prugnaud
355     * @param number $x1
356     * @param number $y1
357     * @param number $x2
358     * @param number $y2
359     * @param number $x3
360     * @param number $y3 
361     */
362    private function _arc($x1, $y1, $x2, $y2, $x3, $y3){
363        $h = $this->h;
364        $this->_out(sprintf('%.2F %.2F %.2F %.2F %.2F %.2F c ', $x1*$this->k, ($h-$y1)*$this->k,$x2*$this->k, ($h-$y2)*$this->k, $x3*$this->k, ($h-$y3)*$this->k));
365    } // fim _Arc
366    
367    /**
368     * DashedRect
369     * Desenha um retangulo com linhas tracejadas
370     * @package     FPDF
371     * @name        DashedRect
372     * @version     1.0
373     * @author      Antoine Michéa
374     * @param number $x1
375     * @param number $y1
376     * @param number $x2
377     * @param number $y2
378     * @param number $width
379     * @param number $nb 
380     */
381    public function DashedRect($x1, $y1, $x2, $y2, $width=1, $nb=15) {
382        $this->SetLineWidth($width);
383        $longueur=abs($x1-$x2);
384        $hauteur=abs($y1-$y2);
385        if($longueur>$hauteur) {
386            $Pointilles=($longueur/$nb)/2;
387        }
388        else {
389            $Pointilles=($hauteur/$nb)/2;
390        }
391        for($i=$x1;$i<=$x2;$i+=$Pointilles+$Pointilles) {
392            for($j=$i;$j<=($i+$Pointilles);$j++) {
393                if($j<=($x2-1)) {
394                    $this->Line($j,$y1,$j+1,$y1);
395                    $this->Line($j,$y2,$j+1,$y2);
396                }
397            }
398        }
399        for($i=$y1;$i<=$y2;$i+=$Pointilles+$Pointilles) {
400            for($j=$i;$j<=($i+$Pointilles);$j++) {
401                if($j<=($y2-1)) {
402                    $this->Line($x1,$j,$x1,$j+1);
403                    $this->Line($x2,$j,$x2,$j+1);
404                }
405            }
406        }
407    }//fim DashedRect
408
409    /**
410     * drawTextBox
411     * Monta uma caixa de texto
412     * @package     FPDF
413     * @name        drawTextBox
414     * @version     1.0
415     * @author      Darren Gates & Adrian Tufa
416     * @param string $strText
417     * @param number $w
418     * @param number $h
419     * @param string $align
420     * @param string $valign
421     * @param boolean $border 
422     */
423    public function drawTextBox($strText, $w, $h, $align='L', $valign='T', $border=true) {
424        $xi=$this->GetX();
425        $yi=$this->GetY();
426        $hrow=$this->FontSize;
427        $textrows=$this->_drawRows($w,$hrow,$strText,0,$align,0,0,0);
428        $maxrows=floor($h/$this->FontSize);
429        $rows=min($textrows,$maxrows);
430        $dy=0;
431        if (strtoupper($valign)=='M'){
432            $dy=($h-$rows*$this->FontSize)/2;
433        }    
434        if (strtoupper($valign)=='B'){
435            $dy=$h-$rows*$this->FontSize;
436        }    
437        $this->SetY($yi+$dy);
438        $this->SetX($xi);
439        $this->_drawRows($w,$hrow,$strText,0,$align,false,$rows,1);
440        if ($border){
441            $this->Rect($xi,$yi,$w,$h);
442        }    
443    }// fim drawTextBox
444    
445    /**
446     * _drawRows
447     * Insere linhas de texto na caixa
448     * @package     FPDF
449     * @name        _drawRows
450     * @version     1.0
451     * @author      Darren Gates & Adrian Tufa
452     * @param number $w
453     * @param number $h
454     * @param string $txt
455     * @param string $border
456     * @param string $align
457     * @param boolean $fill
458     * @param number $maxline
459     * @param number $prn
460     * @return int 
461     */
462    private function _drawRows($w, $h, $txt, $border=0, $align='J', $fill=false, $maxline=0, $prn=0){
463        $cw=&$this->CurrentFont['cw'];
464        if($w==0){
465            $w=$this->w-$this->rMargin-$this->x;
466        }    
467        $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
468        $s=str_replace("\r",'',$txt);
469        $nb=strlen($s);
470        if($nb>0 && $s[$nb-1]=="\n"){
471            $nb--;
472        }    
473        $b=0;
474        if($border){
475            if($border==1){
476                $border='LTRB';
477                $b='LRT';
478                $b2='LR';
479            } else{
480                $b2='';
481                if(is_int(strpos($border,'L'))){
482                    $b2.='L';
483                }    
484                if(is_int(strpos($border,'R'))){
485                    $b2.='R';
486                }    
487                $b=is_int(strpos($border,'T')) ? $b2.'T' : $b2;
488            }
489        }
490        $sep=-1;
491        $i=0;
492        $j=0;
493        $l=0;
494        $ns=0;
495        $nl=1;
496        while($i<$nb){
497            $c=$s[$i];
498            if($c=="\n"){
499                if($this->ws>0){
500                    $this->ws=0;
501                    if ($prn==1){
502                        $this->_out('0 Tw');
503                    }
504                }
505                if ($prn==1) {
506                    $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
507                }
508                $i++;
509                $sep=-1;
510                $j=$i;
511                $l=0;
512                $ns=0;
513                $nl++;
514                if($border && $nl==2){
515                    $b=$b2;
516                }    
517                if ( $maxline && $nl > $maxline ){
518                    return substr($s,$i);
519                }    
520                continue;
521            }
522            if($c==' '){
523                $sep=$i;
524                $ls=$l;
525                $ns++;
526            }
527            $l+=$cw[$c];
528            if($l>$wmax){
529                if($sep==-1){
530                    if($i==$j){
531                        $i++;
532                    }    
533                    if($this->ws>0){
534                        $this->ws=0;
535                        if ($prn==1){
536                            $this->_out('0 Tw');
537                        }
538                    }
539                    if ($prn==1) {
540                        $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
541                    }
542                } else {
543                    if($align=='J') {
544                        $this->ws=($ns>1) ? ($wmax-$ls)/1000*$this->FontSize/($ns-1) : 0;
545                        if ($prn==1){
546                            $this->_out(sprintf('%.3F Tw',$this->ws*$this->k));
547                        }    
548                    }
549                    if ($prn==1){
550                        $this->Cell($w,$h,substr($s,$j,$sep-$j),$b,2,$align,$fill);
551                    }
552                    $i=$sep+1;
553                }
554                $sep=-1;
555                $j=$i;
556                $l=0;
557                $ns=0;
558                $nl++;
559                if($border && $nl==2){
560                    $b=$b2;
561                }    
562                if ( $maxline && $nl > $maxline ){
563                    return substr($s,$i);
564                }    
565            } else {
566                $i++;
567            }    
568        }
569        if($this->ws>0) {
570            $this->ws=0;
571            if ($prn==1){
572                $this->_out('0 Tw');
573            }
574        }
575        if($border && is_int(strpos($border,'B'))){
576            $b.='B';
577        }    
578        if ($prn==1) {
579            $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
580        }
581        $this->x=$this->lMargin;
582        return $nl;
583    }//fim _drawRows
584    
585    /**
586     * WordWrap
587     * Quebra o texto para caber na caixa
588     * @package     FPDF
589     * @name        WordWrap
590     * @version     1.0
591     * @author      Ron Korving
592     * @param type $text
593     * @param type $maxwidth
594     * @return int 
595     */
596    public function WordWrap(&$text, $maxwidth){
597        $text = trim($text);
598        if ($text===''){
599            return 0;
600        }    
601        $space = $this->GetStringWidth(' ');
602        $lines = explode("\n", $text);
603        $text = '';
604        $count = 0;
605        foreach ($lines as $line) {
606            $words = preg_split('/ +/', $line);
607            $width = 0;
608            foreach ($words as $word) {
609                $wordwidth = $this->GetStringWidth($word);
610                if ($wordwidth > $maxwidth){
611                    // Word is too long, we cut it
612                    for($i=0; $i<strlen($word); $i++){
613                        $wordwidth = $this->GetStringWidth(substr($word, $i, 1));
614                        if($width + $wordwidth <= $maxwidth){
615                            $width += $wordwidth;
616                            $text .= substr($word, $i, 1);
617                        } else {
618                            $width = $wordwidth;
619                            $text = rtrim($text)."\n".substr($word, $i, 1);
620                            $count++;
621                        }
622                    }
623                } elseif($width + $wordwidth <= $maxwidth) {
624                    $width += $wordwidth + $space;
625                    $text .= $word.' ';
626                } else {
627                    $width = $wordwidth + $space;
628                    $text = rtrim($text)."\n".$word.' ';
629                    $count++;
630                }
631            }
632            $text = rtrim($text)."\n";
633            $count++;
634        }
635        $text = rtrim($text);
636        return $count;
637    } //fim WordWrap
638    
639    /**
640     * CellFit
641     * Celula com escala horizontal caso o texto seja muito largo
642     * @package     FPDF
643     * @name        CellFit
644     * @version     1.0
645     * @author      Patrick Benny
646     * @param number $w
647     * @param number $h
648     * @param string $txt
649     * @param number $border
650     * @param number $ln
651     * @param string $align
652     * @param boolean $fill
653     * @param string $link
654     * @param boolean $scale
655     * @param boolean $force 
656     */
657    public function CellFit($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='', $scale=false, $force=true){
658        $str_width=$this->GetStringWidth($txt);
659        if($w==0){
660            $w = $this->w-$this->rMargin-$this->x;
661        }    
662        $ratio = ($w-$this->cMargin*2)/$str_width;
663        $fit = ($ratio < 1 || ($ratio > 1 && $force));
664        if ($fit){
665            if ($scale){
666                //Calcula a escala horizontal
667                $horiz_scale=$ratio*100.0;
668                //Ajusta a escala horizontal
669                $this->_out(sprintf('BT %.2F Tz ET',$horiz_scale));
670            } else {
671                //Calcula o espaçamento de caracteres em pontos
672                $char_space=($w-$this->cMargin*2-$str_width)/max($this->_MBGetStringLength($txt)-1,1)*$this->k;
673                //Ajusta o espaçamento de caracteres
674                $this->_out(sprintf('BT %.2F Tc ET',$char_space));
675            }
676            //Sobrescreve o alinhamento informado (desde que o texto caiba na celula)
677            $align='';
678        }
679        //Passa para o método cell
680        $this->Cell($w,$h,$txt,$border,$ln,$align,$fill,$link);
681        //Reseta o espaçamento de caracteres e a escala horizontal
682        if ($fit){
683            $this->_out('BT '.($scale ? '100 Tz' : '0 Tc').' ET');
684        }    
685    }//fim CellFit
686
687    /**
688     * CellFitScale
689     * Celula com escalamento horizontal somente se necessário
690     * @package     FPDF
691     * @name        CellFitScale
692     * @version     1.0
693     * @author      Patrick Benny
694     * @param number $w
695     * @param number $h
696     * @param string $txt
697     * @param number $border
698     * @param number $ln
699     * @param string $align
700     * @param boolean $fill
701     * @param string $link 
702     */
703    public function CellFitScale($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link=''){
704        $this->CellFit($w,$h,$txt,$border,$ln,$align,$fill,$link,true,false);
705    }
706
707    /**
708     * CellFitScaleForce
709     * Celula com escalamento forçado
710     * @package     FPDF
711     * @name        CellFitScaleForce
712     * @version     1.0
713     * @author      Patrick Benny
714     * @param number $w
715     * @param number $h
716     * @param string $txt
717     * @param number $border
718     * @param number $ln
719     * @param string $align
720     * @param boolean $fill
721     * @param string $link 
722     */
723    public function CellFitScaleForce($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link=''){
724        $this->CellFit($w,$h,$txt,$border,$ln,$align,$fill,$link,true,true);
725    }
726
727    /**
728     * CellFitSpace
729     * Celula com espaçamento de caracteres somente se necessário
730     * @package     FPDF
731     * @name        CellFitSpace
732     * @version     1.0
733     * @author      Patrick Benny
734     * @param number $w
735     * @param number $h
736     * @param string $txt
737     * @param number $border
738     * @param number $ln
739     * @param string $align
740     * @param boolean $fill
741     * @param string $link 
742     */
743    public function CellFitSpace($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link=''){
744        $this->CellFit($w,$h,$txt,$border,$ln,$align,$fill,$link,false,false);
745    }
746    
747    /**
748     * CellFitSpaceForce
749     * Celula com espaçamento de caracteres forçado
750     * @package     FPDF
751     * @name        CellFitSpaceForce
752     * @version     1.0
753     * @author      Patrick Benny
754     * @param number $w
755     * @param number $h
756     * @param string $txt
757     * @param number $border
758     * @param number $ln
759     * @param string $align
760     * @param boolean $fill
761     * @param string $link 
762     */
763    public function CellFitSpaceForce($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link=''){
764        $this->CellFit($w,$h,$txt,$border,$ln,$align,$fill,$link,false,true);
765    }
766    
767    /**
768     * _MBGetStringLength
769     * Patch para trabalhar com textos de duplo byte CJK
770     * @package     FPDF
771     * @name        _MBGetStringLength
772     * @version     1.0
773     * @author      Patrick Benny
774     * @param string $s
775     * @return int 
776     */
777    private function _MBGetStringLength($s){
778        if($this->CurrentFont['type']=='Type0'){
779            $len = 0;
780            $nbbytes = strlen($s);
781            for ($i = 0; $i < $nbbytes; $i++){
782                if (ord($s[$i])<128){
783                    $len++;
784                } else {
785                    $len++;
786                    $i++;
787                }
788            }
789            return $len;
790        } else {
791            return strlen($s);
792        }    
793    }
794
795
796    /**
797     * DashedLine
798     * Desenha uma linha horizontal tracejada com o FPDF
799     * @package NFePHP
800     * @name DashedHLine
801     * @version 1.0.1
802     * @author Roberto L. Machado <linux.rlm at gmail dot com>
803     * @param number $x Posição horizontal inicial, em mm
804     * @param number $y Posição vertical inicial, em mm
805     * @param number $w Comprimento da linha, em mm
806     * @param number $h Espessura da linha, em mm
807     * @param number $n Numero de traços na seção da linha com o comprimento $w
808     * @return none
809     */
810    public function DashedHLine($x,$y,$w,$h,$n) {
811        $this->SetDrawColor(110);
812        $this->SetLineWidth($h);
813        $wDash=($w/$n)/2; // comprimento dos traços
814        for( $i=$x; $i<=$x+$w; $i += $wDash+$wDash ) {
815            for( $j=$i; $j<= ($i+$wDash); $j++ ) {
816                if( $j <= ($x+$w-1) ) {
817                    $this->Line($j,$y,$j+1,$y);
818                }
819            }
820        }
821        $this->SetDrawColor(0);
822    } //fim função DashedHLine
823
824   /**
825    * DashedVLine
826    * Desenha uma linha vertical tracejada com o FPDF
827    * @package NFePHP
828    * @name DashedVLine
829    * @version 1.0
830    * @author Roberto L. Machado <linux.rlm at gmail dot com>
831    * @author Guilherme Calabria Filho <guiga86 at gmail dot com>
832    * @param number $x Posição horizontal inicial, em mm
833    * @param number $y Posição vertical inicial, em mm
834    * @param number $w Comprimento da linha, em mm
835    * @param number $yfinal Espessura da linha, em mm
836    * @param number $n Numero de traços na seção da linha com o comprimento $w
837    * @return none
838    */
839    public function DashedVLine($x,$y,$w,$yfinal,$n) {
840        $this->SetLineWidth($w);
841        //Organizando valores
842        if($y>$yfinal) {
843            $aux = $yfinal;
844            $yfinal = $y;
845            $y = $aux;
846        }
847        while($y<$yfinal&&$n>0){
848            $this->Line($x,$y,$x,$y+1);
849            $y += 3;
850            $n--;
851        }
852    } //fim função DashedVLine
853    
854} //fim da classe PdfNFe
855?>