currentfont - mine
. $this->CurrentFont - fpdf's
TODO (in the future...):
- Make font-family, font-size, lineheight customizable
- Increase number of HTML/CSS tags/properties, Image/Font Types, recognized/supported
- allow BMP support? (tried with http://phpthumb.sourceforge.net/ but failed)
- Improve CSS support
- support image side-by-side or one-below-another or both?
- Improve code clarity even more (modularize and get better var names like on textbuffer array's indexes for example)
//////////////////////////////////////////////////////////////////////////////
//////////////DO NOT MODIFY THE CONTENTS OF THIS BOX//////////////////////////
//////////////////////////////////////////////////////////////////////////////
// //
// HTML2FPDF is a php script to read a HTML text and generate a PDF file. //
// Copyright (C) 2004-2005 Renato Coelho //
// This script may be distributed as long as the following files are kept //
// together: //
// //
// fpdf.php, html2fpdf.php, gif.php,htmltoolkit.php,license.txt,credits.txt //
// //
//////////////////////////////////////////////////////////////////////////////
Misc. Observations:
- CSS + align = bug! (?)
OBS1: para textos de mais de 1 página, talvez tenha que juntar varios $texto_artigo
antes de mandar gerar o PDF, para que o PDF gerado seja completo.
OBS2: there are 2 types of spaces 32 and 160 (ascii values)
OBS3: //! is a special comment to be used with source2doc.php, a script I created
in order to generate the doc on the site html2fpdf.sf.net
OBS4: var $LineWidth; // line width in user unit - use this to make css thin/medium/thick work
OBS5: Images and Textareas: when they are inserted you can only type below them (==display:block)
OBS6: Optimized to 'A4' paper (default font: Arial , normal , size 11 )
OBS7: Regexp + Perl ([preg]accepts non-greedy quantifiers while PHP[ereg] does not)
Perl: '/regexp/x' where x == option ( x = i:ignore case , x = s: DOT gets \n as well)
========================END OF INITIAL COMMENTS=================================
*/
define( 'HTML2FPDF_VERSION', '3.0(beta)' );
if ( !defined( 'RELATIVE_PATH' ) ) define( 'RELATIVE_PATH', '' );
if ( !defined( 'FPDF_FONTPATH' ) ) define( 'FPDF_FONTPATH', 'font/' );
if ( !defined( 'REGEXP_NOENDTAG' ) ) define( 'REGEXP_NOENDTAG', '/^(BR|INPUT|IMG|HR)$/i' );
require_once( RELATIVE_PATH . 'fpdf.php' );
require_once( RELATIVE_PATH . 'htmltoolkit.php' );
class HTML2FPDF extends FPDF {
// 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 $CSSbackup; //! array
var $CSSbackupTag; //! array
var $CSSbackupChanged; //! array
var $CSSproperties; //! array
var $textbuffer; //! array
var $currentstyle; //! string
var $currentfont; //! string
var $colorarray; //! array
var $bgcolorarray; //! array
var $internallink; //! array
var $enabledtags; //! string
var $isdisplay; //! bool When false, do not display current tags.
var $lineheight; //! int
var $urlbasepath; //! string
var $urllevels; // !int The URL depth to the filebasepath
var $filebasepath; //! string
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
var $debug_str; //! string
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( 'Helvetica', '', 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->isdisplay = true;
$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->textbuffer = array();
$this->CSS = array();
$this->CSSbackup = array();
$this->CSSbackupTag = array();
$this->CSSbackupChanged = array();
$this->CSSproperties = array();
$this->internallink = array();
$this->urlbasepath = "";
$this->filebasepath = "";
$this->outlineparam = array();
$this->outline_on = false;
$this->specialcontent = '';
$this->selectoption = array();
$this->shownoimg = false;
$this->usetableheader = false;
$this->usecss = true;
$this->usepre = true;
$this->debug_str = "";
}
function debug( $msg )
{
// ! @desc Add a message to the debug messages
// ! @return void
$this->debug_str .= $msg;
}
function debug_out()
{
// ! @desc Send debug information to the output
// ! @return void
print $this->debug_str;
}
function setURLBasePath( $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->urlbasepath = $str . "/";
if ( $this->filebasepath == '' ) {
$this->basepath = str_replace( "\\", "/", $this->urlbasepath ); //If on Windows
$urllevels = substr_count( '/', preg_replace( '/^.*?:\/\//', $this->urlbasepath ) );
} ;
}
function setBasePath( $str )
{
// legacy implementation
if ( preg_match( '/^(http|https|ftp|file):\/\//', $str ) ) {
$this->filebasepath = '';
$this->setURLBasePath( dirname( $str ) );
} else {
$this->urlfilebasepath = '';
$this->setFileBasePath( dirname( $str ) );
}
}
function setFileBasePath( $str )
{
// ! @desc Inform the script where the html file is (full file path) in order to adjust HREF and SRC links. No-Parameter: The directory where this script is.
// ! @return void
$this->filebasepath = $str . "/";
$this->filebasepath = str_replace( "\\", "/", $this->filebasepath ); //If on Windows
if ( $this->urlbasepath == '' ) {
$this->basepath = $this->filebasepath;
}
}
function setURLLevels( $levels )
{
$this->urllevels = $levels;
}
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;
}
function RevertCSSproperties( $tag )
{
// ! @desc Restore previous properties from stack
// ! @return void
// revert until the matching opening tag is found
$this->debug( "End of ${tag}
" );
$found = false;
while ( !empty( $this->CSSbackupTag ) && !$found ) {
$found = ( ( $ltag = array_pop( $this->CSSbackupTag ) ) == $tag );
// $this->debug("End of ${tag}: $ltag
");
// As long as the corresponding opening tag is not found
if ( empty( $this->CSSbackupTag ) ) {
array_pop( $this->CSSbackup );
$this->CSSproperties = array();
$this->Reset();
$this->SetCSS( array() );
$this->debug( "Empty list -> Empty CSS end ${tag}
" );
} elseif ( $change = array_pop( $this->CSSbackupChanged ) ) {
$this->CSSproperties = array();
$this->Reset();
$this->SetCSS( array_pop( $this->CSSbackup ) );
$this->debug( "Revert CSS ${ltag} on end of ${tag}
" );
} else {
array_pop( $this->CSSbackup );
$this->debug( "Popped ${ltag} (changed=$change) on end of ${tag}
" );
}
}
}
function StoreCSSproperties( $tag )
{
// ! @desc Store current properties on stack
// ! @return void
// if(count($this->CSSbackupTag)>0) {
// $ltag=$this->CSSbackupTag[count($this->CSSbackupTag)-1];
// // $this->debug("Test old:${ltag}
");
// //////////////////////////////////////////////////
// // TODO: May need this for tags in which a CSS is specified up to the next boundary (
??)
// //////////////////////////////////////////////////
// if(ereg(REGEXP_NOENDTAG, $ltag)) {
// // Previous tag does not have CloseTag.
// // Restore CSS
// $this->debug("Forced revert of ${ltag}
");
// $this->RevertCSSproperties($ltag);
// }
// }
$this->debug( "Start of ${tag}
" );
$this->CSSbackup[] = $this->CSSproperties;
$this->CSSbackupTag[] = $tag;
// $this->debug("Count".count($this->CSSbackupTag)."
");
$this->CSSbackupChanged[] = 0; // Indicate that there is no change on the CSS (yet)
}
function SetCSSonEndOfOpenTag( $tag )
{
// ! @desc Check if the Tag just opened should be closed immediately.
// ! @return void
if ( count( $this->CSSbackupTag ) > 0 ) {
$ltag = $this->CSSbackupTag[count( $this->CSSbackupTag )-1];
// $this->debug("Test old:${ltag}
");
// ////////////////////////////////////////////////
// TODO: Verify this list of tags without endtags
// ////////////////////////////////////////////////
if ( preg_match( REGEXP_NOENDTAG, $ltag ) ) {
// Previous tag does not have CloseTag.
// Restore CSS
$this->debug( "Forced revert of ${ltag}
" );
$this->RevertCSSproperties( $ltag );
}
}
}
function SetCSSchanged( $properties )
{
// ! @desc Indicate that the CSS changed and a revert will be needed
// ! @return void
$this->debug( "Change of CSS
" );
$this->CSSbackupChanged[count( $this->CSSbackupChanged )-1] = 1;
$this->SetCSS( $properties );
}
// Page header
function Header( $content = '' )
{
// ! @return void
// ! @desc The header is printed in every page.
if ( $this->usetableheader && $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 ) && $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( 'Helvetica', 'B', 9 );
$this->SetTextColor( 0 );
// Arial italic 9
$this->SetFont( 'Helvetica', 'I', 9 );
// Page number
$this->Cell( 0, 10, $this->PageNo() . '/{nb}', 0, 0, 'C' );
// Return Font to normal
$this->SetFont( 'Helvetica', '', 11 );
}
function GetAbsPath( $orgpath )
{
// Get link info and obtain its absolute path
$path = str_replace( "\\", "/", $orgpath ); //If on Windows
$regexp = '|^(\\./)+|';
$path = preg_replace( $regexp, '', $path ); // Remove useless leading ./
if ( $path{0} != '#' ) { // It is not an Internal Link
if ( strpos( $path, "../" ) !== false ) { // It is a Relative Link
$backtrackamount = substr_count( $path, "../" );
$maxbacktrack = $this->urllevels - 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 . preg_replace( "/^\/([^\/]*\/){" . $this->urllevels . "}/", '', $path );
$this->debug( "^/([^/]*/){" . $this->urllevels . "}" );
}
$this->debug( "GetAbsPath $orgpath -> $path
" );
return $path;
}
}
// /////////////////
// / HTML parser ///
// /////////////////
function getTagAndAttrs( $element, &$tag, &$attr )
{
$regexp = '|=\'(.*?)\'|s'; // eliminate single quotes, if any
$element = preg_replace( $regexp, "=\"\$1\"", $element );
$regexp = '|\\s(\\w+?)=([^\\s>"]+)|si'; // changes anykey=anyvalue to anykey="anyvalue" (only do this when this happens inside tags)
$element = preg_replace( $regexp, " \$1=\"\$2\"", $element );
preg_match_all( '/\\S*=["\'][^"\']*["\']/', $element, $contents );
preg_match( '/\\S+/', $element, $a2 );
$tag = strtoupper( $a2[0] );
$attr = array();
if ( !empty( $contents ) ) {
foreach( $contents[0] as $v ) {
if ( preg_match( '/^([^=]*)=["\']?([^"\']*)["\']?$/', $v, $a3 ) ) {
$attr[strtoupper( $a3[1] )] = $a3[2];
}
}
}
// Fix path values, if needed
if ( isset( $attr['HREF'] ) ) {
$attr['HREF'] = $this->GetAbsPath( $attr['HREF'] );
} ;
if ( isset( $attr['SRC'] ) ) {
$attr['SRC'] = $this->GetAbsPath( $attr['SRC'] );
} ;
}
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 '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 and the like by their respective char
else $e = lesser_entity_decode( $e );
*/
// EDIT START
// for use in phpwcms and handle given Charset there
$e = decode_entities( $e );
// EDIT END
}
$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" && $this->selectoption['ACTIVE'] == true ) { // SELECT tag (form element)
$stringwidth = $this->GetStringWidth( $e );
if ( !isset( $this->selectoption['MAXWIDTH'] ) || $stringwidth > $this->selectoption['MAXWIDTH'] ) $this->selectoption['MAXWIDTH'] = $stringwidth;
if ( !isset( $this->selectoption['SELECTED'] ) || $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
tag (this content is usually only a bunch of spaces)
} elseif ( $this->pbegin || $this->HREF || $this->divbegin || $this->SUP || $this->SUB || $this->strike || $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 {
// Extract attributes
$this->GetTagAndAttrs( $e, $tag, $attr );
$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 get_ID_properties( $tag, $id )
{
// //////////////////////////////////////
// ! @desc get ID properties for tag
// ! @return array
$this->debug( "Check ID $tag#$id " ); if ( isset( $this->CSS_ids[$tag][$id] ) ) { $this->debug( "GOT ID $tag#$id " ); return $this->CSS_ids[$tag][$id]; } else if ( isset( $this->CSS_ids[''][$id] ) ) { // foreach($this->CSS_ids[''] as $a => $b) $this->debug("GLOBAL $a "); $this->debug( "GOT ID $tag#$id " ); return $this->CSS_ids[''][$id]; } else { return array(); } } // ///////////////////////////////////////// function get_CLASS_properties( $tag, $id ) { // ///////////////////////////////////////// // ! @desc HTML parser // ! @return array if ( isset( $this->CSS_classes[$tag][$id] ) ) { return $this->CSS_classes[$tag][$id]; } else if ( isset( $this->CSS_classes[''][$id] ) ) { return $this->CSS_classes[''][$id]; } else { return array(); } } // ////////////////////////////////////// function get_TAG_properties( $tag ) { // ////////////////////////////////////// // ! @desc get ID properties for tag // ! @return array $this->debug( "Check TAG $tag " ); if ( isset( $this->CSS_elements[$tag] ) ) { $this->debug( "GOT TAG $tag " ); return $this->CSS_elements[$tag][$id]; } else { return array(); } } // ///////////////////////////////////////// function OpenTag( $tag, $attr ) { // ///////////////////////////////////////// // ! @return void // What this gets: < $tag $attr['WIDTH']="90px" > does not get content here // $this->debug("OpenTag($tag) "); // Handle CSS $this->StoreCSSproperties( $tag ); $properties = $this->get_TAG_properties( $tag ); if ( !empty( $properties ) ) { $this->SetCSSchanged( $properties ); //name found in the CSS array! } if ( isset( $attr['CLASS'] ) || isset( $attr['ID'] ) || isset( $attr['STYLE'] ) ) { if ( isset( $attr['CLASS'] ) ) { $properties = $this->get_CLASS_properties( $tag, $attr['CLASS'] ); } elseif ( isset( $attr['ID'] ) ) { $properties = $this->get_ID_properties( $tag, $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->SetCSSchanged( $properties ); //name found in the CSS array! } } $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) // Paragraph1 (...) // First of all, skip a line if ( !$this->pjustfinished && $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 ( isset( $attr['WIDTH'] ) ) $hrwidth = ConvertSize( $attr['WIDTH'], $this->pgwidth ); if ( isset( $attr['ALIGN'] ) ) $hralign = $align[strtolower( $attr['ALIGN'] )]; if ( isset( $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 'SMALL': $newsize = $this->FontSizePt - 1; $this->SetFontSize( $newsize ); break; case 'BIG': $newsize = $this->FontSizePt + 1; $this->SetFontSize( $newsize ); case 'TITLE': $this->titulo = true; break; case 'STRONG': $this->SetStyle( 'B', true ); break; case 'CITE': case 'EM': $this->SetStyle( 'I', true ); break; case 'INS': $this->SetStyle( 'U', true ); break; case 'B': case 'I': case 'U': $this->SetStyle( $tag, true ); break; case 'A': if ( isset( $attr['NAME'] ) && $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:(...)DIV1 (...)
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'] ) && $attr['ALIGN'] != '' ) $this->divalign = $align[strtolower( $attr['ALIGN'] )];
break;
case 'IMG':
if ( !$this->isdisplay ) break;
if ( !empty( $this->textbuffer ) && !$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 - $this->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;
}
// Edited by Oliver Georgi, 2007-04-30 to better handle src having NO width
// you often see file extensions like *.php?do and so on...
// with old style checking it will always fail
$f_exists = @fopen($srcpath, 'rb');
if($attr['WIDTH'] == 0 || $attr['HEIGHT'] == 0) {
if($f_exists) {
$imgdata = getimagesize($srcpath);
if(isset($imgdata[0]) && isset($imgdata[1])) {
$attr['WIDTH'] = ConvertSize($imgdata[0], $this->pgwidth);
$attr['HEIGHT'] = ConvertSize($imgdata[1], $this->pgwidth );
}
}
}
// End OG
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" ); //Edited by Oliver Georgi, 2007-04-30
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 || $this->divbegin ) {
// In order to support
$ypos = 0;
$bak_x = $this->x;
$bak_y = $this->y;
// Check whether image exists locally or on the URL
//$f_exists = @fopen( $srcpath, "rb" ); //Edited by Oliver Georgi, 2007-04-30
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" ); //Edited by Oliver Georgi, 2007-04-30
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 || $this->pbegin || $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:(...)Paragraph1 (...) 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( ""/* previous: $e, UNDEF:BUG? */ , $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'] )]; 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; 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 || $this->pbegin || $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'] )]; } 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( ""/*previous $e: UNDEF = BUG?*/ , $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 ( !$this->isdisplay ) break; 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'] ) && 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'] ) && 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'] ) && $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'] ) && 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; default: } //end of switch $this->SetCSSonEndOfOpenTag( $tag ); $this->pjustfinished = false; // $this->debug("OpenTag($tag) END"); } function CloseTag( $tag ) { // ! @return void // Closing tag // $this->debug("CloseTag($tag) "); if ( $tag == 'OPTION' ) $this->selectoption['ACTIVE'] = false; if ( $tag == 'BDO' ) $this->divrevert = false; // Renaming tag hurts XXXX // $eq_tag means equivalent tag $eq_tag = $tag; // Default value is actual tag. if ( $tag == 'INS' ) $eq_tag = 'U'; if ( $tag == 'STRONG' ) $eq_tag = 'B'; if ( $tag == 'EM' || $tag == 'CITE' ) $eq_tag = 'I'; if ( $tag == 'OUTLINE' ) { if ( !$this->pbegin && !$this->divbegin && !$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 && !$this->divbegin && !$this->tablestart && !$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' || $tag == 'TD' ) $this->tdbegin = false; if ( $tag == 'SPAN' ) { if ( !$this->pbegin && !$this->divbegin && !$this->tablestart ) { if ( !empty( $this->CSSproperties ) ) { // Check if we have borders to print if ( ( $this->divborder || $this->dash_on || $this->dotted_on || $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 } } // 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' || $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 } 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->Ln( 0.5 * $this->lineheight ); } if ( ( $tag == 'UL' ) || ( $tag == 'OL' ) ) { if ( $this->buffer_on == false ) $this->listnum--; //Adjust minor BUG (this happens when there are two 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' || $tag == 'H2' || $tag == 'H3' || $tag == 'H4' || $tag == 'H5' || $tag == 'H6' ) { $this->blockjustfinished = true; //Eliminate exceeding left-side spaces if ( !$this->pbegin && !$this->divbegin && !$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 && !$this->divbegin && !$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 || $this->pbegin || $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->buffer_on = false; $this->blockjustfinished = true; //Eliminate exceeding left-side spaces $this->pjustfinished = true; //behaves the same way } if ( $tag == 'CODE' || $tag == 'PRE' || $tag == 'TT' || $tag == 'KBD' || $tag == 'SAMP' ) { $this->currentfont = ''; $this->SetFont( 'helvetica' ); } if ( $eq_tag == 'B' || $eq_tag == 'I' || $eq_tag == 'U' ) { $this->SetStyle( $eq_tag, false ); } 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( 'Helvetica' ); } 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( 'Helvetica' ); $this->SetFillColor( 255 ); $this->x += 1; } $this->selectoption = array(); $this->specialcontent = ''; $this->textbuffer = array(); } if ( $tag == 'SUB' || $tag == 'SUP' ) { // subscript or superscript if ( !$this->pbegin && !$this->divbegin && !$this->tablestart && !$this->buffer_on && !$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' || $tag == 'STRIKE' || $tag == 'DEL' ) { if ( !$this->pbegin && !$this->divbegin && !$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' || $tag == 'CENTER' ) { // or "); } /* CloseTag */ 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( 'Helvetica', '', $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() if ( !$this->isdisplay ) return; // HOW TO TAKE DISPLAY == NONE into account? // 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 && $vetor[0] != "\n" ) $vetor[0] = ltrim( $vetor[0] ); if ( empty( $vetor[0] ) && empty( $vetor[7] ) ) continue; //Ignore empty text and not carrying an internal link // Activating buffer properties if ( isset( $vetor[10] ) && !empty( $vetor[10] ) ) { // Background color $cor = $vetor[10]; $this->SetFillColor( $cor['R'], $cor['G'], $cor['B'] ); $this->divbgcolor = true; } if ( isset( $vetor[9] ) && !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] ) && $vetor[8] === true ) { // strike-through the text $this->strike = true; } if ( isset( $vetor[7] ) && $vetor[7] != '' ) { // internal link: $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] ) && $vetor[6] === true ) { // Subscript $this->SUB = true; $this->SetFontSize( 6 ); } if ( isset( $vetor[5] ) && $vetor[5] === true ) { // Superscript $this->SUP = true; $this->SetFontSize( 6 ); } if ( isset( $vetor[4] ) && $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] ) && $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] ) && $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]) && $vetor[0]{0} == '»' && $vetor[0]{1} == '¤' && $vetor[0]{2} == '¬' ) { // identifier has been identified! // OG 2007-04-28 make strpos check -> should be if ( isset($vetor[0]) && strpos($vetor[0], '»¤¬') === 0 ) { $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: $xpos = 0; $ypos = 0; if ( isset( $specialcontent['ypos'] ) && $specialcontent['ypos'] != '' ) $ypos = ( float )$specialcontent['ypos']; if ( isset( $specialcontent['xpos'] ) && $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( 'Helvetica' ); $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( 'Helvetica' ); $this->currentfont = ''; break; default: break; } } else { // THE text if ( $vetor[0] == "\n" ) { // We are reading a 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] ) && $vetor[1] != '' ) || $this->HREF != '' ) { $this->SetTextColor( 0 ); $this->SetStyle( 'U', false ); $this->HREF = ''; } if ( isset( $vetor[2] ) && $vetor[2] != '' ) { $this->SetStyle( 'B', false ); $this->SetStyle( 'I', false ); $this->SetStyle( 'U', false ); } if ( isset( $vetor[3] ) && $vetor[3] != '' ) { unset( $cor ); $this->SetTextColor( 0 ); } if ( isset( $vetor[4] ) && $vetor[4] != '' ) $this->SetFont( 'Helvetica' ); if ( isset( $vetor[5] ) && $vetor[5] === true ) { $this->SUP = false; $this->SetFontSize( 11 ); } if ( isset( $vetor[6] ) && $vetor[6] === true ) { $this->SUB = false; $this->SetFontSize( 11 ); } // vetor7-internal links if ( isset( $vetor[8] ) && $vetor[8] === true ) { // strike-through the text $this->strike = false; } if ( isset( $vetor[9] ) && !empty( $vetor[9] ) ) { // Outline parameters $this->SetTextOutline( false ); $this->outline_on = false; } if ( isset( $vetor[10] ) && !empty( $vetor[10] ) ) { // Background color $this->SetFillColor( 255 ); $this->divbgcolor = false; } } //end of for(i=0;i " ); // 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( 'Helvetica' ); $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; $this->isdisplay = true; $this->SetCSS( $this->CSSproperties ); } function ReadMetaTags( $html ) { // ! @return void // ! @desc Pass meta tag info to PDF file properties $regexp = '/<(meta .*?)>/si'; preg_match_all( $regexp, $html, $aux ); foreach ( $aux[1] as $meta ) { $this->GetTagAndAttrs( $meta, $tag, $attr ); if ( isset( $attr['NAME'] ) && isset( $attr['CONTENT'] ) ) { switch ( $attr['NAME'] ) { case "KEYWORDS": $this->SetKeywords( $attr['CONTENT'] ); break; case "AUTHOR": $this->SetAuthor( $attr['CONTENT'] ); break; case "DESCRIPTION": $this->SetSubject( $attr['CONTENT'] ); break; } } } // Comercial do Aplicativo usado (no caso um script): $this->SetCreator( "HTML2FPDF >> http://html2fpdf.sf.net" ); } // //////////////// // / CSS parser /// // //////////////// function add_properties( &$array, $properties ) { // ! @desc CSS parser // ! @return string // TODO: Take weights, 'important' into account foreach( $properties as $p => $v ) { $array[$p] = $v; } } function ParseStyle( $CSSblock ) { // ! @desc Parse style code, either from style sheet or embedded style code // ! @return string // //////////////////////////// // PARSE THE STYLESHEET ITSELF // Get class/id name and its characteristics from $CSSblock[1] $id_class_exp = '(?:[^#\\.]*[\\.#])?\\S+?\\s*?'; $properties_exp = '\{(.+?)\}'; $regexp = '/(' . $id_class_exp . '(?:,\s*' . $id_class_exp . ')*)' . $properties_exp . '/s'; // $this->debug("EXP2=".$regexp." "); preg_match_all( $regexp, $CSSblock, $extstyle ); // Make CSSXXX[Name-of-the-class] = array(key => value) $property_regexp = '/\\s*?(\\S+?)\\s*:\\s*(\S+?|"[^"]*")(?:\\s*\\\!\\s*important)?\\s*;/si'; $id_class_exp = '/([^\\#\\.,\s]*(?=[\\.\\#]))?([\\.\\#]?)([^,\\.\\#\\s]+)/m'; for( $i = 0; $i < count( $extstyle[1] ) ; $i++ ) { $this->debug( "ID/CLASS=" . $extstyle[1][$i] . " " ); $this->debug( "PROPS=" . $extstyle[2][$i] . " " ); preg_match_all( $property_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] ); } $cnt = preg_match_all( $id_class_exp, $extstyle[1][$i], $id_class_info ); // $this->debug("ID=".$id_class_exp." "); // $this->debug("STR='".$extstyle[1][$i]."' "); // $this->debug("CNT=".$cnt." "); for( $j = 0;$j < count( $id_class_info[0] );$j++ ) { // TODO: Need to check conversion to upper case // $this->debug("RES".$j."='".$id_class_info[1][$j]."''".$id_class_info[2][$j]."''".$id_class_info[3][$j]."' "); if ( $id_class_info[2][$j] == '#' ) { // Id with or without element // $this->debug($id_class_info[0][$j]."=>".$extclassproperties." "); $this->add_properties( $this->CSS_ids[strtoupper( $id_class_info[1][$j] )][$id_class_info[3][$j]], $extclassproperties ); } else if ( $id_class_info[2][$j] == '.' ) { // class with or without element // $this->debug($id_class_info[0][$j]."=>".$extclassproperties." "); $this->add_properties( $this->CSS_classes[strtoupper( $id_class_info[1][$j] )][$id_class_info[3][$j]], $extclassproperties ); } else { // class only // $this->debug($id_class_info[0][$j]."=>".$extclassproperties." "); $this->add_properties( $this->CSS_elements[$id_class_info[3][$j]], $extclassproperties ); } } $extproperties = array(); $extvalues = array(); $extclassproperties = array(); } } 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. * Add support for: selector.class:pseudo-class { property: value } * Add support for respecting the cascading order (see http://www.htmlhelp.com/reference/css/structure.html) * (-> add lists defining weigth and order) */ // TODO: // Check '... ! ...' values in properties; // Remove quotes ("") from values in properties; // Cumulate properties (in stead of replacing them all?) // DONE: // a#hover, p.right are interpreted. To be used elsewhere in the code. $match = 0; // no match yet $regexp = ''; // This helps debugging: showing what is the REAL string being processed // CSS inside external files // /////////////////////////////////////////////////////////////////////////////// // Find links to CSS in external files // /////////////////////////////////////////////////////////////////////////////// $regexp = '//si'; $regexp = '/<(link\\s.*?)>/si'; $match = preg_match_all( $regexp, $html, $CSSext ); $ind = 0; $attr = array(); foreach ( $CSSext[1] as $CSSlink ) { $this->GetTagAndAttrs( $CSSlink, $tag, $attr ); $this->debug( "LINK:$CSSlink " . $attr['HREF'] . " " ); if ( is_array( $attr ) ) foreach ( $attr as $k => $v ) { $this->debug( "LINKATTR: $k $v " ); } if ( isset( $attr['REL'] ) && isset( $attr['HREF'] ) && ( strtoupper( $attr['REL'] ) == 'STYLESHEET' ) ) { if ( !isset( $attr['MEDIA'] ) || preg_match( '/print/', $attr['MEDIA'] ) ) { // ////////////// // Get the file $CSSextblock = file_get_contents( $attr['HREF'] ); $this->debug( "------------ Accepting " . $attr['HREF'] . "------- " ); // Remove comments $CSSextblock = preg_replace( "{/\*.*?\*/}s", "", $CSSextblock ); $CSSextblock = preg_replace( "{//.*?$}sm", "", $CSSextblock ); $this->ParseStyle( $CSSextblock ); } else { $this->debug( '------------ Ignoring ' . $attr['HREF'] . '------- ' ); } } } //end of match // CSS internal // Get content between tags and order it, using regexp $regexp = '/<(style.*?)>(.*?)<\/style>/si'; // it can be |