Project import generated by Copybara.
GitOrigin-RevId: 63746295f1a5ab5a619056791995793d65529e62
diff --git a/src/lib/fpdf-easytable/easyTable.php b/src/lib/fpdf-easytable/easyTable.php
new file mode 100755
index 0000000..7a3840a
--- /dev/null
+++ b/src/lib/fpdf-easytable/easyTable.php
@@ -0,0 +1,1017 @@
+<?php
+ /*********************************************************************
+ * FPDF easyTable *
+ * *
+ * Version: 2.0 *
+ * Date: 12-10-2017 *
+ * Author: Dan Machado *
+ * Require exFPDF v2.0 *
+ **********************************************************************/
+
+class easyTable{
+ const LP=0.4;
+ const XPadding=1;
+ const YPadding=1;
+ const IMGPadding=0.5;
+ const PBThreshold=30;
+ static private $table_counter=false;
+ static private $style=array('width'=>false, 'border'=>false, 'border-color'=>false,
+ 'border-width'=>false, 'line-height'=>false,
+ 'align'=>'', 'valign'=>'', 'bgcolor'=>false, 'split-row'=>false, 'l-margin'=>false,
+ 'font-family'=>false, 'font-style'=>false,'font-size'=>false, 'font-color'=>false,
+ 'paddingX'=>false, 'paddingY'=>false);
+ private $pdf_obj;
+ private $document_style;
+ private $table_style;
+ private $col_num;
+ private $col_width;
+ private $baseX;
+ private $row_style_def;
+ private $row_style;
+ private $row_heights;
+ private $row_data;
+ private $rows;
+ private $total_rowspan;
+ private $col_counter;
+ private $grid;
+ private $blocks;
+ private $overflow;
+ private $header_row;
+ private $new_table;
+
+ private function get_available($colspan, $rowspan){
+ static $k=0;
+ if(count($this->grid)==0){
+ $k=0;
+ }
+ while(isset($this->grid[$k])){
+ $k++;
+ }
+ for($i=0; $i<=$colspan; $i++){
+ for($j=0; $j<=$rowspan; $j++){
+ $this->grid[$k+$i+$j*$this->col_num]=true;
+ }
+ }
+ return $k;
+ }
+
+ private function get_style($str, $c){
+ $result=self::$style;
+ if($c=='C'){
+ $result['colspan']=0;
+ $result['rowspan']=0;
+ $result['img']=false;
+ }
+ if($c=='C' || $c=='R'){
+ unset($result['width']);
+ unset($result['border-width']);
+ unset($result['split-row']);
+ unset($result['l-margin']);
+ }
+ if($c=='R' || $c=='T'){
+ if($c=='R'){
+ $result['c-align']=array_pad(array(), $this->col_num, 'L');
+ }
+ else{
+ $result['c-align']=array();
+ }
+ }
+ if($c=='R'){
+ $result['min-height']=false;
+ }
+ $tmp=explode(';', $str);
+ foreach($tmp as $x){
+ if($x && strpos($x,':')>0){
+ $r=explode(':',$x);
+ $r[0]=trim($r[0]);
+ $r[1]=trim($r[1]);
+ if(isset($result[$r[0]])){
+ $result[$r[0]]=$r[1];
+ }
+ }
+ }
+ return $result;
+ }
+
+ private function inherating(&$sty, $setting, $c){
+ if($c=='C'){
+ $sty[$setting]=$this->row_style[$setting];
+ }
+ elseif($c=='R'){
+ $sty[$setting]=$this->table_style[$setting];
+ }
+ else{
+ $sty[$setting]=$this->document_style[$setting];
+ }
+ }
+
+ private function conv_units($x)
+ {
+ if($this->pdf_obj->get_scale_factor()==72/25.4)
+ {
+ return $x;
+ }
+
+ if($this->pdf_obj->get_scale_factor()==72/2.54)
+ {
+ return $x/10;
+ }
+
+ if($this->pdf_obj->get_scale_factor()==72)
+ {
+ return $x/25.4;
+ }
+
+ return $x/0.3527777778;
+ }
+
+ private function set_style($str, $c, $pos=''){
+ $sty=$this->get_style($str, $c);
+ if($c=='T'){
+ if(is_numeric($sty['width'])){
+ $sty['width']=min(abs($sty['width']),$this->document_style['document_width']);
+ if($sty['width']==0){
+ $sty['width']=$this->document_style['document_width'];
+ }
+ }
+ else{
+ $x=strpos($sty['width'], '%');
+ if($x!=false){
+ $x=min(abs(substr($sty['width'], 0, $x)), 100);
+ if($x){
+ $sty['width']=$x*$this->document_style['document_width']/100.0;
+ }
+ else{
+ $sty['width']=$this->document_style['document_width'];
+ }
+ }
+ else{
+ $sty['width']=$this->document_style['document_width'];
+ }
+ }
+ if(!is_numeric($sty['l-margin'])){
+ $sty['l-margin']=0;
+ }
+ else{
+ $sty['l-margin']=abs($sty['l-margin']);
+ }
+ if(is_numeric($sty['border-width'])){
+ $sty['border-width']=abs($sty['border-width']);
+ }
+ else{
+ $sty['border-width']=false;
+ }
+ if($sty['split-row']=='false'){
+ $sty['split-row']=false;
+ }
+ elseif($sty['split-row']!==false){
+ $sty['split-row']=true;
+ }
+ }
+ if($c=='R'){
+ if(!is_numeric($sty['min-height']) || $sty['min-height']<0){
+ $sty['min-height']=0;
+ }
+ }
+ if(!is_numeric($sty['paddingX'])){
+ if($c=='C' || $c=='R'){
+ $this->inherating($sty, 'paddingX', $c);
+ }
+ else{
+ $sty['paddingX']=$this->conv_units(self::XPadding);
+ }
+ }
+ $sty['paddingX']=abs($sty['paddingX']);
+ if(!is_numeric($sty['paddingY'])){
+ if($c=='C' || $c=='R'){
+ $this->inherating($sty, 'paddingY', $c);
+ }
+ else{
+ $sty['paddingY']=$this->conv_units(self::YPadding);
+ }
+ }
+ $sty['paddingY']=abs($sty['paddingY']);
+ if($sty['border']===false && ($c=='C' || $c=='R')){
+ $this->inherating($sty, 'border', $c);
+ }
+ else{
+ $border=array('T'=>1, 'R'=>1, 'B'=>1, 'L'=>1);
+ if(!(is_numeric($sty['border']) && $sty['border']==1)){
+ foreach($border as $k=>$v){
+ $border[$k]=0;
+ if(strpos($sty['border'], $k)!==false){
+ $border[$k]=1;
+ }
+ }
+ }
+ $sty['border']=$border;
+ }
+ $color_settings=array('bgcolor', 'font-color', 'border-color');
+ foreach($color_settings as $setting){
+ if($sty[$setting]===false || !($this->pdf_obj->is_hex($sty[$setting]) || $this->pdf_obj->is_rgb($sty[$setting]))){
+ if($c=='C' || $c=='R'){
+ $this->inherating($sty, $setting, $c);
+ }
+ elseif($setting=='font-color'){
+ $sty[$setting]=$this->document_style[$setting];
+ }
+ }
+ else{
+ $sty[$setting]=$sty[$setting];
+ }
+ }
+ $font_settings=array('font-family', 'font-style', 'font-size');
+ foreach($font_settings as $setting){
+ if($sty[$setting]===false){
+ $this->inherating($sty, $setting, $c);
+ }
+ }
+ if(is_numeric($sty['line-height'])){
+ $sty['line-height']=$this->conv_units(self::LP)*abs($sty['line-height']);
+ }
+ else{
+ if($c=='C' || $c=='R'){
+ $this->inherating($sty,'line-height', $c);
+ }
+ else{
+ $sty['line-height']=$this->conv_units(self::LP);
+ }
+ }
+ if($c=='C'){
+ if($sty['img']){
+ $tmp=explode(',', $sty['img']);
+ if(file_exists($tmp[0])){
+ $sty['img']=array('path'=>'', 'h'=>0, 'w'=>0);
+ $img=@ getimagesize($tmp[0]);
+ $sty['img']['path']=$tmp[0];
+ for($i=1; $i<3; $i++){
+ if(isset($tmp[$i])){
+ $tmp[$i]=trim(strtolower($tmp[$i]));
+ if($tmp[$i][0]=='w' || $tmp[$i][0]=='h'){
+ $t=substr($tmp[$i],1);
+ if(is_numeric($t)){
+ $sty['img'][$tmp[$i][0]]=abs($t);
+ }
+ }
+ }
+ }
+ $ration=$img[0]/$img[1];
+ if($sty['img']['w']+$sty['img']['h']==0){
+ $sty['img']['w']=$img[0];
+ $sty['img']['h']=$img[1];
+ }
+ elseif($sty['img']['w']==0){
+ $sty['img']['w']=$sty['img']['h']*$ration;
+ }
+ elseif($sty['img']['h']==0){
+ $sty['img']['h']=$sty['img']['w']/$ration;
+ }
+ }
+ else{
+ $sty['img']='failed to open stream: file ' . $tmp[0] .' does not exist';
+ }
+ }
+ if(is_numeric($sty['colspan']) && $sty['colspan']>0){
+ $sty['colspan']--;
+ }
+ else{
+ $sty['colspan']=0;
+ }
+ if(is_numeric($sty['rowspan']) && $sty['rowspan']>0){
+ $sty['rowspan']--;
+ }
+ else{
+ $sty['rowspan']=0;
+ }
+ if($sty['valign']==false && ($sty['rowspan']>0 || $sty['img']!==false)){
+ $sty['valign']='M';
+ }
+ if($sty['align']==false && $sty['img']!==false){
+ $sty['align']='C';
+ }
+ }
+ if($c=='T' || $c=='R'){
+ $tmp=explode('{',$sty['align']);
+ if($c=='T'){
+ $sty['align']=trim($tmp[0]);
+ }
+ if(isset($tmp[1])){
+ $tmp[1]=trim($tmp[1], '}');
+ if(strlen($tmp[1])){
+ for($i=0; $i<strlen($tmp[1]); $i++){
+ if(preg_match("/[LCRJ]/", $tmp[1][$i])!=0){
+ $sty['c-align'][$i]=$tmp[1][$i];
+ }
+ else{
+ $sty['c-align'][$i]='L';
+ }
+ }
+ }
+ if($c=='R'){
+ $sty['align']='L';
+ $sty['c-align']=array_slice($sty['c-align'],0,$this->col_num);
+ }
+ }
+ }
+ if($sty['align']!='L' && $sty['align']!='C' && $sty['align']!='R' && $sty['align']!='J'){
+ if($c=='C'){
+ $sty['align']=$this->row_style['c-align'][$pos];
+ }
+ elseif($c=='R'){
+ $sty['align']='L';
+ $sty['c-align']=$this->table_style['c-align'];
+ }
+ else{
+ $sty['align']='C';
+ }
+ }
+ elseif($c=='T' && $sty['align']=='J'){
+ $sty['align']='C';
+ }
+ if($sty['valign']!='T' && $sty['valign']!='M' && $sty['valign']!='B'){
+ if($c=='C' || $c=='R'){
+ $this->inherating($sty, 'valign', $c);
+ }
+ else{
+ $sty['valign']='T';
+ }
+ }
+ return $sty;
+ }
+
+ private function row_content_loop($counter, $f){
+ $t=0;
+ if($counter>0){
+ $t=$this->rows[$counter-1];
+ }
+ for($index=$t; $index<$this->rows[$counter]; $index++){
+ $f($index);
+ }
+ }
+
+ private function mk_border($i, $y, $split){
+ $w=$this->row_data[$i][2];
+ $h=$this->row_data[$i][5];
+ if($split){
+ $h=$this->pdf_obj->PageBreak()-$y;
+ }
+ if($this->row_data[$i][1]['border-color']!=false){
+ $this->pdf_obj->resetColor($this->row_data[$i][1]['border-color'], 'D');
+ }
+ $a=array(1, 1, 1, 0);
+ $borders=array('L'=>3, 'T'=>0, 'R'=>1, 'B'=>2);
+ foreach($borders as $border=>$j){
+ if($this->row_data[$i][1]['border'][$border]){
+ if($border=='B'){
+ if($split==0){
+ $this->pdf_obj->Line($this->row_data[$i][6]+(1+$a[($j+2)%4])%2*$w, $y+(1+$a[($j+1)%4])%2 * $h, $this->row_data[$i][6]+$a[$j%4]*$w, $y+($a[($j+3)%4])%2 *$h);
+ }
+ }
+ else{
+ $this->pdf_obj->Line($this->row_data[$i][6]+(1+$a[($j+2)%4])%2*$w, $y+(1+$a[($j+1)%4])%2 * $h, $this->row_data[$i][6]+$a[$j%4]*$w, $y+($a[($j+3)%4])%2 *$h);
+ }
+ }
+ }
+
+ if($this->row_data[$i][1]['border-color']!=false){
+ $this->pdf_obj->resetColor($this->document_style['bgcolor'], 'D');
+ }
+ if($split){
+ $this->pdf_obj->row_data[$i][1]['border']['T']=0;
+ }
+ }
+
+ private function print_text($i, $y, $split){
+ $padding=$this->row_data[$i][1]['padding-y'];
+ $k=$padding;
+ if($this->row_data[$i][1]['img']!==false){
+ if($this->row_data[$i][1]['valign']=='B'){
+ $k+=$this->row_data[$i][1]['img']['h']+$this->conv_units(self::IMGPadding);
+ }
+ }
+ $l=0;
+ if(count($this->row_data[$i][0])){
+ $x=$this->row_data[$i][6]+$this->row_data[$i][1]['paddingX'];
+ $xpadding=2*$this->row_data[$i][1]['paddingX'];
+ $l=count($this->row_data[$i][0])* $this->row_data[$i][1]['line-height']*$this->row_data[$i][1]['font-size'];
+ $this->pdf_obj->SetXY($x, $y+$k);
+ $this->pdf_obj->CellBlock($this->row_data[$i][2]-$xpadding, $this->row_data[$i][1]['line-height'], $this->row_data[$i][0], $this->row_data[$i][1]['align']);
+ $this->pdf_obj->resetFont($this->document_style['font-family'], $this->document_style['font-style'], $this->document_style['font-size']);
+ $this->pdf_obj->resetColor($this->document_style['font-color'], 'T');
+ }
+ if($this->row_data[$i][1]['img']!==false ){
+ $x=$this->row_data[$i][6];
+ $k=$padding;
+ if($this->row_data[$i][1]['valign']!='B'){
+ $k+=$l+$this->conv_units(self::IMGPadding);
+ }
+ if($this->imgbreak($i, $y)==0 && $y+$k+$this->row_data[$i][1]['img']['h']<$this->pdf_obj->PageBreak()){
+ $x+=$this->row_data[$i][1]['paddingX'];
+ if($this->row_data[$i][2]>$this->row_data[$i][1]['img']['w']){
+ if($this->row_data[$i][1]['align']=='C'){
+ $x-=$this->row_data[$i][1]['paddingX'];
+ $x+=($this->row_data[$i][2]-$this->row_data[$i][1]['img']['w'])/2;
+ }
+ elseif($this->row_data[$i][1]['align']=='R'){
+ $x+=$this->row_data[$i][2]-$this->row_data[$i][1]['img']['w'];
+ $x-=2*$this->row_data[$i][1]['paddingX'];
+ }
+ }
+ $this->pdf_obj->Image($this->row_data[$i][1]['img']['path'], $x, $y+$k, $this->row_data[$i][1]['img']['w'], $this->row_data[$i][1]['img']['h']);
+ $this->row_data[$i][1]['img']=false;
+ }
+ }
+ }
+
+
+ private function mk_bg($i, $T, $split){
+ $h=$this->row_data[$i][5];
+ if($split){
+ $h=$this->pdf_obj->PageBreak()-$T;
+ }
+ if($this->row_data[$i][1]['bgcolor']!=false){
+ $this->pdf_obj->resetColor($this->row_data[$i][1]['bgcolor']);
+ $this->pdf_obj->Rect($this->row_data[$i][6], $T, $this->row_data[$i][2], $h, 'F');
+ $this->pdf_obj->resetColor($this->document_style['bgcolor']);
+ }
+ }
+
+ private function printing_loop($swap=false){
+ $this->swap_data($swap);
+ $y=$this->pdf_obj->GetY();
+ $tmp=array();
+ $rw=array();
+ $ztmp=array();
+ $total_cells=count($this->row_data);
+ while(count($tmp)!=$total_cells){
+ $a=count($this->rows);
+ $h=0;
+ $y=$this->pdf_obj->GetY();
+ for($j=0; $j<count($this->rows); $j++){
+ $T=$y+$h;
+ if($T<$this->pdf_obj->PageBreak()){
+
+ $this->row_content_loop($j, function($index)use($T, $tmp){
+ if(!isset($tmp[$index])){
+ $split_cell=$this->scan_for_breaks($index,$T, false);
+ $this->mk_bg($index, $T, $split_cell);
+ }
+ });
+ if(!isset($rw[$j])){
+ if($this->pdf_obj->PageBreak()-($T+$this->row_heights[$j])>=0){
+ $h+=$this->row_heights[$j];
+ }
+ else{
+ $a=$j+1;
+ break;
+ }
+ }
+ }
+ else{
+ $a=$j+1;
+ break;
+ }
+ }
+ $h=0;
+ for($j=0; $j<$a; $j++){
+ $T=$y+$h;
+ if($T<$this->pdf_obj->PageBreak()){
+
+ $this->row_content_loop($j, function($index)use($T, &$tmp, &$ztmp){
+ if(!isset($tmp[$index])){
+ $split_cell=$this->scan_for_breaks($index,$T);
+ $this->mk_border($index, $T, $split_cell);
+ $this->print_text($index, $T, $split_cell);
+ if($split_cell==0){
+ $tmp[$index]=$index;
+ }
+ else{
+ $ztmp[]=$index;
+ }
+ }
+ });
+ if(!isset($rw[$j])){
+ $tw=$this->pdf_obj->PageBreak()-($T+$this->row_heights[$j]);
+ if($tw>=0){
+ $h+=$this->row_heights[$j];
+ $rw[$j]=$j;
+ }
+ else{
+ $this->row_heights[$j]=$this->overflow-$tw;
+ }
+ }
+ }
+ }
+ if(count($tmp)!=$total_cells){
+ foreach($ztmp as $index){
+ $this->row_data[$index][5]=$this->row_data[$index][7]+$this->overflow;
+ if(isset($this->row_data[$index][8])){
+ $this->row_data[$index][1]['padding-y']=$this->row_data[$index][8];
+ unset($this->row_data[$index][8]);
+ }
+ }
+ $this->overflow=0;
+ $ztmp=array();
+ $this->pdf_obj->addPage($this->document_style['orientation'], $this->pdf_obj->get_page_size(), $this->pdf_obj->get_rotation());
+ }
+ else{
+ $y+=$h;
+ }
+ }
+ $this->pdf_obj->SetXY($this->baseX, $y);
+ $this->swap_data($swap);
+ }
+
+ private function imgbreak($i, $y){
+ $li=$y+$this->row_data[$i][1]['padding-y'];
+ $ls=$this->row_data[$i][1]['img']['h'];
+ if($this->row_data[$i][1]['valign']=='B'){
+ $ls+=$li;
+ }
+ else{
+ $li+=$this->row_data[$i][3]-$this->row_data[$i][1]['img']['h'];
+ $ls+=$li;
+ }
+ $result=0;
+ if($li<$this->pdf_obj->PageBreak() && $this->pdf_obj->PageBreak()<$ls){
+ $result=$this->pdf_obj->PageBreak()-$li;
+ }
+ return $result;
+ }
+
+ private function scan_for_breaks($index, $H, $l=true){
+ $print_cell=0;
+ $h=($H+$this->row_data[$index][5])-$this->pdf_obj->PageBreak();
+ if($h>0){
+ if($l){
+ $rr=$this->pdf_obj->PageBreak()-($H+$this->row_data[$index][1]['padding-y']);
+ if($rr>0){
+ $mx=0;
+ if(count($this->row_data[$index][0]) && $this->row_data[$index][1]['img']!==false){
+ $mx=$this->imgbreak($index, $H);
+ if($mx==0){
+ if($this->row_data[$index][1]['valign']=='B'){
+ $rr-=$this->row_data[$index][1]['img']['h'];
+ }
+ }
+ }
+ $nh=0;
+ $keys=array_keys($this->row_data[$index][0]);
+ foreach($keys as $i){
+ $nh+=$this->row_data[$index][0][$i]['height'];
+ }
+ $nh*=$this->row_data[$index][1]['line-height'];
+ if($mx==0){
+ if($rr<$nh && $rr>0){
+ $nw=0;
+ foreach($keys as $i){
+ $nw+=$this->row_data[$index][0][$i]['height']*$this->row_data[$index][1]['line-height'];
+ if($nw>$rr){
+ $nw-=$this->row_data[$index][0][$i]['height']*$this->row_data[$index][1]['line-height'];
+ $mx=$rr-$nw;
+ break;
+ }
+ }
+ }
+ else{
+ if($rr< $this->row_data[$index][1]['img']['h']){
+ $mx=$this->row_data[$index][1]['img']['h'];
+ }
+ }
+ }
+ $this->overflow=max($this->overflow, $mx);
+ $this->row_data[$index][8]=1;
+ }
+ else{
+ $this->row_data[$index][8]=-1*$rr;
+ }
+ $this->row_data[$index][7]=$h;
+ }
+ $print_cell=1;
+ }
+ return $print_cell;
+ }
+
+ private function swap_data($swap){
+ if($swap==false){
+ return;
+ }
+ static $data=array();
+ if(count($data)==0){
+ $data=array('header_data'=>$this->header_row['row_data'], 'row_heights'=>&$this->row_heights, 'row_data'=>&$this->row_data, 'rows'=>&$this->rows);
+ unset($this->row_heights, $this->row_data, $this->rows);
+ $this->row_heights=&$this->header_row['row_heights'];
+ $this->row_data=&$this->header_row['row_data'];
+ $this->rows=&$this->header_row['rows'];
+ }
+ else{
+ $this->header_row['row_data']=$data['header_data'];
+ unset($this->row_heights, $this->row_data, $this->rows);
+ $this->row_heights=$data['row_heights'];
+ $this->row_data=$data['row_data'];
+ $this->rows=$data['rows'];
+ $data=array();
+ }
+ }
+ /********************************************************************
+
+ function __construct( FPDF-object $fpdf_obj, Mix $num_cols[, string $style = '' ])
+ -----------------------------------------------------
+ Description:
+ Constructs an easyTable object
+ Parameters:
+ fpdf_obj
+ the current FPDF object (constructed with the FPDF library)
+ that is being used to write the current PDF document
+ num_cols
+ this parameter can be a positive integer (the number of columns)
+ or a string of the following form
+ I) a positive integer, the number of columns for the table. The width
+ of every column will be equal to the width of the table (given by the width property)
+ divided by the number of columns ($num_cols)
+ II) a string of the form '{c1, c2, c3,... cN}'. In this case every
+ element in the curly brackets is a positive numeric value that represent
+ the width of a column. Thus, the n-th numeric value is the width
+ of the n-th colum. If the sum of all the width of the columns is bigger than
+ the width of the table but less than the width of the document, the table
+ will stretch to the sum of the columns width. However, if the sum of the
+ columns is bigger than the width of the document, the width of every column
+ will be reduce proportionally to make the total sum equal to the width of the document.
+ III) a string of the form '%{c1, c2, c3,... cN}'. Similar to the previous case, but
+ this time every element represents a percentage of the width of the table.
+ In this case it the sum of this percentages is bigger than 100, the execution will
+ be terminated.
+ style
+ the global style for the table (see documentation)
+ a semicolon-separated string of attribute values that defines the
+ default layout of the table and all the cells and their contents
+ (see Documentation section in README.md)
+ Examples:
+ $table= new easyTable($fpdf, 3);
+ $table= new easyTable($fpdf, '{35, 45, 55}', 'width:135;');
+ $table= new easyTable($fpdf, '%{35, 45, 55}', 'width:190;');
+ Return value:
+ An easyTable object
+ ***********************************************************************/
+
+ public function __construct($fpdf_obj, $num_cols, $style=''){
+ if(self::$table_counter){
+ error_log('Please use the end_table method to terminate the last table');
+ exit();
+ }
+ self::$table_counter=true;
+ $this->pdf_obj=&$fpdf_obj;
+ $this->document_style['bgcolor']=$this->pdf_obj->get_color('fill');
+ $this->document_style['font-family']=$this->pdf_obj->current_font('family');
+ $this->document_style['font-style']=$this->pdf_obj->current_font('style');
+ $this->document_style['font-size']=$this->pdf_obj->current_font('size');
+ $this->document_style['font-color']=$this->pdf_obj->get_color('text');
+ $this->document_style['document_width']=$this->pdf_obj->GetPageWidth()-$this->pdf_obj->get_margin('l')-$this->pdf_obj->get_margin('r');
+ $this->document_style['orientation']=$this->pdf_obj->get_orientation();
+ $this->document_style['line-width']=$this->pdf_obj->get_linewidth();
+ $this->table_style=$this->set_style($style, 'T');
+ $this->col_num=false;
+ $this->col_width=array();
+ if(is_int($num_cols) && $num_cols!=0){
+ $this->col_num=abs($num_cols);
+ $this->col_width=array_pad(array(), abs($num_cols), $this->table_style['width']/abs($num_cols));
+ }
+ elseif(is_string($num_cols)){
+ $num_cols=trim($num_cols, '}, ');
+ if($num_cols[0]!='{' && $num_cols[0]!='%'){
+ error_log('Bad format for columns in Table constructor');
+ exit();
+ }
+ $tmp=explode('{', $num_cols);
+ $tp=trim($tmp[0]);
+ $num_cols=explode(',', $tmp[1]);
+ $w=0;
+ foreach($num_cols as $c){
+ if(!is_numeric($c)){
+ error_log('Bad parameter format for columns in Table constructor');
+ exit();
+ }
+ if(abs($c)){
+ $w+=abs($c);
+ $this->col_width[]=abs($c);
+ }
+ else{
+ error_log('Column width can not be zero');
+ }
+ }
+ $this->col_num=count($this->col_width);
+ if($tp=='%'){
+ if($w!=100){
+ error_log('The sum of the percentages of the columns is not 100');
+ exit();
+ }
+ foreach($this->col_width as $i=>$c){
+ $this->col_width[$i]=$c*$this->table_style['width']/100;
+ }
+ }
+ elseif($w!=$this->table_style['width'] && $w){
+ if($w<$this->document_style['document_width']){
+ $this->table_style['width']=$w;
+ }
+ else{
+ $this->table_style['width']=$this->document_style['document_width'];
+ $d=$this->table_style['width']/$w;
+ for($i=0; $i<count($num_cols); $i++){
+ $this->col_width[$i]*=$d;
+ }
+ }
+ }
+ }
+ if($this->col_num==false){
+ error_log('Unspecified number of columns in Table constructor');
+ exit();
+ }
+ $this->table_style['c-align']=array_pad($this->table_style['c-align'], $this->col_num, 'L');
+ if($this->table_style['l-margin']){
+ $this->baseX=$this->pdf_obj->get_margin('l')+min($this->table_style['l-margin'],$this->document_style['document_width']-$this->table_style['width']);
+ }
+ else{
+ if($this->table_style['align']=='L'){
+ $this->baseX=$this->pdf_obj->get_margin('l');
+ }
+ elseif($this->table_style['align']=='R'){
+ $this->baseX=$this->pdf_obj->get_margin('l')+$this->document_style['document_width']-$this->table_style['width'];
+ }
+ else{
+ $this->baseX=$this->pdf_obj->get_margin('l')+($this->document_style['document_width']-$this->table_style['width'])/2;
+ }
+ }
+ $this->row_style_def=$this->set_style('', 'R');
+ $this->row_style=$this->row_style_def;
+ $this->row_heights=array();
+ $this->row_data=array();
+ $this->rows=array();
+ $this->total_rowspan=0;
+ $this->col_counter=0;
+ $this->grid=array();
+ $this->blocks=array();
+ $this->overflow=0;
+ if($this->table_style['border-width']!=false){
+ $this->pdf_obj->SetLineWidth($this->table_style['border-width']);
+ }
+ $this->header_row=array();
+ $this->new_table=true;
+ }
+ /***********************************************************************
+
+ function rowStyle( string $style )
+ -------------------------------------------------------------
+ Description:
+ Set or overwrite the style for all the cells in the current row.
+ Parameters:
+ style
+ a semicolon-separated string of attribute values that defines the
+ layout of all the cells and its content in the current row
+ (see Documentation section in README.md)
+ Return values
+ Void
+ Notes:
+
+ This function should be called before the first cell of the current row
+ ***********************************************************************/
+
+ public function rowStyle($style){
+ $this->row_style=$this->set_style($style, 'R');
+ }
+ /***********************************************************************
+
+ function easyCell( string $data [, string $style = '' ])
+ ------------------------------------------------------------------------
+ Description:
+ Makes a cell in the table
+ Parameters:
+ data
+ the content of the respective cell
+ style (optional)
+ a semicolon-separated string of attribute values that defines the
+ layout of the cell and its content (see Documentation section in README.md)
+ Return value
+ void
+ ***********************************************************************/
+
+ public function easyCell($data, $style=''){
+ if($this->col_counter<$this->col_num){
+ $sty=$this->set_style($style, 'C', $this->col_counter);
+ $this->col_counter++;
+ $row_number=count($this->rows);
+ $cell_index=count($this->row_data);
+ $cell_pos=$this->get_available($sty['colspan'], $sty['rowspan']);
+ $colm=$cell_pos %$this->col_num;
+ if($sty['img']!=false && $data!='' && $sty['valign']=='M'){
+ $sty['valign']=$this->row_style['valign'];
+ }
+ if($sty['rowspan']){
+ $this->total_rowspan=max($this->total_rowspan, $sty['rowspan']);
+ $this->blocks[$cell_index]=array($cell_index, $row_number, $sty['rowspan']);
+ }
+ $w=$this->col_width[$colm];
+ $r=0;
+ while($r<$sty['colspan'] && $this->col_counter<$this->col_num){
+ $this->col_counter++;
+ $colm++;
+ $w+=$this->col_width[$colm];
+ $r++;
+ }
+ $w-=2*$sty['paddingX'];
+ if($sty['img']!==false && is_string($sty['img'])){
+ $data=$sty['img'];
+ $sty['img']=false;
+ }
+ $data=& $this->pdf_obj->extMultiCell($sty['font-family'], $sty['font-style'], $sty['font-size'], $sty['font-color'], $w, $data);
+ $h=0;
+ $rn=count($data);
+ for($ri=0; $ri<$rn; $ri++){
+ $h+=$data[$ri]['height']*$sty['line-height'];
+ }
+ if($sty['img']){
+ if($sty['img']['w']>$w){
+ $sty['img']['h']=$w*$sty['img']['h']/$sty['img']['w'];
+ $sty['img']['w']=$w;
+ }
+ if($h){
+ $h+=$this->conv_units(self::IMGPadding);
+ }
+ $h+=$sty['img']['h'];
+ }
+ $w+=2*$sty['paddingX'];
+
+ $posx=$this->baseX;
+ $d=$cell_pos %$this->col_num;
+ for($k=0; $k<$d; $k++){
+ $posx+=$this->col_width[$k];
+ }
+ $this->row_data[$cell_index]=array($data, $sty, $w, $h, $cell_pos, 0, $posx, 0);
+
+ }
+ }
+ /***********************************************************************
+
+ function printRow ( [ bool $setAsHeader = false ] )
+ ------------------------------------------------------------------------
+ Description:
+
+ This function indicates the end of the current row.
+ Parameters:
+ setAsHeader (optional)
+ Optional. When it is set as true, it sets the current row as the header
+ for the table; this means that the current row will be printed as the first
+ row of the table (table header) on every page that the table splits on.
+ Remark: 1. In order to work, the table attribute split-row should set as true.
+ 2. Just the first row where this parameter is set as true will be
+ used as header any other will printed as a normal row.
+ Return values
+ Void
+ Note:
+
+ This function will print the current row as far as the following holds:
+ total_rowspan=0
+ where total_rowspan is set as
+ total_rowspan=max(total_rowspan, max(rowspan of cell in the current row))-1;
+ ***********************************************************************/
+
+ public function printRow($setAsHeader=false){
+ $this->col_counter=0;
+ $row_number=count($this->rows);
+ $this->rows[$row_number]=count($this->row_data);
+ $mx=$this->row_style['min-height'];
+
+ $this->row_content_loop($row_number, function($index)use(&$mx){
+ if($this->row_data[$index][1]['rowspan']==0){
+ $mx=max($mx, $this->row_data[$index][3]+2*$this->row_data[$index][1]['paddingY']);
+ }
+ });
+ $this->row_heights[$row_number]=$mx;
+
+ if($this->total_rowspan>0){
+ $this->total_rowspan--;
+ }
+ else{
+ $row_number=count($this->rows);
+ if(count($this->blocks)>0){
+
+ foreach($this->blocks as $bk_id=>$block){
+ $h=0;
+ for($i=$block[1]; $i<=$block[1]+$block[2]; $i++){
+ $h+=$this->row_heights[$i];
+ }
+ $t=$this->row_data[$block[0]][3]+2*$this->row_data[$block[0]][1]['paddingY'];
+ if($h>0 && $h<$t){
+ for($i=$block[1]; $i<=$block[1]+$block[2]; $i++){
+ $this->row_heights[$i]*=$t/$h;
+ }
+ }
+ }
+ foreach($this->blocks as $j=>$block){
+ $h=0;
+ for($i=$block[1]; $i<=$block[1]+$block[2]; $i++){
+ $h+=$this->row_heights[$i];
+ }
+ $this->row_data[$j][5]=$h;
+ }
+ }
+ $block_height=0;
+ for($j=0; $j<$row_number; $j++){
+
+ $this->row_content_loop($j, function($index)use($j, $block_height){
+ if($this->row_data[$index][1]['rowspan']==0){
+ $this->row_data[$index][5]=$this->row_heights[$j];
+ }
+ $this->row_data[$index][1]['padding-y']=$this->row_data[$index][1]['paddingY'];
+ if($this->row_data[$index][1]['valign']=='M' || ($this->row_data[$index][1]['img'] && count($this->row_data[$index][0]))){
+ $this->row_data[$index][1]['padding-y']=($this->row_data[$index][5]-$this->row_data[$index][3])/2;
+ }
+ elseif($this->row_data[$index][1]['valign']=='B'){
+ $this->row_data[$index][1]['padding-y']=$this->row_data[$index][5]-($this->row_data[$index][3]+$this->row_data[$index][1]['paddingY']);
+ }
+ });
+ $block_height+=$this->row_heights[$j];
+ }
+
+ $rowIsHeader=1+(count($this->header_row)>0);
+ if($setAsHeader===true){
+ if(count($this->header_row)==0){
+ $this->header_row['row_heights']=$this->row_heights;
+ $this->header_row['row_data']=$this->row_data;
+ $this->header_row['rows']=$this->rows;
+ }
+ }
+ if($this->table_style['split-row']==false && $this->pdf_obj->PageBreak()<$this->pdf_obj->GetY()+max($block_height,$this->row_heights[0])){
+ $this->pdf_obj->addPage($this->document_style['orientation'], $this->pdf_obj->get_page_size(), $this->pdf_obj->get_rotation());
+ if(count($this->header_row)>0){
+ $this->printing_loop(true);
+ $rowIsHeader--;
+ }
+ }
+
+ if($this->new_table){
+ if(count($this->header_row)>0){
+ $r=$this->pdf_obj->PageBreak()-($this->pdf_obj->GetY()+$block_height);
+ if($r<0 || $r<$this->conv_units(self::PBThreshold)){
+ $this->pdf_obj->addPage($this->document_style['orientation'], $this->pdf_obj->get_page_size(), $this->pdf_obj->get_rotation());
+ }
+ }
+ $this->new_table=false;
+ }
+ if($rowIsHeader>0){
+ $this->printing_loop();
+ }
+ $this->grid=array();
+ $this->row_data=array();
+ $this->rows=array();
+ $this->row_heights=array();
+ $this->blocks=array();
+ $this->overflow=0;
+ $this->new_table=false;
+ }
+ $this->row_style=$this->row_style_def;
+ }
+ /***********************************************************************
+
+ function endTable( [int $bottomMargin=2])
+ ------------------------------------------
+ Description:
+ Unset all the data members of the easyTable object
+ Parameters:
+ bottomMargin (optional)
+ Optional. Specify the number of white lines left after
+ the last row of the table. Default 2.
+ If it is negative, the vertical position will be set before
+ the end of the table.
+ Return values
+ Void
+ ***********************************************************************/
+
+ public function endTable($bottomMargin=2){
+ self::$table_counter=false;
+ if($this->table_style['border-width']!=false){
+ $this->pdf_obj->SetLineWidth($this->document_style['line-width']);
+ }
+ $this->pdf_obj->SetX($this->pdf_obj->get_margin('l'));
+ $this->pdf_obj->Ln($bottomMargin);
+ $this->pdf_obj->resetStaticData();
+ unset($this->pdf_obj);
+ unset($this->document_style);
+ unset($this->table_style);
+ unset($this->col_num);
+ unset($this->col_width);
+ unset($this->baseX);
+ unset($this->row_style_def);
+ unset($this->row_style);
+ unset($this->row_heights);
+ unset($this->row_data);
+ unset($this->rows);
+ unset($this->total_rowspan);
+ unset($this->col_counter);
+ unset($this->grid);
+ unset($this->blocks);
+ unset($this->overflow);
+ unset($this->header_row);
+ }
+
+}
+?>