Project

General

Profile

Defect #686 » pdf.class.php

Joe Privett, 09/01/2014 12:32 AM

 
1
<?php
2
require_once($UTILS['SERVER_ROOT'].$UTILS['WEB_ROOT']."library/tfpdf/tfpdf.php");
3
require_once($UTILS['SERVER_ROOT'].$UTILS['WEB_ROOT']."library/tfpdf_table/mypdf-table.php");
4
require_once($UTILS['SERVER_ROOT'].$UTILS['WEB_ROOT']."library/tfpdf/class.tfpdftable.php");
5
require_once($UTILS['SERVER_ROOT'].$UTILS['WEB_ROOT']."library/classes/pdf/fpdi/tfpdi.php");
6
require_once($UTILS['SERVER_ROOT'].$UTILS['WEB_ROOT']."library/classes/dom/dom_element_extend.class.php");
7

    
8
//class pdf extends tFPDI {
9
	
10
class pdf extends mypdf {
11
	
12
	var $font_name = 'Arial';
13
	var $font_style = '';
14
	var $font_size = 10;
15
	var $font_color = array(0,0,0);
16
	
17
	var $tag_style = array();
18
	var $logo = "";
19
	var $include_watermark = false;
20
	var $include_header = false;
21
	var $header_template = '';
22
	var $watermark_text = '';
23
	var $watermark_color = array(0,0,0);
24
	var $watermark_angle = 0;
25
	var $watermark_x = 0;
26
	var $watermark_y = 0;
27
	var $watermark_size = 120;
28
	var $watermark_family = 'Arial';
29
	var $watermark_style = 'B';
30
	var $auto_page_break = true;
31
	var $page_numbers = false;
32
	var $page_numbers_excl_first = false;
33
	var $header_email = '';
34
	var $header_title = '';
35
	var $line_height = 5;
36
	
37
	var $fr_data = array();
38
	var $fr_border = array();
39
	var $fr_align = array();
40
	var $fr_style = array();
41
	var $fr_maxline = array();
42
	var $fr_padding_size = array();
43
	var $fr_padding = array();
44
	var $fr_fill = array();
45
	var $fr_fill_color = array();
46
	var $fr_font_color = array();
47
	var $fr_line_height = '';
48
	
49
	
50
	function pdf(){
51
		
52
		global $UTILS;
53
		
54
		define("FPDF_FONTPATH", $UTILS['SERVER_ROOT'].$UTILS['WEB_ROOT'].'library/tfpdf/font');
55
		
56
		$this->tFPDF();
57
		
58
		$this->AddFont('Arial','','Arial.ttf',true);
59
		$this->AddFont('Arial','B','Arial-Bold.ttf',true);
60
		$this->AddFont('Arial','I','Arial-Italic.ttf',true);
61
		$this->AddFont('Arial','N','Arial-Narrow.ttf',true);
62
		$this->AddFont('Arial','BI','Arial-BoldItalic.ttf',true);
63
		$this->AddFont('Arial','NBI','Arial-NarrowBoldItalic.ttf',true);
64
		$this->AddFont('Arial','NB','Arial-NarrowBold.ttf',true);
65
		$this->AddFont('Arial','NI','Arial-NarrowItalic.ttf',true);
66
		$this->AddFont('Arial','BL','Arial-Black.ttf',true);
67
	}
68
	
69
	
70
	function reset_page_style(){
71
		
72
		$this->SetFont($this->font_name,$this->font_style,$this->font_size);
73
		$this->SetTextColor(implode(",",$this->font_color));
74
		$this->SetTopMargin($this->tMargin);
75
		$this->SetLeftMargin($this->lMargin);
76
		$this->SetRightMargin($this->rMargin);
77
		$this->SetAutoPageBreak($this->auto_page_break, $this->bMargin);
78
	}
79
	
80
	
81
	function Header(){
82
		
83
		if($this->include_header == true){
84
			$this->reset_page_style();
85
			switch ($this->header_template){
86
				case "standard_1":
87
					$caption = array($this->header_title);
88
					$aRow = Array();
89
					$aRow['line_height'] = 3.5;
90
					$this->add_row($caption, $aRow);
91
					$this->Ln(10);
92
					break;
93
				case "headed_paper":
94
					$this->headed_paper();
95
					break;
96
			}
97
		    
98
		}
99
		if($this->include_watermark == true){
100
			$this->SetFont($this->watermark_family,$this->watermark_style,$this->watermark_size);
101
			$this->SetTextColor($this->watermark_color[0], $this->watermark_color[1], $this->watermark_color[2]);
102
			$this->RotatedText($this->watermark_x, $this->watermark_y, $this->watermark_text, $this->watermark_angle);
103
			$this->SetFont($this->font_name,'',$this->font_size);
104
			$this->SetTextColor($this->font_color[0], $this->font_color[1], $this->font_color[2]);
105
		}
106
		$this->reset_page_style();
107
	}
108
	
109
	function Footer(){
110
		
111
		// For some reason, of setting bMargin, the auto page breaking for tables is no longe effective!
112
    	//if( $this->bMargin != 0 ){
113
		//	$this->SetY($this->bMargin);
114
    	//}
115
		
116
		// Page numbering
117
		if( $this->page_numbers == true ){
118
				
119
			if( $this->page_numbers_excl_first != true || ($this->page_numbers_excl_first == true && $this->PageNo() > 1) ){
120
				
121
				$this->AliasNbPages();
122
				$this->SetY(-20);
123
				$this->SetFont($this->font_name,$this->font_style,9);
124
				$this->Cell(0,9,'Page '.$this->PageNo().' of {nb}',0,0,'C');
125
			}
126
		}
127
	}
128
	
129
	
130
	
131
	function headed_paper(){
132
		
133
		Global $UTILS;
134
		// Logo
135
		$this->Image($UTILS['SERVER_ROOT'].$UTILS['WEB_ROOT'].$this->logo,140,10,55);
136
		
137
		$this->SetFont($this->font_name,'B',12);
138
		
139
		$this->MultiCell(0,7,'',0,1);
140
		$this->MultiCell(0,12,$this->header_title,0,1);
141
		$old_widths = $this->GetWidths();
142
		$widths = array(12,80);$this->SetWidths($widths);
143
		$this->SetFont($this->font_name,'',8);
144
		$aRow = Array();
145
		$aRow['style'] = array('B', '');
146
		$aRow['line_height'] = 3.5;
147
		$caption = array('Tel:
148
Fax:
149
Add:
150
Email:
151
','0845 002 4229
152
0845 002 4455
153
RMG House, Essex Road, Hoddesdon, EN11 0DR
154
'.$this->header_email.'
155
');
156
		$this->add_row($caption, $aRow);
157
		
158
		$this->MultiCell(0,9,'',0,1);
159
		$this->line(10,37,200,37);
160
		$this->SetWidths($old_widths);	
161
	}
162

    
163
	
164
	// Allow dashed borders/lines. e.g. $pdf_report->SetDash(0.2, 0.2). Call after with no parameters to reset line styles.
165
	function SetDash($black=false, $white=false){
166
		
167
        if($black and $white)
168
            $s=sprintf('[%.3f %.3f] 0 d', $black*$this->k, $white*$this->k);
169
        else
170
            $s='[] 0 d';
171
        $this->_out($s);
172
    }
173
	
174
	function add_page($orientation='', $size=''){
175
		
176
		$this->reset_page_style();
177
		$this->AddPage($orientation, $size);
178
	}
179
	
180
	
181
	
182
	/**
183
	 * Sets current tag to specified style
184
	 *
185
	 * @accesspublic
186
	 * @param   string $tag - tag name
187
	 * @param   string $name - text font family name
188
	 * @param   string $style - text font style
189
	 * @param   numeric $size - text font size
190
	 * @param   array $color - text color
191
	 * @return  void
192
	 */
193
	public function SetStyle($tag, $name="", $style, $size="", $color=""){
194
		
195
		if($name == ""){
196
			$name = $this->font_name;
197
		}
198
		
199
		if($size == ""){
200
			$size = $this->font_size;
201
		}
202
		
203
		if($color == ""){
204
			$color = $this->font_color;
205
		}
206
		
207
	    if ($tag != "") {
208
		    //use case insensitive tags
209
		    $tag=trim(strtoupper($tag));
210
		    
211
		    if (!isset($this->tag_style[$tag])){
212
			    $this->tag_style[$tag]['name']=trim($name);
213
			    $this->tag_style[$tag]['style']=trim($style);
214
			    $this->tag_style[$tag]['size']=trim($size);
215
			    $this->tag_style[$tag]['color']=trim($color);
216
		    }
217
	    }
218
	}
219
	
220
	
221
	function RotatedText($x, $y, $txt, $angle){
222
    
223
		//Text rotated around its origin
224
    	$this->Rotate($angle, $x, $y);
225
   		$this->Text($x, $y, $txt);
226
    	$this->Rotate(0);
227
	}
228
	
229
	
230
	function Rotate($watermarkAngle, $x=-1, $y=-1){
231
			
232
		if($x==-1){
233
			$x=$this->x;
234
		}
235
		if($y==-1){
236
			$y=$this->y;
237
		}
238
		if($this->angle!=0){
239
			$this->_out('Q');
240
		}
241
		$this->angle=$watermarkAngle;
242
		if($watermarkAngle != 0){
243
			
244
			$watermarkAngle*=M_PI/180;
245
			$c=cos($watermarkAngle);
246
			$s=sin($watermarkAngle);
247
			$cx=$x*$this->k;
248
			$cy=($this->h-$y)*$this->k;
249
			$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));
250
		}
251
	}
252
	
253
	function heading($title, $size=20, $a='L', $extra_line = true){
254
		$this->SetFont($this->font_name,'',$size);
255
		$this->MultiCell(0, $this->line_height, $title, 0, $a, 0);
256
		$this->Ln();
257
		if($extra_line == true){
258
			$this->Ln();
259
		}
260
		$this->SetFont($this->font_name,'',$this->font_size);
261
	}
262
	
263
	function subheading($title, $size=16, $a='L', $extra_line = true){
264
		$this->SetFont('','I', $size);
265
		$this->MultiCell(0, $this->line_height, $title, 0, $a, 0);
266
		$this->Ln();
267
		if($extra_line == true){
268
			$this->Ln();
269
		}
270
		$this->SetFont('','',$this->font_size);
271
	}
272
	
273
	function MultiCell($w, $h, $txt, $border=0, $align='J', $fill=false){
274
		
275
		$txt_array = $this->split_by_tags($txt);
276
		// Output text with automatic or explicit line breaks
277
		if($w==0)
278
			$w = $this->w-$this->rMargin-$this->x;
279
		$wmax = ($w-2*$this->cMargin);	    
280
		
281
		$current_font['name'] = $this->FontFamily;
282
		$current_font['size'] = $this->FontSizePt;
283
		$current_font['style'] = $this->FontStyle.($this->underline ? 'U' : '');
284
		$current_font['color'] = $this->TextColor;
285
		
286
		$_x = $this->x;
287
		
288
		$previous_w = 0;
289
		$_w = 0;
290
		
291
		for($t_no=0;$t_no<count($txt_array);$t_no++){
292
			if($txt_array[$t_no][1] == ''){
293
				$this->SetFont($current_font['name'], $current_font['style'], $current_font['size']);	
294
			}else{
295
				$found = true;
296
				$thetag = strtoupper($txt_array[$t_no][1]);
297
				$this->SetFont($this->tag_style[$thetag]['name'], $this->tag_style[$thetag]['style'], $this->tag_style[$thetag]['size']);
298
			}
299
			
300
			$cw = &$this->CurrentFont['cw'];
301
			
302
			$s = str_replace("\r",'',$txt_array[$t_no][0]);
303
			
304
			if ($this->unifontSubset) {
305
				$nb=mb_strlen($s, 'utf-8');
306
				while($nb>0 && mb_substr($s,$nb-1,1,'utf-8')=="\n")	$nb--;
307
			}else {
308
				$nb = strlen($s);
309
				if($nb>0 && $s[$nb-1]=="\n")
310
					$nb--;
311
			}
312
			$b = 0;
313
			if($border){
314
				if($border==1){
315
					$border = 'LTRB';
316
					$b = 'LRT';
317
					$b2 = 'LR';
318
				}else{
319
					$b2 = '';
320
					if(strpos($border,'L')!==false)
321
						$b2 .= 'L';
322
					if(strpos($border,'R')!==false)
323
						$b2 .= 'R';
324
					$b = (strpos($border,'T')!==false) ? $b2.'T' : $b2;
325
				}
326
			}
327
			$sep = -1;
328
			$i = 0;
329
			$j = 0;
330
			$l = $_w;
331
			$ns = 0;
332
			$nl = 1;
333
			if($t_no > 0){
334
				$new_x = ($_w + $_x)-1;
335
				$_h = $h;
336
				if($new_x > $wmax){
337
					$new_x = $this->lMargin;
338
					$_h = 0;
339
					$l = 0;	
340
				}else{
341
					if ($this->unifontSubset) { $new_x += $this->GetStringWidth(' '); }
342
					else { $new_x += ($cw[' '])*$this->FontSize/1000; }
343
				}
344
				
345
				//print($_w . ' - ' . $new_x . ' - ' . $txt_array[$t_no][0] . '<br />');
346
				$this->SetXY($new_x, ($this->y - $_h));
347
			}
348
			
349
			$_w = 0;
350
			while($i<$nb){
351
				// Get next character
352
				if ($this->unifontSubset) {
353
					$c = mb_substr($s,$i,1,'UTF-8');
354
				}else {
355
					$c=$s[$i];
356
				}
357
				if($c=="\n"){
358
					// Explicit line break
359
					if($this->ws>0)
360
					{
361
						$this->ws = 0;
362
						$this->_out('0 Tw');
363
					}
364
					if ($this->unifontSubset) {
365
						$this->Cell($w,$h,mb_substr($s,$j,$i-$j,'UTF-8'),$b,2,$align,$fill);
366
					}
367
					else {
368
						$this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
369
					}
370
					$i++;
371
					$sep = -1;
372
					$j = $i;
373
					$l = 0;
374
					$ns = 0;
375
					$nl++;
376
					$_w = 0;
377
					if($border && $nl==2)
378
						$b = $b2;
379
					continue;
380
				}
381
				if($c==' '){
382
					$sep = $i;
383
					$ls = $l;
384
					$ns++;
385
				}
386
		
387
				if ($this->unifontSubset) { $l += $this->GetStringWidth($c); }
388
				else { $l += $cw[$c]*$this->FontSize/1000; }
389
				
390
				$_w = $l;
391
		
392
				if($l>$wmax){
393
					// Automatic line break
394
					if($sep==-1){
395
						if($i==$j)
396
							$i++;
397
						if($this->ws>0){
398
							$this->ws = 0;
399
							$this->_out('0 Tw');
400
						}
401
						if ($this->unifontSubset) {
402
							$this->Cell($w,$h,mb_substr($s,$j,$i-$j,'UTF-8'),$b,2,$align,$fill);
403
						}else{
404
							$this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
405
						}
406
					}else{
407
						if($align=='J'){
408
							$this->ws = ($ns>1) ? ($wmax-$ls)/($ns-1) : 0;
409
							$this->_out(sprintf('%.3F Tw',$this->ws*$this->k));
410
						}
411
						if ($this->unifontSubset) {
412
							$this->Cell($w,$h,mb_substr($s,$j,$sep-$j,'UTF-8'),$b,2,$align,$fill);
413
						}
414
						else {
415
							$this->Cell($w,$h,substr($s,$j,$sep-$j),$b,2,$align,$fill);
416
						}
417
						$i = $sep+1;
418
					}
419
					$sep = -1;
420
					$j = $i;
421
					$l = 0;
422
					$ns = 0;
423
					$nl++;
424
					$_w = 0;
425
					$this->x = $_x;
426
					if($border && $nl==2)
427
						$b = $b2;
428
				}else{
429
					$i++;
430
				}
431
			}
432
			
433
			// Last chunk
434
			if($this->ws>0){
435
				$this->ws = 0;
436
				$this->_out('0 Tw');
437
			}
438
			if($border && strpos($border,'B')!==false)
439
				$b .= 'B';
440
			if ($this->unifontSubset) {
441
				$this->Cell($w,$h,mb_substr($s,$j,$i-$j,'UTF-8'),$b,2,$align,$fill);
442
			}else{
443
				$this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
444
			}
445
			
446
			$previous_w = $_w;
447
		}
448
		$this->SetFont($current_font['name'], $current_font['style'], $current_font['size']);
449
		$this->x = $this->lMargin;
450
	}
451
	
452
	function MultiCellBlt($w, $h, $blt, $txt, $indent=0, $maxbul="", $border=0, $align='L', $fill=0){
453
		//Get bullet width including margins
454
		$blt_width = $this->GetStringWidth($blt)+$this->cMargin*2;
455
		if($maxbul != ""){
456
			$blt_width = $this->GetStringWidth($maxbul)+$this->cMargin*2;
457
		}
458
		
459
		//Save x
460
		$bak_x = $this->x;
461
		
462
		if($indent > 0){
463
			$this->Cell(($blt_width * $indent), $h, ' ', 0, '', $fill);
464
		}
465

    
466
		//Output bullet
467
		$this->Cell($blt_width, $h, $blt, 0, '', $fill);
468
		//Output text
469
		if($w == 0){
470
			$w = $this->w-$this->rMargin-$this->x;
471
			if($indent > 0){
472
				$w = $w - ($blt_width * $indent);
473
			}
474
		}
475
		$this->MultiCell($w-$blt_width, $h, $txt, $border, $align, $fill);
476

    
477
		//Restore x
478
		$this->x = $bak_x;
479
    }
480
	
481
	function SetWidths($w){
482
	    //Set the array of column widths
483
	    $this->widths=$w;
484
	}
485
	
486
	function GetWidths(){
487
	    //Set the array of column widths
488
	    return $this->widths;
489
	}
490
	
491
	function SetAligns($a){
492
	    //Set the array of column alignments
493
	    $this->aligns=$a;
494
	}
495
	
496
	function CheckPageBreak($h, $do=true){
497
	    //If the height h would cause an overflow, add a new page immediately
498
	    if($this->GetY()+$h>$this->PageBreakTrigger){
499
	    	if($do == true && $h < $this->PageBreakTrigger){
500
	        	$this->AddPage($this->CurOrientation);
501
	    	}
502
	        return true;
503
	    }else{
504
	    	return false;	
505
	    }
506
	}
507
	
508
	function NbLines($w, $txt, $type="text"){
509
	    //Computes the number of lines a MultiCell of width w will take
510
		$cw = &$this->CurrentFont['cw'];
511
	    if($w==0){
512
	        $w=$this->w-$this->rMargin-$this->x;
513
	    }
514

    
515
	   	$wmax = ($w-2*$this->cMargin);
516
	    $s=str_replace("\r", '', $txt);
517
	    
518
		if ($this->unifontSubset) {
519
			$nb=mb_strlen($s, 'utf-8');
520
			while($nb>0 && mb_substr($s,$nb-1,1,'utf-8')=="\n")	$nb--;
521
		}
522
		else {
523
			$nb = strlen($s);
524
			if($nb>0 && $s[$nb-1]=="\n")
525
				$nb--;
526
		}
527
		
528
		$end_tag = false;
529
		$is_tag = false;
530
		$last_tag = '';
531
		
532
		$sep = -1;
533
		$i = 0;
534
		$j = 0;
535
		$l = 0;
536
		$ns = 0;
537
		$nl = 1;
538
		while($i<$nb){
539
			// Get next character
540
			if ($this->unifontSubset) {
541
				$c = mb_substr($s,$i,1,'UTF-8');
542
			}else{
543
				$c=$s[$i];
544
			}
545
			if($c=="\n"){
546
				if($type=="text"){
547
					$i++;
548
					$sep = -1;
549
					$j = $i;
550
					$l = 0;
551
					$ns = 0;
552
					$nl++;
553
					continue;
554
				}
555
			}
556
			if($c==' '){
557
				$sep = $i;
558
				$ls = $l;
559
				$ns++;
560
			}
561
			if($c=='<'){
562
				if ($this->unifontSubset) {
563
					$tempStr = mb_substr($s, $i, $nb,'UTF-8');
564
				}else{
565
					$tempStr = substr($s, $i, $nb);
566
				}
567
				if(strpos($tempStr, '>') < 50){
568
					$is_tag = true;
569
				}
570
			}
571
			
572
			if($is_tag == true){
573
				if($c=="/"){
574
					$end_tag = true;
575
				}elseif($c=='<'){
576
					$last_tag = '';
577
				}elseif($c=='>'){
578
					if($end_tag == true && !isset($this->tag_style[strtoupper($last_tag)])){
579
						$i++;
580
						$sep = -1;
581
						$j = $i;
582
						$l = 0;
583
						$ns = 0;
584
						$nl++;
585
						$end_tag = false;
586
						$is_tag = false;
587
						continue;
588
					}else{
589
						$is_tag = false;
590
					}
591
				}else{
592
					$last_tag .= $c;
593
				}
594
				$i++;
595
			}else{
596
				if ($this->unifontSubset) { $l += $this->GetStringWidth($c); }
597
				else { $l += $cw[$c]*$this->FontSize/1000; }
598
		
599
				if($l>$wmax){
600
					// Automatic line break
601
					if($sep==-1)
602
					{
603
						if($i==$j)
604
							$i++;
605
					}
606
					else
607
					{
608
						$i = $sep+1;
609
					}
610
					$sep = -1;
611
					$j = $i;
612
					$l = 0;
613
					$ns = 0;
614
					$nl++;
615
				}else{
616
					$i++;
617
				}
618
			}
619
		}
620
		
621
		//print($nl . ' - ');
622
		
623
		if($type == 'html' && $nl > 1){
624
			$nl--;
625
		}
626
		
627
		//print($nl . '<br />');
628
	    return $nl;
629
	}
630
	
631
	function cell_contents_split($h, $w, $value, $type, $options){
632
        $darray = array();
633
        
634
		if($type == "text" || $type == "html"){
635
			$darray = $this->split_by_height($h, $w, $value, $options, $type);
636
			$darray[4] = true;
637
        }else{
638
        	$_h = $h;
639
        	//For each list item check whether it will fit on the page
640
        	for($b=0;$b<count($value);$b++){
641
        		$carray = $this->split_by_height($_h, $w, $value[$b], $options, $type);
642
        		//If it does not fit on the page
643
        		if($carray[1] != ''){
644
        			$darray[0] = array();
645
        			$darray[1] = array();
646
        			//Add first half of array to the first item holder
647
        			for($c=0;$c<$b;$c++){
648
        				array_push($darray[0], $value[$c]);
649
        				//Set start variable
650
        				$darray[2] = $c+1;
651
        			}
652
        			//Add first half of last item in first half of array into the first item holder
653
        			array_push($darray[0], $carray[0]);
654

    
655
        			if($carray[0] != ''){
656
        				//If first half is not blank and second half of word to second item holder
657
        				//Set the has split variable to true 
658
        				array_push($darray[1], $carray[1]);
659
        				$darray[4] = true;
660
        				$b ++;
661
        			}else{
662
        				//If first half is blank and set the has split variable to true 
663
        				$darray[4] = false;
664
        			}
665
        			//Add second half of array to the second item holder
666
        			for($c=$b;$c<count($value);$c++){
667
        				array_push($darray[1], $value[$c]);
668
        			}
669
        			//Set end ariable
670
        			$darray[3] = $darray[2] + (count($value) - $darray[2]) - 1;
671
        			break;
672
        		}
673
        		$nb = max($nb, $this->NbLines($w, $value[$b]));
674
            	$height = $nb*$options['line_height'];
675
            	//Make the available height smaller
676
            	$_h -= ($height + $options['line_height']);
677
        	}
678
        }
679
        return $darray;
680
	}
681

    
682
	function split_by_height($h, $w, $txt, $options, $type="text"){
683
		//Splits content into 2, where the first reaches the height supplied and the second is the remainder.
684
	    $cw = &$this->CurrentFont['cw'];
685
	    if($w==0){
686
	        $w=$this->w-$this->rMargin-$this->x;
687
	    }
688
	    
689
	   	$wmax = ($w);
690
	    $s=str_replace("\r", '', $txt);
691
	    
692
	    //Get no characters
693
		if ($this->unifontSubset) {
694
			$nb=mb_strlen($s, 'utf-8');
695
			while($nb>0 && mb_substr($s,$nb-1,1,'utf-8')=="\n")	$nb--;
696
		}
697
		else {
698
			$nb = strlen($s);
699
			if($nb>0 && $s[$nb-1]=="\n")
700
				$nb--;
701
		}
702
		
703
		$end_tag = false;
704
		$is_tag = false;
705
		$tags = array();
706
		$taglist = array();
707
		$last_tag = '';
708
		
709
		$sep = -1;
710
		$i = 0;
711
		$j = 0;
712
		$l = 0;
713
		$ns = 0;
714
		$nl = 1;
715
		$is_tag = false;
716
		while($i<$nb){
717
			// Get next character
718
			if ($this->unifontSubset) {
719
				$c = mb_substr($s,$i,1,'UTF-8');
720
			}else{
721
				$c=$s[$i];
722
			}
723
			//If this is text count new lines
724
			if($c=="\n"){
725
				if($type!="html"){
726
					$i++;
727
					$sep = -1;
728
					$j = $i;
729
					$l = 0;
730
					$ns = 0;
731
					$nl++;
732
					continue;
733
				}
734
			}
735
			if($c==' '){
736
				$sep = $i;
737
				$ls = $l;
738
				$ns++;
739
			}
740
			//Test if there is a tag and set that we are looking for one if there is
741
			if($c=='<'){
742
				if ($this->unifontSubset) {
743
					$tempStr = mb_substr($s, $i, $nb,'UTF-8');
744
				}else{
745
					$tempStr = substr($s, $i, $nb);
746
				}
747
				$thepos = strpos($tempStr, '>');
748
				if($thepos < 50){
749
					$is_tag = true;
750
					$last_tag = '';
751
				}
752
			}
753
			
754
			if($is_tag == true){
755
				//Build tag and add new line if it is an end tag
756
				if($c=="/"){
757
					$end_tag = true;
758
				}elseif($c=='<'){
759
					$last_tag = '';
760
				}elseif($c=='>'){
761
					if(strpos(strtolower($tags[count($tags)-1]), 'ol') !== false || strpos(strtolower($tags[count($tags)-1]), 'ul') !== false){
762
						$wmax = $w - $this->get_list_width($s, $i, $tags[count($tags)-1]);
763
					}
764
					if($end_tag == true){
765
						array_splice($tags,count($tags)-1, 1);
766
					}
767
					if($last_tag != '' && $end_tag == false){
768
						array_push($tags, $last_tag);
769
						if(!isset($this->tag_style[strtoupper($last_tag)])){
770
							array_push($taglist, $last_tag);
771
						}
772
					}
773
					if($end_tag == true && !isset($this->tag_style[strtoupper($last_tag)])){
774
						$i++;
775
						$sep = -1;
776
						$j = $i;
777
						$l = 0;
778
						$ns = 0;
779
						$nl++;		
780
						$end_tag = false;
781
						$is_tag = false;
782
						continue;
783
					}else{
784
						$is_tag = false;
785
					}
786
				}else{
787
					$last_tag .= $c;
788
				}
789
				$i++;
790
			}else{
791
				if(strpos(strtolower($last_tag), 'ol') !== false || strpos(strtolower($last_tag), 'ul') !== false){
792
					$wmax = $w;
793
				}
794
				if ($this->unifontSubset) { $l += $this->GetStringWidth($c); }
795
				else { $l += $cw[$c]*$this->FontSize/1000; }
796
		
797
				if($l>$wmax){
798
					// Automatic line break
799
					if($sep==-1){
800
						if($i==$j)
801
							$i++;
802
					}else{
803
						$i = $sep+1;
804
					}
805
					$sep = -1;
806
					$j = $i;
807
					$l = 0;
808
					$ns = 0;
809
					$nl++;
810
				}else{
811
					$i++;
812
				}
813
				//If the number of lines is greater than the height, work backwards to find the next space or line return  
814
		        if(($nl * $options['line_height']) > $h){
815
	        		for($f = $i; $f > 0; $f--){
816
	        			if ($this->unifontSubset) {
817
							$char = mb_substr($s,$f,1,'UTF-8');
818
						}else{
819
							$char = $s[$f];
820
						}
821
	        			if($char=="\n" || $char==">" || $char==" "){
822
	        				$f++;
823
	        				break;
824
	        			}
825
	        		}
826
	        		
827
	        		for($e = $f; $e > 0; $e--){
828
	        			if($s[$e]=='<'){
829
	        				break;
830
	        			}
831
	        		}
832
	        		$nl--;
833
			        if ($this->unifontSubset) {
834
			        	$string = mb_substr($s, 0, $f,'UTF-8');
835
					}else{
836
						$string = substr($s, 0, $f);
837
					}
838
					$tagings = array_reverse($tags);
839
		        	foreach($tagings as $tag){
840
						$string .= '</'.$tag.'>';
841
					}
842
		        	break;
843
		        }
844
			}
845
	    }
846
	    
847
	    //If the string is blank then it fits in the gap, else build two strings
848
	    if($string == ''){
849
	    	$string = $s;
850
	    	$string2 = '';
851
	    }else{
852
	     
853
		    $string2 = substr($s, $f, $nb);
854
	    
855
		   	if ($this->unifontSubset) {
856
				$c = mb_substr($s,$f,1,'UTF-8');
857
			}else{
858
				$c=$s[$f];
859
			}
860
			
861
		    //Remove first char if it's a space or line return
862
		   	if($c == " " || $c == "\n"){
863
	   			if ($this->unifontSubset) {
864
	   				$string2 = mb_substr($string2,1,strlen($string2),'UTF-8');
865
	   			}else{
866
	   				$string2 = substr($string2, 1, strlen($string2));
867
	   			}
868
		   	}
869
			$is_tag = false;
870
			
871
			//If first char is open tag, check if there is a tag at the beginning
872
		   	if($c=='<'){
873
			   	if ($this->unifontSubset) {
874
					$tempStr = mb_substr($s, $f, $nb,'UTF-8');
875
				}else{
876
					$tempStr = substr($s, $f, $nb);
877
				}
878
				if(strpos($tempStr, '>') < 50){
879
					$is_tag = true;
880
				}
881
			}
882
			
883
			$start = 0;
884
			$end = 0;
885
			
886
			//If there is no tag at the start and type is html, add the last tag
887
			if($is_tag == false && $type == "html"){
888
		   		//If the last tag is an li, find the parent tag and add that.
889
			   	if(strtolower($taglist[count($taglist) -1]) == "li"){
890
			   		$tag = '';
891
					for($i=count($taglist)-1;$i>=0;$i--){
892
						if(strtolower($taglist[$i]) != 'li'){
893
							$tag = $taglist[$i];
894
							break;
895
						}
896
					}
897
					
898
					$tempStr = $string2;
899
					
900
					$tag_name = substr($tag, 0, 2);
901
					$close_tag_pos = strpos($tempStr, $tag_name);
902
					
903
					if ($this->unifontSubset) {
904
						$tempStr = mb_substr($tempStr, 0, $close_tag_pos, 'UTF-8');
905
					}else{
906
						$tempStr = substr($tempStr, 0, $close_tag_pos);
907
					}
908
					
909
					$no_li = substr_count(strtoupper($tempStr), '<LI>');
910
					$start = (count($tags) - $i) - 2;
911
					$end = $no_li + $start - 1;
912
			   	}
913
			}
914
			
915
			$tagings = array_reverse($tags);
916
			
917
	    	foreach($tagings as $tag){
918
				$string2 = '<'.$tag.'>'.$string2;
919
			}
920
		   	$s_array = explode("\r\n", $string2);
921
		   	
922
		   	$string2 = '';
923
		   	for($i=0;$i<count($s_array);$i++){
924
		   		if($s_array[$i] != ''){
925
		   			$string2 .=	$s_array[$i] . "\r\n";
926
		   		}
927
		   	}
928
		   	$string2 = str_replace("\r\n\r\n", "\r\n",substr($string2, 0, -1));
929
	    }
930
	    
931
	    $data_array = Array();
932
	    
933
	    array_push($data_array, $string);
934
	    array_push($data_array, $string2);
935
	    array_push($data_array, $start);
936
	    array_push($data_array, $end);
937
	    return $data_array;
938
	}
939
	
940
	function get_list_width($s, $i, $last_tag){
941
		$data = new data();
942
		$tag = $last_tag;
943
		if ($this->unifontSubset) {
944
			$tempStr = mb_substr($s, $i, strlen($s), 'UTF-8');
945
		}else{
946
			$tempStr = substr($s, $i, strlen($s));
947
		}
948
		
949
		if(strpos(strtolower($last_tag), 'ol') !== false){
950
			$last_tag = 'ol';
951
		}else{
952
			$last_tag = 'ul';	
953
		}
954
		
955
		$no_li = 1;
956
		
957
		if($last_tag == 'ol'){
958
			$close_tag_pos = strpos($tempStr, $last_tag);
959
			
960
			if ($this->unifontSubset) {
961
				$tempStr = mb_substr($tempStr, 0, $close_tag_pos, 'UTF-8');
962
			}else{
963
				$tempStr = substr($tempStr, 0, $close_tag_pos);
964
			}
965
			
966
			$no_li = substr_count(strtoupper($tempStr), '<LI>') - 1;
967
			$style = '';
968
		}else{
969
			$style = 'disc';
970
		}
971
		
972
		if(strpos(strtolower($tag), "list-style-type:") !== false){
973
			$start = strpos(strtolower($tag), "list-style-type:") + 16;
974
			if(strpos(strtolower($tag), ";", $start) !== false){
975
				$end = strpos(strtolower($tag), ";", $start);
976
			}else{
977
				$end = strpos(strtolower($tag), '"', $start);
978
			}
979
			if ($this->unifontSubset) {
980
				$style = mb_substr($tag, $start, $end-$start, 'UTF-8');
981
			}else{
982
				$style = substr($tag, $start, $end-$start);
983
			}
984
		}
985
			
986
		if($style == 'disc'){
987
			$blt = "•";
988
		}elseif($style == 'circle'){
989
			$blt = "◦";
990
		}elseif($style == 'square'){
991
			$blt = "▪";
992
		}elseif($style==''){
993
			$blt = $no_li . ".";
994
		}elseif($style=="upper-roman"){
995
			$blt = strtoupper($data->numberToRoman($no_li) . ".");
996
		}elseif($style=="lower-roman"){
997
			$blt = strtolower($data->numberToRoman($no_li) . ".");
998
		}elseif($style=="lower-alpha" || $style=="lower-latin" || $style=="upper-alpha" || $style=="upper-latin"){
999
			$b = ceil($no_li / 26);
1000
			$c = $no_li % 26;
1001
			if($b == 0){
1002
				$b = 1;
1003
			}
1004
			if($c === 0 && $no_li != 0){
1005
				$b++;
1006
			}
1007
			$the_char = chr((($no_li - (26 * ($b-1))) + 1) + 96);
1008
			$blt = '';
1009
			for($k=0;$k<$b;$k++){
1010
				$blt .= $the_char;
1011
			}
1012
			$blt .= '.';
1013
			if($style=="upper-alpha" || $style=="upper-latin"){
1014
				$blt = strtoupper($blt);	
1015
			}
1016
		}
1017
		
1018
		return $this->GetStringWidth($blt)+$this->cMargin*2;
1019
	}
1020
	
1021
	function calc_width($data, $options, $no){
1022
		$nb = 0;
1023
        
1024
        for($i=0;$i<count($data);$i++) {
1025
        	//Check if standard text or arrayed details
1026
       		if(is_array($data[$i])){
1027
            	$value = $data[$i]['value'];
1028
            	$type = $data[$i]['type'];
1029
            }else{
1030
            	$type = "text";
1031
            	$value = $data[$i];
1032
            }
1033
            
1034
            //Set font before checking
1035
            if (isset($options['style'][$i])) {
1036
                $this->SetFont('', $options['style'][$i]);
1037
            }
1038

    
1039
            $_w = $this->widths[$i];
1040
            
1041
            //Check for padding to take into consideration
1042
            if(!is_null($options['padding_size'][$i]) && !is_null($options['padding'][$i])){
1043
           	 	
1044
            	if($options['padding'][$i] == 1){
1045
	        		$_w -= ($options['padding_size'][$i] * 2);
1046
	        	}
1047
	        	if(strstr($options['padding'][$i], 'L')!==false){
1048
	        		$_w -= $options['padding_size'][$i];
1049
	        	}
1050
	       		if(strstr($options['padding'][$i], 'R')!==false){
1051
	       			$_w -= $options['padding_size'][$i];
1052
	        	}
1053
            }
1054
            
1055
            if($type=="bullet"){
1056
            	//if type is bullet draw bullets
1057
            	$_w -= $this->GetStringWidth($data[$i]['options']['bullet'])+$this->cMargin*2;
1058
            }elseif($type=="numbering"){
1059
            	//if type is numbering draw numbering
1060
            	$start = 0;
1061
            	if(!is_null($data[$i]['options']['start'])){
1062
            		$start = $data[$i]['options']['start'];	
1063
            	}
1064
            	
1065
            	$increment = $start + 1;
1066
            	
1067
            	$oldwidth = 0;
1068
            	
1069
	            for($a=0;$a < count($value);$a++){
1070
					$blt = $a + $increment . ".";
1071
					if($type=="upper-roman"){
1072
						$blt = strtoupper($data->numberToRoman($a + $increment) . ".");
1073
					}elseif($type=="lower-roman"){
1074
						$blt = strtolower($data->numberToRoman($a + $increment) . ".");
1075
					}elseif($type=="lower-alpha" || $type=="lower-latin" || $type=="upper-alpha" || $type=="upper-latin"){
1076
						$b = ceil($a / 26);
1077
						$c = $a % 26;
1078
						if($b == 0){
1079
							$b = 1;
1080
						}
1081
						if($c === 0 && $a != 0){
1082
							$b++;
1083
						}
1084
						$the_char = chr((($a - (26 * ($b-1))) + $increment) + 96);
1085
						$blt = '';
1086
						for($k=0;$k<$b;$k++){
1087
							$blt .= $the_char;
1088
						}
1089
						$blt .= '.';
1090
						if($type=="upper-alpha" || $type=="upper-latin"){
1091
							$blt = strtoupper($blt);	
1092
						}
1093
					}
1094
					
1095
					$newwidth = $this->GetStringWidth($blt);
1096
					
1097
					if($newwidth > $oldwidth){
1098
						$maxbul = $blt;
1099
					}
1100
					
1101
					$oldwidth = $newwidth;
1102
				}
1103
				
1104
				$_w -= $maxbul+$this->cMargin*2;            	
1105
            }
1106
            if($no == $i){
1107
            	break;	
1108
            }
1109
        }
1110
        return $_w;	
1111
	}
1112
	
1113
	function calc_height($data, $options){
1114
		$nb = 0;
1115
        
1116
        for($i=0;$i<count($data);$i++) {
1117
        	//Check if standard text or arrayed details
1118
       		if(is_array($data[$i])){
1119
            	$value = $data[$i]['value'];
1120
            	$type = $data[$i]['type'];
1121
            }else{
1122
            	$type = "text";
1123
            	$value = $data[$i];
1124
            }
1125
            
1126
            //Set font before checking
1127
            if (isset($options['style'][$i])) {
1128
                $this->SetFont('', $options['style'][$i]);
1129
            }
1130

    
1131
            $_w = $this->widths[$i];
1132
            
1133
            //Check for padding to take into consideration
1134
            if(!is_null($options['padding_size'][$i]) && !is_null($options['padding'][$i])){
1135
           	 	
1136
            	if($options['padding'][$i] == 1){
1137
	        		$_w -= ($options['padding_size'][$i] * 2);
1138
	        	}
1139
	        	if(strstr($options['padding'][$i], 'L')!==false){
1140
	        		$_w -= $options['padding_size'][$i];
1141
	        	}
1142
	       		if(strstr($options['padding'][$i], 'R')!==false){
1143
	       			$_w -= $options['padding_size'][$i];
1144
	        	}
1145
            }
1146
            
1147
            if($type=="text"){
1148
            	//if type is text get height
1149
        		$nb = max($nb, $this->NbLines($_w, $value));
1150
            }elseif($type=="bullet"){
1151
            	//if type is bullet draw bullets
1152
            	$_w = $this->calc_width($data, $options, $i);
1153
            	$newval = '';
1154
            	for($b=0;$b<count($value);$b++){
1155
            		$newval .= $value[$b] . "\r\n";
1156
            	}
1157
            	$nb = max($nb, $this->NbLines($_w, $newval));
1158
            }elseif($type=="numbering"){
1159
            	$_w = $this->calc_width($data, $options, $i);
1160
				
1161
            	$newval = '';
1162
            	
1163
            	for($b=0;$b<count($value);$b++){
1164
            		$newval .= $value[$b] . "\r\n";
1165
            	}
1166
            	$nb = max($nb, $this->NbLines($_w, $newval));
1167
            }elseif($type=="html"){
1168
            	//If type is html get height
1169
        		$nb = max($nb, $this->NbLines($_w, $value, "html"));
1170
            }
1171
        }
1172
        return $nb;	
1173
	}
1174
	
1175
	function build_borders($data, $options=Array(), $i, $h){
1176
		$x = $this->GetX();
1177
		$y = $this->GetY();
1178
		// width
1179
		$w = $this->widths[$i];
1180
		// padding size
1181
		$ps = isset($options['padding_size'][$i]) ? $options['padding_size'][$i] : '0';
1182
		// padding
1183
		$p = isset($options['padding'][$i]) ? $options['padding'][$i] : '1';
1184
		// fill
1185
		$f = isset($options['fill'][$i]) ? $options['fill'][$i] : '0';
1186
		// fill colour
1187
		$fc = isset($options['fill_color'][$i]) ? $options['fill_color'][$i] : array(255,255,255);
1188
            
1189
		//Border
1190
		if (is_numeric($options['border'][$i])) {
1191
			//If border surrounds cell
1192
			if(is_numeric($p)){
1193
				//if padding surrounds cell
1194
				$h+=($ps*2);
1195
				if($options['border'][$i] > 0){
1196
					if($f == 1){
1197
						$this->SetFillColor($fc[0], $fc[1], $fc[2]);
1198
						$this->Rect($x, $y, $w+($ps*2), $h, 'DF');
1199
						$this->SetFillColor(0,0,0);
1200
					}else{
1201
						$this->Rect($x, $y, $w+($ps*2), $h);
1202
					}
1203
				}
1204
				$this->SetXY($x + $ps, $y + $ps);
1205
			}else{
1206
				//if padding surrounds part of cell
1207
				$_p = strtoupper($p);
1208
				$_w = $w;
1209
				$_h = $h;
1210
				$_x = $x;
1211
				$_y = $y;
1212
				
1213
				if (strstr($_p, 'L')!==false) {
1214
					$_w += $ps;
1215
				}
1216
				if (strstr($_p, 'R')!==false) {
1217
					$_w += $ps;
1218
				}
1219
				if (strstr($_p, 'T')!==false) {
1220
					$_h += $ps;
1221
					$_y += $ps;
1222
				}
1223
				if (strstr($_p, 'B')!==false) {
1224
					$_h += $ps;
1225
				}
1226
				if($f == 1){
1227
					$this->SetFillColor($fc[0], $fc[1], $fc[2]);
1228
					$this->Rect($x, $y, $_w, $_h, 'DF');
1229
					$this->SetFillColor(0,0,0);
1230
				}else{
1231
					$this->Rect($x, $_y, $_w, $_h);
1232
				}
1233
				
1234
				if (strstr($_p, 'T')!==false) {
1235
					$this->SetXY($x, $_y + $ps);
1236
				}
1237
				if (strstr($_p, 'L')!==false) {
1238
					$this->SetX($x + $ps);
1239
				}
1240
			}
1241
		}else {
1242
			//If border surrounds part of cell
1243
			$_border = strtoupper($options['border'][$i]);
1244
			if(is_numeric($p)){
1245
				//if padding surrounds cell
1246
				if (strstr($_border, 'L')!==false) {
1247
					$this->Line($x, $y, $x, $y+$h+($ps*2));
1248
				}
1249
				if (strstr($_border, 'R')!==false) {
1250
					$this->Line($x+$w+($ps*2), $y, $x+$w+($ps*2), $y+$h+($ps*2));
1251
				}
1252
				if (strstr($_border, 'T')!==false) {
1253
					$this->Line($x, $y, $x+$w+($ps*2), $y);
1254
				}
1255
				if (strstr($_border, 'B')!==false) {
1256
					$this->Line($x, $y+$h+($ps*2), $x+$w+($ps*2), $y+$h+($ps*2));
1257
				}
1258
				if($f == 1){
1259
					$this->SetFillColor($fc[0], $fc[1], $fc[2]);
1260
					$this->SetDrawColor($fc[0], $fc[1], $fc[2]);
1261
					$this->Rect($x, $y, $_w, $_h, 'DF');
1262
					$this->SetFillColor(0,0,0);
1263
					$this->SetDrawColor(0,0,0);
1264
				}
1265
				
1266
				$this->SetXY($x + $ps, $y + $ps);
1267
			}else{
1268
				//if padding surrounds part of cell
1269
				$_p = strtoupper($p);
1270
				$_w = $w;
1271
				$_h = $h;
1272
				$_x = $x;
1273
				$_y = $y;
1274
				
1275
				if (strstr($_p, 'L')!==false) {
1276
					$_w += $ps;
1277
				}
1278
				if (strstr($_p, 'R')!==false) {
1279
					$_w += $ps;
1280
				}
1281
				if (strstr($_p, 'T')!==false) {
1282
					$_h += $ps;
1283
					$_y += $ps;
1284
				}
1285
				if (strstr($_p, 'B')!==false) {
1286
					$_h += $ps;
1287
				}
1288
				
1289
				if($f == 1){
1290
					$this->SetFillColor($fc[0], $fc[1], $fc[2]);
1291
					$this->SetDrawColor($fc[0], $fc[1], $fc[2]);
1292
					$this->Rect($x, $y, $_w, $_h, 'DF');
1293
					$this->SetFillColor(0,0,0);
1294
					$this->SetDrawColor(0,0,0);
1295
				}
1296
				
1297
				if (strstr($_border, 'L')!==false) {
1298
					$this->Line($_x, $_y, $_x, $_y+$_h);
1299
				}
1300
				
1301
				if (strstr($_border, 'R')!==false) {
1302
					$this->Line($_x+$_w, $_y, $_x+$_w, $_y+$_h);
1303
				}
1304
				if (strstr($_border, 'T')!==false) {
1305
					$this->Line($_x, $_y, $_x+$_w, $_y);
1306
				}
1307
				if (strstr($_border, 'B')!==false) {
1308
					$this->Line($_x, $_y+$_h, $_x+$_w, $_y+$_h);
1309
				}
1310
				if (strstr($_p, 'L')!==false) {
1311
					$this->SetX($_x + $ps);
1312
				}
1313
				if (strstr($_p, 'T')!==false) {
1314
					$this->SetXY($_x, $_y + $ps);
1315
				}
1316
			}
1317
		}
1318
		return $h;
1319
	}
1320
	
1321
	/**
1322
	* Create a row header
1323
	*
1324
	* @param		Array	$data			Array of text for each column
1325
	* @param		Array	$options		Array of Options
1326
	* @arrayitem	Array	border			Array of characters/integers for each column, 1 for border, 0 for none or a combination of L for left, T for top, R for right, B for bottom
1327
	* @arrayitem	Array	align			Array of characters for each column, L for Left, R for Right, C for Centre
1328
	* @arrayitem	Array	style			Array of characters for each column, B for Bold, I for Italic, U for underline
1329
	* @arrayitem	Array	maxline			Array of integers for each column, Overrides auto-calculated number of lines
1330
	* @arrayitem	Array	padding_size	Array of integers for each column, sets amount of padding
1331
	* @arrayitem	Array	padding			Array of characters/integers for each column, 1 for padding, 0 for none or a combination of L for left, T for top, R for right, B for bottom
1332
	* @arrayitem	Array	fill			Array of integers for each column, 1 for fill, 0 for not
1333
	* @arrayitem	Array	fill_color		Array of integers for RGB
1334
	* @arrayitem	Array	font_color		Array of integers for RGB
1335
	* @arrayitem	Integer	line_height		Integer to set the line height in mm
1336
	* @param		Boolean	$print_header	Boolean to set whether the header row should be printed now as well as setting for repeats
1337
	*/
1338
	function add_header($data, $options=Array(), $print_header=true){
1339
		$this->fr_data = $data;
1340
		$this->fr_border = $options['border'];
1341
		$this->fr_align = $options['align'];
1342
		$this->fr_style = $options['style'];
1343
		$this->fr_maxline = $options['maxline'];
1344
		$this->fr_padding_size = $options['padding_size'];
1345
		$this->fr_padding = $options['padding'];
1346
		$this->fr_fill = $options['fill'];
1347
		$this->fr_fill_color = $options['fill_color'];
1348
		$this->fr_font_color = $options['font_color'];
1349
		$this->fr_line_height = $options['line_height'];
1350
		
1351
		//calculate number of lines
1352
        $nb = $this->calc_height($data, $options);
1353
        
1354
        if (count($options['maxline'])) {
1355
            $_maxline = max($options['maxline']);
1356
            if ($nb > $_maxline) {
1357
                $nb = $_maxline;
1358
            }
1359
        }
1360
		
1361
		if(!is_null($options['padding_size'][0]) && !is_null($options['padding'][0])){
1362
        	$h = ($options['line_height']*$nb)+($options['padding_size'][0]*2);
1363
        }else{
1364
        	$h = ($options['line_height']*$nb);
1365
        }
1366
        //Issue a page break first if needed
1367
        $page_break = $this->CheckPageBreak($h+5, false);
1368
		
1369
		if($print_header && !$page_break){
1370
			$this->print_header();
1371
		}
1372
	}
1373
	
1374
	function print_header(){
1375
		$aRow = Array();
1376
		$aRow['border'] = $this->fr_border;
1377
		$aRow['align'] = $this->fr_align;
1378
		$aRow['style'] = $this->fr_style;
1379
		$aRow['maxline'] = $this->fr_maxline;
1380
		$aRow['padding_size'] = $this->fr_padding_size;
1381
		$aRow['padding'] = $this->fr_padding;
1382
		$aRow['fill'] = $this->fr_fill;
1383
		$aRow['fill_color'] = $this->fr_fill_color;
1384
		$aRow['font_color'] = $this->fr_font_color;
1385
		$aRow['line_height'] = $this->fr_line_height;
1386
		
1387
		$this->add_row($this->fr_data, $aRow, false);
1388
	}
1389
	
1390
	/**
1391
	* Create a Row
1392
	*
1393
	* @param		Array	$data			Array of text for each column
1394
	* @param		Array	$options		Array of Options
1395
	* @arrayitem	Array	border			Array of characters/integers for each column, 1 for border, 0 for none or a combination of L for left, T for top, R for right, B for bottom
1396
	* @arrayitem	Array	align			Array of characters for each column, L for Left, R for Right, C for Centre
1397
	* @arrayitem	Array	style			Array of characters for each column, B for Bold, I for Italic, U for underline
1398
	* @arrayitem	Array	maxline			Array of integers for each column, Overrides auto-calculated number of lines
1399
	* @arrayitem	Array	padding_size	Array of integers for each column, sets amount of padding
1400
	* @arrayitem	Array	padding			Array of characters/integers for each column, 1 for padding, 0 for none or a combination of L for left, T for top, R for right, B for bottom
1401
	* @arrayitem	Array	margin			Array of integers for each column, height in pixels
1402
	* @arrayitem	Array	fill			Array of integers for each column, 1 for fill, 0 for not
1403
	* @arrayitem	Array	fill_color		Array of integers for RGB
1404
	* @arrayitem	Array	font_color		Array of integers for RGB
1405
	* @arrayitem	Integer	line_height		Integer to set the line height in mm
1406
	* @arrayitem	Boolean	$repeat_header	Boolean to set whether the header row should be repeated when breaking over pages
1407
	* @return 								Prints row
1408
	*/
1409
	function add_row($data, $options=Array(), $repeat_header=false, $extras=Array()){
1410
		
1411
        //Set Line Height
1412
		if(!isset($options['line_height']) || $options['line_height'] == ''){
1413
        	$options['line_height'] = $this->line_height;
1414
        }
1415
        
1416
        //Previous Split
1417
        $previous_split = isset($extras['previous_split']) ? $extras['previous_split'] : false;
1418
        //Indent
1419
        $indent = isset($extras['indent']) ? $extras['indent'] : false;
1420
        //Start
1421
        $start = isset($extras['start']) ? $extras['start'] : false;
1422
        //End
1423
        $end = isset($extras['end']) ? $extras['end'] : false;
1424
        
1425
        $new_extras = $extras;
1426
        
1427
        //Calculate number of lines
1428
        $nb = $this->calc_height($data, $options);
1429
        
1430
        //Override number of lines
1431
        if (count($options['maxline'])) {
1432
            $_maxline = max($options['maxline']);
1433
            if ($nb > $_maxline) {
1434
                $nb = $_maxline;
1435
            }
1436
        }
1437
        
1438
        //Set height to take padding into consideration for page break calculation
1439
        if(!is_null($options['padding_size'][0]) && !is_null($options['padding'][0])){
1440
        	$h = ($options['line_height']*$nb)+($options['padding_size'][0]*2);
1441
        }else{
1442
        	$h = ($options['line_height']*$nb);
1443
        }
1444
        
1445
        //If there is not enough room to fit one line on the page then add a new page
1446
       	if($this->GetY()+$options['line_height']>$this->PageBreakTrigger){
1447
       		$this->AddPage();
1448
       		
1449
       		//Add header variable is set add table header.
1450
       		if($repeat_header == true){
1451
	        	$this->print_header();
1452
	        }
1453
       	}
1454
        
1455
        $new_row = array();
1456
        
1457
        //Draw the cells of the row
1458
        for($i=0;$i<count($data);$i++) {
1459
        	//Set font colour
1460
        	if(count($options['font_color'][$i]) == 3){
1461
        		$this->SetTextColor($options['font_color'][$i][0], $options['font_color'][$i][1], $options['font_color'][$i][2]);
1462
        	}
1463
        	//Width
1464
            $w = $this->widths[$i];
1465
            //Padding size
1466
            $ps = isset($options['padding_size'][$i]) ? $options['padding_size'][$i] : '0';
1467
            //Padding
1468
            $p = isset($options['padding'][$i]) ? $options['padding'][$i] : '1';
1469
            //Fill
1470
            $f = isset($options['fill'][$i]) ? $options['fill'][$i] : '0';
1471
            //Fill colour
1472
            $fc = isset($options['fill_color'][$i]) ? $options['fill_color'][$i] : array(255,255,255);
1473
            //Alignment
1474
            $a = isset($options['align'][$i]) ? $options['align'][$i] : 'L';
1475
            //Maxline
1476
            $m = isset($options['maxline'][$i]) ? $options['maxline'][$i] : false;
1477
            //Margin
1478
            $ma = isset($options['margin'][$i]) ? $options['margin'][$i] : array();
1479
            //Save the current position
1480
            $x = $this->GetX();
1481
            $y = $this->GetY();
1482
            //Setting Style
1483
            if (isset($options['style'][$i])) {
1484
                $this->SetFont('', $options['style'][$i]);
1485
            }
1486
            
1487
            //Set height to number of lines times the height of one line
1488
            $h = ($options['line_height'])*$nb;
1489
            
1490
            if(is_array($data[$i])){
1491
            	$value = $data[$i]['value'];
1492
            	$type = $data[$i]['type'];
1493
            }else{
1494
            	$type = "text";
1495
            	$value = $data[$i];
1496
            }
1497
            
1498
            if($type == "numbering" || $type == "bullet"){
1499
            	if(count($ma) == count($value)){
1500
            		for($margins=0;$margins<count($ma);$margins++){
1501
            			$h += $this->convert($ma[$margins]);
1502
            		}
1503
            	}
1504
            }
1505
            
1506
            $h2 = 0;
1507
            $h3 = $h;
1508
            
1509
        	if($p == 1){
1510
        		$h3 += ($ps * 2);
1511
        	}
1512
        	if(strstr($p, 'T')!==false){
1513
        		$h3 += $ps;
1514
        	}
1515
       		if(strstr($p, 'B')!==false){
1516
       			$h3 += $ps;
1517
        	}
1518
        	
1519
            //If height is greater than the remainder of page height
1520
	        if(($h3 + $y) > $this->PageBreakTrigger){
1521
	        	$h2 = 0;
1522
	        	//Get remaining page height
1523
	        	$h2 = $this->PageBreakTrigger - $this->GetY();
1524
	        	
1525
	        	if($p == 1){
1526
	        		$h2 -= ($ps * 2);
1527
	        	}
1528
	        	if(strstr($p, 'T')!==false){
1529
	        		$h2 -= $ps;
1530
	        	}
1531
	       		if(strstr($p, 'B')!==false){
1532
	       			$h2 -= $ps;
1533
	        	}
1534
	        	
1535
        		$horig = $h;
1536
	        	$htemp = $h - $h2;
1537
        		
1538
	        	//Set height to remaining page height
1539
        		$h = $h2;
1540
	        }
1541
            
1542
	        if($h2 > $options['line_height'] || $h2 == 0){
1543
		        //Create borders and return actual height
1544
		        $h = $this->build_borders($data, $options, $i, $h);
1545
        	}
1546
            
1547
            //Split tall text
1548
            if($h2 != 0){
1549
            	//if it was calculated that the height is taller than the page height
1550
            	if($h2 > $options['line_height']){
1551
	            	$_h = $h;
1552
	            	
1553
	           		if($p == 1){
1554
		        		$_h -= ($ps * 2);
1555
		        		$_w -= ($ps * 2);
1556
		        	}
1557
		        	if(strstr($p, 'T')!==false){
1558
		        		$_h -= $ps;
1559
		        	}
1560
		       		if(strstr($p, 'B')!==false){
1561
		       			$_h -= $ps;
1562
		        	}
1563
		        	
1564
	            	$_w = $this->calc_width($data, $options, $i);
1565
		        	$darray = $this->cell_contents_split($_h, $_w, $value, $type, $options);
1566
		        	
1567
			        $the_data = $darray[0];
1568
			        $new_row[$i]['value'] = $darray[1];
1569
			        $new_row[$i]['type'] = $type;
1570
		        	$newextras['start'] = $darray[2];
1571
		        	$newextras['end'] = $darray[3];
1572
		        	$newextras['previous_split'] = $darray[4];
1573
            	}else{
1574
            		$the_data = '';
1575
			        $new_row[$i]['value'] = $value;
1576
			        $new_row[$i]['type'] = $type;
1577
            	}
1578
            }else{
1579
            	$the_data = $value;
1580
            	$new_row[$i]['value'] = '';
1581
            	$new_row[$i]['type'] = $type;
1582
            }
1583
            
1584
            if($the_data != ''){
1585
	            if($type=="text"){
1586
	            	//If type is text draw cell
1587
	            	$this->MultiCell($w, ($options['line_height']), $the_data, 0, $a, 0, $m);
1588
	            }elseif($type=="bullet"){
1589
	            	//If type is bullet draw bullets
1590
	            	$this->add_bullets($the_data, $data[$i]['options']['bullet'], $indent, $w, $previous_split, $ma);
1591
	            }elseif($type=="numbering"){
1592
	            	//If type is numbering draw numbering
1593
	            	$this->add_numbering($the_data, $data[$i]['options']['type'], $start, $indent, $w, $previous_split, $end, $ma);
1594
	            }elseif($type=="html"){
1595
	            	//If type is html parse html
1596
	            	//print(str_replace("<", "&lt;", $the_data) . ' - ' . $h . '<br />');
1597
	            	$this->parse_html($the_data, $w, $a, $extras);
1598
	            }
1599
            }
1600
            
1601
            //Put the position to the right of the cell
1602
       		if(is_numeric($p)){
1603
       			$_border = strtoupper($options['border'][$i]);
1604
       			if(is_numeric($_border)){
1605
       				$this->SetXY($x+$w+($ps*2), $y);
1606
       			}else{
1607
       				$_x = $w+$x;
1608
       				$_y = $y;
1609
					//if padding surrounds cell
1610
					if (strstr($_border, 'L')!==false) {
1611
						$_x += $ps;
1612
					}
1613
					if (strstr($_border, 'R')!==false) {
1614
						$_x += $ps;
1615
					}
1616
       				if (strstr($_border, 'T')!==false && $i == count($data)-1) {
1617
						$_y += $ps*2;
1618
					}
1619
       				if (strstr($_border, 'B')!==false && $i == count($data)-1) {
1620
						$_y += $ps*2;
1621
					}
1622
					$this->SetXY($_x, $_y);
1623
       			}
1624
       		}else{
1625
               	$_p = strtoupper($p);
1626
               	$_w = $w;
1627
               	$_h = $h;
1628
               	$_x = $x;
1629
               	$_y = $y;
1630
               	
1631
       			if (strstr($_p, 'L')!==false) {
1632
					$_w += $ps;
1633
				}
1634
				if (strstr($_p, 'R')!==false) {
1635
					$_w += $ps;
1636
				}
1637
				if (strstr($_p, 'T')!==false) {
1638
					$_h += $ps;
1639
					//$_y += $ps;
1640
				}
1641
				if (strstr($_p, 'B')!==false) {
1642
					$_h += $ps;
1643
					//$_y += $ps;
1644
				}
1645
            	
1646
               	$this->SetXY($_x+$_w, $_y);
1647
       		}
1648
       		$this->SetTextColor(0,0,0);
1649
        }
1650
        //Go to the next line
1651
        $this->Ln($h);
1652
        
1653
        //If the text was split across pages add the second half
1654
        for($i=0;$i<count($new_row);$i++){
1655
        	if($new_row[$i]['value'] != ''){
1656
        		$this->AddPage();
1657
        		
1658
		        //Print header on new page if variable is true
1659
		        if($repeat_header == true){
1660
		        	$this->print_header();
1661
		        }
1662
        		$this->add_row($new_row, $options, $repeat_header, $newextras);
1663
        		break;
1664
        	}
1665
        }
1666
    }
1667
	
1668
	function add_para($str="", $double=true, $w=0, $a='L'){
1669
		$str = str_replace("Â", "", utf8_encode(html_entity_decode($str)));
1670
		$str = preg_replace("/<br\W*?\/>/i", "\r\n", $str);
1671
		$this->MultiCell($w, $this->line_height, $str, 0, $a, 0);
1672
		if($double == true){
1673
			$this->Ln();
1674
		}
1675
	}
1676
	
1677
	function add_bullets($bullet_array, $blt="•", $indent=0, $width=0, $ignore_first=false, $margins=array()){
1678
		if(is_null($blt)){
1679
			$blt = "•";
1680
		}
1681
		
1682
		if(is_null($indent)){
1683
			$indent = 0;
1684
		}
1685
		
1686
		for($a=0;$a < count($bullet_array);$a++){
1687
			if($bullet_array[$a] != ''){
1688
				$str = str_replace("Â", "", utf8_encode(html_entity_decode($bullet_array[$a])));
1689
				$str = preg_replace("/<br\W*?\/>/i", "\r\n", $str);
1690

    
1691
				if($ignore_first == true && $a==0){
1692
					$this->MultiCellBlt($width, $this->line_height, " ", $str, $indent);
1693
				}else{
1694
					$this->MultiCellBlt($width, $this->line_height, $blt, $str, $indent);
1695
				}
1696
				$height = 0;
1697
				if(count($margins) == count($bullet_array)){
1698
					if($margins[$a] != ''){
1699
						$height += $this->convert($margins[$a]);
1700
						$this->MultiCellBlt($width, $height, " ", " ", $indent);
1701
					}
1702
				}
1703
			}
1704
		}
1705
		$this->Ln();
1706
	}
1707
	
1708
	function add_numbering($number_array, $type="decimal", $start=0, $indent=0, $width=0, $ignore_first=false, $end=0, $margins=array()){
1709
		$data= new data;
1710
		
1711
		$oldwidth = 0;
1712
		
1713
		if($end == 0){
1714
			$end = count($number_array);
1715
		}
1716
		
1717
		$increment = $start + 1;
1718
		
1719
		for($a=0;$a < $end;$a++){
1720
			if($number_array[$a] != ''){
1721
				$blt = $a + $increment . ".";
1722
				if($type=="upper-roman"){
1723
					$blt = strtoupper($data->numberToRoman($a + $increment) . ".");
1724
				}elseif($type=="lower-roman"){
1725
					$blt = strtolower($data->numberToRoman($a + $increment) . ".");
1726
				}elseif($type=="lower-alpha" || $type=="lower-latin" || $type=="upper-alpha" || $type=="upper-latin"){
1727
					$b = ceil($a / 26);
1728
					$c = $a % 26;
1729
					if($b == 0){
1730
						$b = 1;
1731
					}
1732
					if($c === 0 && $a != 0){
1733
						$b++;
1734
					}
1735
					$the_char = chr((($a - (26 * ($b-1))) + $increment) + 96);
1736
					$blt = '';
1737
					for($k=0;$k<$b;$k++){
1738
						$blt .= $the_char;
1739
					}
1740
					$blt .= '.';
1741
					if($type=="upper-alpha" || $type=="upper-latin"){
1742
						$blt = strtoupper($blt);
1743
					}
1744
				}
1745
				
1746
				$newwidth = $this->GetStringWidth($blt);
1747
				
1748
				if($newwidth > $oldwidth){
1749
					$maxbul = $blt;
1750
				}
1751
				
1752
				$oldwidth = $newwidth;
1753
			}
1754
		}
1755
		
1756
		for($a=0;$a < count($number_array);$a++){
1757
			if($number_array[$a] != ''){
1758
				$blt = $a + $increment . ".";
1759
				if($type=="upper-roman"){
1760
					$blt = strtoupper($data->numberToRoman($a + $increment) . ".");
1761
				}elseif($type=="lower-roman"){
1762
					$blt = strtolower($data->numberToRoman($a + $increment) . ".");
1763
				}elseif($type=="lower-alpha" || $type=="lower-latin" || $type=="upper-alpha" || $type=="upper-latin"){
1764
					$b = ceil($a / 26);
1765
					$c = $a % 26;
1766
					if($b == 0){
1767
						$b = 1;
1768
					}
1769
					if($c === 0 && $a != 0){
1770
						$b++;
1771
					}
1772
					$the_char = chr((($a - (26 * ($b-1))) + $increment) + 96);
1773
					$blt = '';
1774
					for($k=0;$k<$b;$k++){
1775
						$blt .= $the_char;
1776
					}
1777
					$blt .= '.';
1778
					if($type=="upper-alpha" || $type=="upper-latin"){
1779
						$blt = strtoupper($blt);
1780
					}
1781
				}
1782
				$str = str_replace("Â", "", utf8_encode(html_entity_decode($number_array[$a])));
1783
				$str = preg_replace("/<br\W*?\/>/i", "\r\n", $str);
1784
				
1785
				if($ignore_first == true && $a==0){
1786
					$this->MultiCellBlt($width, $this->line_height, " ", $str, $indent, $maxbul);
1787
				}else{
1788
					$this->MultiCellBlt($width, $this->line_height, $blt, $str, $indent, $maxbul);
1789
				}
1790
				$height = 0;
1791
				if(count($margins) == count($number_array)){
1792
					if($margins[$a] != ''){
1793
						$height += $this->convert($margins[$a]);
1794
						$this->MultiCellBlt($width, $height, " ", " ", $indent, $maxbul);
1795
					}
1796
				}
1797
			}
1798
		}
1799
		$this->Ln();
1800
	}
1801
	
1802
	function parse_html($string, $w=0, $a='L', $extras=Array()){
1803
		try{
1804
			$string = str_replace("\t", "", $string);
1805
			$string = str_replace("\n", "", $string);
1806
			$string = str_replace("\r", "", $string);
1807
			if($string != ''){
1808
				$dom = new DOMDocument();
1809
				$dom->registerNodeClass('DOMElement', 'extraElement');
1810
				$dom->loadHTML($string);
1811
				
1812
				//Previous Split
1813
		        $previous_split = isset($extras['previous_split']) ? $extras['previous_split'] : false;
1814
		        //Indent
1815
		        $indent = isset($extras['indent']) ? $extras['indent'] : 0;
1816
		        //Start
1817
		        $start = isset($extras['start']) ? $extras['start'] : 0;
1818
		        //Start
1819
		        $end = isset($extras['end']) ? $extras['end'] : 0;
1820
				
1821
				$nodes = $dom->childNodes;
1822
				$nodes = $nodes->item(1)->childNodes->item(0)->childNodes;
1823
				for($i=0;$i<$nodes->length;$i++) {
1824
					
1825
					$item = $nodes->item($i);
1826
					$type = $item->tagName;
1827
					$value = $item->innerHTML;
1828
					
1829
					if(strtoupper($type) == "P"){
1830
						$v_array = preg_split("/<\s*[Bb][Rr]\s*\/*>/", $value);
1831
						foreach($v_array as $value){
1832
							//if($value != ''){
1833
								$x = $this->GetX();
1834
								$this->add_para(utf8_decode($value), false, $w, $a);
1835
								$this->SetXY($x, $this->GetY());
1836
							//}
1837
						}
1838
					}elseif(strtoupper($type) == "UL"){
1839
						$blt = 'disc';
1840
						$margins = array();
1841
						
1842
						foreach($item->attributes as $attr) {
1843
							if(strtoupper($attr->nodeName) == 'STYLE'){
1844
								$value = $attr->nodeValue;
1845
								$style_array = explode(';',$value);
1846
								for($k=0;$k<count($style_array);$k++){
1847
									$styles = explode(':',$style_array[$k]);
1848
									if(strtolower($styles[0]) == 'list-style-type'){
1849
										$blt = $styles[1];
1850
									}
1851
								}
1852
							}
1853
						}
1854
						$children = $item->childNodes;
1855
						$child_array = array();
1856
						for($j=0;$j<$children->length;$j++) {
1857
							$child = $children->item($j);
1858
							$tag = $child->tagName;
1859
							if(strtoupper($tag) == "LI"){
1860
								$margin = '';
1861
								foreach($child->attributes as $attr) {
1862
									if(strtoupper($attr->nodeName) == 'STYLE'){
1863
										$value = $attr->nodeValue;
1864
										$style_array = explode(';',$value);
1865
										for($k=0;$k<count($style_array);$k++){
1866
											$styles = explode(':',$style_array[$k]);
1867
											if(strtolower($styles[0]) == 'margin-bottom'){
1868
												$margin = str_replace('px', '', $styles[1]);
1869
											}
1870
										}
1871
									}
1872
								}
1873
								array_push($child_array, utf8_decode(html_entity_decode($child->innerHTML)));
1874
								array_push($margins, $margin);
1875
							}
1876
						}
1877
						if($blt == 'disc'){
1878
							$symbol = "•";
1879
						}elseif($blt == 'circle'){
1880
							$symbol = "◦";
1881
						}elseif($blt == 'square'){
1882
							$symbol = "▪";
1883
						}
1884
						$x = $this->GetX();
1885
						$this->add_bullets($child_array, $symbol, $indent, $w, $previous_split, $margins);
1886
						$this->SetXY($x, $this->GetY());
1887
					}elseif(strtoupper($type) == "OL"){
1888
						$blt = 'decimal';
1889
						$margins = array();
1890
						
1891
						foreach($item->attributes as $attr) {
1892
							if(strtoupper($attr->nodeName) == 'STYLE'){
1893
								$value = $attr->nodeValue;
1894
								$style_array = explode(';',$value);
1895
								for($k=0;$k<count($style_array);$k++){
1896
									$styles = explode(':',$style_array[$k]);
1897
									if(strtolower($styles[0]) == 'list-style-type'){
1898
										$blt = $styles[1];
1899
									}
1900
								}
1901
							}
1902
						}
1903
						$children = $item->childNodes;
1904
						$child_array = array();
1905
						for($j=0;$j<$children->length;$j++) {
1906
							$child = $children->item($j);
1907
							$tag = $child->tagName;
1908
							if(strtoupper($tag) == "LI"){
1909
								$margin = '';
1910
								foreach($child->attributes as $attr) {
1911
									if(strtoupper($attr->nodeName) == 'STYLE'){
1912
										$value = $attr->nodeValue;
1913
										$style_array = explode(';',$value);
1914
										for($k=0;$k<count($style_array);$k++){
1915
											$styles = explode(':',$style_array[$k]);
1916
											if(strtolower($styles[0]) == 'margin-bottom'){
1917
												$margin = str_replace('px', '', $styles[1]);
1918
											}
1919
										}
1920
									}
1921
								}
1922
								array_push($child_array, utf8_decode(html_entity_decode($child->innerHTML)));
1923
								array_push($margins, $margin);
1924
							}
1925
						}
1926
						$x = $this->GetX();
1927
						$this->add_numbering($child_array, $blt, $start, $indent, $w, $previous_split, $end, $margins);
1928
						$this->SetXY($x, $this->GetY());
1929
					}elseif(strtoupper($type) == "TABLE"){
1930
						$table_width = 0;
1931
						$table_padding_size = 0;
1932
						$table_border_size = 0;
1933
						foreach($item->attributes as $attr) {
1934
							if(strtoupper($attr->nodeName) == 'STYLE'){
1935
								$value = $attr->nodeValue;
1936
								$style_array = explode(';',$value);
1937
								for($k=0;$k<count($style_array);$k++){
1938
									$styles = explode(':',$style_array[$k]);
1939
									if(strtoupper($styles[0]) == 'WIDTH'){
1940
										$table_width = str_replace('px', '', $styles[1]);
1941
									}
1942
								}
1943
							}
1944
							if(strtoupper($attr->nodeName) == 'CELLPADDING'){
1945
								$value = $attr->nodeValue;
1946
								$table_padding_size = $value;
1947
							}
1948
							if(strtoupper($attr->nodeName) == 'BORDER'){
1949
								$value = $attr->nodeValue;
1950
								$table_border_size = $value;
1951
							}
1952
						}
1953
						if(strtolower($table_border_size) == "none"){
1954
							$table_border_size = 0;
1955
						}
1956
						
1957
						$children = $item->childNodes;
1958
						$child_array = array();
1959
						for($j=0;$j<$children->length;$j++) {
1960
							$child = $children->item($j);
1961
							$tag = $child->tagName;
1962
							if(strtoupper($tag) == "THEAD"){
1963
								$rows = $child->childNodes;
1964
								$rows_array = array();
1965
								for($k=0;$k<$rows->length;$k++) {
1966
									$row = $rows->item($k);
1967
									$tag = $row->tagName;
1968
									if(strtoupper($tag) == "TR"){
1969
										$no_cells = 0;
1970
										$cells = $row->childNodes;
1971
										$cells_array = array();
1972
										for($l=0;$l<$cells->length;$l++) {
1973
											$cell = $cells->item($l);
1974
											$tag = $cell->tagName;
1975
											if(strtoupper($tag) == "TH"){
1976
												foreach($cell->attributes as $attr) {
1977
													if(strtoupper($attr->nodeName) == 'STYLE'){
1978
														$value = $attr->nodeValue;
1979
														$style_array = explode(';',$value);
1980
														for($m=0;$m<count($style_array);$m++){
1981
															$styles = explode(':',$style_array[$m]);
1982
															if(strtoupper($styles[0]) == 'WIDTH'){
1983
																$header[$no_cells]['width'] = str_replace('px', '', $styles[1]);
1984
															}
1985
															if(strtoupper($styles[0]) == 'TEXT-ALIGN'){
1986
																$header[$no_cells]['align'] = substr(strtoupper($styles[1]), 0, 1);
1987
															}
1988
															if(strtoupper($styles[0]) == 'BORDER'){
1989
																$border = explode(' ',$styles[1]);
1990
																$header[$no_cells]['border_width'] = str_replace('px', '', $border[0]);
1991
																$header[$no_cells]['border_color'] = $border[2];
1992
															}
1993
															if(strtoupper($styles[0]) == 'BORDER-COLOR'){
1994
																$header[$no_cells]['border_color'] = $styles[1];
1995
															}
1996
															if(strtoupper($styles[0]) == 'BORDER-WIDTH'){
1997
																$header[$no_cells]['border_width'] = str_replace('px', '', $styles[1]);
1998
															}
1999
															if(strtoupper($styles[0]) == 'FONT-WEIGHT'){
2000
																if(strtoupper($styles[1]) == 'BOLD'){
2001
																	$header[$no_cells]['bold'] = 'B';
2002
																}
2003
															}
2004
															if(strtoupper($styles[0]) == 'LINE-HEIGHT'){
2005
																$header[$no_cells]['line_height'] = $styles[1];
2006
															}
2007
															if(strtoupper($styles[0]) == 'FONT-STYLE'){
2008
																if(strtoupper($styles[1]) == 'ITALIC'){
2009
																	$header[$no_cells]['italic'] = 'I';
2010
																}
2011
															}
2012
															if(strtoupper($styles[0]) == 'TEXT-DECORATION'){
2013
																if(strtoupper($styles[1]) == 'UNDERLINE'){
2014
																	$header[$no_cells]['underline'] = 'U';
2015
																}
2016
															}
2017
															if(strtoupper($styles[0]) == 'COLOR'){
2018
																$color_array = $this->hex2RGB($styles[1]);
2019
																$header[$no_cells]['font_color'] = array($color_array['red'], $color_array['green'], $color_array['blue']);
2020
															}
2021
															if(strtoupper($styles[0]) == 'BACKGROUND-COLOR'){
2022
																$color_array = $this->hex2RGB($styles[1]);
2023
																$header[$no_cells]['fill_color'] = array($color_array['red'], $color_array['green'], $color_array['blue']);
2024
															}
2025
														}
2026
													}
2027
												}
2028
												$header[$no_cells]['content'] = $cell->innerHTML;
2029
												$no_cells++;
2030
											}
2031
										}	
2032
									}
2033
								}
2034
							}
2035
						}
2036
						
2037
						$body = Array();
2038
						
2039
						$no_rows = 0;
2040
						$children = $item->childNodes;
2041
						for($j=0;$j<$children->length;$j++) {
2042
							$child = $children->item($j);
2043
							$tag = $child->tagName;
2044
							if(strtoupper($tag) == "TBODY"){
2045
								$rows = $child->childNodes;
2046
								for($k=0;$k<$rows->length;$k++) {
2047
									$row = $rows->item($k);
2048
									$tag = $row->tagName;
2049
									if(strtoupper($tag) == "TR"){
2050
										$no_cells = 0;
2051
										$cells = $row->childNodes;
2052
										for($l=0;$l<$cells->length;$l++) {
2053
											$cell = $cells->item($l);
2054
											$tag = $cell->tagName;
2055
											if(strtoupper($tag) == "TD"){
2056
												foreach($cell->attributes as $attr) {
2057
													if(strtoupper($attr->nodeName) == 'STYLE'){
2058
														$value = $attr->nodeValue;
2059
														$style_array = explode(';',$value);
2060
														for($m=0;$m<count($style_array);$m++){
2061
															$styles = explode(':',$style_array[$m]);
2062
															if(strtoupper($styles[0]) == 'WIDTH'){
2063
																$body[$no_rows][$no_cells]['width'] = str_replace('px', '', $styles[1]);
2064
															}
2065
															if(strtoupper($styles[0]) == 'TEXT-ALIGN'){
2066
																$body[$no_rows][$no_cells]['align'] = substr(strtoupper($styles[1]), 0, 1);
2067
															}
2068
															if(strtoupper($styles[0]) == 'BORDER'){
2069
																$border = explode(' ',$styles[1]);
2070
																$body[$no_rows][$no_cells]['border_width'] = str_replace('px', '', $border[0]);
2071
																$body[$no_rows][$no_cells]['border_color'] = $border[2];
2072
															}
2073
															if(strtoupper($styles[0]) == 'BORDER-COLOR'){
2074
																$body[$no_rows][$no_cells]['border_color'] = $styles[1];
2075
															}
2076
															if(strtoupper($styles[0]) == 'LINE-HEIGHT'){
2077
																$body[$no_rows][$no_cells]['line_height'] = $styles[1];
2078
															}
2079
															if(strtoupper($styles[0]) == 'BORDER-WIDTH'){
2080
																$body[$no_rows][$no_cells]['border_width'] = str_replace('px', '', $styles[1]);
2081
															}
2082
															if(strtoupper($styles[0]) == 'FONT-WEIGHT'){
2083
																if(strtoupper($styles[1]) == 'BOLD'){
2084
																	$body[$no_rows][$no_cells]['bold'] = 'B';
2085
																}
2086
															}
2087
															if(strtoupper($styles[0]) == 'FONT-STYLE'){
2088
																if(strtoupper($styles[1]) == 'ITALIC'){
2089
																	$body[$no_rows][$no_cells]['italic'] = 'I';
2090
																}
2091
															}
2092
															if(strtoupper($styles[0]) == 'TEXT-DECORATION'){
2093
																if(strtoupper($styles[1]) == 'UNDERLINE'){
2094
																	$body[$no_rows][$no_cells]['underline'] = 'U';
2095
																}
2096
															}
2097
															if(strtoupper($styles[0]) == 'COLOR'){
2098
																$color_array = $this->hex2RGB($styles[1]);
2099
																$body[$no_rows][$no_cells]['font_color'] = array($color_array['red'], $color_array['green'], $color_array['blue']);
2100
															}
2101
															if(strtoupper($styles[0]) == 'BACKGROUND-COLOR'){
2102
																$color_array = $this->hex2RGB($styles[1]);
2103
																$body[$no_rows][$no_cells]['fill_color'] = array($color_array['red'], $color_array['green'], $color_array['blue']);
2104
															}
2105
														}
2106
													}
2107
												}
2108
												$body[$no_rows][$no_cells]['content'] = $cell->innerHTML;
2109
												$no_cells++;
2110
											}
2111
										}
2112
										$no_rows++;	
2113
									}
2114
								}
2115
							}
2116
						}
2117
						$total_width = 0;
2118
						$widths = Array();
2119
						
2120
						if(count($header) > 0){
2121
							$widths = $this->calc_col_widths($header, $body, $table_width, $table_padding_size, $table_border_size);
2122
							$this->SetWidths($widths);
2123
							$aRow = Array();
2124
							$aRow['border'] = array();
2125
							$aRow['padding_size'] = array();
2126
							$aRow['padding'] = array();
2127
							$aRow['align'] = array();
2128
							$aRow['style'] = array();
2129
							$aRow['fill'] = array();
2130
							$aRow['fill_color'] = array();
2131
							$aRow['font_color'] = array();
2132
							$aRow['line_height'] = '';
2133
							$caption = array();
2134
							
2135
							for($k=0;$k<count($header);$k++){
2136
								$aRow['border'][$k] = $header[$k]['border'];
2137
								$aRow['border'][$k] = $table_border_size;
2138
								$aRow['padding_size'][$k] = $table_padding_size;
2139
								$aRow['padding'][$k] = 1;
2140
								
2141
								$align = 'L';
2142
								if(isset($header[$k]['align'])){
2143
									$align = $header[$k]['align'];
2144
								}
2145
								$aRow['align'][$k] = $align;
2146
								
2147
								$style = '';
2148
								if(isset($header[$k]['bold'])){
2149
									$style .= $header[$k]['bold'];
2150
								}
2151
								if(isset($header[$k]['italic'])){
2152
									$style .= $header[$k]['italic'];
2153
								}
2154
								if(isset($header[$k]['underline'])){
2155
									$style .= $header[$k]['underline'];
2156
								}
2157
								$aRow['style'][$k] = $style;
2158
								
2159
								$fill = '0';
2160
								$fill_color = array();
2161
								if(isset($header[$k]['fill_color'])){
2162
									$fill = '1';
2163
									$fill_color = $header[$k]['fill_color'];
2164
								}
2165
								$aRow['fill'][$k] = $fill;
2166
								$aRow['fill_color'][$k] = $fill_color;
2167
								
2168
								$font_color = array();
2169
								if(isset($header[$k]['font_color'])){
2170
									$font_color = $header[$k]['font_color'];
2171
								}
2172
								$aRow['font_color'][$k] = $font_color;
2173
								
2174
								$caption[$k]['type'] = "html";
2175
								$caption[$k]['value'] = $header[$k]['content'];
2176
							}
2177
							$this->add_header($caption, $aRow);
2178
						}
2179
						
2180
						for($j=0;$j<count($body);$j++){
2181
							$widths = $this->calc_col_widths($header, $body, $table_width, $table_padding_size, $table_border_size);
2182
							$this->SetWidths($widths);
2183
							$aRow = Array();
2184
							$aRow['border'] = array();
2185
							$aRow['padding_size'] = array();
2186
							$aRow['padding'] = array();
2187
							$aRow['align'] = array();
2188
							$aRow['style'] = array();
2189
							$aRow['fill'] = array();
2190
							$aRow['fill_color'] = array();
2191
							$aRow['font_color'] = array();
2192
							$aRow['line_height'] = '';
2193
							$caption = array();
2194
							
2195
							for($k=0;$k<count($body[$j]);$k++){
2196
								$aRow['border'][$k] = $body[$j][$k]['border'];
2197
								$aRow['border'][$k] = $table_border_size;
2198
								$aRow['padding_size'][$k] = $table_padding_size;
2199
								$aRow['padding'][$k] = 1;
2200
								
2201
								$align = 'L';
2202
								if(isset($body[$j][$k]['align'])){
2203
									$align = $body[$j][$k]['align'];
2204
								}
2205
								$aRow['align'][$k] = $align;
2206
								
2207
								$style = '';
2208
								if(isset($body[$j][$k]['bold'])){
2209
									$style .= $body[$j][$k]['bold'];
2210
								}
2211
								if(isset($body[$j][$k]['italic'])){
2212
									$style .= $body[$j][$k]['italic'];
2213
								}
2214
								if(isset($body[$j][$k]['underline'])){
2215
									$style .= $body[$j][$k]['underline'];
2216
								}
2217
								$aRow['style'][$k] = $style;
2218
								
2219
								$fill = '0';
2220
								$fill_color = array();
2221
								if(isset($body[$j][$k]['fill_color'])){
2222
									$fill = '1';
2223
									$fill_color = $body[$j][$k]['fill_color'];
2224
								}
2225
								$aRow['fill'][$k] = $fill;
2226
								$aRow['fill_color'][$k] = $fill_color;
2227
								
2228
								$font_color = array();
2229
								if(isset($body[$j][$k]['font_color'])){
2230
									$font_color = $body[$j][$k]['font_color'];
2231
								}
2232
								$aRow['font_color'][$k] = $font_color;
2233
								
2234
								$caption[$k]['type'] = "html";
2235
								$caption[$k]['value'] = $body[$j][$k]['content'];
2236
							}
2237
							$this->add_row($caption, $aRow, $extras);
2238
						}
2239
					}else{
2240
						$this->parse_html('<p>'.$string.'</p>', $w, $a, $extras);
2241
					}
2242
				}
2243
			}
2244
		}catch(Exception $e){
2245
			
2246
		}
2247
	}
2248
	
2249
	function calc_col_widths($header, $body, $table_width = 0, $table_padding_size = 0, $table_border_size = 0){
2250
		
2251
		$widths = array();
2252
		
2253
		$j = 0;
2254
		
2255
		$table_border_size = 1;
2256
		
2257
		$total_width = 0;
2258
		if($table_width == 0){
2259
			$table_width = $this->convert($this->w-$this->rMargin-$this->lMargin, 'mm', 'pixels');
2260
		}
2261
		
2262
		$set_widths = array();
2263
		
2264
		for($k=0;$k<count($header);$k++){
2265
			if(isset($header[$k]['width'])){
2266
				array_push($set_widths, $header[$k]['width']);
2267
			}else{
2268
				array_push($set_widths, 0);
2269
			}
2270
		}
2271
		if(count($widths) == 0){
2272
			for($k=0;$k<count($body[$j]);$k++){
2273
				if(isset($body[$j][$k]['width'])){		
2274
					array_push($set_widths, $body[$j][$k]['width']);
2275
				}else{
2276
					array_push($set_widths, 0);
2277
				}
2278
			}
2279
		}
2280
		
2281
		$padding = $this->convert($table_padding_size, 'mm', 'pixels');
2282
		
2283
		$num_cols = count($set_widths);
2284
		$num_no_width = 0;
2285
		$width_used = 0;
2286
		
2287
		foreach($set_widths as $width){
2288
			if($width == 0){
2289
				$num_no_width++;
2290
			}else{
2291
				$width_used += ($width + ($padding*2));
2292
			}
2293
		}
2294
		
2295
		if($num_no_width > 0){
2296
			$col_width = $this->convert((($table_width - $width_used) / $num_no_width) - $padding*2);
2297
		}
2298
		
2299
		for($k=0;$k<count($header);$k++){
2300
			if(isset($header[$k]['width'])){
2301
				array_push($widths, $this->convert($header[$k]['width']));
2302
			}else{
2303
				array_push($widths, $col_width);
2304
			}
2305
		}
2306
		if(count($widths) == 0){
2307
			for($k=0;$k<count($body[$j]);$k++){
2308
				if(isset($body[$j][$k]['width'])){			
2309
					array_push($widths, $this->convert($body[$j][$k]['width']));
2310
				}else{
2311
					array_push($widths, $col_width);
2312
				}
2313
			}
2314
		}
2315
		
2316
		return $widths;
2317
	}
2318
	
2319
	function split_by_tags($string){
2320
		$dom = new DOMDocument();
2321
		$dom->registerNodeClass('DOMElement', 'extraElement');
2322
		@$dom->loadHTML('<p>'.$string.'</p>');
2323
		$result_array = array();
2324
		$data_array = array();
2325
		
2326
		$nodes = $dom->childNodes;
2327
		$nodes = $nodes->item(1)->childNodes->item(0)->childNodes;
2328
		for($i=0;$i<$nodes->length;$i++) {
2329
			
2330
			$item = $nodes->item($i);
2331
			$type = $item->tagName;
2332
			$value = $item->innerHTML;
2333
			
2334
			if(strtoupper($type) == "P"){
2335
				
2336
				$children = $item->childNodes;
2337
				for($j=0;$j<$children->length;$j++) {
2338
					$child = $children->item($j);
2339
					$tag = $child->tagName;
2340
					if($tag != ''){					
2341
						array_push($data_array, array($tag, $child->innerHTML));
2342
					}
2343
				}
2344
			}
2345
		}
2346
		$temp_string = $string;
2347
		for($i=0;$i<count($data_array);$i++){
2348
			$pos = strpos($temp_string, "<".$data_array[$i][0].">");
2349
			if($pos > 0){
2350
				array_push($result_array, array(substr($temp_string, 0, $pos), ''));
2351
			}
2352
			$temp_string =  substr($temp_string, $pos + strlen("<".$data_array[$i][0].">"));
2353
			$pos = strpos($temp_string, "</".$data_array[$i][0].">");
2354
			array_push($result_array, array(substr($temp_string, 0, $pos),$data_array[$i][0]));
2355
			$temp_string =  substr($temp_string, ($pos + strlen("</".$data_array[$i][0].">")));
2356
		}
2357
		if(count($data_array) == 0){
2358
			array_push($result_array, array($string,''));
2359
		}else{
2360
			array_push($result_array, array($temp_string,''));
2361
		}
2362
		return $result_array;
2363
	}
2364
	
2365
	function hex2RGB($hexStr, $returnAsString = false, $seperator = ',') {
2366
	    $hexStr = preg_replace("/[^0-9A-Fa-f]/", '', $hexStr); // Gets a proper hex string
2367
	    $rgbArray = array();
2368
	    if (strlen($hexStr) == 6) { //If a proper hex code, convert using bitwise operation. No overhead... faster
2369
	        $colorVal = hexdec($hexStr);
2370
	        $rgbArray['red'] = 0xFF & ($colorVal >> 0x10);
2371
	        $rgbArray['green'] = 0xFF & ($colorVal >> 0x8);
2372
	        $rgbArray['blue'] = 0xFF & $colorVal;
2373
	    } elseif (strlen($hexStr) == 3) { //if shorthand notation, need some string manipulations
2374
	        $rgbArray['red'] = hexdec(str_repeat(substr($hexStr, 0, 1), 2));
2375
	        $rgbArray['green'] = hexdec(str_repeat(substr($hexStr, 1, 1), 2));
2376
	        $rgbArray['blue'] = hexdec(str_repeat(substr($hexStr, 2, 1), 2));
2377
	    } else {
2378
	        return false; //Invalid hex color code
2379
	    }
2380
	    return $returnAsString ? implode($seperator, $rgbArray) : $rgbArray; // returns the rgb string or the associative array
2381
	}
2382
	
2383
	
2384
	function convert($no, $from='pixels', $to='mm'){
2385
		$output = $no;
2386
		
2387
		if($from == 'pixels' && $to == 'mm'){
2388
			$output = (($no * 25.4) / 72);
2389
		}elseif($from == 'mm' && $to == 'pixels'){
2390
			$output = (($no * 72) / 25.4);
2391
		}
2392
		
2393
		return $output;
2394
	}
2395
	
2396
	
2397

    
2398
}
2399
?>
(2-2/5)