#native_company# #native_desc#
#native_cta#

pdfTag

By Roy Kaldung
on August 6, 2003

Version: 0.30

Type: Class

Category: Other

License: GNU General Public License

Description: A class which helps you to create pdf documents from xml sources. An own set of tags like <page>, <showxy>, <setfont> will be converted into a pdf documents with the help of PHP and the PDFlib(lite).

<?php
/**
* @author Roy Kaldung
* @copyright "2003 Roy Kaldung"
* @package pdfTag
*/
class pdfTag {
    /**
    * @var string where to store the generated PDF (in memory or as a file)
    * @access private
    */
    var $pdfDest;

    /**
    * @var resource the PDFlib resourcehandle
    * @access private
    */
    var $pPDF;

    /**
    * @var string contains the source XML
    * @access private
    */
    var $XML;

    /**
    * @var resource the filehandle, when creating the PDf on the filesystem
    * @access private
    */
    var $fpPDF;

    /**
    * @var string the filename for the created pdf (temporary)
    * @access private
    */
    var $filePDF;           // the filename for creating the PDF on the filesystem

    /**
    * @var string contains the generated PDF data
    * @access private
    */
    var $PDFdata;

    /**
    * @var array pre-defined page formats
    * @access private
    */
    var $pageFormat;

    /**
    * @var string the place to look for an errormessage
    * @access public
    */
    var $error = '';

    /**
    * @var boolean
    */
    var $printDebug;

    /**
    * @var integer
    * @access private
    */
    var $debugIndent;

    /**
    * @var boolean if true, the processing time is measured
    * @access public
    */
    var $pdfProfile;
   
    /**
    * @var array contains the data for images in memory
    * @access private
    */
    var $imgDataStack = array();

    /**
    * @var float
    */
    var $processingTime;

    /**
    * @var double the start time of processing
    * @access private
    */
    var $tStart;

    /**
    * @var double the end time of processing
    * @access private
    */
    var $tEnd;

    /**
    * @var boolean
    */
    var $printWarning;

    /**
    * @var array contains all warnings
    */
    var $warnings = array();

    /**
    * @var array for alias mapping of elements
    * @access private
    */
    var $tagAlias  = array();

    /**
    * @access private
    */
    var $fontStack = array();

    /**
    * @access private
    */
    var $outlineStack = array();

    /**
    * @access private
    */
    var $tmplStack;

    /**
    * @var integer pageCount
    * @access public 
    */
    var $pageCount = 0;

    /**
    * @access private
    */
    var $imgStack = array();

    /**
    * hier steht die beschreibung
    * @access public
    * @var array
    */
    var $allowedAttributes = array();

    /**
    * @var boolean
    * @access private
    */
    var $checkOnly = false;
    
    /**
    * @var double
    * @access private
    */
    var $versionPDFlib;

    /**
    * @var string
    * @access private
    */
    var $useParser;

    /**
    * @var boolean
    * @access private
    */
    var $stopOnWarning = false;

    /**
    * tells pdfTag which XML parser should be used
    * @param string $parser
    * @access public
    * @return boolean
    */
    function setParser($parser = 'DOM') {
        $this->useParser = (strtoupper($parser) == 'DOM') ? 'DOM' : 'SAX';
        return true;
    }

    /**
    * returns which xml parser should be used
    * @return string
    * @access public
    * @return string
    */
    function getParser() {
        return $this->useParser;
    }
    
    /**
    * the constructor for the class
    * @param string $type default 'mem', for creating the pdf in memory, otherwise 'fs' (on filesystem)
    * @param string $src optional, contains the XML source, if $src is a file, the class use it's content
    * @access public
    * @return void
    */
    function pdfTag($type = 'mem', $src = '') {
        if(!defined('PDFTAG_VERSION')) {
            define('PDFTAG_VERSION', '0.30');
        }
        if(!defined('PDFTAG_PTPERMM')) {
            define('PDFTAG_PTPERMM', 0.3528);       // points per mm 1pt = 1/72 inch = 0.3528 mm
        }
        if(!defined('PDFTAG_INDENTCHAR')) {
            define('PDFTAG_INDENTCHAR', '&nbsp;');
        }
        if(!defined('PDFTAG_INDENT')) {
            define('PDFTAG_INDENT', 2);
        }
        if(!defined('MEASURE_REGEX')) {
            define('MEASURE_REGEX', "([0-9]{1,5}(.[0-9]{1,}){0,1})([ ]{0,1})(cm|mm|in|pt){0,1}");
        }
        if(!defined('OP_REGEX')) {
            define('OP_REGEX', "[+*-/]");
        }
        
        /* get the version of the PDFlib */
        $tmpPDF = PDF_new();
        $majorVersion = PDF_get_value($tmpPDF, "major");
        $minorVersion = PDF_get_value($tmpPDF, "minor");
        unset($tmpPDF);
        $this->versionPDFlib = "$majorVersion.$minorVersion";
        
        $this->setType($type);
        $this->pageFormat = array(  'A4' => array( 210 / PDFTAG_PTPERMM, 297 / PDFTAG_PTPERMM),
                        'DIN A4' => array( 210 / PDFTAG_PTPERMM, 297 / PDFTAG_PTPERMM),
                        'A5' => array( 148 / PDFTAG_PTPERMM, 210 / 0.3528),
                        'DIN A5' => array( 148 / PDFTAG_PTPERMM, 210 / PDFTAG_PTPERMM),
                        'A6' => array( 105 / PDFTAG_PTPERMM, 148 / PDFTAG_PTPERMM ),
                        'DIN A6' => array( 105 / PDFTAG_PTPERMM, 148 / PDFTAG_PTPERMM ),
                        'letter' => array( 612, 792 ),
                        'legal' => array( 612, 1008 ),
                        'ledger' => array( 1224, 792 ),
                        '11x17' => array( 792, 1224 )
                );
        $this->tagAlias = array('text' => 'showxy',
                                'setlinewidth' => 'linewidth');
        $this->printDebug = false;
        $this->debugIndent = 1;
        $this->printWarning = true;
        //$this->fontStack = array();
        if($src != '') {
            $this->XML = $src;
        }

        /* check for all required php extensions */
        if(!extension_loaded('domxml')) {
            $this->warning("missing php-extension 'domxml'");
            $this->setParser('SAX');
        } else {
            $this->setParser('DOM');
        }
        if(!extension_loaded('pdf')) {
            $this->error = "missing php-extension 'pdf'";
        }
    }

    /**
    * returns the version of pdfTag
    * @access public
    * @return double
    */
    function version() {
        return (double)PDFTAG_VERSION;
    }

    /**
    * decides if pdfTag will stop on errors, without a parameter it returns the current state
    * @access public
    * @param $mode boolean optional
    * @return boolean
    */
    function stopOnWarning($mode=NULL) {
        if($mode == NULL) {
            return $this->stopOnWarning;
        } else {
            $this->stopOnWarning = ($mode == true) ? true : false;
            return true;
        }
    }

    /**
    * set the attribute checkOnly for pdfTag and enable checking the source without generating the pdf
    * @param boolean
    * @access public
    * @return boolean
    */
    function setCheckOnly($mode) {
        $this->checkOnly = $mode;
        return true;
    }
    
    /**
    * defines where to create the PDF, in memory or in the filesystem
    * @param string $type   either 'mem' or 'fs'
    * @access public
    * @return boolean
    */
    function setType($type = "") {
        $this->pdfDest = (strtoupper($type) == "FS") ? 'fs' : 'mem';
        return true;
    }

    /**
    * read the XML source from a string
    * @param string $XMLstring
    * @access public
    * @return boolean
    */
    function readFromString($XMLstring) {
        $this->XML = $XMLstring;
        return true;
    }

    /**
    * read the source XML from the specified file
    * @param string $file the file containing the XML
    * @access public
    * @return boolean true on success, otherwise false (check pdfTag::error)
    */
    function readFromFile($file) {
        $this->error = '';
        $srcExist = file_exists($file);
        $fp = fopen($file , "r");
        if(!$fp) {
            if(!$srcExist) {
                $this->error = "Can't find source file '$file'";
            } else {
                $this->error = "Can't open source file '$file'";
            }
            return false;
        }
        $data = '';
        while(!feof($fp)) {
                $data .= fgets($fp, 8192);
        }
        fclose($fp);
        $this->XML = $data;
        return true;
    }

    /**
    * sends the generated pdf to the browser, even when no headers are send
    * @param string $desc if not empty this string will be sent with the header 'Content-Description'
    * @return boolean true if all works fine, otherwise false
    * @access public
    */
    function dumpPDF($desc = '') {
        $this->error = '';
        if(!headers_sent()) {
            header('Pragma: ');
            header('Cache-control: cache');
            if($desc != '') {
                header("Content-Description: $desc");
            }
            header("Content-Type: application/pdf");
            $pdf_length = strlen($this->PDFdata);
            header("Content-length: $pdf_length");
            print $this->PDFdata;
            return true;
        } else {
            $this->error = "There are already any headers send";
            return false;
        }
    }

    /**
    * print debug information if requested by setting printDebug to true
    * @access private
    * @param object $node
    * @return boolean
    */
    function debugPrint($node) {
        $output = $node->tagname;
        /* extract id if exist for information */
        $attr = $node->attributes();
        for($i=0; $i<count($attr); $i++) {
            ${$attr[$i]->name} = $attr[$i]->value;
        }
        if(isset($id)) {
            $output .= " ( id = $id )";
        }
        $output = str_repeat(PDFTAG_INDENTCHAR, $this->debugIndent * PDFTAG_INDENT).htmlentities( $output );
        print "$output<br>";
        return true;
    }

    /**
    * add a warning to the warnings array
    * @param string $txt
    * @access private
    * @return boolean
    */
    function warning($txt) {
        $this->warnings[] = $txt;
        if($this->printWarning) {
            $txt = htmlentities($txt);
            print "Warning: $txt<br>";
        }
        return true;
    }

    /**
    * return the current time
    * @access private
    * @return float
    */
    function getMicrotime() {
        list($usec, $sec) = explode(" ", microtime()); 
        return ((float)$usec + (float)$sec);
    }

    /**
    * creates the desired PDF from the source
    * @access public
    * @return boolean true on success, otherwise false
    */
    function generatePDF() {
        $this->error = '';
        if(strlen(trim($this->XML)) == 0) {
            $this->error = "XML source is empty";
            return false;
        }
        $this->tStart = pdfTag::getMicrotime();
        if($this->useParser == 'DOM') {
            $dom = @domxml_open_mem($this->XML);
            if(!$dom) {
                $this->error = "Can't create DOM object";
                return false;
            }
            $root = $dom->document_element();
            $ret = $this->parseXML_DOM($root);
        } else {
            $ret = $this->parseXML_SAX();
        }
        if(!$ret) {
            $this->cleanUp();
            return false;
        }
        $this->tEnd = pdfTag::getMicrotime();
        $this->processingTime = ($this->tEnd - $this->tStart);
        if($this->pdfProfile) {
            print "processing time ".substr($this->processingTime, 0, 5)." sec<br>";
            print "generated pages: ".number_format($this->pageCount,0)."<br>";
            print "Size for source: ".number_format(strlen($this->XML)/1024,2,',','.')." kb<br>";
            print "Size for generatet PDF: ".number_format(strlen($this->PDFdata)/1024, 2, ',', '.')." kb<br>";
            print "Avg size per page: ".number_format(strlen($this->PDFdata)/1024/$this->pageCount,2, ',', '.')." kb<br>";
        }
        return $ret;
    }

    /**
    * clean the workspace, close file and free resources if called
    * @access private
    * @return boolean
    */
    function cleanUp() {
        if(isset($this->pPDF)) {
            @PDF_close($this->pPDF);
        }
        return true;
    }

    /**
    * parses the desired xml node via the domxml extension of php
    * @param object $node
    * @access private
    * @return boolean
    */  
    function parseXML_DOM(&$node) {
        $tag = '';
        $ret = true;
        if($node->type == XML_ELEMENT_NODE) {
            $tag = $node->tagname;
            if($node->has_attributes()) {
                $attributes = $node->attributes();
            } else {
                $attributes = NULL;
            }
        }
        if($tag != "") {
            if($this->printDebug) {
                $this->debugIndent += PDFTAG_INDENT;
                $this->debugPrint($node);
            }
            $fn = "element_$tag";
            if(!method_exists($this, $fn)) {
                if(isset($this->tagAlias[$tag])) {
                    $fn = "element_".$this->tagAlias[$tag];
                }
                if(!method_exists($this, $fn)) {
                    $this->warning("Non-existing handler for $tag");
                    if($this->stopOnWarning == true) {
                        return false;
                    }
                }
            } else {
                $ret = $this->$fn($node);
                if(!$ret) {
                    print "error $tag ".__LINE__."<br>";
                }
            }
            if($node->has_child_nodes()) {
                $child = $node->child_nodes();
                for($i=0; $i<count($child);$i++) {
                    $ret = $this->parseXML_DOM($child[$i]);
                    if($this->error != '') {
                        return false;
                    }
                    if($this->stopOnWarning == true && $ret == false) {
                        return false;
                    }
                }
            }
            if(method_exists($this, $fn)) {
                $nullRef = NULL;
                $ret = $this->$fn($nullRef);
            }
            if($this->printDebug) {
                $this->debugIndent -= PDFTAG_INDENT;
            }
        }
        return $ret;
    }

    /**
    * parses the xml document with the php builtin sax parser
    * @access private
    * @return void
    */
    function parseXML_SAX() {
        $parser = xml_parser_create();
        if(!$parser) {
            $this->error = "Can't create xml parser (sax)";
            return false;
        } else {
            $values = array();
            if(xml_parse_into_struct($parser, $this->XML, $values)) {
                xml_parser_free($parser);
                $nullRef = NULL;
                for($i=0; $i<count($values); $i++) {
                    $tag = strtolower($values[$i]["tag"]);
                    $tag = str_replace("pdftag:","",$tag);
                    $fn =  "element_".$tag;
                    if(!method_exists($this, $fn)) {
                        if(isset($this->tagAlias[$tag])) {
                            $fn = "element_".$this->tagAlias[$tag];
                        }
                        if(!method_exists($this, $fn)) {
                            $this->warning("Non-existing handler for $tag");
                            if($this->stopOnWarning == true) {
                                return false;
                            }
                            break;
                        }
                    }
                    $node = new pdfTagNode($tag, $values[$i]["attributes"]);
                    $node->set_content($values[$i]["value"]);
                    switch($values[$i]["type"]) {
                    case 'open':
                        if($this->printDebug) {
                            $this->debugIndent += PDFTAG_INDENT;
                            $this->debugPrint($node);
                        }
                        $ret = $this->$fn($node);
                        break;
                    case 'close':
                        if($this->printDebug) {
                            $this->debugIndent -= PDFTAG_INDENT;
                        }
                        $ret = $this->$fn($nullRef);
                        break;
                    case 'complete':
                        if($this->printDebug) {
                            $this->debugIndent += PDFTAG_INDENT;
                            $this->debugPrint($node);
                            $this->debugIndent -= PDFTAG_INDENT;
                        }
                        $ret = $this->$fn($node);
                        /* ROY hier steht eigentlich $ret or $ret2 */
                        $ret = $this->$fn($nullRef) || $ret;
                        break;
                    case 'cdata':
                    default:
                    }
                    unset($node);
                    if($this->error != '') {
                        return false;
                    }
                    if($this->stopOnWarning == true && $ret == false) {
                        return false;
                    }
                }
            } else {
                $this->error = "XML parser error (";
                $this->error .= xml_error_string(xml_get_error_code($parser));
                $this->error .= ") in line ".xml_get_current_line_number($parser);
                xml_parser_free($parser);
                return false;
            }
        }
        return true;
    }


    /**
    * process element document
    * @param object $node 
    * @access private
    * @return boolean
    */  
    function element_document(&$node) {
        $this->error = '';
        if($node == NULL) {
            if( $this->pdfDest == 'fs') {
                fclose($this->fpPDF);
            }
            PDF_close($this->pPDF);
            $this->PDFdata = PDF_get_buffer($this->pPDF);
            if(strlen($this->PDFdata) > 0) {
                PDF_delete($this->pPDF);
            }
        } else {
            if($this->pdfDest == 'fs') {
                // generate temporary filename
                if($this->filePDF == '') {
                    $this->filePDF = tempnam('.', 'pdftag_');
                }
                $this->fpPDF = fopen($this->filePDF, 'wb');
                if(!$this->fpPDF) {
                    $this->error = "Can't create outputfile '".$this->filePDF."'";
                    return false;
                }
                $this->pPDF = PDF_open($this->fpPDF);
        
            } else {
                $this->pPDF = PDF_new();
                PDF_open_file($this->pPDF, "");
            }
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = ($this->getParser() == 'DOM') ? utf8_decode($attr[$i]->value) : $attr[$i]->value;
            }
            if(isset($author)) {
                PDF_set_info($this->pPDF, 'Author', $author);
            }
            if(isset($creator)) {
                PDF_set_info($this->pPDF, 'Creator', $creator.' / pdfTag '.$this->version());
            } else {
                PDF_set_info($this->pPDF, 'Creator', 'pdfTag '.$this->version());
            }
            if(isset($title)) {
                PDF_set_info($this->pPDF, 'Title', $title);
            }
            if(isset($subject)) {
                PDF_set_info($this->pPDF, 'Subject', $subject);
            }
            if(isset($keywords)) {
                PDF_set_info($this->pPDF, 'Keywords', $keywords);
            }
            $this->commonAttributes($attr);
        }
        return true;
    }

    /**
    *
    * implements common attributs, will only be called by function _$tag
    * these attributes are:
    *   {font="" size="" encoding="" {embed="embed"}}|{id="" size=""}   set_font / setfont
    *   {bordercolor="r,g,b"}               set_border_color
    *   {borderdash="b,w"}              set_border_dash
    *   {borderstyle="[solid|dashed]" borderwidth=""}   set_border_style
    *   {charspacing=""}                set_char_spacing
    *   {horiz_scaling=""}              set_horiz_scaling
    *   {leading=""}                    set_leading
    *   {text_rendering="[[0|1|2|3|4|5|6|7]|[filled|border|filledborder|hidden|filledclipped|borderclipped|filledborderclipped|clipped]]"}  set_text_rendering
    *   {text_rise=""}                  set_text_rise
    *   {word_spacing=""}               set_word_spacing
    *   {dash="b,w"}                    set_dash
    *   {flat=""}                   set_flat
    *   {gray=""}                   set_gray
    *   {grayfill=""}                   set_grayfill
    *   {graystroke=""}                 set_gray_stroke
    *   {linecap=[0|1|2]}               set_linecap
    *   {linejoin=[0|1|2]}              set_linejoin
    *   {linewidth=""}                  set_linewidth
    *   {matrix="a,b,c,d,e,f"}              setmatrix
    *   {color="r,g,b"}                 setrgbcolor
    *   {fillcolor="r,g,b"}             setrgbcolor_fill
    *   {strokecolor="r,g,b"}               setrgbcolor_stroke
    *
    * @param    $attr   array which contains attributes
    *
    * @access   private
    */
    function commonAttributes(&$attr) {
        for($i=0; $i<count($attr); $i++) {
            ${$attr[$i]->name} = $attr[$i]->value;
        }
        // charspacing
        if(isset($charspacing)) {
            //PDF_set_char_spacing($this->pPDF, (double)$charspacing);
            PDF_set_value($this->pPDF, 'charspacing', (double)pdfTag::measure2Pt($charspacing));
        }
        // gray
        if(isset($gray)) {
            PDF_setgray($this->pPDF, (double)$gray);
        }
        // grayfill
        if(isset($grayfill)) {
            PDF_setgray_fill($this->pPDF, (double)$grayfill);
        }
        // graystroke
        if(isset($graystroke)) {
            PDF_setgray_stroke($this->pPDF, (double)$graystroke);
        }
        // linewidth
        if(isset($linewidth)) {
            PDF_setlinewidth($this->pPDF, (double)pdfTag::measure2Pt($linewidth));
        }
        if(isset($flat)) {
            PDF_setflat($this->pPDF, (double)$flat);
        }
        // color
        if(isset($color)) {
            $color = explode( ',', $color);
            if(count($color) == 3) {
                $r = $color[0];
                $g = $color[1];
                $b = $color[2];
                PDF_setrgbcolor($this->pPDF, (double)$r, (double)$g, (double)$b);
            } else {
                $this->warning("wrong values for color='r,g,b'");
            }
        }
        // strokecolor
        if(isset($strokecolor)) {
            $strokecolor = explode( ',', $strokecolor);
            if(count($strokecolor) == 3) {
                $r = $strokecolor[0];
                $g = $strokecolor[1];
                $b = $strokecolor[2];
                PDF_setrgbcolor_stroke($this->pPDF, (double)$r, (double)$g, (double)$b);
            } else { 
                $this->warning("wrong values for strokecolor='r,g,b'");
            }
        }
        // fillcolor
        if(isset( $fillcolor )) {
            $fillcolor = explode(',', $fillcolor);
            if(count($fillcolor) == 3) {
                $r = $fillcolor[0];
                $g = $fillcolor[1];
                $b = $fillcolor[2];
                PDF_setrgbcolor_fill($this->pPDF, (double)$r, (double)$g, (double)$b);
            } else {
                $this->warning("wrong values for fillcolor="r,g,b"");
            }
        }
        // font
        if(isset($font) && isset($size) && isset($encoding)) {
            $embed = (isset($embed) && $embed == 'embed') ? 1 : 0;
            $fontHandle = PDF_findfont($this->pPDF, $font, $encoding, $embed);
            if(!$fontHandle) {
                die("Error while PDF_findfont");
            }
            PDF_setfont($this->pPDF, $fontHandle, (double)pdfTag::measure2Pt($size));
            //PDF_set_font($this->pPDF, $font, doubleval($size), $encoding, $embed);
        }
        if(isset($fontid)) {
            if(isset($this->fontStack[$fontid])) {
                $curFont = $this->fontStack[$fontid];
                if(!isset($size)) {
                    $size = $curFont["handle"];
                }
                PDF_setfont($this->pPDF, $fontHandle, (double)pdfTag::measure2Pt($size));
                //PDF_set_font($this->pPDF, $curFont["font"], doubleval($curFont["size"]), $curFont["encoding"], $curFont["embed"]);
            } else {
                $this->warning("usage of prior undefined font fontid='$fontid'");
            }
        }
        if(isset($linecap)) {
            $linecap = (int)$linecap;
            if($linecap < 0 || $linecap > 2) {
                $this->warning("wrong value for attribute 'linecap'");
            } else {
                PDF_setlinecap($this->pPDF, $linecap);
            }
        }
        // dash 
        if(isset($dash)) {
            $dash = explode( ',', $dash);
            if(count($dash) == 2) {
                $b = $dash[0];
                $w = $dash[1];
                PDF_setdash($this->pPDF, (double)$b, (double)$w);
            } else {
                $this->warning("wrong values for dash="b,w"");
            }
        }
        return true;
    }

    /**
    * syntaxcheck for attributes
    * @access   private
    * @return boolean
    * EXPERIMENTAL
    */
    function checkAttribute($var) {
        print $$var;
        $attr  = var_export($var);
        $value = $var;
        if($var == '') {
            $this->warning("empty attribute '$attr' not allowed");
        } else {
            switch($attr) {
            case 'border':
                if(in_array($value, array('on', 'off','filled'))) {
                    return true;
                } else {
                    return false;
                }
                break;
            default:
                $this->warning("unkown attribute '$attr'" );
                break;
            }
        }
    }

    /**
    * process element page 
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_page(&$node) {
        if($node == NULL) {
            PDF_restore($this->pPDF);
            PDF_end_page($this->pPDF);
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            if(isset($format)) {
                if(isset($this->pageFormat[$format])) {
                    $width = $this->pageFormat[$format][0];
                    $height = $this->pageFormat[$format][1];
                } else {
                    $this->warning("undefined page-format $format");
                }
            }
            if(isset($width) && isset($height)) {
                if(isset($orientation)) {
                    if($orientation == "landscape") {
                        $save = $width;
                        $width = $height;
                        $height = $save;
                        unset($save);
                    } else {
                        if($orientation != "portrait") {
                            $this->warning('wrong value for <page orientation="">');
                        }
                    }
                }
                PDF_begin_page($this->pPDF, (double)pdftag::measure2Pt($width), (double)pdfTag::measure2Pt($height));
                PDF_save($this->pPDF);
                $this->commonAttributes($attr);
                $this->pageCount++;
            } else { 
                $this->warning("wrong/missing attributes 'format|(width|height)' for element 'page");
            }
        }
        return true;
    }

    /**
    * process element outline
    * @access private
    * @return boolean
    */
    function element_outline(&$node) {
        if($node == NULL) {
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            if( $node->get_content()!='' ) {
                //$text = $node->get_content();
                $text = ($this->getParser() == 'DOM') ? utf8_decode($node->get_content()) : $node->get_content();
            }
            if(isset($text)) {
                $text = utf8_decode($text);
                if(isset($parent)) {
                    if(isset($this->outlineStack[$parent])) {
                        if(isset($open)) {
                            $open = ($open == 'open') ? 1 : 0;
                            $ret = PDF_add_bookmark($this->pPDF, $text, $this->outlineStack[$parent], $open);
                        } else {
                            $ret = PDF_add_bookmark($this->pPDF, $text, $this->outlineStack[$parent]);
                        }
                    } else {
                        $this->warning("undefined parent id '$parent' in element 'outline'");
                        if($this->stopOnWarning == true) {
                            return false;
                        }
                    }
                } else {
                    $ret = PDF_add_bookmark($this->pPDF, $text);
                }
                if(isset($id)) {
                    if(isset($this->outlineStack[$id])) {
                        $this->warning("overwriting existing outline id '$id'");
                        if($this->stopOnWarning == true) {
                            return false;
                        }
                    } else {
                        $this->outlineStack[$id] = $ret;
                    }
                }
            } else {
                $this->warning("element 'outline without content");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
    * process element path
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_path(&$node) {
        if($node == NULL) {
            PDF_restore($this->pPDF);
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            PDF_save($this->pPDF);
            if($node->get_content() != '') {
                $text = $node->get_content();
            }
            if(isset($coord) || isset($text)) {
                if(isset($text)) {
                    $coord = $text;
                }
                $coord = explode(',', $coord);
                if((count($coord) % 2) != 0) {
                    $this->warning("wrong parameter count for element 'path'");
                    if($this->stopOnWarning == true) {
                        return false;
                    }
                } else {
                    PDF_moveto($this->pPDF, (double)pdfTag::measure2Pt($coord[0]), (double)pdfTag::measure2Pt($coord[1]));
                    for($i=2; $i<count($coord); $i=$i+2) {
                        PDF_lineto($this->pPDF, (double)pdfTag::measure2Pt($coord[$i]), (double)pdfTag::measure2Pt($coord[$i+1]));
                    }
                    PDF_closepath($this->pPDF);
                    if(isset($filled) && $filled == "filled") {
                        if(isset($border) && $border == "border") {
                            PDF_fill_stroke($this->pPDF);
                        } else {
                            PDF_fill($this->pPDF);
                        }
                    } else {
                        PDF_stroke($this->pPDF);
                    }
                }
            } else {
                $this->warning("wrong/missing attribute(s)/content for element 'path'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
    * process element setfont
    * @param object $node
    * @return boolean
    * @access private
    */
    function element_setfont(&$node) {
        if($node == NULL) {
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            if(!isset($encoding)) {
                $encoding="winansi";
            }
            if(isset($font) && isset($size) && isset($encoding)) {
                $embed = (isset($embed) && $embed == 'embed') ? 1 : 0;
                $fontHandle = PDF_findfont($this->pPDF, $font, $encoding, $embed);
                if(!$fontHandle) {
                    die("Error while PDF_findfont");
                }
                PDF_setfont($this->pPDF, $fontHandle, (double)pdfTag::measure2Pt($size));
                if(isset($id)) {
                    if(isset($this->fontStack[$id])) {
                        $this->warning("overwriting existing font id '$id'");
                    } else {
                        $this->fontStack[$id]["font"] = "$font"; 
                        $this->fontStack[$id]["size"] = $size;
                        $this->fontStack[$id]["encoding"] = "$encoding";
                        $this->fontStack[$id]["embed"] = (int)$embed;
                        $this->fontStack[$id]["handle"] = $fontHandle;
                    }
                }
            } else {
                if(isset($fontid)) {
                    if(isset($this->fontStack[$id])) {
                        if(!isset($size)) {
                            $size = $this->fontStack[$id]["size"];
                        }
                        PDF_setfont($this->pPDF, $this->fontStack[$id]["handle"], (double)$size);
                    } else {
                        $this->warning("usage of prior undefined font with id='$id'");
                        if($this->stopOnWarning == true) {
                            return false;
                        }
                    }
                } else {
                    $this->warning("missing attributes for element 'setfont'");
                    if($this->stopOnWarning == true) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    /**
    * process element showxy
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_showxy(&$node) {
        if($node == NULL) {
            PDF_restore($this->pPDF);
        } else {
            PDF_save($this->pPDF);
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = ($this->getParser() == 'DOM' ) ? utf8_decode($attr[$i]->value) : $attr[$i]->value;
            }
            $this->commonAttributes($attr);
            if($node->get_content() != '') {
                $text = ($this->getParser() == 'DOM') ? utf8_decode($node->get_content()) : $node->get_content();
            }
            if(isset($x) && isset($y)) {
                if(isset($text)) {
                    PDF_show_xy($this->pPDF, pdfTag::strClean($text), (double)pdfTag::measure2Pt($x), (double)pdfTag::measure2Pt($y));
                }
            } else {
                $this->warning("missing attribute(s) for element 'showxy'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }
    
    /**
    * remove leading and trailing whitespaces
    * @access private
    * @param string $text
    * @return string
    */
    function strClean($text) {
        return pdfTag::strReverse(chop(pdfTag::strReverse($text)));
    }

    /**
    * returns a given string in reversed order
    * @access private
    * @param string $text
    * @return string
    */
    function strReverse($text) {
        $str1 = $text;
        $str2 = '';
        while(strlen($str1) > 0) {
            $str2 .= substr($str1, -1);
            $str1 = substr($str1, 0, -1);
        }
        return $str2;
    }
    
    /**
    * process element annotation
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_annotation(&$node) {
        if($node == NULL) {
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = ($this->getParser() == 'DOM' ) ? utf8_decode($attr[$i]->value) : $attr[$i]->value;
            }
            if($node->get_content() != '') {
                $text = ($this->getParser() == 'DOM') ? utf8_decode($node->get_content()) : $node->get_content;
            }
            if(isset($llx) && isset($lly) && isset($urx) && isset($ury) && isset($title) && isset($text)) {
                $text = $text;
                PDF_add_annotation($this->pPDF, (double)pdfTag::measure2Pt($llx), (double)pdfTag::measure2Pt($lly), (double)pdfTag::measure2Pt($urx), (double)pdfTag::measure2Pt($ury), $title, $text);
            } else {
                $this->warning("missing attribute(s) for element 'annotation'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
    * process element note
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_note(&$node) {
        $iconArray = array('comment', 'insert', 'note', 'paragraph', 'newparagraph', 'key', 'help');
        if($node == NULL) {
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = ($this->getParser() == 'DOM') ? utf8_decode($attr[$i]->value) : $attr[$i]->value;
            }
            if($node->get_content() != '') {
                $text = ($this->getParser() == 'DOM') ? utf8_decode($node->get_content()) : $node->get_content();
            }
            $open = ($open == 'open') ? 1 : 0;
            if(!in_array($icon, $iconArray)) {
                unset($icon);
            }
            if(isset($llx) && isset($lly) && isset($urx) && isset($ury) && isset($title) && isset($text) && isset($icon) && isset($open)) {
                PDF_add_note($this->pPDF, (double)pdfTag::measure2Pt($llx), (double)pdfTag::measure2Pt($lly), (double)pdfTag::measure2Pt($urx), (double)pdfTag::measure2Pt($ury), $text, $title, $icon, (int)$open);
            } else {
                $this->warning("missing attribute(s) for element 'note'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }
    
    /**
    * process element arc
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_arc(&$node) {
        if($node == NULL) {
            PDF_restore($this->pPDF);
        } else {
            PDF_save($this->pPDF);
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            $this->commonAttributes($attr);
            if(isset($x) && isset($y) && isset($radius) && isset($start) && isset($end)) {
                PDF_arc($this->pPDF, (double)pdfTag::measure2Pt($x), (double)pdfTag::measure2Pt($y), (double)pdfTag::measure2Pt($radius), (double)$start, (double)$end);
                if(isset($filled) && $filled == "filled") {
                    if(isset($border)  && $border == "border") {
                        PDF_fill_stroke($this->pPDF);
                    } else {
                        PDF_fill($this->pPDF);
                    }
                } else {
                    PDF_stroke($this->pPDF);
                }
            } else {
                $this->warning("missing attribute(s) for element 'arc'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
    * process element circle
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_circle(&$node) {
        if($node == NULL) {
            PDF_restore($this->pPDF);
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            PDF_save($this->pPDF);
            $this->commonAttributes($attr);
            if(isset($x) && isset($y) && isset($radius)) {
                PDF_circle($this->pPDF, (double)pdfTag::measure2Pt($x), (double)pdfTag::measure2Pt($y), (double)pdfTag::measure2Pt($radius));
                if(isset($filled) && $filled == "filled") {
                    if(isset($border)  && $border == "border") {
                        PDF_fill_stroke($this->pPDF);
                    } else {
                        PDF_fill($this->pPDF);
                    }
                } else {
                    PDF_stroke($this->pPDF);
                }
            } else {
                $this->warning("missing attribute(s) for element 'circle'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
    * processing element clip
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_clip(&$node) {
        if($node == NULL) {
        } else {
            PDF_clip($this->pPDF);
        }
        return true;
    }

    /**
    * process element continue_text
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_continue_text(&$node) {
        if($node == NULL) {
            PDF_restore($this->pPDF);
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = ($this->getParser() == 'DOM') ? utf8_decode($attr[$i]->value) : $attr[$i]->value;
            }
            if($node->get_content() != '') {
                $text = ($this->getParser() == 'DOM') ? utf8_decode($node->get_content) : $node->get_content();
            }
            PDF_save($this->pPDF);
            $this->commonAttributes($attr);
            if(isset($text)) {
                PDF_continue_text($this->pPDF, $text);
            } else {
                $this->warning("missing attribute 'text' for element 'continue_text'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
    * process element curveto
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_curveto(&$node) {
        if($node == NULL) {
            //PDF_restore($this->pPDF);
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            //PDF_save($this->pPDF);
            //$this->commonAttributes($attr);
            if($node->get_content() != '') {
                $coord = $node->get_content();
            }
            if(isset($coord) && trim($coord) != '') {
                $coord = explode(',', $coord);
            }
            if(count($coord) != 6) {
                $this->warning("there must be six doublevalues in element 'curveto' present'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            } else {
                $x1 = $coord[0];
                $y1 = $coord[1];
                $x2 = $coord[2];
                $y2 = $coord[3];
                $x3 = $coord[4];
                $y3 = $coord[5];
            }
            if(isset($x1) && isset($y1) && isset($x2) && isset($y2) && isset($x3) && isset($y3)) {
                PDF_curveto($this->pPDF, (double)pdfTag::calcTerm($x1), (double)pdfTag::calcTerm($y1),
                                         (double)pdfTag::calcTerm($x2), (double)pdfTag::calcTerm($y2),
                                         (double)pdfTag::calcTerm($x3), (double)pdfTag::calcTerm($y3));
            } else {
                $this->warning("missing attribute(s) for element 'curveto'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
    * process element fill
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_fill(&$node) {
        if($node == NULL) {
            PDF_restore($this->pPDF);
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            PDF_save($this->pPDF);
            $this->commonAttributes($attr);
            PDF_fill($this->pPDF);
        }
        return true;
    }

    /**
    * process element fill_stroke
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_fill_stroke(&$node) {
        if($node == NULL) {
            PDF_restore($this->pPDF);
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            PDF_save($this->pPDF);
            $this->commonAttributes($attr);
            PDF_fill_stroke($this->pPDF);
        }
        return true;
    }

    /**
    * process element lineto
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_lineto(&$node) {
        if($node == NULL) {
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            if(isset($x) && isset($y)) {
                PDF_lineto($this->pPDF, (double)pdfTag::measure2Pt($x), (double)pdfTag::measure2Pt($y));
            } else {
                $this->warning("missing attribute(s) for element 'moveto'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
    * process element rect
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_rect(&$node) {
        if($node == NULL) {
            PDF_restore($this->pPDF);
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            PDF_save($this->pPDF);
            $this->commonAttributes($attr);
            if(isset($x) && isset($y) && isset($width) && isset($height)) {
                PDF_rect($this->pPDF, (double)pdfTag::measure2Pt($x), (double)pdfTag::measure2Pt($y), (double)pdfTag::measure2Pt($width), (double)pdfTag::measure2Pt($height));
                if(isset($filled) && $filled == "filled") {
                    if(isset($border)  && $border == "border") {
                        PDF_fill_stroke($this->pPDF);
                    } else {
                        PDF_fill($this->pPDF);
                    }
                } else {
                    PDF_stroke($this->pPDF);
                }
            } else {
                $this->warning("missing attribute(s) for element 'rect'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }
    /**
    * process element save
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_save(&$node) {
        if($node == NULL) {
            PDF_restore($this->pPDF);
        } else {
            PDF_save($this->pPDF);
        }
        return true;
    }

    /**
    * process element rotate
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_rotate(&$node) {
        if($node == NULL) {
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            if(isset($angle)) {
                PDF_rotate($this->pPDF, (double)$angle);
            } else {
                $this->warning("missing attribute 'angle' for element 'rotate'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
    * process element stroke
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_stroke(&$node) {
        if($node == NULL) {
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            if(isset($filled) && $filled == "filled") {
                if(isset($border)) {
                    if(checkAttribute($border)) {
                         PDF_fill_stroke($this->pPDF);
                    }
                } else {
                    PDF_fill($this->pPDF);
                }
            } else {
                PDF_stroke($this->pPDF);
            }
        }
        return true;
    }

    /**
    * process element moveto
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_moveto(&$node) {
        if($node == NULL) {
            //PDF_restore($this->pPDF);
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            //PDF_save($this->pPDF);
            //$this->commonAttributes($attr);
            if(isset($x) && isset($y)) {
                PDF_moveto($this->pPDF, (double)pdfTag::measure2Pt($x), (double)pdfTag::measure2Pt($y));
            } else {
                $this->warning("missing attribute(s) for 'moveto'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
    * process element scale
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_scale(&$node) {
        if($node == NULL) {
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            if(isset($sx) && isset($sy)) {
                PDF_scale($this->pPDF, (double)$sx, (double)$sy);
            } else {
                $this->warning("missing attribute(s) for 'scale'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
    * process element show
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_show(&$node) {
        if($node == NULL) {
            PDF_restore($this->pPDF);
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = ($this->getParser() == 'DOM') ? utf8_decode($attr[$i]->value) : $attr[$i]->value;
            }
            if($node->get_content() != '') {
                $text = ($this->getParser() == 'DOM') ? utf8_decode($node->get_content()) : $node->get_content();
            }
            PDF_save($this->pPDF);
            $this->commonAttributes($attr);
            if(isset($text)) {
                PDF_show($this->pPDF, $text);
            } else {
                $this->warning("missing content/attribute 'text' for element show");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
    * process element set_leading
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_set_leading(&$node) {
        if($node == NULL) {
        } else { 
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            if(isset($offset)) {
                //PDF_set_leading($this->pPDF, doubleval($offset));
                PDF_set_value($this->pPDF, 'leading', (double)$offset);
            } else {
                $this->warning("missing attribute 'offset' for element 'set_leading'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
    * process element initgraphics
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_initgraphics(&$node) {
        if($node == NULL) {
        } else {
            PDF_initgraphics($this->pPDF);
        }
        return true;
    }

    /**
    * process element border_color
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_border_color(&$node) {
        if($node == NULL) {
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            if($node->get_content() != '') {
                $colors = $node->get_content();
            }
            if(isset($colors) || (isset($r) && isset($g) && isset($b))) {
                if(isset($colors)) {
                    $colors = explode(',', $colors);
                    if(count($colors) != 3) {
                        $this->warning("wrong parameter count for element 'border_color'");
                        if($this->stopOnWarning == true) {
                            return false;
                        }
                    } else {
                        $r = $colors[0];
                        $g = $colors[1];
                        $b = $colors[2];
                    }
                }
                PDF_set_border_color($this->pPDF, (double)$r, (double)$g, (double)$b);
            } else {
                $this->warning("missing attribute(s) for element 'border_color'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
    * process element translate
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_translate(&$node) {
        if($node == NULL) {
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            if(isset($x) && isset($y)) {
                PDF_translate($this->pPDF, (double)pdfTag::measure2Pt($x), (double)pdfTag::measure2Pt($y));
            } else {
                $this->warning("missing attribute(s) for element 'translate'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
    * process element duration
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_duration(&$node) {

        if($node == NULL) {
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            if(isset($value)) {
                PDF_set_duration($this->pPDF, (double)$value);
            } else {
                $this->warning("missing attribute 'value' for element 'duration'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
    * process element setrgbcolor
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_setrgbcolor(&$node) {
        if($node == NULL) {
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            if($node->get_content() != '') {
                $colors = $node->get_content();
            }
            if(isset($colors) || (isset($r) && isset( $g) && isset($b))) {
                if(isset($colors)) {
                    $colors = explode(',', $colors);
                    if(count($colors) != 3) {
                        $this->warning("wrong colour value for element 'border_color'");
                        if($this->stopOnWarning == true) {
                            return false;
                        }
                    } else {
                        $r = $colors[0];
                        $g = $colors[1];
                        $b = $colors[2];
                    }
                }
                PDF_setrgbcolor($this->pPDF, (double)$r, (double)$g, (double)$b);
            } else {
                $this->warning("missing attribute(s) for element 'setrgbcolor'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
    * process element set
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_set(&$node) {
        if($node == NULL) {
        } else {
            $attr = $node->attributes();
            $this->commonAttributes($attr);
        }
        return true;
    }

    /**
    * process element closepath
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_closepath(&$node) {
        if($node == NULL) {
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            PDF_closepath($this->pPDF);
        }
        return true;
    }

    /**
    * process element template
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_template(&$node) {
        if($node == NULL) {
            PDF_end_template($this->pPDF);
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            if(isset($width) && isset($height) && isset($id)) {
                $ret = PDF_begin_template($this->pPDF, (float)pdfTag::measure2Pt($width), (float)pdfTag::measure2Pt($height)); 
                if(isset($this->tmplStack[$id])) {
                    $this->warning("overwriting existing template id '$id'");
                    if($this->stopOnWarning == true) {
                        return false;
                    }
                } else {
                    $this->tmplStack[$id] = $ret;
                }
            } else {
                $this->warning("wrong/missing parameter for element 'template'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
    * process element settemplate
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_settemplate(&$node) {
        if($node == NULL) {
            PDF_restore($this->pPDF);
        } else {
            PDF_save($this->pPDF);
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            $this->commonAttributes($attr);
            if(isset($x) && isset($y) && isset($id)) {
                if(isset($this->tmplStack[$id])) {
                    if(!isset($scale)) {
                        $scale = 1.0;
                    }
                    PDF_place_image($this->pPDF, $this->tmplStack[$id], (double)pdfTag::measure2Pt($x), (double)pdfTag::measure2Pt($y), (double)$scale);
                } else {
                    $this->warning("id '$id' is not defined beyond this point");
                    if($this->stopOnWarning == true) {
                        return false;
                    }
                }
            } else {
                $this->warning("wrong/missing attributes for 'settemplate'");
                if($this->stopOnWarning == true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
    * process element openimagefile
    * @param object $node
    * @access private
    * @return boolean
    */
    function element_openimagefile(&$node) {
        if($node == NULL) {
        } else {
            $attr = $node->attributes();
            for($i=0; $i<count($attr); $i++) {
                ${$attr[$i]->name} = $attr[$i]->value;
            }
            if(isset($type)) {
                if(in_array($type, array('tiff', 'png', 'jpeg', 'gif'))) {
                    if(isset($src)) {
                        if(file_exists($src)) {
                            $fp = @fopen($src, "rb");
                            if(!$fp) {
                                $this->error = "Can't open file '$src' for element 'openimagefile'";
                                return false;
                            } else {
                                $imgData = '';
                                while(!feof($fp)) {
                                    $imgData .