Kompetenz/prints2/own.php

4920 lines
176 KiB
PHP
Executable File

<?php
//
// fpdf_tpl - Version 1.0.2
//
// Copyright 2004,2005 Setasign - Jan Slabon
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
require_once("fpdf.php");
class own extends fpdf {
/**
* Array of Tpl-Data
* @var array
*/
var $tpls = array();
/**
* Current Template-ID
* @var int
*/
var $tpl = 0;
/**
* "In Template"-Flag
* @var boolean
*/
var $intpl = false;
/**
* Nameprefix of Templates used in Resources-Dictonary
* @var string A String defining the Prefix used as Template-Object-Names. Have to beginn with an /
*/
var $tplprefix = "/TPL";
/**
* Nameprefix of Fonts used in Resources-Dictonary
* (not realy needed, but for future versions with import-function needed)
* @var string
*/
var $fontprefix = "/F";
/**
* Resources used By Templates and Pages
* @var array
*/
var $res = array();
/**
* Constructor
* See FPDF-Documentation
* @param string $orientation
* @param string $unit
* @param mixed $format
*/
function fpdf_tpl($orientation='P',$unit='mm',$format='A4') {
parent::fpdf($orientation,$unit,$format);
}
/**
* Start a Template
*
* This method starts a template. You can give own coordinates to build an own sized
* Template. Pay attention, that the margins are adapted to the new templatesize.
* If you want to write outside the template, for example to build a clipped Template,
* you have to set the Margins and "Cursor"-Position manual after beginTemplate-Call.
*
* If no parameter is given, the template uses the current page-size.
* The Method returns an ID of the current Template. This ID is used later for using this template.
* Warning: A created Template is used in PDF at all events. Still if you don't use it after creation!
*
* @param int $x The x-coordinate given in user-unit
* @param int $y The y-coordinate given in user-unit
* @param int $w The width given in user-unit
* @param int $h The height given in user-unit
* @return int The ID of new created Template
*/
function beginTemplate($x=null,$y=null,$w=null,$h=null) {
if ($this->page <= 0)
$this->error("You have to add a page to fpdf first!");
// Save settings
$this->tpl++;
$this->tpls[$this->tpl]['o_x'] = $this->x;
$this->tpls[$this->tpl]['o_y'] = $this->y;
$this->tpls[$this->tpl]['o_AutoPageBreak'] = $this->AutoPageBreak;
$this->tpls[$this->tpl]['o_bMargin'] = $this->bMargin;
$this->tpls[$this->tpl]['o_tMargin'] = $this->tMargin;
$this->tpls[$this->tpl]['o_lMargin'] = $this->lMargin;
$this->tpls[$this->tpl]['o_rMargin'] = $this->rMargin;
$this->tpls[$this->tpl]['o_h'] = $this->h;
$this->tpls[$this->tpl]['o_w'] = $this->w;
$this->SetAutoPageBreak(false);
if ($x == null)
$x = 0;
if ($y == null)
$y = 0;
if ($w == null)
$w = $this->w;
if ($h == null)
$h = $this->h;
// Define own high and width to calculate possitions correct
$this->h = $h;
$this->w = $w;
$this->tpls[$this->tpl]['buffer'] = "";
$this->tpls[$this->tpl]['x'] = $x;
$this->tpls[$this->tpl]['y'] = $y;
$this->tpls[$this->tpl]['w'] = $w;
$this->tpls[$this->tpl]['h'] = $h;
$this->intpl = true;
$this->SetXY($x+$this->lMargin,$y+$this->tMargin);
$this->SetRightMargin($this->w-$w+$this->rMargin);
return $this->tpl;
}
/**
* End Template
*
* This method ends a template and reset initiated variables on beginTemplate.
*
* @return mixed If a template is opened, the ID is returned. If not a false is returned.
*/
function endTemplate() {
if ($this->intpl) {
$this->intpl = false;
$this->SetAutoPageBreak($this->tpls[$this->tpl]['o_AutoPageBreak'],$this->tpls[$this->tpl]['o_bMargin']);
$this->SetXY($this->tpls[$this->tpl]['o_x'],$this->tpls[$this->tpl]['o_y']);
$this->tMargin = $this->tpls[$this->tpl]['o_tMargin'];
$this->lMargin = $this->tpls[$this->tpl]['o_lMargin'];
$this->rMargin = $this->tpls[$this->tpl]['o_rMargin'];
$this->h = $this->tpls[$this->tpl]['o_h'];
$this->w = $this->tpls[$this->tpl]['o_w'];
return $this->tpl;
} else {
return false;
}
}
/**
* Use a Template in current Page or other Template
*
* You can use a template in a page or in another template.
* You can give the used template a new size like you use the Image()-method.
* All parameters are optional. The width or height is calculated automaticaly
* if one is given. If no parameter is given the origin size as defined in
* beginTemplate() is used.
* The calculated or used width and height are returned as an array.
*
* @param int $tplidx A valid template-Id
* @param int $_x The x-position
* @param int $_y The y-position
* @param int $_w The new width of the template
* @param int $_h The new height of the template
* @retrun array The height and width of the template
*/
function useTemplate($tplidx, $_x=null, $_y=null, $_w=0, $_h=0) {
if ($this->page <= 0)
$this->error("You have to add a page to fpdf first!");
if (!$this->tpls[$tplidx])
$this->error("Template does not exist!");
if ($this->intpl) {
$this->res['tpl'][$this->tpl]['tpls'][$tplidx] =& $this->tpls[$tplidx];
}
extract($this->tpls[$tplidx]);
if ($_x == null)
$_x = $x;
if ($_y == null)
$_y = $y;
$wh = $this->getTemplateSize($tplidx,$_w,$_h);
$_w = $wh['w'];
$_h = $wh['h'];
$this->_out(sprintf("q %.4f 0 0 %.4f %.2f %.2f cm", ($_w/$w), ($_h/$h), $_x*$this->k, ($this->h-($_y+$_h))*$this->k)); // Translate
$this->_out($this->tplprefix.$tplidx." Do Q");
return array("w" => $_w, "h" => $_h);
}
/**
* Get The calculated Size of a Template
*
* If one size is given, this method calculates the other one.
*
* @param int $tplidx A valid template-Id
* @param int $_w The width of the template
* @param int $_h The height of the template
* @return array The height and width of the template
*/
function getTemplateSize($tplidx, $_w=0, $_h=0) {
if (!$this->tpls[$tplidx])
return false;
extract($this->tpls[$tplidx]);
if ($_w == 0 and $_h == 0) {
$_w = $w;
$_h = $h;
}
if($_w==0)
$_w=$_h*$w/$h;
if($_h==0)
$_h=$_w*$h/$w;
return array("w" => $_w, "h" => $_h);
}
/**
* See FPDF-Documentation ;-)
*/
function SetFont($family,$style='',$size=0) {
//Select a font; size given in points
global $fpdf_charwidths;
$family=strtolower($family);
if($family=='')
$family=$this->FontFamily;
if($family=='arial')
$family='helvetica';
elseif($family=='symbol' or $family=='zapfdingbats')
$style='';
$style=strtoupper($style);
if(is_int(strpos($style,'U')))
{
$this->underline=true;
$style=str_replace('U','',$style);
}
else
$this->underline=false;
if($style=='IB')
$style='BI';
if($size==0)
$size=$this->FontSizePt;
//Test if font is already selected
if($this->FontFamily==$family and $this->FontStyle==$style and $this->FontSizePt==$size and !$this->intpl)
return;
//Test if used for the first time
$fontkey=$family.$style;
if(!isset($this->fonts[$fontkey]))
{
//Check if one of the standard fonts
if(isset($this->CoreFonts[$fontkey]))
{
if(!isset($fpdf_charwidths[$fontkey]))
{
//Load metric file
$file=$family;
if($family=='times' or $family=='helvetica')
$file.=strtolower($style);
$file.='.php';
if(defined('FPDF_FONTPATH'))
$file=FPDF_FONTPATH.$file;
include($file);
if(!isset($fpdf_charwidths[$fontkey]))
$this->Error('Could not include font metric file');
}
$i = $this->findNextAvailFont();
$this->fonts[$fontkey]=array('i'=>$i,'type'=>'core','name'=>$this->CoreFonts[$fontkey],'up'=>-100,'ut'=>50,'cw'=>$fpdf_charwidths[$fontkey]);
}
else
$this->Error('Undefined font: '.$family.' '.$style);
}
//Select it
$this->FontFamily=$family;
$this->FontStyle=$style;
$this->FontSizePt=$size;
$this->FontSize=$size/$this->k;
$this->CurrentFont=&$this->fonts[$fontkey];
if($this->page>0)
$this->_out(sprintf('BT '.$this->fontprefix.'%d %.2f Tf ET',$this->CurrentFont['i'],$this->FontSizePt));
if ($this->intpl) {
$this->res['tpl'][$this->tpl]['fonts'][$fontkey] =& $this->fonts[$fontkey];
} else {
$this->res['page'][$this->page]['fonts'][$fontkey] =& $this->fonts[$fontkey];
}
}
/**
* Find the next available Font-No.
*
* @return int
*/
function findNextAvailFont() {
return count($this->fonts)+1;
}
/**
* See FPDF-Documentation ;-)
*/
function Image($file,$x,$y,$w=0,$h=0,$type='',$link='') {
parent::Image($file,$x,$y,$w,$h,$type,$link);
if ($this->intpl) {
$this->res['tpl'][$this->tpl]['images'][$file] =& $this->images[$file];
} else {
$this->res['page'][$this->page]['images'][$file] =& $this->images[$file];
}
}
/**
* See FPDF-Documentation ;-)
*
* AddPage is not available when you're "in" a template.
*/
function AddPage($orientation='') {
if ($this->intpl)
$this->Error('Adding pages in templates isn\'t possible!');
parent::AddPage($orientation);
}
/**
* Preserve adding Links in Templates ...won't work
*/
function Link($x,$y,$w,$h,$link) {
if ($this->intpl)
$this->Error('Using links in templates aren\'t possible!');
parent::Link($x,$y,$w,$h,$link);
}
function AddLink() {
if ($this->intpl)
$this->Error('Adding links in templates aren\'t possible!');
return parent::AddLink();
}
function SetLink($link,$y=0,$page=-1) {
if ($this->intpl)
$this->Error('Setting links in templates aren\'t possible!');
parent::SetLink($link,$y,$page);
}
/**
* Private Method that writes the Resources-Objects
*/
function _puttemplates() {
$filter=($this->compress) ? '/Filter /FlateDecode ' : '';
reset($this->tpls);
foreach($this->tpls AS $tplidx => $tpl) {
$p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer'];
$this->_newobj();
$this->tpls[$tplidx]['n'] = $this->n;
$this->_out('<<'.$filter.'/Type /XObject');
$this->_out('/Subtype /Form');
$this->_out('/FormType 1');
$this->_out(sprintf('/BBox [%.2f %.2f %.2f %.2f]',$tpl['x']*$this->k, ($tpl['h']-$tpl['y'])*$this->k, $tpl['w']*$this->k, ($tpl['h']-$tpl['y']-$tpl['h'])*$this->k)); // ($this->h-$tpl['y'])*$this->k
$this->_out('/Resources ');
$this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
if (count($this->res['tpl'][$tplidx]['fonts'])) {
$this->_out('/Font <<');
foreach($this->res['tpl'][$tplidx]['fonts'] as $font)
$this->_out($this->fontprefix.$font['i'].' '.$font['n'].' 0 R');
$this->_out('>>');
}
if(count($this->res['tpl'][$tplidx]['images']) || count($this->res['tpl'][$tplidx]['tpls']))
{
$this->_out('/XObject <<');
if (count($this->res['tpl'][$tplidx]['images'])) {
foreach($this->res['tpl'][$tplidx]['images'] as $image)
$this->_out('/I'.$image['i'].' '.$image['n'].' 0 R');
}
if (count($this->res['tpl'][$tplidx]['tpls'])) {
foreach($this->res['tpl'][$tplidx]['tpls'] as $i => $tpl)
$this->_out($this->tplprefix.$i.' '.$tpl['n'].' 0 R');
}
$this->_out('>>');
}
$this->_out('>>');
$this->_out('/Length '.strlen($p).' >>');
$this->_putstream($p);
$this->_out('endobj');
}
}
/**
* Private Method
*/
function _putresources() {
$this->_putfonts();
$this->_putimages();
$this->_puttemplates();
//Resource dictionary
$this->offsets[2]=strlen($this->buffer);
$this->_out('2 0 obj');
$this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
$this->_out('/Font <<');
foreach($this->fonts as $font)
$this->_out($this->fontprefix.$font['i'].' '.$font['n'].' 0 R');
$this->_out('>>');
if(count($this->images) || count($this->tpls))
{
$this->_out('/XObject <<');
if (count($this->images)) {
foreach($this->images as $image)
$this->_out('/I'.$image['i'].' '.$image['n'].' 0 R');
}
if (count($this->tpls)) {
foreach($this->tpls as $tplidx => $tpl)
$this->_out($this->tplprefix.$tplidx.' '.$tpl['n'].' 0 R');
}
$this->_out('>>');
}
$this->_out('>>');
$this->_out('endobj');
}
/**
* Private Method
*/
function _out($s) {
//Add a line to the document
if ($this->state==2) {
if (!$this->intpl)
$this->pages[$this->page].=$s."\n";
else
$this->tpls[$this->tpl]['buffer'] .= $s."\n";
} else {
$this->buffer.=$s."\n";
}
}
}
require_once("fpdi_pdf_parser.php");
class own2 extends own {
/**
* Actual filename
* @var string
*/
var $current_filename;
/**
* Parser-Objects
* @var array
*/
var $parsers;
/**
* Current parser
* @var object
*/
var $current_parser;
/**
* FPDF/FPDI - PDF-Version
* @var double
*/
var $PDFVersion = 1.3;
/**
* Highest version of imported PDF
* @var double
*/
var $importVersion = 1.3;
/**
* object stack
* @var array
*/
var $obj_stack;
/**
* done object stack
* @var array
*/
var $don_obj_stack;
/**
* Current Object Id.
* @var integer
*/
var $current_obj_id;
/**
* Constructor
* See FPDF-Manual
*/
function fpdi($orientation='P',$unit='mm',$format='A4') {
parent::fpdf_tpl($orientation,$unit,$format);
}
/**
* Set a source-file
*
* @param string $filename a valid filename
* @return int number of available pages
*/
function setSourceFile($filename) {
$this->current_filename = $filename;
$fn =& $this->current_filename;
$this->parsers[$fn] = new fpdi_pdf_parser($fn,$this);
$this->current_parser =& $this->parsers[$fn];
return $this->parsers[$fn]->getPageCount();
}
/**
* Import a page
*
* @param int $pageno pagenumber
* @return int Index of imported page - to use with fpdf_tpl::useTemplate()
*/
function ImportPage($pageno) {
$fn =& $this->current_filename;
$this->parsers[$fn]->setPageno($pageno);
$this->tpl++;
$this->tpls[$this->tpl] = array();
$this->tpls[$this->tpl]['parser'] =& $this->parsers[$fn];
$this->tpls[$this->tpl]['resources'] = $this->parsers[$fn]->getPageResources();
$this->tpls[$this->tpl]['buffer'] = $this->parsers[$fn]->getContent();
// $mediabox holds the dimensions of the source page
$mediabox = $this->parsers[$fn]->getPageMediaBox($pageno);
// To build array that can used by pdf_tpl::useTemplate()
$this->tpls[$this->tpl] = array_merge($this->tpls[$this->tpl],$mediabox);
return $this->tpl;
}
/**
* Private method, that rebuilds all needed objects of source files
*/
function _putOobjects() {
if (is_array($this->parsers) && count($this->parsers) > 0) {
foreach($this->parsers AS $filename => $p) {
$this->current_parser =& $this->parsers[$filename];
if (is_array($this->obj_stack[$filename])) {
while($n = key($this->obj_stack[$filename])) {
$nObj = $this->current_parser->pdf_resolve_object($this->current_parser->c,$this->obj_stack[$filename][$n][1]);
$this->_newobj($this->obj_stack[$filename][$n][0]);
if ($nObj[0] == PDF_TYPE_STREAM) {
$this->pdf_write_value ($nObj);
} else {
$this->pdf_write_value ($nObj[1]);
}
$this->_out('endobj');
$this->obj_stack[$filename][$n] = null; // free memory
unset($this->obj_stack[$filename][$n]);
reset($this->obj_stack[$filename]);
}
}
}
}
}
/**
* Rewritten for handling own defined PDF-Versions
* only needed by FPDF 1.52
*/
function _begindoc() {
//Start document
$this->state=1;
}
/**
* Sets the PDF Version to the highest of imported documents
*/
function setVersion() {
if ($this->importVersion > $this->PDFVersion)
$this->PDFVersion = $this->importVersion;
if (!method_exists($this, '_putheader')) {
$this->buffer = '%PDF-'.$this->PDFVersion."\n".$this->buffer;
}
}
/**
* rewritten for handling higher PDF Versions
*/
function _enddoc() {
$this->setVersion();
parent::_enddoc();
}
/**
* Put resources
*/
function _putresources() {
$this->_putfonts();
$this->_putimages();
$this->_puttemplates();
$this->_putOobjects();
//Resource dictionary
$this->offsets[2]=strlen($this->buffer);
$this->_out('2 0 obj');
$this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
$this->_out('/Font <<');
foreach($this->fonts as $font)
$this->_out($this->fontprefix.$font['i'].' '.$font['n'].' 0 R');
$this->_out('>>');
if(count($this->images) || count($this->tpls))
{
$this->_out('/XObject <<');
if (count($this->images)) {
foreach($this->images as $image)
$this->_out('/I'.$image['i'].' '.$image['n'].' 0 R');
}
if (count($this->tpls)) {
foreach($this->tpls as $tplidx => $tpl)
$this->_out($this->tplprefix.$tplidx.' '.$tpl['n'].' 0 R');
}
$this->_out('>>');
}
$this->_out('>>');
$this->_out('endobj');
}
/**
* Private Method that writes /XObjects - "Templates"
*/
function _puttemplates() {
$filter=($this->compress) ? '/Filter /FlateDecode ' : '';
reset($this->tpls);
foreach($this->tpls AS $tplidx => $tpl) {
$p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer'];
$this->_newobj();
$this->tpls[$tplidx]['n'] = $this->n;
$this->_out('<<'.$filter.'/Type /XObject');
$this->_out('/Subtype /Form');
$this->_out('/FormType 1');
$this->_out(sprintf('/BBox [%.2f %.2f %.2f %.2f]',$tpl['x']*$this->k, ($tpl['h']-$tpl['y'])*$this->k, $tpl['w']*$this->k, ($tpl['h']-$tpl['y']-$tpl['h'])*$this->k));
$this->_out('/Resources ');
if ($tpl['resources']) {
$this->current_parser =& $tpl['parser'];
$this->pdf_write_value($tpl['resources']);
} else {
$this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
if (count($this->res['tpl'][$tplidx]['fonts'])) {
$this->_out('/Font <<');
foreach($this->res['tpl'][$tplidx]['fonts'] as $font)
$this->_out($this->fontprefix.$font['i'].' '.$font['n'].' 0 R');
$this->_out('>>');
}
if(count($this->res['tpl'][$tplidx]['images']) || count($this->res['tpl'][$tplidx]['tpls']))
{
$this->_out('/XObject <<');
if (count($this->res['tpl'][$tplidx]['images'])) {
foreach($this->res['tpl'][$tplidx]['images'] as $image)
$this->_out('/I'.$image['i'].' '.$image['n'].' 0 R');
}
if (count($this->res['tpl'][$tplidx]['tpls'])) {
foreach($this->res['tpl'][$tplidx]['tpls'] as $i => $tpl)
$this->_out($this->tplprefix.$i.' '.$tpl['n'].' 0 R');
}
$this->_out('>>');
}
$this->_out('>>');
}
$this->_out('/Length '.strlen($p).' >>');
$this->_putstream($p);
$this->_out('endobj');
}
}
/**
* Rewritten to handle existing own defined objects
*/
function _newobj($obj_id=false,$onlynewobj=false) {
if (!$obj_id) {
$obj_id = ++$this->n;
}
//Begin a new object
if (!$onlynewobj) {
$this->offsets[$obj_id]=strlen($this->buffer);
$this->_out($obj_id.' 0 obj');
$this->current_obj_id = $obj_id; // for later use with encryption
}
}
/**
* Writes a value
* Needed to rebuild the source document
*
* @param mixed $value A PDF-Value. Structure of values see cases in this method
*/
function pdf_write_value(&$value)
{
switch ($value[0]) {
case PDF_TYPE_NUMERIC :
case PDF_TYPE_TOKEN :
// A numeric value or a token.
// Simply output them
$this->_out($value[1]." ");
break;
case PDF_TYPE_ARRAY :
// An array. Output the proper
// structure and move on.
$this->_out("[",false);
for ($i = 0; $i < count($value[1]); $i++) {
$this->pdf_write_value($value[1][$i]);
}
$this->_out("]");
break;
case PDF_TYPE_DICTIONARY :
// A dictionary.
$this->_out("<<",false);
reset ($value[1]);
while (list($k, $v) = each($value[1])) {
$this->_out($k . " ",false);
$this->pdf_write_value($v);
}
$this->_out(">>");
break;
case PDF_TYPE_OBJREF :
// An indirect object reference
// Fill the object stack if needed
if (!isset($this->don_obj_stack[$this->current_parser->filename][$value[1]])) {
$this->_newobj(false,true);
$this->obj_stack[$this->current_parser->filename][$value[1]] = array($this->n,$value);
$this->don_obj_stack[$this->current_parser->filename][$value[1]] = array($this->n,$value);
}
$objid = $this->don_obj_stack[$this->current_parser->filename][$value[1]][0];
$this->_out("{$objid} 0 R"); //{$value[2]}
break;
case PDF_TYPE_STRING :
// A string.
$this->_out('(' . $value[1] . ')');
break;
case PDF_TYPE_STREAM :
// A stream. First, output the
// stream dictionary, then the
// stream data itself.
$this->pdf_write_value($value[1]);
$this->_out("stream");
$this->_out($value[2][1]);
$this->_out("endstream");
break;
case PDF_TYPE_HEX :
$this->_out("<" . $value[1] . ">");
break;
case PDF_TYPE_NULL :
// The null object.
$this->_out("null");
break;
}
}
/**
* Private Method
*/
function _out($s,$ln=true) {
//Add a line to the document
if ($this->state==2) {
if (!$this->intpl)
$this->pages[$this->page].=$s.($ln == true ? "\n" : '');
else
$this->tpls[$this->tpl]['buffer'] .= $s.($ln == true ? "\n" : '');
} else {
$this->buffer.=$s.($ln == true ? "\n" : '');
}
}
/**
* close all files opened by parsers
*/
function closeParsers() {
foreach ($this->parsers as $parser){
$parser->closeFile();
}
}
}
// Bis hierher fpdi, die letzte Klasse von fpdi, wird der ersten Klasse von Table vererbt:
// --> extends own2 hieß ursprünglich extends fpdf. fpdf ist die erste vererbung ganz oben
// daher ist hier die schnittstelle, wo man die zwei Pakete vererben kann: http://www.cix88.de/cix_fpdf/fpdf_allgemein/cix_tut_052.php
require_once("class.string_tags.php");
if (!defined('PARAGRAPH_STRING')) define('PARAGRAPH_STRING', '~~~');
class FPDF_MULTICELLTAG extends own2{
var $wt_Current_Tag;
var $wt_FontInfo;//tags font info
var $wt_DataInfo;//parsed string data info
var $wt_DataExtraInfo;//data extra INFO
var $wt_TempData; //some temporary info
function _wt_Reset_Datas(){
$this->wt_Current_Tag = "";
$this->wt_DataInfo = array();
$this->wt_DataExtraInfo = array(
"LAST_LINE_BR" => "", //CURRENT LINE BREAK TYPE
"CURRENT_LINE_BR" => "", //LAST LINE BREAK TYPE
"TAB_WIDTH" => 10 //The tab WIDTH IS IN mm
);
//if another measure unit is used ... calculate your OWN
$this->wt_DataExtraInfo["TAB_WIDTH"] *= (72/25.4) / $this->k;
/*
$this->wt_FontInfo - do not reset, once read ... is OK!!!
*/
}//function _wt_Reset_Datas(){
/**
Sets current tag to specified style
@param $tag - tag name
$family - text font family
$style - text style
$size - text size
$color - text color
@return nothing
*/
function SetStyle($tag,$family,$style,$size,$color)
{
if ($tag == "ttags") $this->Error (">> ttags << is reserved TAG Name.");
if ($tag == "") $this->Error ("Empty TAG Name.");
//use case insensitive tags
$tag=trim(strtoupper($tag));
$this->TagStyle[$tag]['family']=trim($family);
$this->TagStyle[$tag]['style']=trim($style);
$this->TagStyle[$tag]['size']=trim($size);
$this->TagStyle[$tag]['color']=trim($color);
}//function SetStyle
/**
Sets current tag style as the current settings
- if the tag name is not in the tag list then de "DEFAULT" tag is saved.
This includes a fist call of the function SaveCurrentStyle()
@param $tag - tag name
@return nothing
*/
function ApplyStyle($tag){
//use case insensitive tags
$tag=trim(strtoupper($tag));
if ($this->wt_Current_Tag == $tag) return;
if (($tag == "") || (! isset($this->TagStyle[$tag]))) $tag = "DEFAULT";
$this->wt_Current_Tag = $tag;
$style = & $this->TagStyle[$tag];
if (isset($style)){
$this->SetFont($style['family'], $style['style'], $style['size']);
//this is textcolor in FPDF format
if (isset($style['textcolor_fpdf'])) {
$this->TextColor = $style['textcolor_fpdf'];
$this->ColorFlag=($this->FillColor!=$this->TextColor);
}else
{
if ($style['color'] <> ""){//if we have a specified color
$temp = explode(",", $style['color']);
$this->SetTextColor($temp[0], $temp[1], $temp[2]);
}//fi
}
/**/
}//isset
}//function ApplyStyle($tag){
/**
Save the current settings as a tag default style under the DEFAUTLT tag name
@param none
@return nothing
*/
function SaveCurrentStyle(){
//*
$this->TagStyle['DEFAULT']['family'] = $this->FontFamily;;
$this->TagStyle['DEFAULT']['style'] = $this->FontStyle;
$this->TagStyle['DEFAULT']['size'] = $this->FontSizePt;
$this->TagStyle['DEFAULT']['textcolor_fpdf'] = $this->TextColor;
$this->TagStyle['DEFAULT']['color'] = "";
/**/
}//function SaveCurrentStyle
/**
Divides $this->wt_DataInfo and returnes a line from this variable
@param $w - Width of the text
@return $aLine = array() -> contains informations to draw a line
*/
function MakeLine($w){
$aDataInfo = & $this->wt_DataInfo;
$aExtraInfo = & $this->wt_DataExtraInfo;
//last line break >> current line break
$aExtraInfo['LAST_LINE_BR'] = $aExtraInfo['CURRENT_LINE_BR'];
$aExtraInfo['CURRENT_LINE_BR'] = "";
if($w==0)
$w=$this->w - $this->rMargin - $this->x;
$wmax = ($w - 2*$this->cMargin) * 1000;//max width
$aLine = array();//this will contain the result
$return_result = false;//if break and return result
$reset_spaces = false;
$line_width = 0;//line string width
$total_chars = 0;//total characters included in the result string
$space_count = 0;//numer of spaces in the result string
$fw = & $this->wt_FontInfo;//font info array
$last_sepch = ""; //last separator character
foreach ($aDataInfo as $key => $val){
$s = $val['text'];
$tag = &$val['tag'];
$bParagraph = false;
if (($s == "\t") && ($tag == 'pparg')){
$bParagraph = true;
$s = "\t";//place instead a TAB
}
$s_lenght=strlen($s);
$i = 0;//from where is the string remain
$j = 0;//untill where is the string good to copy -- leave this == 1->> copy at least one character!!!
$str = "";
$s_width = 0; //string width
$last_sep = -1; //last separator position
$last_sepwidth = 0;
$last_sepch_width = 0;
$ante_last_sep = -1; //ante last separator position
$spaces = 0;
//parse the whole string
while ($i < $s_lenght){
$c = $s[$i];
if($c == "\n"){//Explicit line break
$i++; //ignore/skip this caracter
$aExtraInfo['CURRENT_LINE_BR'] = "BREAK";
$return_result = true;
$reset_spaces = true;
break;
}
//space
if($c == " "){
$space_count++;//increase the number of spaces
$spaces ++;
}
// Font Width / Size Array
if (!isset($fw[$tag]) || ($tag == "")){
//if this font was not used untill now,
$this->ApplyStyle($tag);
$fw[$tag]['w'] = $this->CurrentFont['cw'];//width
$fw[$tag]['s'] = $this->FontSize;//size
}
$char_width = $fw[$tag]['w'][$c] * $fw[$tag]['s'];
//separators
if(is_int(strpos(" ,.:;",$c))){
$ante_last_sep = $last_sep;
$ante_last_sepch = $last_sepch;
$ante_last_sepwidth = $last_sepwidth;
$ante_last_sepch_width = $last_sepch_width;
$last_sep = $i;//last separator position
$last_sepch = $c;//last separator char
$last_sepch_width = $char_width;//last separator char
$last_sepwidth = $s_width;
}
if ($c == "\t"){//TAB
$c = $s[$i] = "";
$char_width = $aExtraInfo['TAB_WIDTH'] * 1000;
}
if ($bParagraph == true){
$c = $s[$i] = "";
$char_width = $this->wt_TempData['LAST_TAB_REQSIZE']*1000 - $this->wt_TempData['LAST_TAB_SIZE'];
if ($char_width < 0) $char_width = 0;
}
$line_width += $char_width;
if($line_width > $wmax){//Automatic line break
$aExtraInfo['CURRENT_LINE_BR'] = "AUTO";
if ($total_chars == 0) {
/* This MEANS that the $w (width) is lower than a char width...
Put $i and $j to 1 ... otherwise infinite while*/
$i = 1;
$j = 1;
$return_result = true;//YES RETURN THE RESULT!!!
break;
}//fi
if ($last_sep <> -1){
//we have a separator in this tag!!!
//untill now there one separator
if (($last_sepch == $c) && ($last_sepch != " ") && ($ante_last_sep <> -1)){
/* this is the last character and it is a separator, if it is a space the leave it...
Have to jump back to the last separator... even a space
*/
$last_sep = $ante_last_sep;
$last_sepch = $ante_last_sepch;
$last_sepwidth = $ante_last_sepwidth;
}
if ($last_sepch == " "){
$j = $last_sep;//just ignore the last space (it is at end of line)
$i = $last_sep + 1;
if ( $spaces > 0 ) $spaces --;
$s_width = $last_sepwidth;
}else{
$j = $last_sep + 1;
$i = $last_sep + 1;
$s_width = $last_sepwidth + $last_sepch_width;
}
}elseif(count($aLine) > 0){
//we have elements in the last tag!!!!
if ($last_sepch == " "){//the last tag ends with a space, have to remove it
$temp = & $aLine[ count($aLine)-1 ];
if ($temp['text'][strlen($temp['text'])-1] == " "){
$temp['text'] = substr($temp['text'], 0, strlen($temp['text']) - 1);
$temp['width'] -= $fw[ $temp['tag'] ]['w'][" "] * $fw[ $temp['tag'] ]['s'];
$temp['spaces'] --;
//imediat return from this function
break 2;
}else{
#die("should not be!!!");
}//fi
}//fi
}//fi else
$return_result = true;
break;
}//fi - Auto line break
//increase the string width ONLY when it is added!!!!
$s_width += $char_width;
$i++;
$j = $i;
$total_chars ++;
}//while
$str = substr($s, 0, $j);
$sTmpStr = & $aDataInfo[$key]['text'];
$sTmpStr = substr($sTmpStr, $i, strlen($sTmpStr));
if (($sTmpStr == "") || ($sTmpStr === FALSE))//empty
array_shift($aDataInfo);
if ($val['text'] == $str){
}
if (!isset($val['href'])) $val['href']='';
if (!isset($val['ypos'])) $val['ypos']=0;
//we have a partial result
array_push($aLine, array(
'text' => $str,
'tag' => $val['tag'],
'href' => $val['href'],
'width' => $s_width,
'spaces' => $spaces,
'ypos' => $val['ypos']
));
$this->wt_TempData['LAST_TAB_SIZE'] = $s_width;
$this->wt_TempData['LAST_TAB_REQSIZE'] = (isset($val['size'])) ? $val['size'] : 0;
if ($return_result) break;//break this for
}//foreach
// Check the first and last tag -> if first and last caracters are " " space remove them!!!"
if ((count($aLine) > 0) && ($aExtraInfo['LAST_LINE_BR'] == "AUTO")){
//first tag
$temp = & $aLine[0];
if ( (strlen($temp['text']) > 0) && ($temp['text'][0] == " ")){
$temp['text'] = substr($temp['text'], 1, strlen($temp['text']));
$temp['width'] -= $fw[ $temp['tag'] ]['w'][" "] * $fw[ $temp['tag'] ]['s'];
$temp['spaces'] --;
}
//last tag
$temp = & $aLine[count($aLine) - 1];
if ( (strlen($temp['text'])>0) && ($temp['text'][strlen($temp['text'])-1] == " ")){
$temp['text'] = substr($temp['text'], 0, strlen($temp['text']) - 1);
$temp['width'] -= $fw[ $temp['tag'] ]['w'][" "] * $fw[ $temp['tag'] ]['s'];
$temp['spaces'] --;
}
}
if ($reset_spaces){//this is used in case of a "Explicit Line Break"
//put all spaces to 0 so in case of "J" align there is no space extension
for ($k=0; $k< count($aLine); $k++) $aLine[$k]['spaces'] = 0;
}//fi
return $aLine;
}//function MakeLine
/**
Draws a MultiCell with TAG recognition parameters
@param $w - with of the cell
$h - height of the cell
$pData - string or data to be printed
$border - border
$align - align
$fill - fill
$pDataIsString - true if $pData is a string
- false if $pData is an array containing lines formatted with $this->MakeLine($w) function
(the false option is used in relation with StringToLines, to avoid double formatting of a string
These paramaters are the same and have the same behavior as at Multicell function
@return nothing
*/
function MultiCellTag($w, $h, $pData, $border=0, $align='J', $fill=0, $pDataIsString = true){
//save the current style settings, this will be the default in case of no style is specified
$this->SaveCurrentStyle();
$this->_wt_Reset_Datas();
//if data is string
if ($pDataIsString === true) $this->DivideByTags($pData);
$b = $b1 = $b2 = $b3 = '';//borders
//save the current X position, we will have to jump back!!!!
$startX = $this -> GetX();
if($border)
{
if($border==1)
{
$border = 'LTRB';
$b1 = 'LRT';//without the bottom
$b2 = 'LR';//without the top and bottom
$b3 = 'LRB';//without the top
}
else
{
$b2='';
if(is_int(strpos($border,'L')))
$b2.='L';
if(is_int(strpos($border,'R')))
$b2.='R';
$b1=is_int(strpos($border,'T')) ? $b2 . 'T' : $b2;
$b3=is_int(strpos($border,'B')) ? $b2 . 'B' : $b2;
}
//used if there is only one line
$b = '';
$b .= is_int(strpos($border,'L')) ? 'L' : "";
$b .= is_int(strpos($border,'R')) ? 'R' : "";
$b .= is_int(strpos($border,'T')) ? 'T' : "";
$b .= is_int(strpos($border,'B')) ? 'B' : "";
}
$first_line = true;
$last_line = false;
if ($pDataIsString === true){
$last_line = !(count($this->wt_DataInfo) > 0);
}else {
$last_line = !(count($pData) > 0);
}
while(!$last_line){
if ($fill == 1){
//fill in the cell at this point and write after the text without filling
$this->Cell($w,$h,"",0,0,"",1);
$this->SetX($startX);//restore the X position
}
if ($pDataIsString === true){
//make a line
$str_data = $this->MakeLine($w);
//check for last line
$last_line = !(count($this->wt_DataInfo) > 0);
}else {
//make a line
$str_data = array_shift($pData);
//check for last line
$last_line = !(count($pData) > 0);
}
if ($last_line && ($align == "J")){//do not Justify the Last Line
$align = "L";
}
//outputs a line
$this->PrintLine($w, $h, $str_data, $align);
//see what border we draw:
if($first_line && $last_line){
//we have only 1 line
$real_brd = $b;
}elseif($first_line){
$real_brd = $b1;
}elseif($last_line){
$real_brd = $b3;
}else{
$real_brd = $b2;
}
if ($first_line) $first_line = false;
//draw the border and jump to the next line
$this->SetX($startX);//restore the X
$this->Cell($w,$h,"",$real_brd,2);
}//while(! $last_line){
//APPLY THE DEFAULT STYLE
$this->ApplyStyle("DEFAULT");
$this->x=$this->lMargin;
}//function MultiCellExt
/**
This method divides the string into the tags and puts the result into wt_DataInfo variable.
@param $pStr - string to be printed
@return nothing
*/
function DivideByTags($pStr, $return = false){
$pStr = str_replace("\t", "<ttags>\t</ttags>", $pStr);
$pStr = str_replace(PARAGRAPH_STRING, "<pparg>\t</pparg>", $pStr);
$pStr = str_replace("\r", "", $pStr);
//initialize the String_TAGS class
$sWork = new String_TAGS(5);
//get the string divisions by tags
$this->wt_DataInfo = $sWork->get_tags($pStr);
if ($return) return $this->wt_DataInfo;
}//function DivideByTags($pStr){
/**
This method parses the current text and return an array that contains the text information for
each line that will be drawed.
@param $w - with of the cell
$pStr - String to be parsed
@return $aStrLines - array - contains parsed text information.
*/
function StringToLines($w = 0, $pStr){
//save the current style settings, this will be the default in case of no style is specified
$this->SaveCurrentStyle();
$this->_wt_Reset_Datas();
$this->DivideByTags($pStr);
$last_line = !(count($this->wt_DataInfo) > 0);
$aStrLines = array();
while (!$last_line){
//make a line
$str_data = $this->MakeLine($w);
array_push($aStrLines, $str_data);
//check for last line
$last_line = !(count($this->wt_DataInfo) > 0);
}//while(! $last_line){
//APPLY THE DEFAULT STYLE
$this->ApplyStyle("DEFAULT");
return $aStrLines;
}//function StringToLines
/**
Draws a line returned from MakeLine function
@param $w - with of the cell
$h - height of the cell
$aTxt - array from MakeLine
$align - text align
@return nothing
*/
function PrintLine($w, $h, $aTxt, $align='J'){
if($w==0)
$w=$this->w-$this->rMargin - $this->x;
$wmax = $w; //Maximum width
$total_width = 0; //the total width of all strings
$total_spaces = 0; //the total number of spaces
$nr = count($aTxt);//number of elements
for ($i=0; $i<$nr; $i++){
$total_width += ($aTxt[$i]['width']/1000);
$total_spaces += $aTxt[$i]['spaces'];
}
//default
$w_first = $this->cMargin;
switch($align){
case 'J':
if ($total_spaces > 0)
$extra_space = ($wmax - 2 * $this->cMargin - $total_width) / $total_spaces;
else $extra_space = 0;
break;
case 'L':
break;
case 'C':
$w_first = ($wmax - $total_width) / 2;
break;
case 'R':
$w_first = $wmax - $total_width - $this->cMargin;;
break;
}
// Output the first Cell
if ($w_first != 0){
$this->Cell($w_first, $h, "", 0, 0, "L", 0);
}
$last_width = $wmax - $w_first;
while (list($key, $val) = each($aTxt)) {
$bYPosUsed = false;
//apply current tag style
$this->ApplyStyle($val['tag']);
//If > 0 then we will move the current X Position
$extra_X = 0;
if ($val['ypos'] != 0){
$lastY = $this->y;
$this->y = $lastY - $val['ypos'];
$bYPosUsed = true;
}
//string width
$width = $this->GetStringWidth($val['text']);
$width = $val['width'] / 1000;
if ($width == 0) continue;// No width jump over!!!
if($align=='J'){
if ($val['spaces'] < 1) $temp_X = 0;
else $temp_X = $extra_space;
$this->ws = $temp_X;
$this->_out(sprintf('%.3f Tw', $temp_X * $this->k));
$extra_X = $extra_space * $val['spaces'];//increase the extra_X Space
}else{
$this->ws = 0;
$this->_out('0 Tw');
}//fi
//Output the Text/Links
$this->Cell($width, $h, $val['text'], 0, 0, "C", 0, $val['href']);
$last_width -= $width;//last column width
if ($extra_X != 0){
$this -> SetX($this->GetX() + $extra_X);
$last_width -= $extra_X;
}//fi
if ($bYPosUsed) $this->y = $lastY;
}//while
// Output the Last Cell
if ($last_width != 0){
$this->Cell($last_width, $h, "", 0, 0, "", 0);
}//fi
}//function PrintLine(
}//class
class FPDF_TABLE extends FPDF_MULTICELLTAG
{
var $tb_columns; //number of columns of the table
var $tb_header_type; //array which contains the header characteristics and texts
var $tb_header_draw; //TRUE or FALSE, the header is drawed or not
var $tb_header_height; //This is the Table Header Maximum Height
var $tb_border_draw; //TRUE or FALSE, the table border is drawed or not
var $tb_data_type; //array which contains the data characteristics (only the characteristics)
var $tb_table_type; //array which contains the table charactersitics
var $table_startx, $table_starty; //the X and Y position where the table starts
var $tb_split_normal; /* << ** special request from Marc Ulfig >>
= false - the split is made only if the cell width does not fit into a page height
= true - the split of a cell will ocuur whenever necesary
*/
var $Draw_Header_Command; //command which determines in the DrawData first the header draw
var $Data_On_Current_Page; // = true/false ... if on current page was some data written
//returns the width of the page in user units
function PageWidth(){
return (int) $this->w-$this->rMargin-$this->lMargin;
}
//constructor(not a real one, but have to call it first)
//we initialize all the variables that we use
function Table_Init($col_no = 0, $header_draw = true, $border_draw = true){
$this->tb_columns = $col_no;
$this->tb_header_type = Array();
$this->tb_header_draw = $header_draw;
$this->tb_header_height = 0;
$this->tb_border_draw = $border_draw;
$this->tb_data_type = Array();
$this->tb_split_normal = true;
$this->tb_type = Array();
$this->table_startx = $this->GetX();
$this->table_starty = $this->GetY();
$this->Draw_Header_Command = false; //by default we don't draw the header
$this->Data_On_Current_Page = false;
}
//Sets the number of columns of the table
function Set_Table_Columns($nr){
$this->tb_columns = $nr;
}
//Sets the number of columns of the table
function Set_Table_SplitMode($pSplit = true){
$this->tb_split_normal = $pSplit;
}
/*
Characteristics constants for Header Type:
EVERY CELL FROM THE TABLE IS A MULTICELL
WIDTH - this is the cell width. This value must be sent only to the HEADER!!!!!!!!
T_COLOR - text color = array(r,g,b);
T_SIZE - text size
T_FONT - text font - font type = "Arial", "Times"
T_ALIGN - text align - "RLCJ"
V_ALIGN - text vertical alignment - "TMB"
T_TYPE - text type (Bold Italic etc)
LN_SPACE - space between lines
BG_COLOR - background color = array(r,g,b);
BRD_COLOR - border color = array(r,g,b);
BRD_SIZE - border size --
BRD_TYPE - border size -- up down, with border without!!! etc
BRD_TYPE_NEW_PAGE - border type on new page - this is user only if specified(<>'')
TEXT - header text -- THIS ALSO BELONGS ONLY TO THE HEADER!!!!
all these setting conform to the settings from the multicell functions!!!!
*/
/*
Function: Set_Header_Type($type_arr) -- sets the array for the header type
type array =
array(
0=>array(
"WIDTH" => 10,
"T_COLOR" => array(120,120,120),
"T_SIZE" => 5,
...
"TEXT" => "Header text 1"
),
1=>array(
...
),
);
where 0,1... are the column number
*/
function Set_Header_Type($type_arr){
$this->tb_header_type = $type_arr;
}
/*
Characteristics constants for Data Type:
EVERY CELL FROM THE TABLE IS A MULTICELL
T_COLOR - text color = array(r,g,b);
T_SIZE - text size
T_FONT - text font - font type = "Arial", "Times"
T_ALIGN - text align - "RLCJ"
V_ALIGN - text vertical alignment - "TMB"
T_TYPE - text type (Bold Italic etc)
LN_SPACE - space between lines
BG_COLOR - background color = array(r,g,b);
BRD_COLOR - border color = array(r,g,b);
BRD_SIZE - border size --
BRD_TYPE - border size -- up down, with border without!!! etc
BRD_TYPE_NEW_PAGE - border type on new page - this is user only if specified(<>'')
all these settings conform to the settings from the multicell functions!!!!
*/
/*
Function: Set_data_Type($type_arr) -- sets the array for the header type
type array =
array(
0=>array(
"T_COLOR" => array(120,120,120),
"T_SIZE" => 5,
...
"BRD_TYPE" => 1
),
1=>array(
...
),
);
where 0,1... are the column number
*/
function Set_Data_Type($type_arr){
$this->tb_data_type = $type_arr;
}
/*
Function Set_Table_Type
$type_arr = array(
"BRD_COLOR"=> array (120,120,120), //border color
"BRD_SIZE"=>5), //border line width
"TB_COLUMNS"=>5), //the number of columns
"TB_ALIGN"=>"L"), //the align of the table, possible values = L, R, C equivalent to Left, Right, Center
'L_MARGIN' => 0// left margin... reference from this->lmargin values
)
*/
function Set_Table_Type($type_arr){
if (isset($type_arr['TB_COLUMNS'])) $this->tb_columns = $type_arr['TB_COLUMNS'];
if (!isset($type_arr['L_MARGIN'])) $type_arr['L_MARGIN']=0;//default values
$this->tb_table_type = $type_arr;
}
//this functiondraws the exterior table border!!!!
function Draw_Table_Border(){
/* "BRD_COLOR"=> array (120,120,120), //border color
"BRD_SIZE"=>5), //border line width
"TB_COLUMNS"=>5), //the number of columns
"TB_ALIGN"=>"L"), //the align of the table, possible values = L, R, C equivalent to Left, Right, Center
*/
if ( ! $this->tb_border_draw ) return;
if ( ! $this->Data_On_Current_Page) return; //there was no data on the current page
//set the colors
list($r, $g, $b) = $this->tb_table_type['BRD_COLOR'];
$this->SetDrawColor($r, $g, $b);
//set the line width
$this->SetLineWidth($this->tb_table_type['BRD_SIZE']);
#echo $this->GetY()-$this->table_starty." ";;
//draw the border
$this->Rect(
$this->table_startx,
$this->table_starty,
$this->Get_Table_Width(),
$this->GetY()-$this->table_starty);
}
function End_Page_Border(){
if (isset($this->tb_table_type['BRD_TYPE_END_PAGE'])){
if (strpos($this->tb_table_type['BRD_TYPE_END_PAGE'], 'B') >= 0){
//set the colors
list($r, $g, $b) = $this->tb_table_type['BRD_COLOR'];
$this->SetDrawColor($r, $g, $b);
//set the line width
$this->SetLineWidth($this->tb_table_type['BRD_SIZE']);
//draw the line
$this->Line($this->table_startx, $this->GetY(), $this->table_startx + $this->Get_Table_Width(), $this->GetY());
}
}
}
//returns the table width in user units
function Get_Table_Width()
{
//calculate the table width
$tb_width = 0;
for ($i=0; $i < $this->tb_columns; $i++){
$tb_width += $this->tb_header_type[$i]['WIDTH'];
}
return $tb_width;
}
//alignes the table to C, L or R(default is L)
function Table_Align(){
//check if the table is aligned
if (isset($this->tb_table_type['TB_ALIGN'])) $tb_align = $this->tb_table_type['TB_ALIGN']; else $tb_align='';
//set the table align
switch($tb_align){
case 'C':
$this->SetX($this->lMargin + $this->tb_table_type['L_MARGIN'] + ($this->PageWidth() - $this->Get_Table_Width())/2);
break;
case 'R':
$this->SetX($this->lMargin + $this->tb_table_type['L_MARGIN'] + ($this->PageWidth() - $this->Get_Table_Width()));
break;
default:
$this->SetX($this->lMargin + $this->tb_table_type['L_MARGIN']);
break;
}//if (isset($this->tb_table_type['TB_ALIGN'])){
}
//Draws the Header
function Draw_Header(){
$this->Draw_Header_Command = true;
$this->tb_header_height = 0;
}
function Init_Table_Position(){
$this->Table_Align();
$this->table_startx = $this->GetX();
$this->table_starty = $this->GetY();
}
/**
Draws the header line from a table.
Call:
@param none
@return nothing
*/
function Draw_Header_(){
$this->tb_header_height = 0;
$this->Init_Table_Position();
$this->Draw_Header_Command = false;
//if the header will be showed
if ( ! $this->tb_header_draw ) return;
$this->DrawTableLine($this->tb_header_type, false, 1);
$this->Data_On_Current_Page = true;
}
/**
Draws a data line from the table.
Call this function after the table initialization, table, header and data types are set
Call:
@param $data - array containing line informations
$header - header will be drawed or not in case of new page
@return nothing
*/
function Draw_Data($data, $header = true){
$this->DrawTableLine($data, $header, 0);
}
/** Draws a data or header line from the table.
Call:
@param $data - array containing line informations
$header - header will be drawed or not in case of new page
$pDataType = 0 - normal line
1 - header line
2 - not implemented
@return nothing
*/
function DrawTableLine($data, $header, $pDataType = 0){
$h = 0;
$hm = 0;
$xx = Array();
$tt = Array();
if (!$this->Data_On_Current_Page) $this->Init_Table_Position();
if ($pDataType == 0){//data line
if ($this->Draw_Header_Command){//draw the header
$this->Draw_Header_();
}
}
//maximum Height available on this page
$AvailPageH = $this->PageBreakTrigger - $this->GetY();
if ($AvailPageH <= 0){ //there is no more space on this page
$this->TableAddPage($header);//add a page without header
$this->DrawTableLine($data, $header, $pDataType);//recall this function
return;//exit this function
}
$MaxPageH = $this->PageBreakTrigger - $this->tMargin;
$split = false;
$backdata = $data; //backup data in case of split or recall;
//calculate the maximum height of the cells
for($i=0; $i < $this->tb_columns; $i++)
{
if (!isset($data[$i]['TEXT']) || ($data[$i]['TEXT']=='')) $data[$i]['TEXT'] = " ";
if (!isset($data[$i]['T_FONT'])) $data[$i]['T_FONT'] = $this->tb_data_type[$i]['T_FONT'];
if (!isset($data[$i]['T_TYPE'])) $data[$i]['T_TYPE'] = $this->tb_data_type[$i]['T_TYPE'];
if (!isset($data[$i]['T_SIZE'])) $data[$i]['T_SIZE'] = $this->tb_data_type[$i]['T_SIZE'];
if (!isset($data[$i]['T_COLOR'])) $data[$i]['T_COLOR'] = $this->tb_data_type[$i]['T_COLOR'];
if (!isset($data[$i]['T_ALIGN'])) $data[$i]['T_ALIGN'] = $this->tb_data_type[$i]['T_ALIGN'];
if (!isset($data[$i]['V_ALIGN'])) $data[$i]['V_ALIGN'] = $this->tb_data_type[$i]['V_ALIGN'];
if (!isset($data[$i]['LN_SIZE'])) $data[$i]['LN_SIZE'] = $this->tb_data_type[$i]['LN_SIZE'];
if (!isset($data[$i]['BRD_SIZE'])) $data[$i]['BRD_SIZE'] = $this->tb_data_type[$i]['BRD_SIZE'];
if (!isset($data[$i]['BRD_COLOR'])) $data[$i]['BRD_COLOR'] = $this->tb_data_type[$i]['BRD_COLOR'];
if (!isset($data[$i]['BRD_TYPE'])) $data[$i]['BRD_TYPE'] = $this->tb_data_type[$i]['BRD_TYPE'];
if (!isset($data[$i]['BG_COLOR'])) $data[$i]['BG_COLOR'] = $this->tb_data_type[$i]['BG_COLOR'];
$this->SetFont( $data[$i]['T_FONT'],
$data[$i]['T_TYPE'],
$data[$i]['T_SIZE']);
$data[$i]['CELL_WIDTH'] = $this->tb_header_type[$i]['WIDTH'];
if (isset($data[$i]['COLSPAN'])){
$colspan = (int) $data[$i]['COLSPAN'];//convert to integer
for ($j = 1; $j < $colspan; $j++){
//if there is a colspan, then calculate the number of lines also with the with of the next cell
if (($i + $j) < $this->tb_columns)
$data[$i]['CELL_WIDTH'] += $this->tb_header_type[$i + $j]['WIDTH'];
}
}
$MaxLines = floor($AvailPageH / $data[$i]['LN_SIZE']);//floor this value, must be the lowest possible
if (!isset($data[$i]['TEXT_STRLINES'])) $data[$i]['TEXT_STRLINES'] = $this->StringToLines($data[$i]['CELL_WIDTH'], $data[$i]['TEXT']);
$NoLines = count($data[$i]['TEXT_STRLINES']);
$hm = max($hm, $data[$i]['LN_SIZE'] * $NoLines);//this would be the normal height
if ($NoLines > $MaxLines){
$split = true;
$NoLines = $MaxLines;
$data[$i]['TEXT_SPLITLINES'] = array_splice($data[$i]['TEXT_STRLINES'], $MaxLines);
}
$data[$i]['CELL_LINES'] = $NoLines;
//this is the maximum cell height
$h = max($h, $data[$i]['LN_SIZE'] * $data[$i]['CELL_LINES']);
if (isset($data[$i]['COLSPAN'])){
//just skip the other cells
$i = $i + $colspan - 1;
}
}
if ($pDataType == 0){//data line
if (!$this->tb_split_normal){//split only if the cell height is bigger than a page size
if ($split && (($hm + $this->tb_header_height) < $MaxPageH)){//if the header is splitted and it has space on a page
$this->TableAddPage($header);//add a page without header
$this->DrawTableLine($backdata, $header, 0);//recall this function
return;
}
}
}
if ($pDataType == 1){//header line
$this->tb_header_height = $hm;
if ($split && ($hm < $MaxPageH)){//if the header is splitted and it has space on a page
//new page
$this->TableAddPage(false);//add a page without header
$this->DrawTableLine($backdata, $header, 1);//recall this function
return;
}
if ( ((2*$h) > $AvailPageH) && ((2*$h) < $MaxPageH)){
/*
if the header double size is bigger then the available size
but the double size is smaller than a page size
>>> we draw a new page
**/
$this->TableAddPage(false);//add a page withot header
$this->DrawTableLine($backdata, $header, 1);//recall this function
return;
}
}
$this->Table_Align();
//Draw the cells of the row
for( $i = 0; $i < $this->tb_columns; $i++ )
{
//border size BRD_SIZE
$this->SetLineWidth($data[$i]['BRD_SIZE']);
//fill color = BG_COLOR
list($r, $g, $b) = $data[$i]['BG_COLOR'];
$this->SetFillColor($r, $g, $b);
//Draw Color = BRD_COLOR
list($r, $g, $b) = $data[$i]['BRD_COLOR'];
$this->SetDrawColor($r, $g, $b);
//Text Color = T_COLOR
list($r, $g, $b) = $data[$i]['T_COLOR'];
$this->SetTextColor($r, $g, $b);
//Set the font, font type and size
$this->SetFont( $data[$i]['T_FONT'],
$data[$i]['T_TYPE'],
$data[$i]['T_SIZE']);
//Save the current position
$x=$this->GetX();
$y=$this->GetY();
//print the text
$this->MultiCellTable(
$data[$i]['CELL_WIDTH'],
$data[$i]['LN_SIZE'],
$data[$i]['TEXT_STRLINES'],
$data[$i]['BRD_TYPE'],
$data[$i]['T_ALIGN'],
$data[$i]['V_ALIGN'],
1,
$h - $data[$i]['LN_SIZE'] * $data[$i]['CELL_LINES']
);
//Put the position to the right of the cell
$this->SetXY($x + $data[$i]['CELL_WIDTH'],$y);
//if we have colspan, just ignore the next cells
if (isset($data[$i]['COLSPAN'])){
$i = $i + (int)$data[$i]['COLSPAN'] - 1;
}
}
$this->Data_On_Current_Page = true;
//Go to the next line
$this->Ln($h);
if ($split){
//calculate the maximum height of the cells
for($i=0; $i < $this->tb_columns; $i++){
$backdata[$i]['TEXT_STRLINES'] = isset($data[$i]['TEXT_SPLITLINES']) ? $data[$i]['TEXT_SPLITLINES'] : array();
}
$this->TableAddPage($header);//we have a page split, add a page
if ($pDataType == 1) $header = false;
$this->DrawTableLine($backdata, $header, $pDataType);
}
}//DrawTableLine
/** Adds a new page in the pdf document and initializes the table and the header if necessary.
Call:
@param
$header - boolean - if the header is drawed or not
@return nothing
*/
function TableAddPage($header = true){
$this->Draw_Table_Border();//draw the table border
$this->End_Page_Border();//if there is a special handling for end page??? this is specific for me
$this->AddPage($this->CurOrientation);//add a new page
$this->Data_On_Current_Page = false;
$this->table_startx = $this->GetX();
$this->table_starty = $this->GetY();
if ($header) $this ->Draw_Header();//if we have to draw the header!!!
}//TableAddPage
/** This method allows printing text with line breaks.
It works like a modified MultiCell
Call:
@param
$w - width
$h - line height
$txtData - the outputed text
$border - border(LRTB 0 or 1)
$align - horizontal align 'JLR'
$valign - Vertical Alignment - Top, Middle, Bottom
$fill - fill (1/0)
$vh - vertical adjustment - the Multicell Height will be with this VH Higher!!!!
@return nothing
*/
function MultiCellTable($w, $h, $txtData, $border=0, $align='J', $valign='T', $fill=0, $vh=0)
{
$b1 = '';//border for top cell
$b2 = '';//border for middle cell
$b3 = '';//border for bottom cell
if($border)
{
if($border==1)
{
$border = 'LTRB';
$b1 = 'LRT';//without the bottom
$b2 = 'LR';//without the top and bottom
$b3 = 'LRB';//without the top
}
else
{
$b2='';
if(is_int(strpos($border,'L')))
$b2.='L';
if(is_int(strpos($border,'R')))
$b2.='R';
$b1=is_int(strpos($border,'T')) ? $b2.'T' : $b2;
$b3=is_int(strpos($border,'B')) ? $b2.'B' : $b2;
}
}
switch ($valign){
case 'T':
$wh_T = 0;//Top width
$wh_B = $vh - $wh_T;//Bottom width
break;
case 'M':
$wh_T = $vh/2;
$wh_B = $vh/2;
break;
case 'B':
$wh_T = $vh;
$wh_B = 0;
break;
default://default is TOP ALIGN
$wh_T = 0;//Top width
$wh_B = $vh - $wh_T;//Bottom width
}
//save the X position
$x = $this->x;
/*
if $wh_T == 0 that means that we have no vertical adjustments so I will skip the cells that
draws the top and bottom borders
*/
if ($wh_T != 0)//only when there is a difference
{
//draw the top borders!!!
$this->Cell($w,$wh_T,'',$b1,2,$align,$fill);
}
$b2 = is_int(strpos($border,'T')) && ($wh_T == 0) ? $b2.'T' : $b2;
$b2 = is_int(strpos($border,'B')) && ($wh_B == 0) ? $b2.'B' : $b2;
#$this->MultiCell($w,$h,$txt,$b2,$align,$fill);
$this->MultiCellTag($w, $h, $txtData, $b2, $align, 1, false);
if ($wh_B != 0){//only when there is a difference
//go to the saved X position
//a multicell always runs to the begin of line
$this->x = $x;
$this->Cell($w, $wh_B, '', $b3, 2, $align,$fill);
$this->x=$this->lMargin;
}
}
}//end of pdf_table class
define('HTML2FPDF_VERSION','3.0(beta)');
if (!defined('RELATIVE_PATH')) define('RELATIVE_PATH','');
if (!defined('FPDF_FONTPATH')) define('FPDF_FONTPATH','font/');
require_once(RELATIVE_PATH.'fpdf.php');
require_once(RELATIVE_PATH.'htmltoolkit.php');
class HTML2FPDF extends FPDF_TABLE
{
//internal attributes
var $HREF; //! string
var $pgwidth; //! float
var $fontlist; //! array
var $issetfont; //! bool
var $issetcolor; //! bool
var $titulo; //! string
var $oldx; //! float
var $oldy; //! float
var $B; //! int
var $U; //! int
var $I; //! int
var $tablestart; //! bool
var $tdbegin; //! bool
var $table; //! array
var $cell; //! array
var $col; //! int
var $row; //! int
var $divbegin; //! bool
var $divalign; //! char
var $divwidth; //! float
var $divheight; //! float
var $divbgcolor; //! bool
var $divcolor; //! bool
var $divborder; //! int
var $divrevert; //! bool
var $listlvl; //! int
var $listnum; //! int
var $listtype; //! string
//array(lvl,# of occurrences)
var $listoccur; //! array
//array(lvl,occurrence,type,maxnum)
var $listlist; //! array
//array(lvl,num,content,type)
var $listitem; //! array
var $buffer_on; //! bool
var $pbegin; //! bool
var $pjustfinished; //! bool
var $blockjustfinished; //! bool
var $SUP; //! bool
var $SUB; //! bool
var $toupper; //! bool
var $tolower; //! bool
var $dash_on; //! bool
var $dotted_on; //! bool
var $strike; //! bool
var $CSS; //! array
var $cssbegin; //! bool
var $backupcss; //! array
var $textbuffer; //! array
var $currentstyle; //! string
var $currentfont; //! string
var $colorarray; //! array
var $bgcolorarray; //! array
var $internallink; //! array
var $enabledtags; //! string
var $lineheight; //! int
var $basepath; //! string
// array('COLOR','WIDTH','OLDWIDTH')
var $outlineparam; //! array
var $outline_on; //! bool
var $specialcontent; //! string
var $selectoption; //! array
//options attributes
var $usecss; //! bool
var $usepre; //! bool
var $usetableheader; //! bool
var $shownoimg; //! bool
function HTML2FPDF($orientation='P',$unit='mm',$format='A4')
{
//! @desc Constructor
//! @return An object (a class instance)
//Call parent constructor
$this->FPDF($orientation,$unit,$format);
//To make the function Footer() work properly
$this->AliasNbPages();
//Enable all tags as default
$this->DisableTags();
//Set default display preferences
$this->DisplayPreferences('');
//Initialization of the attributes
$this->SetFont('Arial','',11); // Changeable?(not yet...)
$this->lineheight = 5; // Related to FontSizePt == 11
$this->pgwidth = $this->fw - $this->lMargin - $this->rMargin ;
$this->SetFillColor(255);
$this->HREF='';
$this->titulo='';
$this->oldx=-1;
$this->oldy=-1;
$this->B=0;
$this->U=0;
$this->I=0;
$this->listlvl=0;
$this->listnum=0;
$this->listtype='';
$this->listoccur=array();
$this->listlist=array();
$this->listitem=array();
$this->tablestart=false;
$this->tdbegin=false;
$this->table=array();
$this->cell=array();
$this->col=-1;
$this->row=-1;
$this->divbegin=false;
$this->divalign="L";
$this->divwidth=0;
$this->divheight=0;
$this->divbgcolor=false;
$this->divcolor=false;
$this->divborder=0;
$this->divrevert=false;
$this->fontlist=array("arial","times","courier","helvetica","symbol","monospace","serif","sans");
$this->issetfont=false;
$this->issetcolor=false;
$this->pbegin=false;
$this->pjustfinished=false;
$this->blockjustfinished = true; //in order to eliminate exceeding left-side spaces
$this->toupper=false;
$this->tolower=false;
$this->dash_on=false;
$this->dotted_on=false;
$this->SUP=false;
$this->SUB=false;
$this->buffer_on=false;
$this->strike=false;
$this->currentfont='';
$this->currentstyle='';
$this->colorarray=array();
$this->bgcolorarray=array();
$this->cssbegin=false;
$this->textbuffer=array();
$this->CSS=array();
$this->backupcss=array();
$this->internallink=array();
$this->basepath = "";
$this->outlineparam = array();
$this->outline_on = false;
$this->specialcontent = '';
$this->selectoption = array();
$this->shownoimg=false;
$this->usetableheader=false;
$this->usecss=true;
$this->usepre=true;
}
function setBasePath($str)
{
//! @desc Inform the script where the html file is (full path - e.g. http://www.google.com/dir1/dir2/dir3/file.html ) in order to adjust HREF and SRC links. No-Parameter: The directory where this script is.
//! @return void
$this->basepath = dirname($str) . "/";
$this->basepath = str_replace("\\","/",$this->basepath); //If on Windows
}
function ShowNOIMG_GIF($opt=true)
{
//! @desc Enable/Disable Displaying the no_img.gif when an image is not found. No-Parameter: Enable
//! @return void
$this->shownoimg=$opt;
}
function UseCSS($opt=true)
{
//! @desc Enable/Disable CSS recognition. No-Parameter: Enable
//! @return void
$this->usecss=$opt;
}
function UseTableHeader($opt=true)
{
//! @desc Enable/Disable Table Header to appear every new page. No-Parameter: Enable
//! @return void
$this->usetableheader=$opt;
}
function UsePRE($opt=true)
{
//! @desc Enable/Disable pre tag recognition. No-Parameter: Enable
//! @return void
$this->usepre=$opt;
}
//Page header
function Header($content='')
{
//! @return void
//! @desc The header is printed in every page.
if($this->usetableheader and $content != '')
{
$y = $this->y;
foreach($content as $tableheader)
{
$this->y = $y;
//Set some cell values
$x = $tableheader['x'];
$w = $tableheader['w'];
$h = $tableheader['h'];
$va = $tableheader['va'];
$mih = $tableheader['mih'];
$fill = $tableheader['bgcolor'];
$border = $tableheader['border'];
$align = $tableheader['a'];
//Align
$this->divalign=$align;
$this->x = $x;
//Vertical align
if (!isset($va) || $va=='M') $this->y += ($h-$mih)/2;
elseif (isset($va) && $va=='B') $this->y += $h-$mih;
if ($fill)
{
$color = ConvertColor($fill);
$this->SetFillColor($color['R'],$color['G'],$color['B']);
$this->Rect($x, $y, $w, $h, 'F');
}
//Border
if (isset($border) and $border != 'all') $this->_tableRect($x, $y, $w, $h, $border);
elseif (isset($border) && $border == 'all') $this->Rect($x, $y, $w, $h);
//Print cell content
$this->divwidth = $w-2;
$this->divheight = 1.1*$this->lineheight;
$textbuffer = $tableheader['textbuffer'];
if (!empty($textbuffer)) $this->printbuffer($textbuffer,false,true/*inside a table*/);
$textbuffer = array();
}
$this->y = $y + $h; //Update y coordinate
}//end of 'if usetableheader ...'
}
//Page footer
function Footer()
{
//! @return void
//! @desc The footer is printed in every page!
//Position at 1.0 cm from bottom
$this->SetY(-10);
//Copyright //especial para esta versão
$this->SetFont('Arial','B',9);
$this->SetTextColor(0);
//Arial italic 9
$this->SetFont('Arial','I',9);
//Page number
$this->Cell(0,10,$this->PageNo().'/{nb}',0,0,'C');
//Return Font to normal
$this->SetFont('Arial','',11);
}
///////////////////
/// HTML parser ///
///////////////////
function WriteHTML($html)
{
//! @desc HTML parser
//! @return void
/* $e == content */
$this->ReadMetaTags($html);
$html = AdjustHTML($html,$this->usepre); //Try to make HTML look more like XHTML
if ($this->usecss) $html = $this->ReadCSS($html);
//Add new supported tags in the DisableTags function
$html=str_replace('<?','< ',$html); //Fix '<?XML' bug from HTML code generated by MS Word
$html=strip_tags($html,$this->enabledtags); //remove all unsupported tags, but the ones inside the 'enabledtags' string
//Explode the string in order to parse the HTML code
$a=preg_split('/<(.*?)>/ms',$html,-1,PREG_SPLIT_DELIM_CAPTURE);
foreach($a as $i => $e)
{
if($i%2==0)
{
//TEXT
//Adjust lineheight
// $this->lineheight = (5*$this->FontSizePt)/11; //should be inside printbuffer?
//Adjust text, if needed
if (strpos($e,"&") !== false) //HTML-ENTITIES decoding
{
if (strpos($e,"#") !== false) $e = value_entity_decode($e); // Decode value entities
//Avoid crashing the script on PHP 4.0
$version = phpversion();
$version = str_replace('.','',$version);
if ($version >= 430) $e = html_entity_decode($e,ENT_QUOTES,'cp1252'); // changes &nbsp; and the like by their respective char
else $e = lesser_entity_decode($e);
}
$e = str_replace(chr(160),chr(32),$e); //unify ascii code of spaces (in order to recognize all of them correctly)
if (strlen($e) == 0) continue;
if ($this->divrevert) $e = strrev($e);
if ($this->toupper) $e = strtoupper($e);
if ($this->tolower) $e = strtolower($e);
//Start of 'if/elseif's
if($this->titulo) $this->SetTitle($e);
elseif($this->specialcontent)
{
if ($this->specialcontent == "type=select" and $this->selectoption['ACTIVE'] == true) //SELECT tag (form element)
{
$stringwidth = $this->GetStringWidth($e);
if (!isset($this->selectoption['MAXWIDTH']) or $stringwidth > $this->selectoption['MAXWIDTH']) $this->selectoption['MAXWIDTH'] = $stringwidth;
if (!isset($this->selectoption['SELECTED']) or $this->selectoption['SELECTED'] == '') $this->selectoption['SELECTED'] = $e;
}
else $this->textbuffer[] = array("»¤¬"/*identifier*/.$this->specialcontent."»¤¬".$e);
}
elseif($this->tablestart)
{
if($this->tdbegin)
{
$this->cell[$this->row][$this->col]['textbuffer'][] = array($e,$this->HREF,$this->currentstyle,$this->colorarray,$this->currentfont,$this->SUP,$this->SUB,''/*internal link*/,$this->strike,$this->outlineparam,$this->bgcolorarray);
$this->cell[$this->row][$this->col]['text'][] = $e;
$this->cell[$this->row][$this->col]['s'] += $this->GetStringWidth($e);
}
//Ignore content between <table>,<tr> and a <td> tag (this content is usually only a bunch of spaces)
}
elseif($this->pbegin or $this->HREF or $this->divbegin or $this->SUP or $this->SUB or $this->strike or $this->buffer_on) $this->textbuffer[] = array($e,$this->HREF,$this->currentstyle,$this->colorarray,$this->currentfont,$this->SUP,$this->SUB,''/*internal link*/,$this->strike,$this->outlineparam,$this->bgcolorarray); //Accumulate text on buffer
else
{
if ($this->blockjustfinished) $e = ltrim($e);
if ($e != '')
{
$this->Write($this->lineheight,$e); //Write text directly in the PDF
if ($this->pjustfinished) $this->pjustfinished = false;
}
}
}
else
{
//Tag
if($e{0}=='/') $this->CloseTag(strtoupper(substr($e,1)));
else
{
$regexp = '|=\'(.*?)\'|s'; // eliminate single quotes, if any
$e = preg_replace($regexp,"=\"\$1\"",$e);
$regexp = '| (\\w+?)=([^\\s>"]+)|si'; // changes anykey=anyvalue to anykey="anyvalue" (only do this when this happens inside tags)
$e = preg_replace($regexp," \$1=\"\$2\"",$e);
//Fix path values, if needed
if ((stristr($e,"href=") !== false) or (stristr($e,"src=") !== false) )
{
$regexp = '/ (href|src)="(.*?)"/i';
preg_match($regexp,$e,$auxiliararray);
$path = $auxiliararray[2];
$path = str_replace("\\","/",$path); //If on Windows
//Get link info and obtain its absolute path
$regexp = '|^./|';
$path = preg_replace($regexp,'',$path);
if($path{0} != '#') //It is not an Internal Link
{
if (strpos($path,"../") !== false ) //It is a Relative Link
{
$backtrackamount = substr_count($path,"../");
$maxbacktrack = substr_count($this->basepath,"/") - 1;
$filepath = str_replace("../",'',$path);
$path = $this->basepath;
//If it is an invalid relative link, then make it go to directory root
if ($backtrackamount > $maxbacktrack) $backtrackamount = $maxbacktrack;
//Backtrack some directories
for( $i = 0 ; $i < $backtrackamount + 1 ; $i++ ) $path = substr( $path, 0 , strrpos($path,"/") );
$path = $path . "/" . $filepath; //Make it an absolute path
}
elseif( strpos($path,":/") === false) //It is a Local Link
{
$path = $this->basepath . $path;
}
//Do nothing if it is an Absolute Link
}
$regexp = '/ (href|src)="(.*?)"/i';
$e = preg_replace($regexp,' \\1="'.$path.'"',$e);
}//END of Fix path values
//Extract attributes
$contents=array();
preg_match_all('/\\S*=["\'][^"\']*["\']/',$e,$contents);
preg_match('/\\S+/',$e,$a2);
$tag=strtoupper($a2[0]);
$attr=array();
if (!empty($contents))
{
foreach($contents[0] as $v)
{
if(ereg('^([^=]*)=["\']?([^"\']*)["\']?$',$v,$a3))
{
$attr[strtoupper($a3[1])]=$a3[2];
}
}
}
$this->OpenTag($tag,$attr);
}
}
}//end of foreach($a as $i=>$e)
//Create Internal Links, if needed
if (!empty($this->internallink) )
{
foreach($this->internallink as $k=>$v)
{
if (strpos($k,"#") !== false ) continue; //ignore
$ypos = $v['Y'];
$pagenum = $v['PAGE'];
$sharp = "#";
while (array_key_exists($sharp.$k,$this->internallink))
{
$internallink = $this->internallink[$sharp.$k];
$this->SetLink($internallink,$ypos,$pagenum);
$sharp .= "#";
}
}
}
}
function OpenTag($tag,$attr)
{
//! @return void
// What this gets: < $tag $attr['WIDTH']="90px" > does not get content here </closeTag here>
$align = array('left'=>'L','center'=>'C','right'=>'R','top'=>'T','middle'=>'M','bottom'=>'B','justify'=>'J');
$this->blockjustfinished=false;
//Opening tag
switch($tag){
case 'PAGE_BREAK': //custom-tag
case 'NEWPAGE': //custom-tag
$this->blockjustfinished = true;
$this->AddPage();
break;
case 'OUTLINE': //custom-tag (CSS2 property - browsers don't support it yet - Jan2005)
//Usage: (default: width=normal color=white)
//<outline width="(thin|medium|thick)" color="(usualcolorformat)" >Text</outline>
//Mix this tag with the <font color="(usualcolorformat)"> tag to get mixed colors on outlined text!
$this->buffer_on = true;
if (isset($attr['COLOR'])) $this->outlineparam['COLOR'] = ConvertColor($attr['COLOR']);
else $this->outlineparam['COLOR'] = array('R'=>255,'G'=>255,'B'=>255); //white
$this->outlineparam['OLDWIDTH'] = $this->LineWidth;
if (isset($attr['WIDTH']))
{
switch(strtoupper($attr['WIDTH']))
{
case 'THIN': $this->outlineparam['WIDTH'] = 0.75*$this->LineWidth; break;
case 'MEDIUM': $this->outlineparam['WIDTH'] = $this->LineWidth; break;
case 'THICK': $this->outlineparam['WIDTH'] = 1.75*$this->LineWidth; break;
}
}
else $this->outlineparam['WIDTH'] = $this->LineWidth; //width == oldwidth
break;
case 'BDO':
if (isset($attr['DIR']) and (strtoupper($attr['DIR']) == 'RTL' )) $this->divrevert = true;
break;
case 'S':
case 'STRIKE':
case 'DEL':
$this->strike=true;
break;
case 'SUB':
$this->SUB=true;
break;
case 'SUP':
$this->SUP=true;
break;
case 'CENTER':
$this->buffer_on = true;
if ($this->tdbegin) $this->cell[$this->row][$this->col]['a'] = $align['center'];
else
{
$this->divalign = $align['center'];
if ($this->x != $this->lMargin) $this->Ln($this->lineheight);
}
break;
case 'ADDRESS':
$this->buffer_on = true;
$this->SetStyle('I',true);
if (!$this->tdbegin and $this->x != $this->lMargin) $this->Ln($this->lineheight);
break;
case 'TABLE': // TABLE-BEGIN
if ($this->x != $this->lMargin) $this->Ln($this->lineheight);
$this->tablestart = true;
$this->table['nc'] = $this->table['nr'] = 0;
if (isset($attr['REPEAT_HEADER']) and $attr['REPEAT_HEADER'] == true) $this->UseTableHeader(true);
if (isset($attr['WIDTH'])) $this->table['w'] = ConvertSize($attr['WIDTH'],$this->pgwidth);
if (isset($attr['HEIGHT'])) $this->table['h'] = ConvertSize($attr['HEIGHT'],$this->pgwidth);
if (isset($attr['ALIGN'])) $this->table['a'] = $align[strtolower($attr['ALIGN'])];
if (isset($attr['BORDER'])) $this->table['border'] = $attr['BORDER'];
if (isset($attr['BGCOLOR'])) $this->table['bgcolor'][-1] = $attr['BGCOLOR'];
break;
case 'TR':
$this->row++;
$this->table['nr']++;
$this->col = -1;
if (isset($attr['BGCOLOR']))$this->table['bgcolor'][$this->row] = $attr['BGCOLOR'];
break;
case 'TH':
$this->SetStyle('B',true);
if (!isset($attr['ALIGN'])) $attr['ALIGN'] = "center";
case 'TD':
$this->tdbegin = true;
$this->col++;
while (isset($this->cell[$this->row][$this->col])) $this->col++;
//Update number column
if ($this->table['nc'] < $this->col+1) $this->table['nc'] = $this->col+1;
$this->cell[$this->row][$this->col] = array();
$this->cell[$this->row][$this->col]['text'] = array();
$this->cell[$this->row][$this->col]['s'] = 3;
if (isset($attr['WIDTH'])) $this->cell[$this->row][$this->col]['w'] = ConvertSize($attr['WIDTH'],$this->pgwidth);
if (isset($attr['HEIGHT'])) $this->cell[$this->row][$this->col]['h'] = ConvertSize($attr['HEIGHT'],$this->pgwidth);
if (isset($attr['ALIGN'])) $this->cell[$this->row][$this->col]['a'] = $align[strtolower($attr['ALIGN'])];
if (isset($attr['VALIGN'])) $this->cell[$this->row][$this->col]['va'] = $align[strtolower($attr['VALIGN'])];
if (isset($attr['BORDER'])) $this->cell[$this->row][$this->col]['border'] = $attr['BORDER'];
if (isset($attr['BGCOLOR'])) $this->cell[$this->row][$this->col]['bgcolor'] = $attr['BGCOLOR'];
$cs = $rs = 1;
if (isset($attr['COLSPAN']) && $attr['COLSPAN']>1) $cs = $this->cell[$this->row][$this->col]['colspan'] = $attr['COLSPAN'];
if (isset($attr['ROWSPAN']) && $attr['ROWSPAN']>1) $rs = $this->cell[$this->row][$this->col]['rowspan'] = $attr['ROWSPAN'];
//Chiem dung vi tri de danh cho cell span (¿mais hein?)
for ($k=$this->row ; $k < $this->row+$rs ;$k++)
for($l=$this->col; $l < $this->col+$cs ;$l++)
{
if ($k-$this->row || $l-$this->col) $this->cell[$k][$l] = 0;
}
if (isset($attr['NOWRAP'])) $this->cell[$this->row][$this->col]['nowrap']= 1;
break;
case 'OL':
if ( !isset($attr['TYPE']) or $attr['TYPE'] == '' ) $this->listtype = '1'; //OL default == '1'
else $this->listtype = $attr['TYPE']; // ol and ul types are mixed here
case 'UL':
if ( (!isset($attr['TYPE']) or $attr['TYPE'] == '') and $tag=='UL')
{
//Insert UL defaults
if ($this->listlvl == 0) $this->listtype = 'disc';
elseif ($this->listlvl == 1) $this->listtype = 'circle';
else $this->listtype = 'square';
}
elseif (isset($attr['TYPE']) and $tag=='UL') $this->listtype = $attr['TYPE'];
$this->buffer_on = false;
if ($this->listlvl == 0)
{
//First of all, skip a line
if (!$this->pjustfinished)
{
if ($this->x != $this->lMargin) $this->Ln($this->lineheight);
$this->Ln($this->lineheight);
}
$this->oldx = $this->x;
$this->listlvl++; // first depth level
$this->listnum = 0; // reset
$this->listoccur[$this->listlvl] = 1;
$this->listlist[$this->listlvl][1] = array('TYPE'=>$this->listtype,'MAXNUM'=>$this->listnum);
}
else
{
if (!empty($this->textbuffer))
{
$this->listitem[] = array($this->listlvl,$this->listnum,$this->textbuffer,$this->listoccur[$this->listlvl]);
$this->listnum++;
}
$this->textbuffer = array();
$occur = $this->listoccur[$this->listlvl];
$this->listlist[$this->listlvl][$occur]['MAXNUM'] = $this->listnum; //save previous lvl's maxnum
$this->listlvl++;
$this->listnum = 0; // reset
if ($this->listoccur[$this->listlvl] == 0) $this->listoccur[$this->listlvl] = 1;
else $this->listoccur[$this->listlvl]++;
$occur = $this->listoccur[$this->listlvl];
$this->listlist[$this->listlvl][$occur] = array('TYPE'=>$this->listtype,'MAXNUM'=>$this->listnum);
}
break;
case 'LI':
//Observation: </LI> is ignored
if ($this->listlvl == 0) //in case of malformed HTML code. Example:(...)</p><li>Content</li><p>Paragraph1</p>(...)
{
//First of all, skip a line
if (!$this->pjustfinished and $this->x != $this->lMargin) $this->Ln(2*$this->lineheight);
$this->oldx = $this->x;
$this->listlvl++; // first depth level
$this->listnum = 0; // reset
$this->listoccur[$this->listlvl] = 1;
$this->listlist[$this->listlvl][1] = array('TYPE'=>'disc','MAXNUM'=>$this->listnum);
}
if ($this->listnum == 0)
{
$this->buffer_on = true; //activate list 'bufferization'
$this->listnum++;
$this->textbuffer = array();
}
else
{
$this->buffer_on = true; //activate list 'bufferization'
if (!empty($this->textbuffer))
{
$this->listitem[] = array($this->listlvl,$this->listnum,$this->textbuffer,$this->listoccur[$this->listlvl]);
$this->listnum++;
}
$this->textbuffer = array();
}
break;
case 'H1': // 2 * fontsize
case 'H2': // 1.5 * fontsize
case 'H3': // 1.17 * fontsize
case 'H4': // 1 * fontsize
case 'H5': // 0.83 * fontsize
case 'H6': // 0.67 * fontsize
//Values obtained from: http://www.w3.org/TR/REC-CSS2/sample.html
if(isset($attr['ALIGN'])) $this->divalign = $align[strtolower($attr['ALIGN'])];
$this->buffer_on = true;
if ($this->x != $this->lMargin) $this->Ln(2*$this->lineheight);
elseif (!$this->pjustfinished) $this->Ln($this->lineheight);
$this->SetStyle('B',true);
switch($tag)
{
case 'H1':
$this->SetFontSize(2*$this->FontSizePt);
$this->lineheight *= 2;
break;
case 'H2':
$this->SetFontSize(1.5*$this->FontSizePt);
$this->lineheight *= 1.5;
break;
case 'H3':
$this->SetFontSize(1.17*$this->FontSizePt);
$this->lineheight *= 1.17;
break;
case 'H4':
$this->SetFontSize($this->FontSizePt);
break;
case 'H5':
$this->SetFontSize(0.83*$this->FontSizePt);
$this->lineheight *= 0.83;
break;
case 'H6':
$this->SetFontSize(0.67*$this->FontSizePt);
$this->lineheight *= 0.67;
break;
}
break;
case 'HR': //Default values: width=100% align=center color=gray
//Skip a line, if needed
if ($this->x != $this->lMargin) $this->Ln($this->lineheight);
$this->Ln(0.2*$this->lineheight);
$hrwidth = $this->pgwidth;
$hralign = 'C';
$hrcolor = array('R'=>200,'G'=>200,'B'=>200);
if($attr['WIDTH'] != '') $hrwidth = ConvertSize($attr['WIDTH'],$this->pgwidth);
if($attr['ALIGN'] != '') $hralign = $align[strtolower($attr['ALIGN'])];
if($attr['COLOR'] != '') $hrcolor = ConvertColor($attr['COLOR']);
$this->SetDrawColor($hrcolor['R'],$hrcolor['G'],$hrcolor['B']);
$x = $this->x;
$y = $this->y;
switch($hralign)
{
case 'L':
case 'J':
break;
case 'C':
$empty = $this->pgwidth - $hrwidth;
$empty /= 2;
$x += $empty;
break;
case 'R':
$empty = $this->pgwidth - $hrwidth;
$x += $empty;
break;
}
$oldlinewidth = $this->LineWidth;
$this->SetLineWidth(0.3);
$this->Line($x,$y,$x+$hrwidth,$y);
$this->SetLineWidth($oldlinewidth);
$this->Ln(0.2*$this->lineheight);
$this->SetDrawColor(0);
$this->blockjustfinished = true; //Eliminate exceeding left-side spaces
break;
case 'INS':
$this->SetStyle('U',true);
break;
case 'SMALL':
$newsize = $this->FontSizePt - 1;
$this->SetFontSize($newsize);
break;
case 'BIG':
$newsize = $this->FontSizePt + 1;
$this->SetFontSize($newsize);
case 'STRONG':
$this->SetStyle('B',true);
break;
case 'CITE':
case 'EM':
$this->SetStyle('I',true);
break;
case 'TITLE':
$this->titulo = true;
break;
case 'B':
case 'I':
case 'U':
if( isset($attr['CLASS']) or isset($attr['ID']) or isset($attr['STYLE']) )
{
$this->cssbegin=true;
if (isset($attr['CLASS'])) $properties = $this->CSS[$attr['CLASS']];
elseif (isset($attr['ID'])) $properties = $this->CSS[$attr['ID']];
//Read Inline CSS
if (isset($attr['STYLE'])) $properties = $this->readInlineCSS($attr['STYLE']);
//Look for name in the $this->CSS array
$this->backupcss = $properties;
if (!empty($properties)) $this->setCSS($properties); //name found in the CSS array!
}
$this->SetStyle($tag,true);
break;
case 'A':
if (isset($attr['NAME']) and $attr['NAME'] != '') $this->textbuffer[] = array('','','',array(),'',false,false,$attr['NAME']); //an internal link (adds a space for recognition)
if (isset($attr['HREF'])) $this->HREF=$attr['HREF'];
break;
case 'DIV':
//in case of malformed HTML code. Example:(...)</div><li>Content</li><div>DIV1</div>(...)
if ($this->listlvl > 0) // We are closing (omitted) OL/UL tag(s)
{
$this->buffer_on = false;
if (!empty($this->textbuffer)) $this->listitem[] = array($this->listlvl,$this->listnum,$this->textbuffer,$this->listoccur[$this->listlvl]);
$this->textbuffer = array();
$this->listlvl--;
$this->printlistbuffer();
$this->pjustfinished = true; //act as if a paragraph just ended
}
$this->divbegin=true;
if ($this->x != $this->lMargin) $this->Ln($this->lineheight);
if( isset($attr['ALIGN']) and $attr['ALIGN'] != '' ) $this->divalign = $align[strtolower($attr['ALIGN'])];
if( isset($attr['CLASS']) or isset($attr['ID']) or isset($attr['STYLE']) )
{
$this->cssbegin=true;
if (isset($attr['CLASS'])) $properties = $this->CSS[$attr['CLASS']];
elseif (isset($attr['ID'])) $properties = $this->CSS[$attr['ID']];
//Read Inline CSS
if (isset($attr['STYLE'])) $properties = $this->readInlineCSS($attr['STYLE']);
//Look for name in the $this->CSS array
if (!empty($properties)) $this->setCSS($properties); //name found in the CSS array!
}
break;
case 'IMG':
if(!empty($this->textbuffer) and !$this->tablestart)
{
//Output previously buffered content and output image below
//Set some default values
$olddivwidth = $this->divwidth;
$olddivheight = $this->divheight;
if ( $this->divwidth == 0) $this->divwidth = $this->pgwidth - $x + $this->lMargin;
if ( $this->divheight == 0) $this->divheight = $this->lineheight;
//Print content
$this->printbuffer($this->textbuffer,true/*is out of a block (e.g. DIV,P etc.)*/);
$this->textbuffer=array();
//Reset values
$this->divwidth = $olddivwidth;
$this->divheight = $olddivheight;
$this->textbuffer=array();
$this->Ln($this->lineheight);
}
if(isset($attr['SRC']))
{
$srcpath = $attr['SRC'];
if(!isset($attr['WIDTH'])) $attr['WIDTH'] = 0;
else $attr['WIDTH'] = ConvertSize($attr['WIDTH'],$this->pgwidth);//$attr['WIDTH'] /= 4;
if(!isset($attr['HEIGHT'])) $attr['HEIGHT'] = 0;
else $attr['HEIGHT'] = ConvertSize($attr['HEIGHT'],$this->pgwidth);//$attr['HEIGHT'] /= 4;
if ($this->tdbegin)
{
$bak_x = $this->x;
$bak_y = $this->y;
//Check whether image exists locally or on the URL
$f_exists = @fopen($srcpath,"rb");
if (!$f_exists) //Show 'image not found' icon instead
{
if(!$this->shownoimg) break;
$srcpath = str_replace("\\","/",dirname(__FILE__)) . "/";
$srcpath .= 'no_img.gif';
}
$sizesarray = $this->Image($srcpath, $this->GetX(), $this->GetY(), $attr['WIDTH'], $attr['HEIGHT'],'','',false);
$this->y = $bak_y;
$this->x = $bak_x;
}
elseif($this->pbegin or $this->divbegin)
{
//In order to support <div align='center'><img ...></div>
$ypos = 0;
$bak_x = $this->x;
$bak_y = $this->y;
//Check whether image exists locally or on the URL
$f_exists = @fopen($srcpath,"rb");
if (!$f_exists) //Show 'image not found' icon instead
{
if(!$this->shownoimg) break;
$srcpath = str_replace("\\","/",dirname(__FILE__)) . "/";
$srcpath .= 'no_img.gif';
}
$sizesarray = $this->Image($srcpath, $this->GetX(), $this->GetY(), $attr['WIDTH'], $attr['HEIGHT'],'','',false);
$this->y = $bak_y;
$this->x = $bak_x;
$xpos = '';
switch($this->divalign)
{
case "C":
$spacesize = $this->CurrentFont[ 'cw' ][ ' ' ] * ( $this->FontSizePt / 1000 );
$empty = ($this->pgwidth - $sizesarray['WIDTH'])/2;
$xpos = 'xpos='.$empty.',';
break;
case "R":
$spacesize = $this->CurrentFont[ 'cw' ][ ' ' ] * ( $this->FontSizePt / 1000 );
$empty = ($this->pgwidth - $sizesarray['WIDTH']);
$xpos = 'xpos='.$empty.',';
break;
default: break;
}
$numberoflines = (integer)ceil($sizesarray['HEIGHT']/$this->lineheight) ;
$ypos = $numberoflines * $this->lineheight;
$this->textbuffer[] = array("»¤¬"/*identifier*/."type=image,ypos=$ypos,{$xpos}width=".$sizesarray['WIDTH'].",height=".$sizesarray['HEIGHT']."»¤¬".$sizesarray['OUTPUT']);
while($numberoflines) {$this->textbuffer[] = array("\n",$this->HREF,$this->currentstyle,$this->colorarray,$this->currentfont,$this->SUP,$this->SUB,''/*internal link*/,$this->strike,$this->outlineparam,$this->bgcolorarray);$numberoflines--;}
}
else
{
$imgborder = 0;
if (isset($attr['BORDER'])) $imgborder = ConvertSize($attr['BORDER'],$this->pgwidth);
//Check whether image exists locally or on the URL
$f_exists = @fopen($srcpath,"rb");
if (!$f_exists) //Show 'image not found' icon instead
{
$srcpath = str_replace("\\","/",dirname(__FILE__)) . "/";
$srcpath .= 'no_img.gif';
}
$sizesarray = $this->Image($srcpath, $this->GetX(), $this->GetY(), $attr['WIDTH'], $attr['HEIGHT'],'',$this->HREF); //Output Image
$ini_x = $sizesarray['X'];
$ini_y = $sizesarray['Y'];
if ($imgborder)
{
$oldlinewidth = $this->LineWidth;
$this->SetLineWidth($imgborder);
$this->Rect($ini_x,$ini_y,$sizesarray['WIDTH'],$sizesarray['HEIGHT']);
$this->SetLineWidth($oldlinewidth);
}
}
if ($sizesarray['X'] < $this->x) $this->x = $this->lMargin;
if ($this->tablestart)
{
$this->cell[$this->row][$this->col]['textbuffer'][] = array("»¤¬"/*identifier*/."type=image,width=".$sizesarray['WIDTH'].",height=".$sizesarray['HEIGHT']."»¤¬".$sizesarray['OUTPUT']);
$this->cell[$this->row][$this->col]['s'] += $sizesarray['WIDTH'] + 1;// +1 == margin
$this->cell[$this->row][$this->col]['form'] = true; // in order to make some width adjustments later
if (!isset($this->cell[$this->row][$this->col]['w'])) $this->cell[$this->row][$this->col]['w'] = $sizesarray['WIDTH'] + 3;
if (!isset($this->cell[$this->row][$this->col]['h'])) $this->cell[$this->row][$this->col]['h'] = $sizesarray['HEIGHT'] + 3;
}
}
break;
case 'BLOCKQUOTE':
case 'BR':
if($this->tablestart)
{
$this->cell[$this->row][$this->col]['textbuffer'][] = array("\n",$this->HREF,$this->currentstyle,$this->colorarray,$this->currentfont,$this->SUP,$this->SUB,''/*internal link*/,$this->strike,$this->outlineparam,$this->bgcolorarray);
$this->cell[$this->row][$this->col]['text'][] = "\n";
if (!isset($this->cell[$this->row][$this->col]['maxs'])) $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'] +2; //+2 == margin
elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s']+2;//+2 == margin
$this->cell[$this->row][$this->col]['s'] = 0;// reset
}
elseif($this->divbegin or $this->pbegin or $this->buffer_on) $this->textbuffer[] = array("\n",$this->HREF,$this->currentstyle,$this->colorarray,$this->currentfont,$this->SUP,$this->SUB,''/*internal link*/,$this->strike,$this->outlineparam,$this->bgcolorarray);
else {$this->Ln($this->lineheight);$this->blockjustfinished = true;}
break;
case 'P':
//in case of malformed HTML code. Example:(...)</p><li>Content</li><p>Paragraph1</p>(...)
if ($this->listlvl > 0) // We are closing (omitted) OL/UL tag(s)
{
$this->buffer_on = false;
if (!empty($this->textbuffer)) $this->listitem[] = array($this->listlvl,$this->listnum,$this->textbuffer,$this->listoccur[$this->listlvl]);
$this->textbuffer = array();
$this->listlvl--;
$this->printlistbuffer();
$this->pjustfinished = true; //act as if a paragraph just ended
}
if ($this->tablestart)
{
$this->cell[$this->row][$this->col]['textbuffer'][] = array($e,$this->HREF,$this->currentstyle,$this->colorarray,$this->currentfont,$this->SUP,$this->SUB,''/*internal link*/,$this->strike,$this->outlineparam,$this->bgcolorarray);
$this->cell[$this->row][$this->col]['text'][] = "\n";
break;
}
$this->pbegin=true;
if ($this->x != $this->lMargin) $this->Ln(2*$this->lineheight);
elseif (!$this->pjustfinished) $this->Ln($this->lineheight);
//Save x,y coords in case we need to print borders...
$this->oldx = $this->x;
$this->oldy = $this->y;
if(isset($attr['ALIGN'])) $this->divalign = $align[strtolower($attr['ALIGN'])];
if(isset($attr['CLASS']) or isset($attr['ID']) or isset($attr['STYLE']) )
{
$this->cssbegin=true;
if (isset($attr['CLASS'])) $properties = $this->CSS[$attr['CLASS']];
elseif (isset($attr['ID'])) $properties = $this->CSS[$attr['ID']];
//Read Inline CSS
if (isset($attr['STYLE'])) $properties = $this->readInlineCSS($attr['STYLE']);
//Look for name in the $this->CSS array
$this->backupcss = $properties;
if (!empty($properties)) $this->setCSS($properties); //name(id/class/style) found in the CSS array!
}
break;
case 'SPAN':
$this->buffer_on = true;
//Save x,y coords in case we need to print borders...
$this->oldx = $this->x;
$this->oldy = $this->y;
if( isset($attr['CLASS']) or isset($attr['ID']) or isset($attr['STYLE']) )
{
$this->cssbegin=true;
if (isset($attr['CLASS'])) $properties = $this->CSS[$attr['CLASS']];
elseif (isset($attr['ID'])) $properties = $this->CSS[$attr['ID']];
//Read Inline CSS
if (isset($attr['STYLE'])) $properties = $this->readInlineCSS($attr['STYLE']);
//Look for name in the $this->CSS array
$this->backupcss = $properties;
if (!empty($properties)) $this->setCSS($properties); //name found in the CSS array!
}
break;
case 'PRE':
if($this->tablestart)
{
$this->cell[$this->row][$this->col]['textbuffer'][] = array("\n",$this->HREF,$this->currentstyle,$this->colorarray,$this->currentfont,$this->SUP,$this->SUB,''/*internal link*/,$this->strike,$this->outlineparam,$this->bgcolorarray);
$this->cell[$this->row][$this->col]['text'][] = "\n";
}
elseif($this->divbegin or $this->pbegin or $this->buffer_on) $this->textbuffer[] = array("\n",$this->HREF,$this->currentstyle,$this->colorarray,$this->currentfont,$this->SUP,$this->SUB,''/*internal link*/,$this->strike,$this->outlineparam,$this->bgcolorarray);
else
{
if ($this->x != $this->lMargin) $this->Ln(2*$this->lineheight);
elseif (!$this->pjustfinished) $this->Ln($this->lineheight);
$this->buffer_on = true;
//Save x,y coords in case we need to print borders...
$this->oldx = $this->x;
$this->oldy = $this->y;
if(isset($attr['ALIGN'])) $this->divalign = $align[strtolower($attr['ALIGN'])];
if(isset($attr['CLASS']) or isset($attr['ID']) or isset($attr['STYLE']) )
{
$this->cssbegin=true;
if (isset($attr['CLASS'])) $properties = $this->CSS[$attr['CLASS']];
elseif (isset($attr['ID'])) $properties = $this->CSS[$attr['ID']];
//Read Inline CSS
if (isset($attr['STYLE'])) $properties = $this->readInlineCSS($attr['STYLE']);
//Look for name in the $this->CSS array
$this->backupcss = $properties;
if (!empty($properties)) $this->setCSS($properties); //name(id/class/style) found in the CSS array!
}
}
case 'TT':
case 'KBD':
case 'SAMP':
case 'CODE':
$this->SetFont('courier');
$this->currentfont='courier';
break;
case 'TEXTAREA':
$this->buffer_on = true;
$colsize = 20; //HTML default value
$rowsize = 2; //HTML default value
if (isset($attr['COLS'])) $colsize = $attr['COLS'];
if (isset($attr['ROWS'])) $rowsize = $attr['ROWS'];
if (!$this->tablestart)
{
if ($this->x != $this->lMargin) $this->Ln($this->lineheight);
$this->col = $colsize;
$this->row = $rowsize;
}
else //it is inside a table
{
$this->specialcontent = "type=textarea,lines=$rowsize,width=".((2.2*$colsize) + 3); //Activate form info in order to paint FORM elements within table
$this->cell[$this->row][$this->col]['s'] += (2.2*$colsize) + 6;// +6 == margin
if (!isset($this->cell[$this->row][$this->col]['h'])) $this->cell[$this->row][$this->col]['h'] = 1.1*$this->lineheight*$rowsize + 2.5;
}
break;
case 'SELECT':
$this->specialcontent = "type=select"; //Activate form info in order to paint FORM elements within table
break;
case 'OPTION':
$this->selectoption['ACTIVE'] = true;
if (empty($this->selectoption))
{
$this->selectoption['MAXWIDTH'] = '';
$this->selectoption['SELECTED'] = '';
}
if (isset($attr['SELECTED'])) $this->selectoption['SELECTED'] = '';
break;
case 'FORM':
if($this->tablestart)
{
$this->cell[$this->row][$this->col]['textbuffer'][] = array($e,$this->HREF,$this->currentstyle,$this->colorarray,$this->currentfont,$this->SUP,$this->SUB,''/*internal link*/,$this->strike,$this->outlineparam,$this->bgcolorarray);
$this->cell[$this->row][$this->col]['text'][] = "\n";
}
elseif ($this->x != $this->lMargin) $this->Ln($this->lineheight); //Skip a line, if needed
break;
case 'INPUT':
if (!isset($attr['TYPE'])) $attr['TYPE'] == ''; //in order to allow default 'TEXT' form (in case of malformed HTML code)
if (!$this->tablestart)
{
switch(strtoupper($attr['TYPE'])){
case 'CHECKBOX': //Draw Checkbox
$checked = false;
if (isset($attr['CHECKED'])) $checked = true;
$this->SetFillColor(235,235,235);
$this->x += 3;
$this->Rect($this->x,$this->y+1,3,3,'DF');
if ($checked)
{
$this->Line($this->x,$this->y+1,$this->x+3,$this->y+1+3);
$this->Line($this->x,$this->y+1+3,$this->x+3,$this->y+1);
}
$this->SetFillColor(255);
$this->x += 3.5;
break;
case 'RADIO': //Draw Radio button
$checked = false;
if (isset($attr['CHECKED'])) $checked = true;
$this->x += 4;
$this->Circle($this->x,$this->y+2.2,1,'D');
$this->_out('0.000 g');
if ($checked) $this->Circle($this->x,$this->y+2.2,0.4,'DF');
$this->Write(5,$texto,$this->x);
$this->x += 2;
break;
case 'BUTTON': // Draw a button
case 'SUBMIT':
case 'RESET':
$texto='';
if (isset($attr['VALUE'])) $texto = $attr['VALUE'];
$nihil = 2.5;
$this->x += 2;
$this->SetFillColor(190,190,190);
$this->Rect($this->x,$this->y,$this->GetStringWidth($texto)+2*$nihil,4.5,'DF'); // 4.5 in order to avoid overlapping
$this->x += $nihil;
$this->Write(5,$texto,$this->x);
$this->x += $nihil;
$this->SetFillColor(255);
break;
case 'PASSWORD':
if (isset($attr['VALUE']))
{
$num_stars = strlen($attr['VALUE']);
$attr['VALUE'] = str_repeat('*',$num_stars);
}
case 'TEXT': //Draw TextField
default: //default == TEXT
$texto='';
if (isset($attr['VALUE'])) $texto = $attr['VALUE'];
$tamanho = 20;
if (isset($attr['SIZE']) and ctype_digit($attr['SIZE']) ) $tamanho = $attr['SIZE'];
$this->SetFillColor(235,235,235);
$this->x += 2;
$this->Rect($this->x,$this->y,2*$tamanho,4.5,'DF');// 4.5 in order to avoid overlapping
if ($texto != '')
{
$this->x += 1;
$this->Write(5,$texto,$this->x);
$this->x -= $this->GetStringWidth($texto);
}
$this->SetFillColor(255);
$this->x += 2*$tamanho;
break;
}
}
else //we are inside a table
{
$this->cell[$this->row][$this->col]['form'] = true; // in order to make some width adjustments later
$type = '';
$text = '';
$height = 0;
$width = 0;
switch(strtoupper($attr['TYPE'])){
case 'CHECKBOX': //Draw Checkbox
$checked = false;
if (isset($attr['CHECKED'])) $checked = true;
$text = $checked;
$type = 'CHECKBOX';
$width = 4;
$this->cell[$this->row][$this->col]['textbuffer'][] = array("»¤¬"/*identifier*/."type=input,subtype=$type,width=$width,height=$height"."»¤¬".$text);
$this->cell[$this->row][$this->col]['s'] += $width;
if (!isset($this->cell[$this->row][$this->col]['h'])) $this->cell[$this->row][$this->col]['h'] = $this->lineheight;
break;
case 'RADIO': //Draw Radio button
$checked = false;
if (isset($attr['CHECKED'])) $checked = true;
$text = $checked;
$type = 'RADIO';
$width = 3;
$this->cell[$this->row][$this->col]['textbuffer'][] = array("»¤¬"/*identifier*/."type=input,subtype=$type,width=$width,height=$height"."»¤¬".$text);
$this->cell[$this->row][$this->col]['s'] += $width;
if (!isset($this->cell[$this->row][$this->col]['h'])) $this->cell[$this->row][$this->col]['h'] = $this->lineheight;
break;
case 'BUTTON': $type = 'BUTTON'; // Draw a button
case 'SUBMIT': if ($type == '') $type = 'SUBMIT';
case 'RESET': if ($type == '') $type = 'RESET';
$texto='';
if (isset($attr['VALUE'])) $texto = " " . $attr['VALUE'] . " ";
$text = $texto;
$width = $this->GetStringWidth($texto)+3;
$this->cell[$this->row][$this->col]['textbuffer'][] = array("»¤¬"/*identifier*/."type=input,subtype=$type,width=$width,height=$height"."»¤¬".$text);
$this->cell[$this->row][$this->col]['s'] += $width;
if (!isset($this->cell[$this->row][$this->col]['h'])) $this->cell[$this->row][$this->col]['h'] = $this->lineheight + 2;
break;
case 'PASSWORD':
if (isset($attr['VALUE']))
{
$num_stars = strlen($attr['VALUE']);
$attr['VALUE'] = str_repeat('*',$num_stars);
}
$type = 'PASSWORD';
case 'TEXT': //Draw TextField
default: //default == TEXT
$texto='';
if (isset($attr['VALUE'])) $texto = $attr['VALUE'];
$tamanho = 20;
if (isset($attr['SIZE']) and ctype_digit($attr['SIZE']) ) $tamanho = $attr['SIZE'];
$text = $texto;
$width = 2*$tamanho;
if ($type == '') $type = 'TEXT';
$this->cell[$this->row][$this->col]['textbuffer'][] = array("»¤¬"/*identifier*/."type=input,subtype=$type,width=$width,height=$height"."»¤¬".$text);
$this->cell[$this->row][$this->col]['s'] += $width;
if (!isset($this->cell[$this->row][$this->col]['h'])) $this->cell[$this->row][$this->col]['h'] = $this->lineheight + 2;
break;
}
}
break;
case 'FONT':
//Font size is ignored for now
if (isset($attr['COLOR']) and $attr['COLOR']!='')
{
$cor = ConvertColor($attr['COLOR']);
//If something goes wrong switch color to black
$cor['R'] = (isset($cor['R'])?$cor['R']:0);
$cor['G'] = (isset($cor['G'])?$cor['G']:0);
$cor['B'] = (isset($cor['B'])?$cor['B']:0);
$this->colorarray = $cor;
$this->SetTextColor($cor['R'],$cor['G'],$cor['B']);
$this->issetcolor = true;
}
if (isset($attr['FACE']) and in_array(strtolower($attr['FACE']), $this->fontlist))
{
$this->SetFont(strtolower($attr['FACE']));
$this->issetfont=true;
}
//'If' disabled in this version due lack of testing (you may enable it if you want)
// if (isset($attr['FACE']) and in_array(strtolower($attr['FACE']), $this->fontlist) and isset($attr['SIZE']) and $attr['SIZE']!='') {
// $this->SetFont(strtolower($attr['FACE']),'',$attr['SIZE']);
// $this->issetfont=true;
// }
break;
}//end of switch
$this->pjustfinished=false;
}
function CloseTag($tag)
{
//! @return void
//Closing tag
if($tag=='OPTION') $this->selectoption['ACTIVE'] = false;
if($tag=='BDO') $this->divrevert = false;
if($tag=='INS') $tag='U';
if($tag=='STRONG') $tag='B';
if($tag=='EM' or $tag=='CITE') $tag='I';
if($tag=='OUTLINE')
{
if(!$this->pbegin and !$this->divbegin and !$this->tablestart)
{
//Deactivate $this->outlineparam for its info is already stored inside $this->textbuffer
//if (isset($this->outlineparam['OLDWIDTH'])) $this->SetTextOutline($this->outlineparam['OLDWIDTH']);
$this->SetTextOutline(false);
$this->outlineparam=array();
//Save x,y coords ???
$x = $this->x;
$y = $this->y;
//Set some default values
$this->divwidth = $this->pgwidth - $x + $this->lMargin;
//Print content
$this->printbuffer($this->textbuffer,true/*is out of a block (e.g. DIV,P etc.)*/);
$this->textbuffer=array();
//Reset values
$this->Reset();
$this->buffer_on=false;
}
$this->SetTextOutline(false);
$this->outlineparam=array();
}
if($tag=='A')
{
if(!$this->pbegin and !$this->divbegin and !$this->tablestart and !$this->buffer_on)
{
//Deactivate $this->HREF for its info is already stored inside $this->textbuffer
$this->HREF='';
//Save x,y coords ???
$x = $this->x;
$y = $this->y;
//Set some default values
$this->divwidth = $this->pgwidth - $x + $this->lMargin;
//Print content
$this->printbuffer($this->textbuffer,true/*is out of a block (e.g. DIV,P etc.)*/);
$this->textbuffer=array();
//Reset values
$this->Reset();
}
$this->HREF='';
}
if($tag=='TH') $this->SetStyle('B',false);
if($tag=='TH' or $tag=='TD') $this->tdbegin = false;
if($tag=='SPAN')
{
if(!$this->pbegin and !$this->divbegin and !$this->tablestart)
{
if($this->cssbegin)
{
//Check if we have borders to print
if ($this->cssbegin and ($this->divborder or $this->dash_on or $this->dotted_on or $this->divbgcolor))
{
$texto='';
foreach($this->textbuffer as $vetor) $texto.=$vetor[0];
$tempx = $this->x;
if($this->divbgcolor) $this->Cell($this->GetStringWidth($texto),$this->lineheight,'',$this->divborder,'','L',$this->divbgcolor);
if ($this->dash_on) $this->Rect($this->oldx,$this->oldy,$this->GetStringWidth($texto),$this->lineheight);
if ($this->dotted_on) $this->DottedRect($this->x - $this->GetStringWidth($texto),$this->y,$this->GetStringWidth($texto),$this->lineheight);
$this->x = $tempx;
$this->x -= 1; //adjust alignment
}
$this->cssbegin=false;
$this->backupcss=array();
}
//Save x,y coords ???
$x = $this->x;
$y = $this->y;
//Set some default values
$this->divwidth = $this->pgwidth - $x + $this->lMargin;
//Print content
$this->printbuffer($this->textbuffer,true/*is out of a block (e.g. DIV,P etc.)*/);
$this->textbuffer=array();
//Reset values
$this->Reset();
}
$this->buffer_on=false;
}
if($tag=='P' or $tag=='DIV') //CSS in BLOCK mode
{
$this->blockjustfinished = true; //Eliminate exceeding left-side spaces
if(!$this->tablestart)
{
if ($this->divwidth == 0) $this->divwidth = $this->pgwidth;
if ($tag=='P')
{
$this->pbegin=false;
$this->pjustfinished=true;
}
else $this->divbegin=false;
$content='';
foreach($this->textbuffer as $aux) $content .= $aux[0];
$numlines = $this->WordWrap($content,$this->divwidth);
if ($this->divheight == 0) $this->divheight = $numlines * 5;
//Print content
$this->printbuffer($this->textbuffer);
$this->textbuffer=array();
if ($tag=='P') $this->Ln($this->lineheight);
}//end of 'if (!this->tablestart)'
//Reset values
$this->Reset();
$this->cssbegin=false;
$this->backupcss=array();
}
if($tag=='TABLE') { // TABLE-END
$this->blockjustfinished = true; //Eliminate exceeding left-side spaces
$this->table['cells'] = $this->cell;
$this->table['wc'] = array_pad(array(),$this->table['nc'],array('miw'=>0,'maw'=>0));
$this->table['hr'] = array_pad(array(),$this->table['nr'],0);
$this->_tableColumnWidth($this->table);
$this->_tableWidth($this->table);
$this->_tableHeight($this->table);
//Output table on PDF
$this->_tableWrite($this->table);
//Reset values
$this->tablestart=false; //bool
$this->table=array(); //array
$this->cell=array(); //array
$this->col=-1; //int
$this->row=-1; //int
$this->Reset();
$this->Ln(0.5*$this->lineheight);
}
if(($tag=='UL') or ($tag=='OL')) {
if ($this->buffer_on == false) $this->listnum--;//Adjust minor BUG (this happens when there are two </OL> together)
if ($this->listlvl == 1) // We are closing the last OL/UL tag
{
$this->blockjustfinished = true; //Eliminate exceeding left-side spaces
$this->buffer_on = false;
if (!empty($this->textbuffer)) $this->listitem[] = array($this->listlvl,$this->listnum,$this->textbuffer,$this->listoccur[$this->listlvl]);
$this->textbuffer = array();
$this->listlvl--;
$this->printlistbuffer();
}
else // returning one level
{
if (!empty($this->textbuffer)) $this->listitem[] = array($this->listlvl,$this->listnum,$this->textbuffer,$this->listoccur[$this->listlvl]);
$this->textbuffer = array();
$occur = $this->listoccur[$this->listlvl];
$this->listlist[$this->listlvl][$occur]['MAXNUM'] = $this->listnum; //save previous lvl's maxnum
$this->listlvl--;
$occur = $this->listoccur[$this->listlvl];
$this->listnum = $this->listlist[$this->listlvl][$occur]['MAXNUM']; // recover previous level's number
$this->listtype = $this->listlist[$this->listlvl][$occur]['TYPE']; // recover previous level's type
$this->buffer_on = false;
}
}
if($tag=='H1' or $tag=='H2' or $tag=='H3' or $tag=='H4' or $tag=='H5' or $tag=='H6')
{
$this->blockjustfinished = true; //Eliminate exceeding left-side spaces
if(!$this->pbegin and !$this->divbegin and !$this->tablestart)
{
//These 2 codelines are useless?
$texto='';
foreach($this->textbuffer as $vetor) $texto.=$vetor[0];
//Save x,y coords ???
$x = $this->x;
$y = $this->y;
//Set some default values
$this->divwidth = $this->pgwidth;
//Print content
$this->printbuffer($this->textbuffer);
$this->textbuffer=array();
if ($this->x != $this->lMargin) $this->Ln($this->lineheight);
//Reset values
$this->Reset();
}
$this->buffer_on=false;
$this->lineheight = 5;
$this->Ln($this->lineheight);
$this->SetFontSize(11);
$this->SetStyle('B',false);
}
if($tag=='TITLE') {$this->titulo=false; $this->blockjustfinished = true;}
if($tag=='FORM') $this->Ln($this->lineheight);
if($tag=='PRE')
{
if(!$this->pbegin and !$this->divbegin and !$this->tablestart)
{
if ($this->divwidth == 0) $this->divwidth = $this->pgwidth;
$content='';
foreach($this->textbuffer as $aux) $content .= $aux[0];
$numlines = $this->WordWrap($content,$this->divwidth);
if ($this->divheight == 0) $this->divheight = $numlines * 5;
//Print content
$this->textbuffer[0][0] = ltrim($this->textbuffer[0][0]); //Remove exceeding left-side space
$this->printbuffer($this->textbuffer);
$this->textbuffer=array();
if ($this->x != $this->lMargin) $this->Ln($this->lineheight);
//Reset values
$this->Reset();
$this->Ln(1.1*$this->lineheight);
}
if($this->tablestart)
{
$this->cell[$this->row][$this->col]['textbuffer'][] = array("\n",$this->HREF,$this->currentstyle,$this->colorarray,$this->currentfont,$this->SUP,$this->SUB,''/*internal link*/,$this->strike,$this->outlineparam,$this->bgcolorarray);
$this->cell[$this->row][$this->col]['text'][] = "\n";
}
if($this->divbegin or $this->pbegin or $this->buffer_on) $this->textbuffer[] = array("\n",$this->HREF,$this->currentstyle,$this->colorarray,$this->currentfont,$this->SUP,$this->SUB,''/*internal link*/,$this->strike,$this->outlineparam,$this->bgcolorarray);
$this->cssbegin=false;
$this->backupcss=array();
$this->buffer_on = false;
$this->blockjustfinished = true; //Eliminate exceeding left-side spaces
$this->pjustfinished = true; //behaves the same way
}
if($tag=='CODE' or $tag=='PRE' or $tag=='TT' or $tag=='KBD' or $tag=='SAMP')
{
$this->currentfont='';
$this->SetFont('arial');
}
if($tag=='B' or $tag=='I' or $tag=='U')
{
$this->SetStyle($tag,false);
if ($this->cssbegin and !$this->divbegin and !$this->pbegin and !$this->buffer_on)
{
//Reset values
$this->Reset();
$this->cssbegin=false;
$this->backupcss=array();
}
}
if($tag=='TEXTAREA')
{
if (!$this->tablestart) //not inside a table
{
//Draw arrows too?
$texto = '';
foreach($this->textbuffer as $v) $texto .= $v[0];
$this->SetFillColor(235,235,235);
$this->SetFont('courier');
$this->x +=3;
$linesneeded = $this->WordWrap($texto,($this->col*2.2)+3);
if ( $linesneeded > $this->row ) //Too many words inside textarea
{
$textoaux = explode("\n",$texto);
$texto = '';
for($i=0;$i < $this->row;$i++)
{
if ($i == $this->row-1) $texto .= $textoaux[$i];
else $texto .= $textoaux[$i] . "\n";
}
//Inform the user that some text has been truncated
$texto{strlen($texto)-1} = ".";
$texto{strlen($texto)-2} = ".";
$texto{strlen($texto)-3} = ".";
}
$backup_y = $this->y;
$this->Rect($this->x,$this->y,(2.2*$this->col)+6,5*$this->row,'DF');
if ($texto != '') $this->MultiCell((2.2*$this->col)+6,$this->lineheight,$texto);
$this->y = $backup_y + $this->row*$this->lineheight;
$this->SetFont('arial');
}
else //inside a table
{
$this->cell[$this->row][$this->col]['textbuffer'][] = $this->textbuffer[0];
$this->cell[$this->row][$this->col]['text'][] = $this->textbuffer[0];
$this->cell[$this->row][$this->col]['form'] = true; // in order to make some width adjustments later
$this->specialcontent = '';
}
$this->SetFillColor(255);
$this->textbuffer=array();
$this->buffer_on = false;
}
if($tag=='SELECT')
{
$texto = '';
$tamanho = 0;
if (isset($this->selectoption['MAXWIDTH'])) $tamanho = $this->selectoption['MAXWIDTH'];
if ($this->tablestart)
{
$texto = "»¤¬".$this->specialcontent."»¤¬".$this->selectoption['SELECTED'];
$aux = explode("»¤¬",$texto);
$texto = $aux[2];
$texto = "»¤¬".$aux[1].",width=$tamanho,height=".($this->lineheight + 2)."»¤¬".$texto;
$this->cell[$this->row][$this->col]['s'] += $tamanho + 7; // margin + arrow box
$this->cell[$this->row][$this->col]['form'] = true; // in order to make some width adjustments later
if (!isset($this->cell[$this->row][$this->col]['h'])) $this->cell[$this->row][$this->col]['h'] = $this->lineheight + 2;
$this->cell[$this->row][$this->col]['textbuffer'][] = array($texto);
$this->cell[$this->row][$this->col]['text'][] = '';
}
else //not inside a table
{
$texto = $this->selectoption['SELECTED'];
$this->SetFillColor(235,235,235);
$this->x += 2;
$this->Rect($this->x,$this->y,$tamanho+2,5,'DF');//+2 margin
$this->x += 1;
if ($texto != '') $this->Write(5,$texto,$this->x);
$this->x += $tamanho - $this->GetStringWidth($texto) + 2;
$this->SetFillColor(190,190,190);
$this->Rect($this->x-1,$this->y,5,5,'DF'); //Arrow Box
$this->SetFont('zapfdingbats');
$this->Write(5,chr(116),$this->x); //Down arrow
$this->SetFont('arial');
$this->SetFillColor(255);
$this->x += 1;
}
$this->selectoption = array();
$this->specialcontent = '';
$this->textbuffer = array();
}
if($tag=='SUB' or $tag=='SUP') //subscript or superscript
{
if(!$this->pbegin and !$this->divbegin and !$this->tablestart and !$this->buffer_on and !$this->strike)
{
//Deactivate $this->SUB/SUP for its info is already stored inside $this->textbuffer
$this->SUB=false;
$this->SUP=false;
//Save x,y coords ???
$x = $this->x;
$y = $this->y;
//Set some default values
$this->divwidth = $this->pgwidth - $x + $this->lMargin;
//Print content
$this->printbuffer($this->textbuffer,true/*is out of a block (e.g. DIV,P etc.)*/);
$this->textbuffer=array();
//Reset values
$this->Reset();
}
$this->SUB=false;
$this->SUP=false;
}
if($tag=='S' or $tag=='STRIKE' or $tag=='DEL')
{
if(!$this->pbegin and !$this->divbegin and !$this->tablestart)
{
//Deactivate $this->strike for its info is already stored inside $this->textbuffer
$this->strike=false;
//Save x,y coords ???
$x = $this->x;
$y = $this->y;
//Set some default values
$this->divwidth = $this->pgwidth - $x + $this->lMargin;
//Print content
$this->printbuffer($this->textbuffer,true/*is out of a block (e.g. DIV,P etc.)*/);
$this->textbuffer=array();
//Reset values
$this->Reset();
}
$this->strike=false;
}
if($tag=='ADDRESS' or $tag=='CENTER') // <ADDRESS> or <CENTER> tag
{
$this->blockjustfinished = true; //Eliminate exceeding left-side spaces
if(!$this->pbegin and !$this->divbegin and !$this->tablestart)
{
//Save x,y coords ???
$x = $this->x;
$y = $this->y;
//Set some default values
$this->divwidth = $this->pgwidth - $x + $this->lMargin;
//Print content
$this->printbuffer($this->textbuffer);
$this->textbuffer=array();
//Reset values
$this->Reset();
}
$this->buffer_on=false;
if ($tag == 'ADDRESS') $this->SetStyle('I',false);
}
if($tag=='BIG')
{
$newsize = $this->FontSizePt - 1;
$this->SetFontSize($newsize);
$this->SetStyle('B',false);
}
if($tag=='SMALL')
{
$newsize = $this->FontSizePt + 1;
$this->SetFontSize($newsize);
}
if($tag=='FONT')
{
if ($this->issetcolor == true)
{
$this->colorarray = array();
$this->SetTextColor(0);
$this->issetcolor = false;
}
if ($this->issetfont)
{
$this->SetFont('arial');
$this->issetfont=false;
}
if ($this->cssbegin)
{
//Get some attributes back!
$this->setCSS($this->backupcss);
}
}
}
function printlistbuffer()
{
//! @return void
//! @desc Prints all list-related buffered info
//Save x coordinate
$x = $this->oldx;
foreach($this->listitem as $item)
{
//Set default width & height values
$this->divwidth = $this->pgwidth;
$this->divheight = $this->lineheight;
//Get list's buffered data
$lvl = $item[0];
$num = $item[1];
$this->textbuffer = $item[2];
$occur = $item[3];
$type = $this->listlist[$lvl][$occur]['TYPE'];
$maxnum = $this->listlist[$lvl][$occur]['MAXNUM'];
switch($type) //Format type
{
case 'A':
$num = dec2alpha($num,true);
$maxnum = dec2alpha($maxnum,true);
$type = str_pad($num,strlen($maxnum),' ',STR_PAD_LEFT) . ".";
break;
case 'a':
$num = dec2alpha($num,false);
$maxnum = dec2alpha($maxnum,false);
$type = str_pad($num,strlen($maxnum),' ',STR_PAD_LEFT) . ".";
break;
case 'I':
$num = dec2roman($num,true);
$maxnum = dec2roman($maxnum,true);
$type = str_pad($num,strlen($maxnum),' ',STR_PAD_LEFT) . ".";
break;
case 'i':
$num = dec2roman($num,false);
$maxnum = dec2roman($maxnum,false);
$type = str_pad($num,strlen($maxnum),' ',STR_PAD_LEFT) . ".";
break;
case '1':
$type = str_pad($num,strlen($maxnum),' ',STR_PAD_LEFT) . ".";
break;
case 'disc':
$type = chr(149);
break;
case 'square':
$type = chr(110); //black square on Zapfdingbats font
break;
case 'circle':
$type = chr(186);
break;
default: break;
}
$this->x = (5*$lvl) + $x; //Indent list
//Get bullet width including margins
$oldsize = $this->FontSize * $this->k;
if ($type == chr(110)) $this->SetFont('zapfdingbats','',5);
$type .= ' ';
$blt_width = $this->GetStringWidth($type)+$this->cMargin*2;
//Output bullet
$this->Cell($blt_width,5,$type,'','','L');
$this->SetFont('times','',$oldsize);
$this->divwidth = $this->divwidth + $this->lMargin - $this->x;
//Print content
$this->printbuffer($this->textbuffer);
$this->textbuffer=array();
}
//Reset all used values
$this->listoccur = array();
$this->listitem = array();
$this->listlist = array();
$this->listlvl = 0;
$this->listnum = 0;
$this->listtype = '';
$this->textbuffer = array();
$this->divwidth = 0;
$this->divheight = 0;
$this->oldx = -1;
//At last, but not least, skip a line
$this->Ln($this->lineheight);
}
function printbuffer($arrayaux,$outofblock=false,$is_table=false)
{
//! @return headache
//! @desc Prepares buffered text to be printed with FlowingBlock()
//Save some previous parameters
$save = array();
$save['strike'] = $this->strike;
$save['SUP'] = $this->SUP;
$save['SUB'] = $this->SUB;
$save['DOTTED'] = $this->dotted_on;
$save['DASHED'] = $this->dash_on;
$this->SetDash(); //restore to no dash
$this->dash_on = false;
$this->dotted_on = false;
$bak_y = $this->y;
$bak_x = $this->x;
$align = $this->divalign;
$oldpage = $this->page;
//Overall object size == $old_height
//Line height == $this->divheight
$old_height = $this->divheight;
if ($is_table)
{
$this->divheight = 1.1*$this->lineheight;
$fill = 0;
}
else
{
$this->divheight = $this->lineheight;
if ($this->FillColor == '1.000 g') $fill = 0; //avoid useless background painting (1.000 g == white background color)
else $fill = 1;
}
$this->newFlowingBlock( $this->divwidth,$this->divheight,$this->divborder,$align,$fill,$is_table);
$array_size = count($arrayaux);
for($i=0;$i < $array_size; $i++)
{
$vetor = $arrayaux[$i];
if ($i == 0 and $vetor[0] != "\n") $vetor[0] = ltrim($vetor[0]);
if (empty($vetor[0]) and empty($vetor[7])) continue; //Ignore empty text and not carrying an internal link
//Activating buffer properties
if(isset($vetor[10]) and !empty($vetor[10])) //Background color
{
$cor = $vetor[10];
$this->SetFillColor($cor['R'],$cor['G'],$cor['B']);
$this->divbgcolor = true;
}
if(isset($vetor[9]) and !empty($vetor[9])) // Outline parameters
{
$cor = $vetor[9]['COLOR'];
$outlinewidth = $vetor[9]['WIDTH'];
$this->SetTextOutline($outlinewidth,$cor['R'],$cor['G'],$cor['B']);
$this->outline_on = true;
}
if(isset($vetor[8]) and $vetor[8] === true) // strike-through the text
{
$this->strike = true;
}
if(isset($vetor[7]) and $vetor[7] != '') // internal link: <a name="anyvalue">
{
$this->internallink[$vetor[7]] = array("Y"=>$this->y,"PAGE"=>$this->page );
$this->Bookmark($vetor[7]." (pg. $this->page)",0,$this->y);
if (empty($vetor[0])) continue; //Ignore empty text
}
if(isset($vetor[6]) and $vetor[6] === true) // Subscript
{
$this->SUB = true;
$this->SetFontSize(6);
}
if(isset($vetor[5]) and $vetor[5] === true) // Superscript
{
$this->SUP = true;
$this->SetFontSize(6);
}
if(isset($vetor[4]) and $vetor[4] != '') $this->SetFont($vetor[4]); // Font Family
if (!empty($vetor[3])) //Font Color
{
$cor = $vetor[3];
$this->SetTextColor($cor['R'],$cor['G'],$cor['B']);
}
if(isset($vetor[2]) and $vetor[2] != '') //Bold,Italic,Underline styles
{
if (strpos($vetor[2],"B") !== false) $this->SetStyle('B',true);
if (strpos($vetor[2],"I") !== false) $this->SetStyle('I',true);
if (strpos($vetor[2],"U") !== false) $this->SetStyle('U',true);
}
if(isset($vetor[1]) and $vetor[1] != '') //LINK
{
if (strpos($vetor[1],".") === false) //assuming every external link has a dot indicating extension (e.g: .html .txt .zip www.somewhere.com etc.)
{
//Repeated reference to same anchor?
while(array_key_exists($vetor[1],$this->internallink)) $vetor[1]="#".$vetor[1];
$this->internallink[$vetor[1]] = $this->AddLink();
$vetor[1] = $this->internallink[$vetor[1]];
}
$this->HREF = $vetor[1];
$this->SetTextColor(0,0,255);
$this->SetStyle('U',true);
}
//Print-out special content
if (isset($vetor[0]) and $vetor[0]{0} == '»' and $vetor[0]{1} == '¤' and $vetor[0]{2} == '¬') //identifier has been identified!
{
$content = explode("»¤¬",$vetor[0]);
$texto = $content[2];
$content = explode(",",$content[1]);
foreach($content as $value)
{
$value = explode("=",$value);
$specialcontent[$value[0]] = $value[1];
}
if ($this->flowingBlockAttr[ 'contentWidth' ] > 0) // Print out previously accumulated content
{
$width_used = $this->flowingBlockAttr[ 'contentWidth' ] / $this->k;
//Restart Flowing Block
$this->finishFlowingBlock($outofblock);
$this->x = $bak_x + ($width_used % $this->divwidth) + 0.5;// 0.5 == margin
$this->y -= ($this->lineheight + 0.5);
$extrawidth = 0; //only to be used in case $specialcontent['width'] does not contain all used width (e.g. Select Box)
if ($specialcontent['type'] == 'select') $extrawidth = 7; //arrow box + margin
if(($this->x - $bak_x) + $specialcontent['width'] + $extrawidth > $this->divwidth )
{
$this->x = $bak_x;
$this->y += $this->lineheight - 1;
}
$this->newFlowingBlock( $this->divwidth,$this->divheight,$this->divborder,$align,$fill,$is_table );
}
switch(strtoupper($specialcontent['type']))
{
case 'IMAGE':
//xpos and ypos used in order to support: <div align='center'><img ...></div>
$xpos = 0;
$ypos = 0;
if (isset($specialcontent['ypos']) and $specialcontent['ypos'] != '') $ypos = (float)$specialcontent['ypos'];
if (isset($specialcontent['xpos']) and $specialcontent['xpos'] != '') $xpos = (float)$specialcontent['xpos'];
$width_used = (($this->x - $bak_x) + $specialcontent['width'])*$this->k; //in order to adjust x coordinate later
//Is this the best way of fixing x,y coordinates?
$fix_x = ($this->x+2) * $this->k + ($xpos*$this->k); //+2 margin
$fix_y = ($this->h - (($this->y+2) + $specialcontent['height'])) * $this->k;//+2 margin
$imgtemp = explode(" ",$texto);
$imgtemp[5]=$fix_x; // x
$imgtemp[6]=$fix_y; // y
$texto = implode(" ",$imgtemp);
$this->_out($texto);
//Readjust x coordinate in order to allow text to be placed after this form element
$this->x = $bak_x;
$spacesize = $this->CurrentFont[ 'cw' ][ ' ' ] * ( $this->FontSizePt / 1000 );
$spacenum = (integer)ceil(($width_used / $spacesize));
//Consider the space used so far in this line as a bunch of spaces
if ($ypos != 0) $this->Ln($ypos);
else $this->WriteFlowingBlock(str_repeat(' ',$spacenum));
break;
case 'INPUT':
switch($specialcontent['subtype'])
{
case 'PASSWORD':
case 'TEXT': //Draw TextField
$width_used = (($this->x - $bak_x) + $specialcontent['width'])*$this->k; //in order to adjust x coordinate later
$this->SetFillColor(235,235,235);
$this->x += 1;
$this->y += 1;
$this->Rect($this->x,$this->y,$specialcontent['width'],4.5,'DF');// 4.5 in order to avoid overlapping
if ($texto != '')
{
$this->x += 1;
$this->Write(5,$texto,$this->x);
$this->x -= $this->GetStringWidth($texto);
}
$this->SetFillColor(255);
$this->y -= 1;
//Readjust x coordinate in order to allow text to be placed after this form element
$this->x = $bak_x;
$spacesize = $this->CurrentFont[ 'cw' ][ ' ' ] * ( $this->FontSizePt / 1000 );
$spacenum = (integer)ceil(($width_used / $spacesize));
//Consider the space used so far in this line as a bunch of spaces
$this->WriteFlowingBlock(str_repeat(' ',$spacenum));
break;
case 'CHECKBOX': //Draw Checkbox
$width_used = (($this->x - $bak_x) + $specialcontent['width'])*$this->k; //in order to adjust x coordinate later
$checked = $texto;
$this->SetFillColor(235,235,235);
$this->y += 1;
$this->x += 1;
$this->Rect($this->x,$this->y,3,3,'DF');
if ($checked)
{
$this->Line($this->x,$this->y,$this->x+3,$this->y+3);
$this->Line($this->x,$this->y+3,$this->x+3,$this->y);
}
$this->SetFillColor(255);
$this->y -= 1;
//Readjust x coordinate in order to allow text to be placed after this form element
$this->x = $bak_x;
$spacesize = $this->CurrentFont[ 'cw' ][ ' ' ] * ( $this->FontSizePt / 1000 );
$spacenum = (integer)ceil(($width_used / $spacesize));
//Consider the space used so far in this line as a bunch of spaces
$this->WriteFlowingBlock(str_repeat(' ',$spacenum));
break;
case 'RADIO': //Draw Radio button
$width_used = (($this->x - $bak_x) + $specialcontent['width']+0.5)*$this->k; //in order to adjust x coordinate later
$checked = $texto;
$this->x += 2;
$this->y += 1.5;
$this->Circle($this->x,$this->y+1.2,1,'D');
$this->_out('0.000 g');
if ($checked) $this->Circle($this->x,$this->y+1.2,0.4,'DF');
$this->y -= 1.5;
//Readjust x coordinate in order to allow text to be placed after this form element
$this->x = $bak_x;
$spacesize = $this->CurrentFont[ 'cw' ][ ' ' ] * ( $this->FontSizePt / 1000 );
$spacenum = (integer)ceil(($width_used / $spacesize));
//Consider the space used so far in this line as a bunch of spaces
$this->WriteFlowingBlock(str_repeat(' ',$spacenum));
break;
case 'BUTTON': // Draw a button
case 'SUBMIT':
case 'RESET':
$nihil = ($specialcontent['width']-$this->GetStringWidth($texto))/2;
$this->x += 1.5;
$this->y += 1;
$this->SetFillColor(190,190,190);
$this->Rect($this->x,$this->y,$specialcontent['width'],4.5,'DF'); // 4.5 in order to avoid overlapping
$this->x += $nihil;
$this->Write(5,$texto,$this->x);
$this->x += $nihil;
$this->SetFillColor(255);
$this->y -= 1;
break;
default: break;
}
break;
case 'SELECT':
$width_used = (($this->x - $bak_x) + $specialcontent['width'] + 8)*$this->k; //in order to adjust x coordinate later
$this->SetFillColor(235,235,235); //light gray
$this->x += 1.5;
$this->y += 1;
$this->Rect($this->x,$this->y,$specialcontent['width']+2,$this->lineheight,'DF'); // +2 == margin
$this->x += 1;
if ($texto != '') $this->Write($this->lineheight,$texto,$this->x); //the combobox content
$this->x += $specialcontent['width'] - $this->GetStringWidth($texto) + 2;
$this->SetFillColor(190,190,190); //dark gray
$this->Rect($this->x-1,$this->y,5,5,'DF'); //Arrow Box
$this->SetFont('zapfdingbats');
$this->Write($this->lineheight,chr(116),$this->x); //Down arrow
$this->SetFont('arial');
$this->SetFillColor(255);
//Readjust x coordinate in order to allow text to be placed after this form element
$this->x = $bak_x;
$spacesize = $this->CurrentFont[ 'cw' ][ ' ' ] * ( $this->FontSizePt / 1000 );
$spacenum = (integer)ceil(($width_used / $spacesize));
//Consider the space used so far in this line as a bunch of spaces
$this->WriteFlowingBlock(str_repeat(' ',$spacenum));
break;
case 'TEXTAREA':
//Setup TextArea properties
$this->SetFillColor(235,235,235);
$this->SetFont('courier');
$this->currentfont='courier';
$ta_lines = $specialcontent['lines'];
$ta_height = 1.1*$this->lineheight*$ta_lines;
$ta_width = $specialcontent['width'];
//Adjust x,y coordinates
$this->x += 1.5;
$this->y += 1.5;
$linesneeded = $this->WordWrap($texto,$ta_width);
if ( $linesneeded > $ta_lines ) //Too many words inside textarea
{
$textoaux = explode("\n",$texto);
$texto = '';
for($i=0;$i<$ta_lines;$i++)
{
if ($i == $ta_lines-1) $texto .= $textoaux[$i];
else $texto .= $textoaux[$i] . "\n";
}
//Inform the user that some text has been truncated
$texto{strlen($texto)-1} = ".";
$texto{strlen($texto)-2} = ".";
$texto{strlen($texto)-3} = ".";
}
$backup_y = $this->y;
$backup_x = $this->x;
$this->Rect($this->x,$this->y,$ta_width+3,$ta_height,'DF');
if ($texto != '') $this->MultiCell($ta_width+3,$this->lineheight,$texto);
$this->y = $backup_y - 1.5;
$this->x = $backup_x + $ta_width + 2.5;
$this->SetFillColor(255);
$this->SetFont('arial');
$this->currentfont='';
break;
default: break;
}
}
else //THE text
{
if ($vetor[0] == "\n") //We are reading a <BR> now turned into newline ("\n")
{
//Restart Flowing Block
$this->finishFlowingBlock($outofblock);
if($outofblock) $this->Ln($this->lineheight);
$this->x = $bak_x;
$this->newFlowingBlock( $this->divwidth,$this->divheight,$this->divborder,$align,$fill,$is_table );
}
else $this->WriteFlowingBlock( $vetor[0] , $outofblock );
}
//Check if it is the last element. If so then finish printing the block
if ($i == ($array_size-1)) $this->finishFlowingBlock($outofblock);
//Now we must deactivate what we have used
if( (isset($vetor[1]) and $vetor[1] != '') or $this->HREF != '')
{
$this->SetTextColor(0);
$this->SetStyle('U',false);
$this->HREF = '';
}
if(isset($vetor[2]) and $vetor[2] != '')
{
$this->SetStyle('B',false);
$this->SetStyle('I',false);
$this->SetStyle('U',false);
}
if(isset($vetor[3]) and $vetor[3] != '')
{
unset($cor);
$this->SetTextColor(0);
}
if(isset($vetor[4]) and $vetor[4] != '') $this->SetFont('arial');
if(isset($vetor[5]) and $vetor[5] === true)
{
$this->SUP = false;
$this->SetFontSize(11);
}
if(isset($vetor[6]) and $vetor[6] === true)
{
$this->SUB = false;
$this->SetFontSize(11);
}
//vetor7-internal links
if(isset($vetor[8]) and $vetor[8] === true) // strike-through the text
{
$this->strike = false;
}
if(isset($vetor[9]) and !empty($vetor[9])) // Outline parameters
{
$this->SetTextOutline(false);
$this->outline_on = false;
}
if(isset($vetor[10]) and !empty($vetor[10])) //Background color
{
$this->SetFillColor(255);
$this->divbgcolor = false;
}
}//end of for(i=0;i<arraysize;i++)
//Restore some previously set parameters
$this->strike = $save['strike'];
$this->SUP = $save['SUP'];
$this->SUB = $save['SUB'];
$this->dotted_on = $save['DOTTED'];
$this->dash_on = $save['DASHED'];
if ($this->dash_on) $this->SetDash(2,2);
//Check whether we have borders to paint or not
//(only works 100% if whole content spans only 1 page)
if ($this->cssbegin and ($this->divborder or $this->dash_on or $this->dotted_on or $this->divbgcolor))
{
if ($oldpage != $this->page)
{
//Only border on last page is painted (known bug)
$x = $this->lMargin;
$y = $this->tMargin;
$old_height = $this->y - $y;
}
else
{
if ($this->oldx < 0) $x = $this->x;
else $x = $this->oldx;
if ($this->oldy < 0) $y = $this->y - $old_height;
else $y = $this->oldy;
}
if ($this->divborder) $this->Rect($x,$y,$this->divwidth,$old_height);
if ($this->dash_on) $this->Rect($x,$y,$this->divwidth,$old_height);
if ($this->dotted_on) $this->DottedRect($x,$y,$this->divwidth,$old_height);
$this->x = $bak_x;
}
}
function Reset()
{
//! @return void
//! @desc Resets several class attributes
// if ( $this->issetcolor !== true )
// {
$this->SetTextColor(0);
$this->SetDrawColor(0);
$this->SetFillColor(255);
$this->colorarray = array();
$this->bgcolorarray = array();
$this->issetcolor = false;
// }
$this->HREF = '';
$this->SetTextOutline(false);
//$this->strike = false;
$this->SetFontSize(11);
$this->SetStyle('B',false);
$this->SetStyle('I',false);
$this->SetStyle('U',false);
$this->SetFont('arial');
$this->divwidth = 0;
$this->divheight = 0;
$this->divalign = "L";
$this->divrevert = false;
$this->divborder = 0;
$this->divbgcolor = false;
$this->toupper = false;
$this->tolower = false;
$this->SetDash(); //restore to no dash
$this->dash_on = false;
$this->dotted_on = false;
$this->oldx = -1;
$this->oldy = -1;
}
function ReadMetaTags($html)
{
//! @return void
//! @desc Pass meta tag info to PDF file properties
$regexp = '/ (\\w+?)=([^\\s>"]+)/si'; // changes anykey=anyvalue to anykey="anyvalue" (only do this when this happens inside tags)
$html = preg_replace($regexp," \$1=\"\$2\"",$html);
$regexp = '/<meta .*?(name|content)="(.*?)" .*?(name|content)="(.*?)".*?>/si';
preg_match_all($regexp,$html,$aux);
$firstattr = $aux[1];
$secondattr = $aux[3];
for( $i = 0 ; $i < count($aux[0]) ; $i++)
{
$name = ( strtoupper($firstattr[$i]) == "NAME" )? strtoupper($aux[2][$i]) : strtoupper($aux[4][$i]);
$content = ( strtoupper($firstattr[$i]) == "CONTENT" )? $aux[2][$i] : $aux[4][$i];
switch($name)
{
case "KEYWORDS": $this->SetKeywords($content); break;
case "AUTHOR": $this->SetAuthor($content); break;
case "DESCRIPTION": $this->SetSubject($content); break;
}
}
//Comercial do Aplicativo usado (no caso um script):
$this->SetCreator("HTML2FPDF >> http://html2fpdf.sf.net");
}
//////////////////
/// CSS parser ///
//////////////////
function ReadCSS($html)
{
//! @desc CSS parser
//! @return string
/*
* This version ONLY supports: .class {...} / #id { .... }
* It does NOT support: body{...} / a#hover { ... } / p.right { ... } / other mixed names
* This function must read the CSS code (internal or external) and order its value inside $this->CSS.
*/
$match = 0; // no match for instance
$regexp = ''; // This helps debugging: showing what is the REAL string being processed
//CSS inside external files
$regexp = '/<link rel="stylesheet".*?href="(.+?)"\\s*?\/?>/si';
$match = preg_match_all($regexp,$html,$CSSext);
$ind = 0;
while($match){
//Fix path value
$path = $CSSext[1][$ind];
$path = str_replace("\\","/",$path); //If on Windows
//Get link info and obtain its absolute path
$regexp = '|^./|';
$path = preg_replace($regexp,'',$path);
if (strpos($path,"../") !== false ) //It is a Relative Link
{
$backtrackamount = substr_count($path,"../");
$maxbacktrack = substr_count($this->basepath,"/") - 1;
$filepath = str_replace("../",'',$path);
$path = $this->basepath;
//If it is an invalid relative link, then make it go to directory root
if ($backtrackamount > $maxbacktrack) $backtrackamount = $maxbacktrack;
//Backtrack some directories
for( $i = 0 ; $i < $backtrackamount + 1 ; $i++ ) $path = substr( $path, 0 , strrpos($path,"/") );
$path = $path . "/" . $filepath; //Make it an absolute path
}
elseif( strpos($path,":/") === false) //It is a Local Link
{
$path = $this->basepath . $path;
}
//Do nothing if it is an Absolute Link
//END of fix path value
$CSSextblock = file_get_contents($path);
//Get class/id name and its characteristics from $CSSblock[1]
$regexp = '/[.# ]([^.]+?)\\s*?\{(.+?)\}/s'; // '/s' PCRE_DOTALL including \n
preg_match_all( $regexp, $CSSextblock, $extstyle);
//Make CSS[Name-of-the-class] = array(key => value)
$regexp = '/\\s*?(\\S+?):(.+?);/si';
for($i=0; $i < count($extstyle[1]) ; $i++)
{
preg_match_all( $regexp, $extstyle[2][$i], $extstyleinfo);
$extproperties = $extstyleinfo[1];
$extvalues = $extstyleinfo[2];
for($j = 0; $j < count($extproperties) ; $j++)
{
//Array-properties and Array-values must have the SAME SIZE!
$extclassproperties[strtoupper($extproperties[$j])] = trim($extvalues[$j]);
}
$this->CSS[$extstyle[1][$i]] = $extclassproperties;
$extproperties = array();
$extvalues = array();
$extclassproperties = array();
}
$match--;
$ind++;
} //end of match
$match = 0; // reset value, if needed
//CSS internal
//Get content between tags and order it, using regexp
$regexp = '/<style.*?>(.*?)<\/style>/si'; // it can be <style> or <style type="txt/css">
$match = preg_match($regexp,$html,$CSSblock);
if ($match) {
//Get class/id name and its characteristics from $CSSblock[1]
$regexp = '/[.#]([^.]+?)\\s*?\{(.+?)\}/s'; // '/s' PCRE_DOTALL including \n
preg_match_all( $regexp, $CSSblock[1], $style);
//Make CSS[Name-of-the-class] = array(key => value)
$regexp = '/\\s*?(\\S+?):(.+?);/si';
for($i=0; $i < count($style[1]) ; $i++)
{
preg_match_all( $regexp, $style[2][$i], $styleinfo);
$properties = $styleinfo[1];
$values = $styleinfo[2];
for($j = 0; $j < count($properties) ; $j++)
{
//Array-properties and Array-values must have the SAME SIZE!
$classproperties[strtoupper($properties[$j])] = trim($values[$j]);
}
$this->CSS[$style[1][$i]] = $classproperties;
$properties = array();
$values = array();
$classproperties = array();
}
} // end of match
//Remove CSS (tags and content), if any
$regexp = '/<style.*?>(.*?)<\/style>/si'; // it can be <style> or <style type="txt/css">
$html = preg_replace($regexp,'',$html);
return $html;
}
function readInlineCSS($html)
{
//! @return array
//! @desc Reads inline CSS and returns an array of properties
//Fix incomplete CSS code
$size = strlen($html)-1;
if ($html{$size} != ';') $html .= ';';
//Make CSS[Name-of-the-class] = array(key => value)
$regexp = '|\\s*?(\\S+?):(.+?);|i';
preg_match_all( $regexp, $html, $styleinfo);
$properties = $styleinfo[1];
$values = $styleinfo[2];
//Array-properties and Array-values must have the SAME SIZE!
$classproperties = array();
for($i = 0; $i < count($properties) ; $i++) $classproperties[strtoupper($properties[$i])] = trim($values[$i]);
return $classproperties;
}
function setCSS($arrayaux)
{
//! @return void
//! @desc Change some class attributes according to CSS properties
if (!is_array($arrayaux)) return; //Removes PHP Warning
foreach($arrayaux as $k => $v)
{
switch($k){
case 'WIDTH':
$this->divwidth = ConvertSize($v,$this->pgwidth);
break;
case 'HEIGHT':
$this->divheight = ConvertSize($v,$this->pgwidth);
break;
case 'BORDER': // width style color (width not supported correctly - it is always considered as normal)
$prop = explode(' ',$v);
if ( count($prop) != 3 ) break; // Not supported: borders not fully declared
//style: dashed dotted none (anything else => solid )
if (strnatcasecmp($prop[1],"dashed") == 0) //found "dashed"! (ignores case)
{
$this->dash_on = true;
$this->SetDash(2,2); //2mm on, 2mm off
}
elseif (strnatcasecmp($prop[1],"dotted") == 0) //found "dotted"! (ignores case)
{
$this->dotted_on = true;
}
elseif (strnatcasecmp($prop[1],"none") == 0) $this->divborder = 0;
else $this->divborder = 1;
//color
$coul = ConvertColor($prop[2]);
$this->SetDrawColor($coul['R'],$coul['G'],$coul['B']);
$this->issetcolor=true;
break;
case 'FONT-FAMILY': // one of the $this->fontlist fonts
//If it is a font list, get all font types
$aux_fontlist = explode(",",$v);
$fontarraysize = count($aux_fontlist);
for($i=0;$i<$fontarraysize;$i++)
{
$fonttype = $aux_fontlist[$i];
$fonttype = trim($fonttype);
//If font is found, set it, and exit loop
if ( in_array(strtolower($fonttype), $this->fontlist) ) {$this->SetFont(strtolower($fonttype));break;}
//If font = "courier new" for example, try simply looking for "courier"
$fonttype = explode(" ",$fonttype);
$fonttype = $fonttype[0];
if ( in_array(strtolower($fonttype), $this->fontlist) ) {$this->SetFont(strtolower($fonttype));break;}
}
break;
case 'FONT-SIZE': //Does not support: smaller, larger
if(is_numeric($v{0}))
{
$mmsize = ConvertSize($v,$this->pgwidth);
$this->SetFontSize( $mmsize*(72/25.4) ); //Get size in points (pt)
}
else{
$v = strtoupper($v);
switch($v)
{
//Values obtained from http://www.w3schools.com/html/html_reference.asp
case 'XX-SMALL': $this->SetFontSize( (0.7)* 11);
break;
case 'X-SMALL': $this->SetFontSize( (0.77) * 11);
break;
case 'SMALL': $this->SetFontSize( (0.86)* 11);
break;
case 'MEDIUM': $this->SetFontSize(11);
break;
case 'LARGE': $this->SetFontSize( (1.2)*11);
break;
case 'X-LARGE': $this->SetFontSize( (1.5)*11);
break;
case 'XX-LARGE': $this->SetFontSize( 2*11);
break;
}
}
break;
case 'FONT-STYLE': // italic normal oblique
switch (strtoupper($v))
{
case 'ITALIC':
case 'OBLIQUE':
$this->SetStyle('I',true);
break;
case 'NORMAL': break;
}
break;
case 'FONT-WEIGHT': // normal bold //Does not support: bolder, lighter, 100..900(step value=100)
switch (strtoupper($v))
{
case 'BOLD':
$this->SetStyle('B',true);
break;
case 'NORMAL': break;
}
break;
case 'TEXT-DECORATION': // none underline //Does not support: overline, blink
switch (strtoupper($v))
{
case 'LINE-THROUGH':
$this->strike = true;
break;
case 'UNDERLINE':
$this->SetStyle('U',true);
break;
case 'NONE': break;
}
case 'TEXT-TRANSFORM': // none uppercase lowercase //Does not support: capitalize
switch (strtoupper($v)) //Not working 100%
{
case 'UPPERCASE':
$this->toupper=true;
break;
case 'LOWERCASE':
$this->tolower=true;
break;
case 'NONE': break;
}
case 'TEXT-ALIGN': //left right center justify
switch (strtoupper($v))
{
case 'LEFT':
$this->divalign="L";
break;
case 'CENTER':
$this->divalign="C";
break;
case 'RIGHT':
$this->divalign="R";
break;
case 'JUSTIFY':
$this->divalign="J";
break;
}
break;
case 'DIRECTION': //ltr(default) rtl
if (strtolower($v) == 'rtl') $this->divrevert = true;
break;
case 'BACKGROUND': // bgcolor only
$cor = ConvertColor($v);
$this->bgcolorarray = $cor;
$this->SetFillColor($cor['R'],$cor['G'],$cor['B']);
$this->divbgcolor = true;
break;
case 'COLOR': // font color
$cor = ConvertColor($v);
$this->colorarray = $cor;
$this->SetTextColor($cor['R'],$cor['G'],$cor['B']);
$this->issetcolor=true;
break;
}//end of switch($k)
}//end of foreach
}
function SetStyle($tag,$enable)
{
//! @return void
//! @desc Enables/Disables B,I,U styles
//Modify style and select corresponding font
$this->$tag+=($enable ? 1 : -1);
$style='';
//Fix some SetStyle misuse
if ($this->$tag < 0) $this->$tag = 0;
if ($this->$tag > 1) $this->$tag = 1;
foreach(array('B','I','U') as $s)
if($this->$s>0)
$style.=$s;
$this->currentstyle=$style;
$this->SetFont('',$style);
}
function DisableTags($str='')
{
//! @return void
//! @desc Disable some tags using ',' as separator. Enable all tags calling this function without parameters.
if ($str == '') //enable all tags
{
//Insert new supported tags in the long string below.
$this->enabledtags = "<tt><kbd><samp><option><outline><span><newpage><page_break><s><strike><del><bdo><big><small><address><ins><cite><font><center><sup><sub><input><select><option><textarea><title><form><ol><ul><li><h1><h2><h3><h4><h5><h6><pre><b><u><i><a><img><p><br><strong><em><code><th><tr><blockquote><hr><td><tr><table><div>";
}
else
{
$str = explode(",",$str);
foreach($str as $v) $this->enabledtags = str_replace(trim($v),'',$this->enabledtags);
}
}
////////////////////////TABLE CODE (from PDFTable)/////////////////////////////////////
//Thanks to vietcom (vncommando at yahoo dot com)
/* Modified by Renato Coelho
in order to print tables that span more than 1 page and to allow
bold,italic and the likes inside table cells (and alignment now works with styles!)
*/
//table Array of (w, h, bc, nr, wc, hr, cells)
//w Width of table
//h Height of table
//nc Number column
//nr Number row
//hr List of height of each row
//wc List of width of each column
//cells List of cells of each rows, cells[i][j] is a cell in the table
function _tableColumnWidth(&$table){
//! @return void
$cs = &$table['cells'];
$mw = $this->getStringWidth('W');
$nc = $table['nc'];
$nr = $table['nr'];
$listspan = array();
//Xac dinh do rong cua cac cell va cac cot tuong ung
for($j = 0 ; $j < $nc ; $j++ ) //columns
{
$wc = &$table['wc'][$j];
for($i = 0 ; $i < $nr ; $i++ ) //rows
{
if (isset($cs[$i][$j]) && $cs[$i][$j])
{
$c = &$cs[$i][$j];
$miw = $mw;
if (isset($c['maxs']) and $c['maxs'] != '') $c['s'] = $c['maxs'];
$c['maw'] = $c['s'];
if (isset($c['nowrap'])) $miw = $c['maw'];
if (isset($c['w']))
{
if ($miw<$c['w']) $c['miw'] = $c['w'];
if ($miw>$c['w']) $c['miw'] = $c['w'] = $miw;
if (!isset($wc['w'])) $wc['w'] = 1;
}
else $c['miw'] = $miw;
if ($c['maw'] < $c['miw']) $c['maw'] = $c['miw'];
if (!isset($c['colspan']))
{
if ($wc['miw'] < $c['miw']) $wc['miw'] = $c['miw'];
if ($wc['maw'] < $c['maw']) $wc['maw'] = $c['maw'];
}
else $listspan[] = array($i,$j);
//Check if minimum width of the whole column is big enough for a huge word to fit
$auxtext = implode("",$c['text']);
$minwidth = $this->WordWrap($auxtext,$wc['miw']-2);// -2 == margin
if ($minwidth < 0 and (-$minwidth) > $wc['miw']) $wc['miw'] = (-$minwidth) +2; //increase minimum width
if ($wc['miw'] > $wc['maw']) $wc['maw'] = $wc['miw']; //update maximum width, if needed
}
}//rows
}//columns
//Xac dinh su anh huong cua cac cell colspan len cac cot va nguoc lai
$wc = &$table['wc'];
foreach ($listspan as $span)
{
list($i,$j) = $span;
$c = &$cs[$i][$j];
$lc = $j + $c['colspan'];
if ($lc > $nc) $lc = $nc;
$wis = $wisa = 0;
$was = $wasa = 0;
$list = array();
for($k=$j;$k<$lc;$k++)
{
$wis += $wc[$k]['miw'];
$was += $wc[$k]['maw'];
if (!isset($c['w']))
{
$list[] = $k;
$wisa += $wc[$k]['miw'];
$wasa += $wc[$k]['maw'];
}
}
if ($c['miw'] > $wis)
{
if (!$wis)
{//Cac cot chua co kich thuoc => chia deu
for($k=$j;$k<$lc;$k++) $wc[$k]['miw'] = $c['miw']/$c['colspan'];
}
elseif(!count($list))
{//Khong co cot nao co kich thuoc auto => chia deu phan du cho tat ca
$wi = $c['miw'] - $wis;
for($k=$j;$k<$lc;$k++) $wc[$k]['miw'] += ($wc[$k]['miw']/$wis)*$wi;
}
else
{//Co mot so cot co kich thuoc auto => chia deu phan du cho cac cot auto
$wi = $c['miw'] - $wis;
foreach ($list as $k) $wc[$k]['miw'] += ($wc[$k]['miw']/$wisa)*$wi;
}
}
if ($c['maw'] > $was)
{
if (!$wis)
{//Cac cot chua co kich thuoc => chia deu
for($k=$j;$k<$lc;$k++) $wc[$k]['maw'] = $c['maw']/$c['colspan'];
}
elseif (!count($list))
{
//Khong co cot nao co kich thuoc auto => chia deu phan du cho tat ca
$wi = $c['maw'] - $was;
for($k=$j;$k<$lc;$k++) $wc[$k]['maw'] += ($wc[$k]['maw']/$was)*$wi;
}
else
{//Co mot so cot co kich thuoc auto => chia deu phan du cho cac cot auto
$wi = $c['maw'] - $was;
foreach ($list as $k) $wc[$k]['maw'] += ($wc[$k]['maw']/$wasa)*$wi;
}
}
}
}
function _tableWidth(&$table){
//! @return void
//! @desc Calculates the Table Width
// @desc Xac dinh chieu rong cua table
$widthcols = &$table['wc'];
$numcols = $table['nc'];
$tablewidth = 0;
for ( $i = 0 ; $i < $numcols ; $i++ )
{
$tablewidth += isset($widthcols[$i]['w']) ? $widthcols[$i]['miw'] : $widthcols[$i]['maw'];
}
if ($tablewidth > $this->pgwidth) $table['w'] = $this->pgwidth;
if (isset($table['w']))
{
$wis = $wisa = 0;
$list = array();
for( $i = 0 ; $i < $numcols ; $i++ )
{
$wis += $widthcols[$i]['miw'];
if (!isset($widthcols[$i]['w'])){ $list[] = $i;$wisa += $widthcols[$i]['miw'];}
}
if ($table['w'] > $wis)
{
if (!count($list))
{//Khong co cot nao co kich thuoc auto => chia deu phan du cho tat ca
//http://www.ksvn.com/anhviet_new.htm - translating comments...
//bent shrink essence move size measure automatic => divide against give as a whole
//$wi = $table['w'] - $wis;
$wi = ($table['w'] - $wis)/$numcols;
for($k=0;$k<$numcols;$k++)
//$widthcols[$k]['miw'] += ($widthcols[$k]['miw']/$wis)*$wi;
$widthcols[$k]['miw'] += $wi;
}
else
{//Co mot so cot co kich thuoc auto => chia deu phan du cho cac cot auto
//$wi = $table['w'] - $wis;
$wi = ($table['w'] - $wis)/count($list);
foreach ($list as $k)
//$widthcols[$k]['miw'] += ($widthcols[$k]['miw']/$wisa)*$wi;
$widthcols[$k]['miw'] += $wi;
}
}
for ($i=0;$i<$numcols;$i++)
{
$tablewidth = $widthcols[$i]['miw'];
unset($widthcols[$i]);
$widthcols[$i] = $tablewidth;
}
}
else //table has no width defined
{
$table['w'] = $tablewidth;
for ( $i = 0 ; $i < $numcols ; $i++)
{
$tablewidth = isset($widthcols[$i]['w']) ? $widthcols[$i]['miw'] : $widthcols[$i]['maw'];
unset($widthcols[$i]);
$widthcols[$i] = $tablewidth;
}
}
}
function _tableHeight(&$table){
//! @return void
//! @desc Calculates the Table Height
$cells = &$table['cells'];
$numcols = $table['nc'];
$numrows = $table['nr'];
$listspan = array();
for( $i = 0 ; $i < $numrows ; $i++ )//rows
{
$heightrow = &$table['hr'][$i];
for( $j = 0 ; $j < $numcols ; $j++ ) //columns
{
if (isset($cells[$i][$j]) && $cells[$i][$j])
{
$c = &$cells[$i][$j];
list($x,$cw) = $this->_tableGetWidth($table, $i,$j);
//Check whether width is enough for this cells' text
$auxtext = implode("",$c['text']);
$auxtext2 = $auxtext; //in case we have text with styles
$nostyles_size = $this->GetStringWidth($auxtext) + 3; // +3 == margin
$linesneeded = $this->WordWrap($auxtext,$cw-2);// -2 == margin
if ($c['s'] > $nostyles_size and !isset($c['form'])) //Text with styles
{
$auxtext = $auxtext2; //recover original characteristics (original /n placements)
$diffsize = $c['s'] - $nostyles_size; //with bold et al. char width gets a bit bigger than plain char
if ($linesneeded == 0) $linesneeded = 1; //to avoid division by zero
$diffsize /= $linesneeded;
$linesneeded = $this->WordWrap($auxtext,$cw-2-$diffsize);//diffsize used to wrap text correctly
}
if (isset($c['form']))
{
$linesneeded = ceil(($c['s']-3)/($cw-2)); //Text + form in a cell
//Presuming the use of styles
if ( ($this->GetStringWidth($auxtext) + 3) > ($cw-2) ) $linesneeded++;
}
$ch = $linesneeded * 1.1 * $this->lineheight;
//If height is bigger than page height...
if ($ch > ($this->fh - $this->bMargin - $this->tMargin)) $ch = ($this->fh - $this->bMargin - $this->tMargin);
//If height is defined and it is bigger than calculated $ch then update values
if (isset($c['h']) && $c['h'] > $ch)
{
$c['mih'] = $ch; //in order to keep valign working
$ch = $c['h'];
}
else $c['mih'] = $ch;
if (isset($c['rowspan'])) $listspan[] = array($i,$j);
elseif ($heightrow < $ch) $heightrow = $ch;
if (isset($c['form'])) $c['mih'] = $ch;
}
}//end of columns
}//end of rows
$heightrow = &$table['hr'];
foreach ($listspan as $span)
{
list($i,$j) = $span;
$c = &$cells[$i][$j];
$lr = $i + $c['rowspan'];
if ($lr > $numrows) $lr = $numrows;
$hs = $hsa = 0;
$list = array();
for($k=$i;$k<$lr;$k++)
{
$hs += $heightrow[$k];
if (!isset($c['h']))
{
$list[] = $k;
$hsa += $heightrow[$k];
}
}
if ($c['mih'] > $hs)
{
if (!$hs)
{//Cac dong chua co kich thuoc => chia deu
for($k=$i;$k<$lr;$k++) $heightrow[$k] = $c['mih']/$c['rowspan'];
}
elseif (!count($list))
{//Khong co dong nao co kich thuoc auto => chia deu phan du cho tat ca
$hi = $c['mih'] - $hs;
for($k=$i;$k<$lr;$k++) $heightrow[$k] += ($heightrow[$k]/$hs)*$hi;
}
else
{//Co mot so dong co kich thuoc auto => chia deu phan du cho cac dong auto
$hi = $c['mih'] - $hsa;
foreach ($list as $k) $heightrow[$k] += ($heightrow[$k]/$hsa)*$hi;
}
}
}
}
function _tableGetWidth(&$table, $i,$j){
//! @return array(x,w)
// @desc Xac dinh toa do va do rong cua mot cell
$cell = &$table['cells'][$i][$j];
if ($cell)
{
if (isset($cell['x0'])) return array($cell['x0'], $cell['w0']);
$x = 0;
$widthcols = &$table['wc'];
for( $k = 0 ; $k < $j ; $k++ ) $x += $widthcols[$k];
$w = $widthcols[$j];
if (isset($cell['colspan']))
{
for ( $k = $j+$cell['colspan']-1 ; $k > $j ; $k-- ) $w += $widthcols[$k];
}
$cell['x0'] = $x;
$cell['w0'] = $w;
return array($x, $w);
}
return array(0,0);
}
function _tableGetHeight(&$table, $i,$j){
//! @return array(y,h)
$cell = &$table['cells'][$i][$j];
if ($cell){
if (isset($cell['y0'])) return array($cell['y0'], $cell['h0']);
$y = 0;
$heightrow = &$table['hr'];
for ($k=0;$k<$i;$k++) $y += $heightrow[$k];
$h = $heightrow[$i];
if (isset($cell['rowspan'])){
for ($k=$i+$cell['rowspan']-1;$k>$i;$k--)
$h += $heightrow[$k];
}
$cell['y0'] = $y;
$cell['h0'] = $h;
return array($y, $h);
}
return array(0,0);
}
function _tableRect($x, $y, $w, $h, $type=1){
//! @return void
if ($type==1) $this->Rect($x, $y, $w, $h);
elseif (strlen($type)==4){
$x2 = $x + $w; $y2 = $y + $h;
if (intval($type{0})) $this->Line($x , $y , $x2, $y );
if (intval($type{1})) $this->Line($x2, $y , $x2, $y2);
if (intval($type{2})) $this->Line($x , $y2, $x2, $y2);
if (intval($type{3})) $this->Line($x , $y , $x , $y2);
}
}
function _tableWrite(&$table){
//! @desc Main table function
//! @return void
$cells = &$table['cells'];
$numcols = $table['nc'];
$numrows = $table['nr'];
$x0 = $this->x;
$y0 = $this->y;
$right = $this->pgwidth - $this->rMargin;
if (isset($table['a']) and ($table['w'] != $this->pgwidth))
{
if ($table['a']=='C') $x0 += (($right-$x0) - $table['w'])/2;
elseif ($table['a']=='R') $x0 = $right - $table['w'];
}
$returny = 0;
$tableheader = array();
//Draw Table Contents and Borders
for( $i = 0 ; $i < $numrows ; $i++ ) //Rows
{
$skippage = false;
for( $j = 0 ; $j < $numcols ; $j++ ) //Columns
{
if (isset($cells[$i][$j]) && $cells[$i][$j])
{
$cell = &$cells[$i][$j];
list($x,$w) = $this->_tableGetWidth($table, $i, $j);
list($y,$h) = $this->_tableGetHeight($table, $i, $j);
$x += $x0;
$y += $y0;
$y -= $returny;
if ((($y + $h) > ($this->fh - $this->bMargin)) && ($y0 >0 || $x0 > 0))
{
if (!$skippage)
{
$y -= $y0;
$returny += $y;
$this->AddPage();
if ($this->usetableheader) $this->Header($tableheader);
if ($this->usetableheader) $y0 = $this->y;
else $y0 = $this->tMargin;
$y = $y0;
}
$skippage = true;
}
//Align
$this->x = $x; $this->y = $y;
$align = isset($cell['a'])? $cell['a'] : 'L';
//Vertical align
if (!isset($cell['va']) || $cell['va']=='M') $this->y += ($h-$cell['mih'])/2;
elseif (isset($cell['va']) && $cell['va']=='B') $this->y += $h-$cell['mih'];
//Fill
$fill = isset($cell['bgcolor']) ? $cell['bgcolor']
: (isset($table['bgcolor'][$i]) ? $table['bgcolor'][$i]
: (isset($table['bgcolor'][-1]) ? $table['bgcolor'][-1] : 0));
if ($fill)
{
$color = ConvertColor($fill);
$this->SetFillColor($color['R'],$color['G'],$color['B']);
$this->Rect($x, $y, $w, $h, 'F');
}
//Border
if (isset($cell['border'])) $this->_tableRect($x, $y, $w, $h, $cell['border']);
elseif (isset($table['border']) && $table['border']) $this->Rect($x, $y, $w, $h);
$this->divalign=$align;
$this->divwidth=$w-2;
//Get info of first row == table header
if ($this->usetableheader and $i == 0 )
{
$tableheader[$j]['x'] = $x;
$tableheader[$j]['y'] = $y;
$tableheader[$j]['h'] = $h;
$tableheader[$j]['w'] = $w;
$tableheader[$j]['text'] = $cell['text'];
$tableheader[$j]['textbuffer'] = $cell['textbuffer'];
$tableheader[$j]['a'] = isset($cell['a'])? $cell['a'] : 'L';
$tableheader[$j]['va'] = $cell['va'];
$tableheader[$j]['mih'] = $cell['mih'];
$tableheader[$j]['bgcolor'] = $fill;
if ($table['border']) $tableheader[$j]['border'] = 'all';
elseif (isset($cell['border'])) $tableheader[$j]['border'] = $cell['border'];
}
if (!empty($cell['textbuffer'])) $this->printbuffer($cell['textbuffer'],false,true/*inside a table*/);
//Reset values
$this->Reset();
}//end of (if isset(cells)...)
}// end of columns
if ($i == $numrows-1) $this->y = $y + $h; //last row jump (update this->y position)
}// end of rows
}//END OF FUNCTION _tableWrite()
/////////////////////////END OF TABLE CODE//////////////////////////////////
}//end of Class
/*
---- JUNK(?)/OLD CODE: ------
// <? <- this fixes HIGHLIGHT PSPAD bug ...
*/
?>