<?php
class PHPJasperXML{
private $adjust=1.2;
public function PHPJasperXML()
{	

	
}

public function connect($db_host,$db_user,$db_pass,$db_name)
{
 	 if(!$this->con)  
         { 
             $myconn = @mysql_connect($db_host,$db_user,$db_pass);  
	     if($myconn)  
             {   
                 $seldb = @mysql_select_db($db_name,$myconn);  
                 if($seldb)  
                 {  
                     $this->con = true;   
                     return true;   
                 }
		 else  
                 {  
                     return false;   
                 }  
             } else  
             {  
                 return false;   
             }  
         } else  
         {  
             return true;   
         }  
}

public function disconnect()  
    {  
        if($this->con)  
        {  
            if(@mysql_close())  
            {  
                           $this->con = false;   
                return true;   
            }  
           else  
           {  
              return false;   
           }  
       }  
   }     

public function xml_dismantle($xml)
{	
	$this->page_setting($xml);
	foreach ($xml as $k=>$out)
	{
	switch($k)
	 {
	    case "parameter":
		$this->parameter_handler($out);
		break;
	    case "queryString":
		$this->queryString_handler($out);
		break;
	    case "field":
		$this->field_handler($out);
		break;
	    case "variable":
		$this->variable_handler($out);
		break;
	    case "group":
		$this->group_handler($out);
		break;
	    case "background":
		$this->pointer=&$this->arraybackground;
		$this->pointer[]=array("height"=>$out->band[height],"splitType"=>$out->band[splitType]);
		foreach ($out as $bg)
		{
		$this->default_handler($bg);
		}
		break;
	    default:
		foreach ($out as $object)
		{
		eval("\$this->pointer=&"."\$this->array$k".";");
		$this->arrayband[]=array("name"=>$k);
		$this->pointer[]=array("type"=>"band","height"=>$object[height],"splitType"=>$object[splitType],"y_axis"=>$this->y_axis);
		$this->default_handler($object);}
		$this->y_axis=$this->y_axis+$out->band[height];	//after handle , then adjust y axis
		break;
	     
	 }
	
	}
}

public function page_setting($xml_path)		//read level 0,Jasperreport page setting
{
	$this->arrayPageSetting[orientation]="P";
	$this->arrayPageSetting[name]=$xml_path[name];
	$this->arrayPageSetting[language]=$xml_path[language];
	$this->arrayPageSetting[pageWidth]=$xml_path[pageWidth];
	$this->arrayPageSetting[pageHeight]=$xml_path[pageHeight];
	if(isset($xml_path[orientation])){$this->arrayPageSetting[orientation]=substr($xml_path[orientation],0,1);}
	$this->arrayPageSetting[columnWidth]=$xml_path[columnWidth];
	$this->arrayPageSetting[leftMargin]=$xml_path[leftMargin];
	$this->arrayPageSetting[rightMargin]=$xml_path[rightMargin];
	$this->arrayPageSetting[topMargin]=$xml_path[topMargin];	$this->y_axis=$xml_path[topMargin];
	$this->arrayPageSetting[bottomMargin]=$xml_path[bottomMargin];
}


public function parameter_handler($xml_path)
{
	$this->arrayParameter["$xml_path[name]"];
}

public function queryString_handler($xml_path)
{
		$this->sql =$xml_path;
		if(isset($this->arrayParameter))
		{
			foreach($this->arrayParameter as  $v => $a)
			{
			   $this->sql = str_replace('$P{'.$v.'}', $a, $this->sql);
			}
		}
}

public function field_handler($xml_path)
{
	$this->arrayfield[]=$xml_path[name];
}

public function variable_handler($xml_path)
{	
	$this->arrayVariable["$xml_path[name]"]=array("calculation"=>$xml_path[calculation],"target"=>substr($xml_path->variableExpression,3,-1),"class"=>$xml_path['class']);
}

public function group_handler($xml_path)
{
	$this->arrayband[]=array("gname"=>$xml_path[name],"isStartNewPage"=>$xml_path[isStartNewPage],"groupExpression"=>substr($xml_path->groupExpression,3,-1),"name"=>"group");
		foreach($xml_path as $tag=>$out)
		{	
		switch ($tag)
		{
		case (groupHeader):
		$this->pointer=&$this->arraygroup["$xml_path[name]"][groupHeader];
		$this->pointer[]=array("type"=>"band","height"=>$out->band[height]+0,"y_axis"=>"","groupExpression"=>substr($xml_path->groupExpression,3,-1));
			foreach($out as $band)
			{
			$this->default_handler($band);
			}
		$this->y_axis=$this->y_axis+$out->band[height];		//after handle , then adjust y axis 
		break;
		case (groupFooter):
		$this->pointer=&$this->arraygroup["$xml_path[name]"][groupFooter];
		$this->pointer[]=array("type"=>"band","height"=>$out->band[height]+0,"y_axis"=>"","groupExpression"=>substr($xml_path->groupExpression,3,-1));
			foreach($out as $band)
			{
			$this->default_handler($band);
			}
		break;
		default:
		break;
		}
	
	}
}

public function default_handler($xml_path)
{
	foreach($xml_path as $k=>$out)
	{
	
	switch($k)
	 {
	    case "staticText":
		$this->element_staticText($out);
		break;
	    case "image":
		$this->element_image($out);
		break;
	    case "line":
		$this->element_line($out);
		break;
	    case "rectangle":
		$this->element_rectangle($out);
		break;
	    case "textField":
		$this->element_textField($out);
		break;
	    default:
		break;
	 }
	};
}

public function element_staticText($data)
{
	$align="L";	$fill=0;	$border=0;	$fontsize=10;	$font="helvetica";	$fontstyle="";
	$textcolor = array("r"=>0,"g"=>0,"b"=>0);	$fillcolor = array("r"=>255,"g"=>255,"b"=>255);	$txt="";
	$drawcolor=array("r"=>0,"g"=>0,"b"=>0);	$height=$data->reportElement[height];
	$stretchoverflow="true";		$printoverflow="false";
	if(isset($data->reportElement[forecolor]))
	{$textcolor = array("r"=>hexdec(substr($data->reportElement[forecolor],1,2)),"g"=>hexdec(substr($data->reportElement[forecolor],3,2)),"b"=>hexdec(substr($data->reportElement[forecolor],5,2)));}
	if(isset($data->reportElement[backcolor]))
	{$fillcolor = array("r"=>hexdec(substr($data->reportElement[backcolor],1,2)),"g"=>hexdec(substr($data->reportElement[backcolor],3,2)),"b"=>hexdec(substr($data->reportElement[backcolor],5,2)));
	}
	if($data->reportElement[mode]=="Opaque"){$fill=1;}
	if(isset($data[isStretchWithOverflow])&&$data[isStretchWithOverflow]=="true"){$stretchoverflow="true";}
	if(isset($data->reportElement[isPrintWhenDetailOverflows])&&$data->reportElement[isPrintWhenDetailOverflows]=="true"){$printoverflow="true"; $stretchoverflow="false";}
	if((isset($data->box))&&($data->box->pen[lineWidth]>0))
	{$border=1;
		if(isset($data->box->pen[lineColor]))
		{$drawcolor=array("r"=>hexdec(substr($data->box->pen[lineColor],1,2)),"g"=>hexdec(substr($data->box->pen[lineColor],3,2)),"b"=>hexdec(substr($data->box->pen[lineColor],5,2)));}
	}
	if(isset($data->textElement[textAlignment])){$align=$this->get_first_value($data->textElement[textAlignment]);}
	if(isset($data->textElement->font[pdfFontName])){$font=$data->textElement->font[pdfFontName];}
	if(isset($data->textElement->font[size])){$fontsize=$data->textElement->font[size];}	
	if(isset($data->textElement->font[isBold])&&$data->textElement->font[isBold]=="true"){$fontstyle=$fontstyle."B";}
	if(isset($data->textElement->font[isItalic])&&$data->textElement->font[isItalic]=="true"){$fontstyle=$fontstyle."I";}
	if(isset($data->textElement->font[isUnderline])&&$data->textElement->font[isUnderline]=="true"){$fontstyle=$fontstyle."U";}
	if(isset($data->reportElement[key])){$height=$fontsize*$this->adjust;}
	$this->pointer[]=array("type"=>"SetXY","x"=>$data->reportElement[x],"y"=>$data->reportElement[y],"hidden_type"=>"SetXY");
	$this->pointer[]=array("type"=>"SetTextColor","r"=>$textcolor[r],"g"=>$textcolor[g],"b"=>$textcolor[b],"hidden_type"=>"textcolor");
	$this->pointer[]=array("type"=>"SetDrawColor","r"=>$drawcolor[r],"g"=>$drawcolor[g],"b"=>$drawcolor[b],"hidden_type"=>"drawcolor");	
	$this->pointer[]=array("type"=>"SetFillColor","r"=>$fillcolor[r],"g"=>$fillcolor[g],"b"=>$fillcolor[b],"hidden_type"=>"fillcolor");
	$this->pointer[]=array("type"=>"SetFont","font"=>$font,"fontstyle"=>$fontstyle,"fontsize"=>$fontsize,"hidden_type"=>"font");
	//"height"=>$data->reportElement[height]
	$this->pointer[]=array("type"=>"MultiCell","width"=>$data->reportElement[width],"height"=>$height,"txt"=>$data->text,"border"=>$border,"align"=>$align,"fill"=>$fill,"hidden_type"=>"statictext","soverflow"=>$stretchoverflow,"poverflow"=>$printoverflow);

}

public function element_image($data)
{
	$imagepath=$data->imageExpression;
	//$imagepath= substr($data->imageExpression, 1, -1);
	//$imagetype= substr($imagepath,-3);

	switch($data[scaleImage])
	{
	case "FillFrame":
	$this->pointer[]=array("type"=>"Image","path"=>$imagepath,"x"=>$data->reportElement[x]+0,"y"=>$data->reportElement[y]+0,"width"=>$data->reportElement[width]+0,"height"=>$data->reportElement[height]+0,"imgtype"=>$imagetype,"link"=>substr($data->hyperlinkReferenceExpression,1,-1),"hidden_type"=>"image");
	break;
	default:
	$this->pointer[]=array("type"=>"Image","path"=>$imagepath,"x"=>$data->reportElement[x]+0,"y"=>$data->reportElement[y]+0,"width"=>$data->reportElement[width]+0,"height"=>$data->reportElement[height]+0,"imgtype"=>$imagetype,"link"=>substr($data->hyperlinkReferenceExpression,1,-1),"hidden_type"=>"image");
	break;
	}
}

public function element_line($data)
{	//default line width=0.567(no detect line width)
	$drawcolor=array("r"=>0,"g"=>0,"b"=>0); $hidden_type="line";
	if(isset($data->reportElement[forecolor]))
	{$drawcolor=array("r"=>hexdec(substr($data->reportElement[forecolor],1,2)),"g"=>hexdec(substr($data->reportElement[forecolor],3,2)),"b"=>hexdec(substr($data->reportElement[forecolor],5,2)));}
	$this->pointer[]=array("type"=>"SetDrawColor","r"=>$drawcolor[r],"g"=>$drawcolor[g],"b"=>$drawcolor[b],"hidden_type"=>"drawcolor");	
	if(isset($data->reportElement[positionType])&&$data->reportElement[positionType]=="FixRelativeToBottom")
	{$hidden_type="relativebottomline";}
	if($data->reportElement[width][0]+0 > $data->reportElement[height][0]+0)	//width > height means horizontal line
	{$this->pointer[]=array("type"=>"Line", "x1"=>$data->reportElement[x],"y1"=>$data->reportElement[y],"x2"=>$data->reportElement[x]+$data->reportElement[width],"y2"=>$data->reportElement[y]+$data->reportElement[height]-1,"hidden_type"=>$hidden_type);}
	elseif($data->reportElement[height][0]+0>$data->reportElement[width][0]+0)		//vertical line
	{$this->pointer[]=array("type"=>"Line", "x1"=>$data->reportElement[x],"y1"=>$data->reportElement[y],"x2"=>$data->reportElement[x]+$data->reportElement[width]-1,"y2"=>$data->reportElement[y]+$data->reportElement[height],"hidden_type"=>$hidden_type);}
	$this->pointer[]=array("type"=>"SetDrawColor","r"=>0,"g"=>0,"b"=>0,"hidden_type"=>"drawcolor");
}

public function element_rectangle($data)
{
	$drawcolor=array("r"=>0,"g"=>0,"b"=>0);
	if(isset($data->reportElement[forecolor]))
	{$drawcolor=array("r"=>hexdec(substr($data->reportElement[forecolor],1,2)),"g"=>hexdec(substr($data->reportElement[forecolor],3,2)),"b"=>hexdec(substr($data->reportElement[forecolor],5,2)));}
	$this->pointer[]=array("type"=>"SetDrawColor","r"=>$drawcolor[r],"g"=>$drawcolor[g],"b"=>$drawcolor[b],"hidden_type"=>"drawcolor");
	$this->pointer[]=array("type"=>"Rect","x"=>$data->reportElement[x],"y"=>$data->reportElement[y],"width"=>$data->reportElement[width],"height"=>$data->reportElement[height],"hidden_type"=>"rect");
	$this->pointer[]=array("type"=>"SetDrawColor","r"=>0,"g"=>0,"b"=>0,"hidden_type"=>"drawcolor");
}

public function element_textField($data)
{
	$align="L";	$fill=0;	$border=0;	$fontsize=10;	$font="helvetica";	$fontstyle="";
	$textcolor = array("r"=>0,"g"=>0,"b"=>0);	$fillcolor = array("r"=>255,"g"=>255,"b"=>255);
	$stretchoverflow="false";		$printoverflow="false";	$height=$data->reportElement[height];
	$drawcolor=array("r"=>0,"g"=>0,"b"=>0);
	if(isset($data->reportElement[forecolor]))
	{$textcolor = array("r"=>hexdec(substr($data->reportElement[forecolor],1,2)),"g"=>hexdec(substr($data->reportElement[forecolor],3,2)),"b"=>hexdec(substr($data->reportElement[forecolor],5,2)));}
	if(isset($data->reportElement[backcolor]))
	{$fillcolor = array("r"=>hexdec(substr($data->reportElement[backcolor],1,2)),"g"=>hexdec(substr($data->reportElement[backcolor],3,2)),"b"=>hexdec(substr($data->reportElement[backcolor],5,2)));}
	if($data->reportElement[mode]=="Opaque"){$fill=1;}
	if(isset($data[isStretchWithOverflow])&&$data[isStretchWithOverflow]=="true"){$stretchoverflow="true";}
	if(isset($data->reportElement[isPrintWhenDetailOverflows])&&$data->reportElement[isPrintWhenDetailOverflows]=="true"){$printoverflow="true";}
	if(isset($data->box)&&$data->box->pen[lineWidth]>0)
	{$border=1;
		if(isset($data->box->pen[lineColor]))
		{$drawcolor=array("r"=>hexdec(substr($data->box->pen[lineColor],1,2)),"g"=>hexdec(substr($data->box->pen[lineColor],3,2)),"b"=>hexdec(substr($data->box->pen[lineColor],5,2)));}
	}
	if(isset($data->reportElement[key])){$height=$fontsize*$this->adjust;}
	if(isset($data->textElement[textAlignment])){$align=$this->get_first_value($data->textElement[textAlignment]);}
	if(isset($data->textElement->font[pdfFontName])){$font=$data->textElement->font[pdfFontName];}
	if(isset($data->textElement->font[size])){$fontsize=$data->textElement->font[size];}	
	if(isset($data->textElement->font[isBold])&&$data->textElement->font[isBold]=="true"){$fontstyle=$fontstyle."B";}
	if(isset($data->textElement->font[isItalic])&&$data->textElement->font[isItalic]=="true"){$fontstyle=$fontstyle."I";}
	if(isset($data->textElement->font[isUnderline])&&$data->textElement->font[isUnderline]=="true"){$fontstyle=$fontstyle."U";}
	$this->pointer[]=array("type"=>"SetXY","x"=>$data->reportElement["x"],"y"=>$data->reportElement["y"],"hidden_type"=>"SetXY");
	$this->pointer[]=array("type"=>"SetTextColor","r"=>$textcolor[r],"g"=>$textcolor[g],"b"=>$textcolor[b],"hidden_type"=>"textcolor");
	$this->pointer[]=array("type"=>"SetDrawColor","r"=>$drawcolor[r],"g"=>$drawcolor[g],"b"=>$drawcolor[b],"hidden_type"=>"drawcolor");	
	$this->pointer[]=array("type"=>"SetFillColor","r"=>$fillcolor[r],"g"=>$fillcolor[g],"b"=>$fillcolor[b],"hidden_type"=>"fillcolor");
	
	$this->pointer[]=array("type"=>"SetFont","font"=>$font,"fontstyle"=>$fontstyle,"fontsize"=>$fontsize,"hidden_type"=>"font");
	
	switch ($data->textFieldExpression)
	{
	case 'new java.util.Date()':
	$this->pointer[]=array("type"=>"MultiCell","width"=>$data->reportElement[width],"height"=>$height,"txt"=>date("d/m/y h:i A", time()),"border"=>$border,"align"=>$align,"fill"=>$fill,"hidden_type"=>"date","soverflow"=>$stretchoverflow,"poverflow"=>$printoverflow,"link"=>substr($data->hyperlinkReferenceExpression,1,-1));	
	break;
	case '"Page "+$V{PAGE_NUMBER}+" of"':
	$this->pointer[]=array("type"=>"MultiCell","width"=>$data->reportElement[width],"height"=>$height,"txt"=>'Page $this->PageNo() of',"border"=>$border,"align"=>$align,"fill"=>$fill,"hidden_type"=>"pageno","soverflow"=>$stretchoverflow,"poverflow"=>$printoverflow,"link"=>substr($data->hyperlinkReferenceExpression,1,-1));	
	break;
	case '$V{PAGE_NUMBER}':
		if(isset($data[evaluationTime])&&$data[evaluationTime]=="Report")
		{$this->pointer[]=array("type"=>"MultiCell","width"=>$data->reportElement[width],"height"=>$height,"txt"=>'{nb}',"border"=>$border,"align"=>$align,"fill"=>$fill,"hidden_type"=>"pageno","soverflow"=>$stretchoverflow,"poverflow"=>$printoverflow,"link"=>substr($data->hyperlinkReferenceExpression,1,-1));}
		else{$this->pointer[]=array("type"=>"MultiCell","width"=>$data->reportElement[width],"height"=>$height,"txt"=>'$this->PageNo()',"border"=>$border,"align"=>$align,"fill"=>$fill,"hidden_type"=>"pageno","soverflow"=>$stretchoverflow,"poverflow"=>$printoverflow,"link"=>substr($data->hyperlinkReferenceExpression,1,-1));}
	break;
	case '" " + $V{PAGE_NUMBER}':
	$this->pointer[]=array("type"=>"MultiCell","width"=>$data->reportElement[width],"height"=>$height,"txt"=>' {nb}',"border"=>$border,"align"=>$align,"fill"=>$fill,"hidden_type"=>"nb","soverflow"=>$stretchoverflow,"poverflow"=>$printoverflow,"link"=>substr($data->hyperlinkReferenceExpression,1,-1));
	break;
	case '$V{REPORT_COUNT}':
	$this->report_count=0;
	$this->pointer[]=array("type"=>"MultiCell","width"=>$data->reportElement[width],"height"=>$height,"txt"=>&$this->report_count,"border"=>$border,"align"=>$align,"fill"=>$fill,"hidden_type"=>"report_count","soverflow"=>$stretchoverflow,"poverflow"=>$printoverflow,"link"=>substr($data->hyperlinkReferenceExpression,1,-1));
	break;
	default:
	$this->pointer[]=array("type"=>"MultiCell","width"=>$data->reportElement[width],"height"=>$height,"txt"=>$data->textFieldExpression,"border"=>$border,"align"=>$align,"fill"=>$fill,"hidden_type"=>"field","soverflow"=>$stretchoverflow,"poverflow"=>$printoverflow,"printWhenExpression"=>$data->reportElement->printWhenExpression,"link"=>substr($data->hyperlinkReferenceExpression,1,-1));
	break;
	}
}

public function transferDBtoArray($host,$user,$password,$db)  
{ $this->m=0;
	if(!$this->connect($host,$user,$password,$db))	//connect database
	{
	echo "Fail to connect database";
	exit(0);
	}
	$result = @mysql_query($this->sql); //query from db
	while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) 
	{
		foreach($this->arrayfield as $out)
		{
		$this->arraysqltable[$this->m]["$out"]=$row["$out"];
		}
		$this->m++;
	}
	$this->disconnect();	//close connection to db

	if(isset($this->arrayVariable))	//if self define variable existing, go to do the calculation
	{$this->variable_calculation($m);}
}  

public function variable_calculation($m=0)
{
	foreach($this->arrayVariable as $k=>$out)
	{
		switch($out[calculation])
		{case "Sum":
			$sum=0;
			if(isset($this->arrayVariable[$k]['class'])&&$this->arrayVariable[$k]['class']=="java.sql.Time")
			{
				foreach($this->arraysqltable as $table)
				{
				$sum=$sum+substr($table["$out[target]"],0,2)*3600+substr($table["$out[target]"],3,2)*60+substr($table["$out[target]"],6,2);			
				}
				$sum= floor($sum / 3600).":".floor($sum%3600 / 60);
				if($sum=="0:0"){$sum="00:00";}
			}
			else
			{
			foreach($this->arraysqltable as $table)
			{
			$sum=$sum+$table["$out[target]"];
			$table["$out[target]"];
			}
			}
			
			$this->arrayVariable[$k][ans]=$sum;
		break;
		case "Average":
			$sum=0;
			foreach($this->arraysqltable as $table)
			{$sum=$sum+$table["$out[target]"];
			}
			$this->arrayVariable[$k][ans]=$sum/$m;	
		break;
		case "DistinctCount":
		break;
		case "Lowest":
			
			foreach($this->arraysqltable as $table)
			{	$lowest=$table["$out[target]"];
				if($table["$out[target]"]<$lowest)
				{$lowest=$table["$out[target]"];}
				$this->arrayVariable[$k][ans]=$lowest;
			}
		break;
		case "Highest":
			$out[ans]=0;
			foreach($this->arraysqltable as $table)
			{
				if($table["$out[target]"]>$out[ans])
				{$this->arrayVariable[$k][ans]=$table["$out[target]"];}
			}
		break;
		default:
		$out[target]=0;		//other cases needed, temporary leave 0 if not suitable case
		break;
		
		}
	}
}
/////////////////////////////////////////////////////display to pdf part/////////////////////////////////////////////////////////////

public function outpage($out_method="I")
{
	if($this->arrayPageSetting[orientation]=="P")
	{$this->pdf=new FPDF($this->arrayPageSetting[orientation],'pt',array($this->arrayPageSetting[pageWidth],$this->arrayPageSetting[pageHeight]));
	}
	else
	{$this->pdf=new FPDF($this->arrayPageSetting[orientation],'pt',array($this->arrayPageSetting[pageHeight],$this->arrayPageSetting[pageWidth]));
	}
	//$this->arrayPageSetting[language]=$xml_path[language];
	$this->pdf->SetLeftMargin($this->arrayPageSetting[leftMargin]);
	$this->pdf->SetRightMargin($this->arrayPageSetting[rightMargin]);
	$this->pdf->SetTopMargin($this->arrayPageSetting[topMargin]);
	$this->pdf->SetAutoPageBreak(true,$this->arrayPageSetting[bottomMargin]/2);
	$this->pdf->AddPage();
	$this->pdf->AliasNbPages();
	$this->global_pointer=0;
	$this->background();
	foreach ($this->arrayband as $band)
	{
		switch($band[name])
		{
		case "pageHeader":
		$this->pageHeader();
		break;
		case "detail":
		$this->detail();
		break;
		case "group":
		$this->group_pointer=$band[groupExpression];
		$this->group_name=$band[gname];
		break;
		default:
		break;
		
		}

	}
	return $this->pdf->Output($this->arrayPageSetting[name].".pdf",$out_method);	//send out the complete page
	
}
public function background()
{
	foreach ($this->arraybackground as $out)
	{
	switch($out[hidden_type])
	{
	case "field":
	$this->display($out,$this->arrayPageSetting[topMargin],true);
	break;
	default:
	$this->display($out,$this->arrayPageSetting[topMargin],false);
	break;
	}
	}
}

public function pageHeader()
{
	if(isset($this->arraypageHeader))
	{$this->arraypageHeader[0][y_axis]=$this->arrayPageSetting[topMargin];}
	foreach ($this->arraypageHeader as $out)
	{
	switch($out[hidden_type])
	{
	case "field":
	$this->display($out,$this->arraypageHeader[0][y_axis],true);
	break;
	default:
	$this->display($out,$this->arraypageHeader[0][y_axis],false);
	break;
	}
	}
	if(isset($this->arraygroup))
	{$this->group();}
}

public function group()
{	$gname=$this->arrayband[0][gname]."";
	if(isset($this->arraypageHeader))
	{$this->arraygroup[$gname][groupHeader][0][y_axis]=$this->arrayPageSetting[topMargin]+$this->arraypageHeader[0][height];}
	if(isset($this->arraypageFooter))
	{$this->arraygroup[$gname][groupFooter][0][y_axis]=$this->arrayPageSetting[pageHeight]-$this->arraypageFooter[0][height]-$this->arrayPageSetting[bottomMargin]-$this->arraygroup[$gname][groupFooter][0][height];}
	else{$this->arraygroup[$gname][groupFooter][0][y_axis]=$this->arrayPageSetting[pageHeight]-$this->arrayPageSetting[bottomMargin]-$this->arraygroup[$gname][groupFooter][0][height];}

	if(isset($this->arraygroup))
	{
	foreach($this->arraygroup[$gname] as $name=>$out)
	{
		switch($name)
		{
		case "groupHeader":
			foreach($out as $path)
			{	switch($path[hidden_type])
				{
				case "field":
				$this->display($path,$this->arraygroup[$gname][groupHeader][0][y_axis],true);
				break;
				default:
				$this->display($path,$this->arraygroup[$gname][groupHeader][0][y_axis],false);
				break;
				}
			}
		break;
		case "groupFooter":
			foreach($out as $path)
			{	switch($path[hidden_type])
				{
				case "field":
				$this->display($path,$this->arraygroup[$gname][groupFooter][0][y_axis],true);
				break;
				default:
				$this->display($path,$this->arraygroup[$gname][groupFooter][0][y_axis],false);
				break;
				}
			}
		break;
		default:
		break;
		}
	}
	}
}

public function pageFooter()
{
	if(isset($this->arraypageFooter))
	{
		foreach ($this->arraypageFooter as $out)
		{
		switch($out[hidden_type])
		{
		case "field":
		$this->display($out,$this->arrayPageSetting[pageHeight]-$this->arraypageFooter[0][height]-$this->arrayPageSetting[bottomMargin],true);
		break;
		default:
		$this->display($out,$this->arrayPageSetting[pageHeight]-$this->arraypageFooter[0][height]-$this->arrayPageSetting[bottomMargin],false);
		break;
		}
		}
	}
	else{$this->lastPageFooter();}
}

public function lastPageFooter()
{
	if(isset($this->arraylastPageFooter))
	{
	foreach ($this->arraylastPageFooter as $out)
	{
	switch($out[hidden_type])
	{
	case "field":
	$this->display($out,$this->arrayPageSetting[pageHeight]-$this->arraylastPageFooter[0][height]-$this->arrayPageSetting[bottomMargin],true);
	break;
	default:
	$this->display($out,$this->arrayPageSetting[pageHeight]-$this->arraylastPageFooter[0][height]-$this->arrayPageSetting[bottomMargin],false);
	break;
	}
	}
	}
}


public function NbLines($w,$txt)
{
	//Computes the number of lines a MultiCell of width w will take
	$cw=&$this->pdf->CurrentFont['cw'];
	if($w==0)
		$w=$this->pdf->w-$this->pdf->rMargin-$this->pdf->x;
	$wmax=($w-2*$this->pdf->cMargin)*1000/$this->pdf->FontSize;
	$s=str_replace("\r",'',$txt);
	$nb=strlen($s);
	if($nb>0 and $s[$nb-1]=="\n")
		$nb--;
	$sep=-1;
	$i=0;
	$j=0;
	$l=0;
	$nl=1;
	while($i<$nb)
	{
		$c=$s[$i];
		if($c=="\n")
		{
			$i++;
			$sep=-1;
			$j=$i;
			$l=0;
			$nl++;
			continue;
		}
		if($c==' ')
			$sep=$i;
		$l+=$cw[$c];
		if($l>$wmax)
		{
			if($sep==-1)
			{
				if($i==$j)
					$i++;
			}
			else
				$i=$sep+1;
			$sep=-1;
			$j=$i;
			$l=0;
			$nl++;
		}
		else
			$i++;
	}
	return $nl;
}

public function detail()
{$field_pos_y=$this->arraydetail[0][y_axis];	$biggestY=0;	$checkpoint=$this->arraydetail[0][y_axis];	$tempY=$this->arraydetail[0][y_axis];

foreach($this->arraysqltable as $row)
{	
	
	if(isset($this->arraygroup)&&($this->global_pointer>0)&&($this->arraysqltable["$this->global_pointer"]["$this->group_pointer"]!=$this->arraysqltable["$this->global_pointer"-1]["$this->group_pointer"]))	//check the group's groupExpression existed and same or not
	{
	$this->pageFooter();
	$this->pdf->AddPage();
	$this->background();
	$this->pageHeader();
	$checkpoint=$this->arraydetail[0][y_axis];
	$biggestY=0;	$tempY=$this->arraydetail[0][y_axis];
	}	

	foreach($this->arraydetail as $compare)	//this loop is to count possible biggest Y of the coming row
	{
		switch($compare[hidden_type])
		{
		case "field":
		$txt=$this->analyse_expression($row["$compare[txt]"]);
		if(isset($this->arraygroup["$this->group_name"][groupFooter])&&(($checkpoint+($compare[height]*$txt))>($this->arrayPageSetting[pageHeight]-$this->arraygroup["$this->group_name"][groupFooter][0][height]-$this->arrayPageSetting[bottomMargin])))//check group footer existed or not
		{
		$this->pageFooter();
		$this->pdf->AddPage();
		$this->background();
		$this->pageHeader();
		$checkpoint=$this->arraydetail[0][y_axis];
		$biggestY=0;	$tempY=$this->arraydetail[0][y_axis];
		}
		elseif(isset($this->arraypageFooter)&&(($checkpoint+($compare[height]*($this->NbLines($compare[width],$txt))))>($this->arrayPageSetting[pageHeight]-$this->arraypageFooter[0][height]-$this->arrayPageSetting[bottomMargin])))//check pagefooter existed or not
		{
		$this->pageFooter();
		$this->pdf->AddPage();
		$this->background();
		$this->pageHeader();
		$checkpoint=$this->arraydetail[0][y_axis];
		$biggestY=0;	$tempY=$this->arraydetail[0][y_axis];
		}
		elseif(isset($this->arraylastPageFooter)&&(($checkpoint+($compare[height]*($this->NbLines($compare[width],$txt))))>($this->arrayPageSetting[pageHeight]-$this->arraylastPageFooter[0][height]-$this->arrayPageSetting[bottomMargin])))//check lastpagefooter existed or not
		{
		$this->lastPageFooter();
		$this->pdf->AddPage();
		$this->background();
		$this->pageHeader();
		$checkpoint=$this->arraydetail[0][y_axis];
		$biggestY=0;	$tempY=$this->arraydetail[0][y_axis];
		}
	
		if(($checkpoint+($compare[height]*($this->NbLines($compare[width],$txt))))>$tempY)
		{$tempY=$checkpoint+($compare[height]*($this->NbLines($compare[width],$txt)));}
		break;
		case "relativebottomline":
		break;
		case "report_count":
			$this->report_count++;
		break;
		default:
		$this->display($compare,$checkpoint);
		break;
		}
	}

	

	if($checkpoint+$this->arraydetail[0][height]>($this->arrayPageSetting[pageHeight]-$this->arraypageFooter[0][height]-$this->arrayPageSetting[bottomMargin]))	//check the upcoming band is greater than footer position or not
	{$this->pageFooter();
	$this->pdf->AddPage();
	$this->background();
	$this->pageHeader();
	$checkpoint=$this->arraydetail[0][y_axis];
	$biggestY=0; $tempY=$this->arraydetail[0][y_axis];}

	foreach ($this->arraydetail as $out)
	{
		switch ($out[hidden_type])
		{
		case "field":
	
		$this->prepare_print_array=array("type"=>"MultiCell","width"=>$out[width],"height"=>$out[height],"txt"=>$out[txt],"border"=>$out[border],"align"=>$out[align],"fill"=>$out[fill],"hidden_type"=>$out[hidden_type],"printWhenExpression"=>$out[printWhenExpression],"soverflow"=>$out[soverflow],"poverflow"=>$out[poverflow],"link"=>$out[link]);
		$this->display($this->prepare_print_array,0,true);

		if($this->pdf->GetY()>$biggestY)
		{$biggestY=$this->pdf->GetY();}
		break;
		case "relativebottomline":
		//$this->relativebottomline($out,$tempY);
		$this->relativebottomline($out,$biggestY);	
		break;
		default:

		$this->display($out,$checkpoint);
		
		//$checkpoint=$this->pdf->GetY();
		break;		
		}
	}
	$this->pdf->SetY($biggestY);
	if($biggestY>$checkpoint+$this->arraydetail[0][height])
	{$checkpoint=$biggestY;}
	elseif($biggestY<$checkpoint+$this->arraydetail[0][height])
	{$checkpoint=$checkpoint+$this->arraydetail[0][height];}
	else{$checkpoint=$biggestY;}

	//if(isset($this->arraygroup)){$this->global_pointer++;}
	$this->global_pointer++;
}	
$this->global_pointer--;
if(isset($this->arraylastPageFooter))
{$this->lastPageFooter();}
else{$this->pageFooter();}
}



public function display($arraydata,$y_axis=0,$fielddata=false)
{

	if($arraydata[type]=="MultiCell")
	{
		if($fielddata==false)
		{
		$this->checkoverflow($arraydata,$this->updatePageNo($arraydata[txt]));
		}
		elseif($fielddata==true)
		{
		$this->checkoverflow($arraydata,$this->updatePageNo($this->analyse_expression($arraydata[txt])));
		}
	}		
	elseif($arraydata[type]=="SetXY")
	{$this->pdf->SetXY($arraydata[x]+$this->arrayPageSetting[leftMargin],$arraydata[y]+$y_axis);}
	elseif($arraydata[type]=="Cell")
	{$this->pdf->Cell($arraydata[width],$arraydata[height],$this->updatePageNo($arraydata[txt]),$arraydata[border],$arraydata[ln],$arraydata[align],$arraydata[fill],$arraydata[link]);}
	elseif($arraydata[type]=="Rect")
	{$this->pdf->Rect($arraydata[x]+$this->arrayPageSetting[leftMargin],$arraydata[y]+$y_axis,$arraydata[width],$arraydata[height]);}
	elseif($arraydata[type]=="Image")
	{
	 $path=$this->analyse_expression($arraydata[path]);
	$imgtype=substr($path,-3);

	$this->pdf->Image($path,$arraydata[x]+$this->arrayPageSetting[leftMargin],$arraydata[y]+$y_axis,$arraydata[width],$arraydata[height],$imgtype,$arraydata[link]);}
	elseif($arraydata[type]=="SetFont")
	{$this->pdf->SetFont($arraydata[font],$arraydata[fontstyle],$arraydata[fontsize]);}
	elseif($arraydata[type]=="SetTextColor")
	{$this->pdf->SetTextColor($arraydata[r],$arraydata[g],$arraydata[b]);}
	elseif($arraydata[type]=="SetDrawColor")
	{$this->pdf->SetDrawColor($arraydata[r],$arraydata[g],$arraydata[b]);}
	elseif($arraydata[type]=="SetLineWidth")
	{$this->pdf->SetLineWidth($arraydata[width]);}
	elseif($arraydata[type]=="Line")
	{$this->pdf->Line($arraydata[x1]+$this->arrayPageSetting[leftMargin],$arraydata[y1]+$y_axis,$arraydata[x2]+$this->arrayPageSetting[leftMargin],$arraydata[y2]+$y_axis);}

	elseif($arraydata[type]=="SetFillColor")
	{$this->pdf->SetFillColor($arraydata[r],$arraydata[g],$arraydata[b]);}	

}

public function relativebottomline($path,$y)
{
	$extra=$y-$path[y1];
	$this->display($path,$extra);
}

public function updatePageNo($s)
{
 return str_replace('$this->PageNo()', $this->pdf->PageNo(),$s);
}

public function staticText($xml_path)
{//$this->pointer[]=array("type"=>"SetXY","x"=>$xml_path->reportElement[x],"y"=>$xml_path->reportElement[y]);
}

public function checkoverflow($arraydata,$txt="")
{	$this->print_expression($arraydata);
	if($this->print_expression_result==true)
	{
	if($arraydata[poverflow]=="true"&&$arraydata[soverflow]=="false")
	{$this->pdf->Cell($arraydata[width], $arraydata[height], $txt,$arraydata[border],"",$arraydata[align],$arraydata[fill],$arraydata[link]);
	//$this->pdf->MultiCell($arraydata[width], $arraydata[height], $txt,$arraydata[border],$arraydata[align],$arraydata[fill]);
	}
	elseif($arraydata[poverflow]=="false"&&$arraydata[soverflow]=="false")
	{
	while($this->pdf->GetStringWidth($txt) > $arraydata[width])
	{$txt=substr_replace($txt,"",-1);}
	$this->pdf->Cell($arraydata[width], $arraydata[height],$txt,$arraydata[border],"",$arraydata[align],$arraydata[fill],$arraydata[link]);
	}
	elseif($arraydata[poverflow]=="false"&&$arraydata[soverflow]=="true")
	{$this->pdf->MultiCell($arraydata[width], $arraydata[height], $txt, $arraydata[border], $arraydata[align], $arraydata[fill]);}
	else
	{$this->pdf->MultiCell($arraydata[width], $arraydata[height], $txt, $arraydata[border], $arraydata[align], $arraydata[fill]);
	}
	}
	$this->print_expression_result=false;
}

public function hex_code_color($value)
{	$r=hexdec(substr($value,1,2));
	$g=hexdec(substr($value,3,2));
	$b=hexdec(substr($value,5,2));
	return array("r"=>$r,"g"=>$g,"b"=>$b);
}

public function get_first_value($value)
{	
	return (substr($value,0,1));
}

public function analyse_expression($data)
{
	$data=explode("+",$data);
	foreach($data as $num=>$out)
	{ 
		$data["$num"]=str_replace('"',"",$out);
		if(substr($out,0,3)=='$F{')
		{$data["$num"]=$this->arraysqltable[$this->global_pointer][substr($out,3,-1)];}
		elseif(substr($out,0,3)=='$V{')
		{$data["$num"]=&$this->arrayVariable[substr($out,3,-1)]["ans"];}
		elseif(substr($out,0,3)=='$P{')
		{$data["$num"]=$this->arrayParameter[substr($out,3,-1)];}
	}
	return implode($data);
}

public function print_expression($data)
{	
	$expression=$data[printWhenExpression];
	$expression=str_replace('$F{','$this->arraysqltable[$this->global_pointer][',$expression);
	$expression=str_replace('$P{','$this->arraysqltable[$this->global_pointer][',$expression);
	$expression=str_replace('$V{','$this->arraysqltable[$this->global_pointer][',$expression);
	$expression=str_replace('}',']',$expression);
	$this->print_expression_result=false;
	if($expression!="")
	{eval('if('.$expression.'){$this->print_expression_result=true;}');}
	elseif($expression=="")
	{$this->print_expression_result=true;}
	//echo 'if('.$expression.'){return true;}'."<br>";
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function test ()
{print_r($this->arraypageFooter);}

}
?>
