diff --git a/main/inc/lib/html2pdf/_LGPL.txt b/main/inc/lib/html2pdf/_LGPL.txt
new file mode 100644
index 0000000000..e8bec28dfa
--- /dev/null
+++ b/main/inc/lib/html2pdf/_LGPL.txt
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/main/inc/lib/html2pdf/_balises_html.xls b/main/inc/lib/html2pdf/_balises_html.xls
new file mode 100644
index 0000000000..ec70bbff99
Binary files /dev/null and b/main/inc/lib/html2pdf/_balises_html.xls differ
diff --git a/main/inc/lib/html2pdf/_lisez_moi.txt b/main/inc/lib/html2pdf/_lisez_moi.txt
new file mode 100644
index 0000000000..fbb7b5e094
--- /dev/null
+++ b/main/inc/lib/html2pdf/_lisez_moi.txt
@@ -0,0 +1,181 @@
+*******************************************************
+** Ce programme est distribué sous la licence LGPL, **
+** reportez-vous au fichier _LGPL.txt ou à **
+** http://www.gnu.org/licenses/lgpl.html **
+** pour en savoir plus. **
+** **
+** Copyright 2000-2009 par Laurent Minguet **
+*******************************************************
+********************************
+* HTML2PDF v3.22a - 15/06/2009 *
+********************************
+
+Utilisation :
+------------
+ - regardez les exemples fournis pour voir le fonctionnement.
+
+ - les formulaires ne marchent QUE avec ADOBE READER 8 et ADOBE READER 9.0
+
+ - il est TRES IMPORTANT de fournir du HTML 4.01 valide au convertisseur,
+ mais seulement ce que contient le
+
+ - pour les borders : il est conseillé qu'ils soient au format "solid 1mm #000000"
+
+ - pour les paddings : ils ne sont applicables qu'aux balises table, th, td, div, li
+
+ - la liste des balises HTML reconnues se trouve dans le fichier "_balises_html.xls"
+
+ - la possibilité de protégé vos PDF est présente, CF Exemple 7. Elle utilise le script
+ fpdf_protection de Klemen Vodopivec.
+
+ - Certaines balises spécifiques ont été introduites :
+ * (CF Exemple 7) :
+ permet de définir l'orientation, les marges left, right, top et bottom, l'image
+ et la couleur de fond d'une page, sa taille et position, le footer.
+ Il est egalement possible de garder les header et footer des pages précédentes,
+ grace à l'attribue pageset="old" (CF Exemple 3)
+
+ * (CF Exemple 3)
+
+ * (CF Exemple 3)
+
+ * :
+ permet de forcer l'affichage d'une partie sur une même page.
+ Si cette partie ne rentre pas dans le reste de la page, un saut de page est
+ effectué avant.
+
+ * (CF Exemples 0 et 9) :
+ permet d'inserer des barcodes dans les pdfs, CF Exemples 0 et 9
+ Les types de codebar possible sont : EAN13, UPC_A, CODE39. Ceci utilise les
+ scripts de The-eh et Olivier
+
+ * (CF Exemples 7 et About) :
+ permet d'inserer des bookmark dans les pdfs, CF Exemple 7 et About.
+ Il est egalement possible de créer un index automatiquement en fin de
+ document, CF exemple About.
+ Ceci utilise les scripts d'Olivier et de Min's
+
+Modification :
+-------------
+ 3.22a: redistribution de HTML2PDF sous la licence LGPL !!! (au lieu de GPL)
+ 3.22 : correction sur le background-color
+ refonte totale de la gestion de text-align. les valeurs center et right marchent maintenant meme en cas de contenu riche
+ 3.21 : ajout de la propriété css FLOAT pour la balise IMG
+ correction sur la gestion des TFOOT
+ correction sur le positionnement des images
+ 3.20 : ajout de la gestion des margins pour la balise DIV
+ ajout de la gestion de la propriete css LINE-HEIGHT
+ correction sur l'interpretation de la valeur de certains styles CSS (background-image, background-position, ...)
+ correction sur la reconnaissance des balises thead et tfoot
+ correction sur la balise select
+ correction sur les fichiers de langue (merci à Sinan)
+ 3.19 : optimisation du parseur HTML - merci à Jezelinside
+ ajout de la balise TFOOT
+ amélioration de la gestion des tableaux : les contenus des balises THEAD et TFOOT sont maintenant répétés sur chaque page.
+ ajout de la balise spécifique BOOKMARK afin de créer des "marques-page"
+ possibilité de rajouter un index automatique en fin de fichier
+ ajout de la langue turque TR (merci à Hidayet)
+ amélioration de la méthode Output. Elle est maintenant également utilisable comme celle de FPDF
+ 3.18 : correction sur les sauts de page automatique pour les balises TABLE, UL, OL
+ correction sur l'interpretation des styles pour la balise HR
+ correction sur l'interpretation du style border-collapse pour la balise TABLE
+ prise en compte de margin:auto pour les tables et les divs
+ les commentaires dans les CSS sont acceptés
+ 3.17 : ajout de la gestion des balises INPUT (text, radio, checkbox, button, hidden, ...), SELECT, OPTION, TEXTAREA (cf exemple 14)
+ ajout de la possibilité de mettre des scripts dans le pdf, via $html2pdf->pdf->IncludeJS(...); (cf exemples JS)
+ correction sur le saut de page automatique pour les images
+ correction sur les sauts de lignes automatiques pour certaines balises (UL, P, ...)
+ ajout de la langue NL (merci à Roland)
+ 3.16 : ajout de la gestion de list-style: none (cf exemple 13)
+ correction dans la gestion des fontes ajoutées à fpdf (via la méthode AddFont)
+ nombreuses corrections sur le calcul des largeurs des éléments table, div, hr, td, th
+ ajout de l'exemple about.php
+ (pour info, les PDF générés à partir des exemples sont maintenant dans le répertoire /exemples/pdf/, et sont supprimables)
+ 3.15 : correction sur l'identification des styles en cas de valeurs multiples dans la propriete class
+ prise en compte de border-radius pour la limite des backgrounds (color et image)
+ ajout des proprietes CSS border-top-*, border-right-*, border-bottom-*, border-left-*
+ ajout de la propriété CSS list-style-image (cf exemple 12)
+ pour la balise table, ajout de l'interprétation de align="center" et align="right" (cf exemple 1)
+ correction dans le positionnement des images
+ correction de quelques bugs
+ ajout d'une fonction d'analyse des ressources HTML2PDFgetTimerDebug (cf début du fichier html2pdf.class.php)
+ 3.14 : ajout d'une langue (pt : Brazilian Portuguese language) et amelioration de la methode vueHTML (merci à Rodrigo)
+ correction du positionnement du contenu des DIVs. gestion des proprietes valign et align
+ ajout de la propriete CSS border-collapse (cf exemple 0)
+ ajout de la propriete CSS border-radius (cf exemple 1)
+ correction de quelques bugs
+ 3.13 : reecriture de la balise hr, avec prise en compte des styles (cf exemple 0)
+ ajout de la propriete backcolor pour la balise page (cf exemple 9)
+ ajout des proprietes backleft et backright pour la balise page afin de pouvoir changer les marges des pages (cf exemple 8)
+ nombreuses corrections sur les balises et les styles
+ 3.12 : ajout des balises ol, ul, li (cf exemple 12)
+ correction sur le calcul de la taille des td en cas de colspan et rowspan
+ ajout de la méthode setTestTdInOnePage afin de pouvoir desactiver le test sur la taille des TD (cf exemple 11)
+ correction de quelques bugs
+ 3.11 : ajout des balises div, p, pre, s
+ gestion des styles CSS position (relative, absolute), left, top, right, bottom (cf exemple 10)
+ meilleur gestion des border : border-style, border-color, border-width (cf exemple 10)
+ possibilité d'indiquer les marges par défault, via le constructeur (cf exemple 2)
+ 3.10a: correction pour compatibilité php4 / php5
+ 3.10 : ajout des liens internes (cf exemple 7)
+ gestion complete des background : image, repeat, position, color (cf exemple 1)
+ gestion de underline, overline, linethrough (cf exemple 2)
+ correction de quelques bugs
+ 3.09 : mise à jour vers fpdf version 1.6, ajout de barcode, correction de l'affichage de certains caractères spéciaux
+ correction du calcul de la hauteur de ligne de la balise br
+ detection en cas de contenu trop grand dans un TD
+ amélioration de la balise page (ajout de l'attribue pageset, avec les valeurs new et old)
+ ajout de FPDF_PROTECTION, accesible via $pdf->pdf->SetProtection(...)
+ 3.08 : version opérationnelle de page_header, ajout de page_footer, correction des borders des tableaux
+ 3.07 : correction de l'interpretation de cellspacing, amélioration de la balise page_header
+ 3.06 : première gestion de la balise page_header, correction des dimensions des tableaux
+ 3.05 : ajout de la propriété vertical-align, ajout de la gestion des fichiers de langue
+ 3.04 : correction du saut de page automatique pour les tableaux. Ajout de propriétés à la balise PAGE
+ 3.03 : correction de bugs au niveau de la gestion des images PHP par FPDF, meilleure gestion des erreurs
+ 3.02 : ajout de la gestion des noms des couleurs, correction de la gestion des images générées par php, correction de quelques bugs
+ 3.01 : correction de quelques bugs, ajout d'une protection pour les balises non existantes
+ 3.00 : refont totale du calcul des tableaux. Prise en compte des colspan et rowspan
+ 2.85 : ajout de la propriété cellspacing, nouvelle gestion des padding des tableaux (identique à l'html)
+ 2.80 : ajout des types de border dotted et dasheds
+ 2.75 : ajout des top, left, right, bottom pour padding et border
+ 2.70 : correction de la balise HR, ajout de la propriété padding pour les table, th, td
+ correction des dimensions, les unités px, mm, in, pt sont enfin réellement reproduites, correction de font-size, border, ...
+ ajout d'une propriété à la balise page : footer
+ correction dans l'affichage et le calcul des tables
+ 2.55 : vérification de la validité du code (ouverture / fermeture) - ajout des unités mm, in, pt
+ 2.50 : correction de nobreak, des marges, ajout de nombreuses balises
+ 2.40 : refonte totale de l'identification des styles CSS. Les héritages marchent.
+ 2.39 : corrections diverses, ajout de certaines propriétés (bgcolor, ...)
+ 2.38 : meilleur identification des propriétés border et color
+ 2.37 : nombreuses corrections : balise A, couleur de fond, retour à la ligne, gestion des images dans un texte, ...
+ 2.36 : ajout des balises STRONG, EM
+ 2.35 : amélioration de la gestion des feuilles de style
+ 2.31 : correction de quelques bugs
+ 2.30 : première version opérationnel des feuilles de style
+ 2.25 : ajout de la balise LINK pour le type text/css
+ 2.20 : premier jet de la gestion des feuilles de style, ajout de la balise STYLE
+ 2.15 : n'interprète plus l'HTML en commentaire
+ 2.10 : ajout des balises H1 -> H6
+ 2.01 : correction de quelques bugs
+ 2.00 : première version diffusée
+
+Aide et Support :
+----------------
+ pour toutes questions et rapport de bug, merci d'utiliser exclusivement le lien de support ci-dessous.
+ Je ne répondrais à aucune question en dehors, afin que tout le monde puisse profiter des réponses.
+
+Informations :
+-------------
+ Programmation en PHP4
+
+ Programmeur : Spipu
+ email : webmaster@spipu.net
+ site : http://html2pdf.fr/
+ wiki : http://html2pdf.fr/wiki.php
+ support : http://html2pdf.fr/forum.php
+
+Remerciement :
+-------------
+ * Olivier PLATHEY pour sa librairie Fpdf (http://www.fpdf.org/)
+ * yAronet pour l'hebergement du forum de support
+ * toutes les personnes qui m'ont aidé à développer cet librairie, et à traduire les différents textes
diff --git a/main/inc/lib/html2pdf/_read_me.txt b/main/inc/lib/html2pdf/_read_me.txt
new file mode 100644
index 0000000000..a89200403e
--- /dev/null
+++ b/main/inc/lib/html2pdf/_read_me.txt
@@ -0,0 +1,79 @@
+*********************************************************
+** This program is distributed under the LGPL License, **
+** for more information see file _LGPL.txt or **
+** http://www.gnu.org/licenses/lgpl.html **
+** **
+** Copyright 2000-2009 by Laurent Minguet **
+*********************************************************
+********************************
+* HTML2PDF v3.22a - 2009-06-15 *
+********************************
+
+How to use :
+------------
+ - Look at the examples provided to see how it works.
+
+ - forms work only with ADOBE READER 8 and 9.0
+
+ - It is very important to provide valid HTML 4.01 to the converter,
+ but only what is in the
+
+ - for borders: it is advised that they are like "solid 1mm #000000"
+
+ - for padding, they are applicable only on tags table, th, td, div, li
+
+ - the list of recognized HTML tags is in the file "_balises_html.xls"
+
+ - The possibility to protect your PDF is present, CF Example 7. It uses the script
+ fpdf_protection of Klemen Vodopivec.
+
+ - Some specific tags have been introduced:
+ * (CF Exemple 7) :
+ determines the orientation, margins left, right, top and bottom, the background image
+ and the background color of a page, its size and position, the footer.
+ It is also possible to keep the header and footer of the previous pages,
+ through the attribut pageset="old" (see Example 3)
+
+ * (CF Example 3)
+
+ * (CF Example 3)
+
+ * :
+ used to force the display of a section on the same page.
+ If this section does not fit into the rest of the page, a page break is done before.
+
+ * (CF Examples 0 et 9) :
+ can insert barcodes in pdfs, CF Examples 0 and 9
+ The possible types od codebar are: EAN13, UPC_A, CODE39.
+ This uses the scripts of The-eh and Olivier
+
+ * (CF Examples 7 et About) :
+ can insert bookmark in pdfs, CF Example 7 and About.
+ It is also possible to automatically create an index at the end of
+ documentv CF Example About.
+ This uses the scripts of Olivier and Min's
+
+change log :
+-----------
+ see the _lisez_moi.txt file, in french sorry ;)
+
+Help & Support :
+---------------
+ For questions and bug reports, thank you to use only the support link below.
+ I will answer to your questions only on it...
+
+Informations :
+-------------
+ Programming in PHP4
+
+ Programmer : Spipu
+ email : webmaster@spipu.net
+ web site : http://html2pdf.fr/
+ wiki : http://html2pdf.fr/wiki.php
+ support : http://html2pdf.fr/forum.php
+
+Thanks :
+-------
+ * Olivier PLATHEY for his library Fpdf (http://www.fpdf.org/)
+ * yAronet for hosting support forum
+ * everyone who helped me to develop this library and to bring the texts
diff --git a/main/inc/lib/html2pdf/html2pdf.class.php b/main/inc/lib/html2pdf/html2pdf.class.php
new file mode 100644
index 0000000000..6566079a23
--- /dev/null
+++ b/main/inc/lib/html2pdf/html2pdf.class.php
@@ -0,0 +1,4644 @@
+ PDF, utilise fpdf de Olivier PLATHEY
+ * Distribué sous la licence LGPL.
+ *
+ * @author Laurent MINGUET
+ * @version 3.22a - 15/06/2009
+ */
+
+if (!defined('__CLASS_HTML2PDF__'))
+{
+ define('__CLASS_HTML2PDF__', '3.22a');
+
+ // vous pouvez utiliser cette fonction de debug comme suit
+ // pour voir le temps et la mémoire utilisés (sous linux) pour la conversion :
+ // echo HTML2PDFgetTimerDebug();
+ // $html2pdf->WriteHTML($content);
+ // echo HTML2PDFgetTimerDebug();
+ function HTML2PDFgetTimerDebug($debug=false)
+ {
+ global $TIMER_ACTION_LAST;
+ list($usec, $sec) = explode(" ", microtime());
+ $time = (float)$sec + (float)$usec;
+ $mem = HTML2PDFgetMem();
+
+ if (!$TIMER_ACTION_LAST)
+ {
+ if ($debug) $ret = null;
+ else $ret = 'Debug : init'." \n";
+ }
+ else
+ {
+ $aff_time = $time-$TIMER_ACTION_LAST[0];
+ $aff_mem = $mem;
+ if ($debug) $ret = array($aff_time, $aff_mem);
+ else $ret = 'Timer : '.number_format($aff_time, 3, '.', '').'s - Memory used '.$aff_mem.' Ko'." \n";
+ }
+ $TIMER_ACTION_LAST = array($time, $mem);
+ return $ret;
+ }
+ function HTML2PDFgetMem() { return function_exists('memory_get_usage') ? floor(memory_get_usage()/1024) : 0; }
+
+ require_once(dirname(__FILE__).'/_mypdf/mypdf.class.php'); // classe mypdf dérivé de fpdf de Olivier PLATHEY
+ require_once(dirname(__FILE__).'/parsingHTML.class.php'); // classe de parsing HTML
+ require_once(dirname(__FILE__).'/styleHTML.class.php'); // classe de gestion des styles
+
+ global $HTML2PDF_TABLEAU; $HTML2PDF_TABLEAU = array(); // tableau global necessaire à la gestion des tables imbriquées
+
+ class HTML2PDF
+ {
+ var $langue = 'fr'; // langue des messages
+ var $sens = 'P'; // sens d'affichage Portrait ou Landscape
+ var $format = 'A4'; // format de la page : A4, A3, ...
+ var $background = array(); // informations sur le background
+ var $testTDin1page = true; // activer le test de TD ne devant pas depasser une page
+
+ var $style = null; // objet de style
+ var $parsing = null; // objet de parsing
+ var $parse_pos = 0; // position du parsing
+ var $temp_pos = 0; // position temporaire pour multi tableau
+
+ var $sub_html = null; // sous html
+ var $sub_part = false; // indicateur de sous html
+ var $isSubPart = false; // indique que le convertisseur courant est un sous html
+
+ var $pdf = null; // objet PDF
+ var $maxX = 0; // zone maxi X
+ var $maxY = 0; // zone maxi Y
+
+ var $FirstPage = true; // premier page
+
+ var $defaultLeft = 0; // marges par default de la page
+ var $defaultTop = 0;
+ var $defaultRight = 0;
+ var $defaultBottom = 0;
+
+ var $margeLeft = 0; //marges réelles de la page
+ var $margeTop = 0;
+ var $margeRight = 0;
+ var $margeBottom = 0;
+ var $marges = array();
+ var $Maxs = array();
+
+ var $maxH = 0; // plus grande hauteur dans la ligne, pour saut de ligne à corriger
+ var $inLink = ''; // indique si on est à l'interieur d'un lien
+ var $lstAncre = array(); // liste des ancres détectées ou créées
+ var $subHEADER = array(); // tableau des sous commandes pour faire l'HEADER
+ var $subFOOTER = array(); // tableau des sous commandes pour faire le FOOTER
+ var $subSTATES = array(); // tableau de sauvegarde de certains paramètres
+ var $defLIST = array(); // tableau de sauvegarde de l'etat des UL et OL
+
+ var $lstChamps = array(); // liste des champs
+ var $lstSelect = array(); // options du select en cours
+ var $previousCall = null; // dernier appel
+ var $isInTfoot = false; // indique si on est dans un tfoot
+ var $pageMarges = array(); // marges spécifiques dues aux floats
+ var $isAfterFloat = false; // indique si on est apres un float
+ var $forOneLine = false; // indique si on est dans un sous HTML ne servant qu'a calculer la taille de la prochaine ligne
+
+ /**
+ * Constructeur
+ *
+ * @param string sens portrait ou landscape
+ * @param string format A4, A5, ...
+ * @param string langue : fr, en, it...
+ * @param array marges par defaut, dans l'ordre (left, top, right, bottom)
+ * @param boolean forcer la création de la premiere page, ne pas utiliser, c'est utilisé en interne pour la gestion des tableaux
+ * @return null
+ */
+ function HTML2PDF($sens = 'P', $format = 'A4', $langue='fr', $marges = array(5, 5, 5, 8), $force_page = false)
+ {
+ // sauvegarde des paramètres
+ $this->sens = $sens;
+ $this->format = $format;
+ $this->FirstPage = true;
+ $this->langue = strtolower($langue);
+ $this->setTestTdInOnePage(true);
+
+ // chargement du fichier de langue
+ $this->textLOAD($this->langue);
+
+ // création de l' objet PDF
+ $this->pdf = new MyPDF($sens, 'mm', $format);
+
+ // initialisation des styles
+ $this->style = new styleHTML($this->pdf);
+ $this->style->FontSet();
+ $this->defLIST = array();
+
+ // initialisation du parsing
+ $this->parsing = new parsingHTML();
+ $this->sub_html = null;
+ $this->sub_part = false;
+
+ // initialisation des marges
+ $this->setDefaultMargins($marges[0], $marges[1], $marges[2], $marges[3]);
+ $this->setMargins();
+ $this->marges = array();
+
+ // initialisation des champs de formulaire
+ $this->lstChamps = array();
+
+ // premier page forcée
+ if ($force_page) $this->setNewPage($this->sens);
+ }
+
+ /**
+ * activer ou desactiver le test de TD ne devant pas depasser une page
+ *
+ * @param boolean nouvel etat
+ * @return boolean ancien etat
+ */
+ function setTestTdInOnePage($mode = true)
+ {
+ $old = $this->testTDin1page;
+
+ $this->testTDin1page = $mode ? true : false;
+
+ return $old;
+ }
+
+ /**
+ * définir les marges par défault
+ *
+ * @param int en mm, marge left
+ * @param int en mm, marge top
+ * @param int en mm, marge right. si null, left=right
+ * @param int en mm, marge bottom. si null, bottom=8
+ * @return null
+ */
+ function setDefaultMargins($left, $top, $right = null, $bottom = null)
+ {
+ if ($right===null) $right = $left;
+ if ($bottom===null) $bottom = 8;
+
+ $this->defaultLeft = $this->style->ConvertToMM($left.'mm');
+ $this->defaultTop = $this->style->ConvertToMM($top.'mm');
+ $this->defaultRight = $this->style->ConvertToMM($right.'mm');
+ $this->defaultBottom = $this->style->ConvertToMM($bottom.'mm');
+ }
+
+ /**
+ * définir les marges réelles, fonctions de la balise page
+ *
+ * @return null
+ */
+ function setMargins()
+ {
+ $this->margeLeft = $this->defaultLeft + (isset($this->background['left']) ? $this->background['left'] : 0);
+ $this->margeRight = $this->defaultRight + (isset($this->background['right']) ? $this->background['right'] : 0);
+ $this->margeTop = $this->defaultTop + (isset($this->background['top']) ? $this->background['top'] : 0);
+ $this->margeBottom = $this->defaultBottom + (isset($this->background['bottom']) ? $this->background['bottom'] : 0);
+
+ $this->pdf->SetMargins($this->margeLeft, $this->margeTop, $this->margeRight);
+ $this->pdf->cMargin = 0;
+ $this->pdf->SetAutoPageBreak(false, $this->margeBottom);
+ }
+
+ /**
+ * recuperer les positions x minimales et maximales en fonction d'une hauteur
+ *
+ * @param float y
+ * @return array(float, float)
+ */
+ function getMargins($y)
+ {
+ $y = floor($y*100);
+ $x = array($this->pdf->lMargin, $this->pdf->w-$this->pdf->rMargin);
+
+ foreach($this->pageMarges as $m_y => $m_x)
+ if ($m_y<=$y) $x = $m_x;
+
+ return $x;
+ }
+
+ /**
+ * ajouter une marge suite a un float
+ *
+ * @param string left ou right
+ * @param float x1
+ * @param float y1
+ * @param float x2
+ * @param float y2
+ * @return null
+ */
+ function addMargins($float, $x1, $y1, $x2, $y2)
+ {
+ $old1 = $this->getMargins($y1);
+ $old2 = $this->getMargins($y2);
+ if ($float=='left') $old1[0] = $x2;
+ if ($float=='right') $old1[1] = $x1;
+
+ $y1 = floor($y1*100);
+ $y2 = floor($y2*100);
+
+ foreach($this->pageMarges as $m_y => $m_x)
+ {
+ if ($m_y<$y1) continue;
+ if ($m_y>$y2) break;
+ if ($float=='left' && $this->pageMarges[$m_y][0]<$x2) unset($this->pageMarges[$m_y]);
+ if ($float=='right' && $this->pageMarges[$m_y][1]>$x1) unset($this->pageMarges[$m_y]);
+ }
+
+ $this->pageMarges[$y1] = $old1;
+ $this->pageMarges[$y2] = $old2;
+
+ ksort($this->pageMarges);
+
+ $this->isAfterFloat = true;
+ }
+
+ /**
+ * définir des nouvelles marges et sauvegarder les anciennes
+ *
+ * @param float marge left
+ * @param float marge top
+ * @param float marge right
+ * @return null
+ */
+ function saveMargin($ml, $mt, $mr)
+ {
+ $this->marges[] = array('l' => $this->pdf->lMargin, 't' => $this->pdf->tMargin, 'r' => $this->pdf->rMargin, 'page' => $this->pageMarges);
+ $this->pdf->SetMargins($ml, $mt, $mr);
+
+ $this->pageMarges = array();
+ $this->pageMarges[floor($mt*100)] = array($ml, $this->pdf->w-$mr);
+ }
+
+ /**
+ * récuperer les dernières marches sauvées
+ *
+ * @return null
+ */
+ function loadMargin()
+ {
+ $old = array_pop($this->marges);
+ if ($old)
+ {
+ $ml = $old['l'];
+ $mt = $old['t'];
+ $mr = $old['r'];
+ $mP = $old['page'];
+ }
+ else
+ {
+ $ml = $this->margeLeft;
+ $mt = 0;
+ $mr = $this->margeRight;
+ $mP = array($mt => array($ml, $this->pdf->w-$mr));
+ }
+
+ $this->pdf->SetMargins($ml, $mt, $mr);
+ $this->pageMarges = $mP;
+ }
+
+ /**
+ * permet d'ajouter une fonte.
+ *
+ * @param string nom de la fonte
+ * @param string style de la fonte
+ * @param string fichier de la fonte
+ * @return null
+ */
+ function AddFont($family, $style='', $file='')
+ {
+ $this->pdf->AddFont($family, $style, $file);
+ }
+
+ /**
+ * sauvegarder l'état actuelle des maximums
+ *
+ * @return null
+ */
+ function saveMax()
+ {
+ $this->Maxs[] = array($this->maxX, $this->maxY, $this->maxH);
+ }
+
+ /**
+ * charger le dernier état sauvé des maximums
+ *
+ * @return null
+ */
+ function loadMax()
+ {
+ $old = array_pop($this->Maxs);
+
+ if ($old)
+ {
+ $this->maxX = $old[0];
+ $this->maxY = $old[1];
+ $this->maxH = $old[2];
+ }
+ else
+ {
+ $this->maxX = 0;
+ $this->maxY = 0;
+ $this->maxH = 0;
+ }
+ }
+
+ /**
+ * afficher l'header contenu dans page_header
+ *
+ * @return null
+ */
+ function SetPageHeader()
+ {
+ if (!count($this->subHEADER)) return false;
+
+ $OLD_parse_pos = $this->parse_pos;
+ $OLD_parse_code = $this->parsing->code;
+
+ $this->parse_pos = 0;
+ $this->parsing->code = $this->subHEADER;
+ $this->MakeHTMLcode();
+
+ $this->parse_pos = $OLD_parse_pos;
+ $this->parsing->code = $OLD_parse_code;
+ }
+
+ /**
+ * afficher le footer contenu dans page_footer
+ *
+ * @return null
+ */
+ function SetPageFooter()
+ {
+ if (!count($this->subFOOTER)) return false;
+
+ $OLD_parse_pos = $this->parse_pos;
+ $OLD_parse_code = $this->parsing->code;
+
+ $this->parse_pos = 0;
+ $this->parsing->code = $this->subFOOTER;
+ $this->MakeHTMLcode();
+
+ $this->parse_pos = $OLD_parse_pos;
+ $this->parsing->code = $OLD_parse_code;
+ }
+
+ /**
+ * saut de ligne avec une hauteur spécifique
+ *
+ * @param float hauteur de la ligne
+ * @param integer position reelle courante si saut de ligne pendant l'ecriture d'un texte
+ * @return null
+ */
+ function setNewLine($h, $curr = null)
+ {
+ $this->pdf->Ln($h);
+
+ $this->setNewPositionForNewLine($curr);
+ }
+
+ /**
+ * création d'une nouvelle page avec une orientation particuliere
+ *
+ * @param string sens P=portrait ou L=landscape
+ * @param array tableau des propriétés du fond de la page
+ * @param integer position reelle courante si saut de ligne pendant l'ecriture d'un texte
+ * @return null
+ */
+ function setNewPage($orientation = '', $background = null, $curr = null)
+ {
+/*
+ if (!$this->FirstPage)
+ {
+ $info = debug_backtrace(); foreach($info as $k => $v) { unset($info[$k]['object']); unset($info[$k]['type']); unset($info[$k]['args']);}
+ echo ''.print_r($info, true).' ';
+ }
+*/
+ $this->FirstPage = false;
+
+ $this->sens = $orientation ? $orientation : $this->sens;
+ $this->background = $background!==null ? $background : $this->background;
+ $this->maxY = 0;
+ $this->maxX = 0;
+
+ $this->pdf->lMargin = $this->defaultLeft;
+ $this->pdf->rMargin = $this->defaultRight;
+ $this->pdf->tMargin = $this->defaultTop;
+ $this->pdf->AddPage($this->sens);
+
+ if (!$this->sub_part && !$this->isSubPart)
+ {
+ if (is_array($this->background))
+ {
+ if (isset($this->background['color']) && $this->background['color'])
+ {
+ $this->pdf->SetFillColor($this->background['color'][0], $this->background['color'][1], $this->background['color'][2]);
+ $this->pdf->Rect(0, 0, $this->pdf->w, $this->pdf->h, 'F');
+ }
+
+ if (isset($this->background['img']) && $this->background['img'])
+ $this->pdf->Image($this->background['img'], $this->background['posX'], $this->background['posY'], $this->background['width']);
+ }
+
+ $this->SetPageHeader();
+ $this->SetPageFooter();
+ }
+
+ $this->SetMargins();
+ $this->pdf->y = $this->margeTop;
+
+ $this->setNewPositionForNewLine($curr);
+ }
+
+ /**
+ * calcul de la position de debut de la prochaine ligne en fonction de l'alignement voulu
+ *
+ * @param integer position reelle courante si saut de ligne pendant l'ecriture d'un texte
+ * @return null
+ */
+ function setNewPositionForNewLine($curr = null)
+ {
+ list($lx, $rx) = $this->getMargins($this->pdf->y);
+ $this->pdf->x=$lx;
+
+ if (
+ $this->style->value['text-align']!='right' &&
+ $this->style->value['text-align']!='center'
+ )
+ return null;
+
+ $sub = null;
+ $this->CreateSubHTML($sub);
+ $sub->saveMargin(0, 0, $sub->pdf->w-$rx+$lx);
+ $sub->forOneLine = true;
+ $sub->parse_pos = $this->parse_pos;
+ $sub->parsing->code = $this->parsing->code;
+
+ if ($curr!==null && $sub->parsing->code[$this->parse_pos]['name']=='write')
+ $sub->parsing->code[$this->parse_pos]['param']['txt'] = substr($sub->parsing->code[$this->parse_pos]['param']['txt'], $curr);
+ else
+ $sub->parse_pos++;
+
+ // pour chaque element identifié par le parsing
+ for($sub->parse_pos; $sub->parse_posparsing->code); $sub->parse_pos++)
+ {
+ $todo = $sub->parsing->code[$sub->parse_pos];
+ if (!$sub->loadAction($todo)) break;
+ }
+
+ $w = $sub->maxX;
+
+ unset($sub);
+ if ($this->style->value['text-align']=='center')
+ $this->pdf->x+= ($rx-$this->pdf->x-$w)*0.5-0.01;
+ else
+ $this->pdf->x = $rx-$w-0.01;
+ }
+
+ /**
+ * récupération du PDF
+ *
+ * @param string nom du fichier PDF
+ * @param boolean destination
+ * @return string contenu éventuel du pdf
+ *
+ *
+ * Destination où envoyer le document. Le paramètre peut prendre les valeurs suivantes :
+ * true : equivalent à I
+ * false : equivalent à S
+ * I : envoyer en inline au navigateur. Le plug-in est utilisé s'il est installé. Le nom indiqué dans name est utilisé lorsque l'on sélectionne "Enregistrer sous" sur le lien générant le PDF.
+ * D : envoyer au navigateur en forçant le téléchargement, avec le nom indiqué dans name.
+ * F : sauver dans un fichier local, avec le nom indiqué dans name (peut inclure un répertoire).
+ * S : renvoyer le document sous forme de chaîne. name est ignoré.
+ */
+ function Output($name = '', $dest = false)
+ {
+ // nettoyage
+ global $HTML2PDF_TABLEAU; $HTML2PDF_TABLEAU = array();
+
+ // interpretation des paramètres
+ if ($dest===false) $dest = 'I';
+ if ($dest===true) $dest = 'S';
+ if ($dest==='') $dest = 'I';
+ if ($name=='') $name='document.pdf';
+
+ // verification de la destination
+ $dest = strtoupper($dest);
+ if (!in_array($dest, array('I', 'D', 'F', 'S'))) $dest = 'I';
+
+ // verification du nom
+ if (strtolower(substr($name, -4))!='.pdf')
+ {
+ echo 'ERROR : The output document name "'.$name.'" is not a PDF name';
+ exit;
+ }
+
+
+ return $this->pdf->Output($name, $dest);
+ }
+
+ /**
+ * création d'un sous HTML2PDF pour la gestion des tableaux imbriqués
+ *
+ * @param HTML2PDF futur sous HTML2PDF passé en référence pour création
+ * @param integer marge eventuelle de l'objet si simulation d'un TD
+ * @return null
+ */
+ function CreateSubHTML(&$sub_html, $cellmargin=0)
+ {
+ // initialisation du sous objet
+ $sub_html = new HTML2PDF(
+ $this->sens,
+ $this->format,
+ $this->langue,
+ array($this->defaultLeft,$this->defaultTop,$this->defaultRight,$this->defaultBottom),
+ true
+ );
+ $sub_html->isSubPart = true;
+ $sub_html->setTestTdInOnePage($this->testTDin1page);
+
+ $sub_html->style->css = $this->style->css;
+ $sub_html->style->css_keys = $this->style->css_keys;
+ $sub_html->style->table = $this->style->table;
+ $sub_html->style->value = $this->style->value;
+ $sub_html->style->value['text-align'] = 'left';
+ $sub_html->defLIST = $this->defLIST;
+ $sub_html->style->onlyLeft = true;
+
+ // initialisation de la largeur
+ if ($this->style->value['width'])
+ {
+ $marge = $cellmargin*2;
+ $marge+= $this->style->value['padding']['l'] + $this->style->value['padding']['r'];
+ $marge+= $this->style->value['border']['l']['width'] + $this->style->value['border']['r']['width'];
+ $marge = $sub_html->pdf->w - $this->style->value['width'] + $marge;
+ }
+ else
+ $marge = $this->margeLeft+$this->margeRight;
+
+ $sub_html->saveMargin(0, 0, $marge);
+
+ // initialisation des fontes
+ $sub_html->pdf->fonts = &$this->pdf->fonts;
+ $sub_html->pdf->FontFiles = &$this->pdf->FontFiles;
+ $sub_html->pdf->diffs = &$this->pdf->diffs;
+
+ // initialisation des positions et autre
+ $sub_html->maxX = 0;
+ $sub_html->maxY = 0;
+ $sub_html->maxH = 0;
+ $sub_html->pdf->setX(0);
+ $sub_html->pdf->setY(0);
+ $sub_html->style->FontSet();
+ }
+
+ /**
+ * destruction d'un sous HTML2PDF pour la gestion des tableaux imbriqués
+ *
+ * @return null
+ */
+ function DestroySubHTML()
+ {
+
+ unset($this->sub_html);
+ $this->sub_html = null;
+ }
+
+ /**
+ * Convertir un nombre arabe en nombre romain
+ *
+ * @param integer nombre à convertir
+ * @return string nombre converti
+ */
+ function listeArab2Rom($nb_ar)
+ {
+ $nb_b10 = array('I','X','C','M');
+ $nb_b5 = array('V','L','D');
+ $nb_ro = '';
+
+ if ($nb_ar<1) return $nb_ar;
+ if ($nb_ar>3999) return $nb_ar;
+
+ for($i=3; $i>=0 ; $i--)
+ {
+ $chiffre=floor($nb_ar/pow(10,$i));
+ if($chiffre>=1)
+ {
+ $nb_ar=$nb_ar-$chiffre*pow(10,$i);
+ if($chiffre<=3)
+ {
+ for($j=$chiffre; $j>=1; $j--)
+ {
+ $nb_ro=$nb_ro.$nb_b10[$i];
+ }
+ }
+ else if($chiffre==9)
+ {
+ $nb_ro=$nb_ro.$nb_b10[$i].$nb_b10[$i+1];
+ }
+ elseif($chiffre==4)
+ {
+ $nb_ro=$nb_ro.$nb_b10[$i].$nb_b5[$i];
+ }
+ else
+ {
+ $nb_ro=$nb_ro.$nb_b5[$i];
+ for($j=$chiffre-5; $j>=1; $j--)
+ {
+ $nb_ro=$nb_ro.$nb_b10[$i];
+ }
+ }
+ }
+ }
+ return $nb_ro;
+ }
+
+ /**
+ * Ajouter un LI au niveau actuel
+ *
+ * @return null
+ */
+ function listeAddLi()
+ {
+ $this->defLIST[count($this->defLIST)-1]['nb']++;
+ }
+
+ function listeGetWidth() { return '7mm'; }
+ function listeGetPadding() { return '1mm'; }
+
+ /**
+ * Recuperer le LI du niveau actuel
+ *
+ * @return string chaine à afficher
+ */
+ function listeGetLi()
+ {
+ $im = $this->defLIST[count($this->defLIST)-1]['img'];
+ $st = $this->defLIST[count($this->defLIST)-1]['style'];
+ $nb = $this->defLIST[count($this->defLIST)-1]['nb'];
+ $up = (substr($st, 0, 6)=='upper-');
+
+ if ($im) return array(false, false, $im);
+
+ switch($st)
+ {
+ case 'none':
+ return array('arial', true, ' ');
+
+ case 'upper-alpha':
+ case 'lower-alpha':
+ $str = '';
+ while($nb>26)
+ {
+ $str = chr(96+$nb%26).$str;
+ $nb = floor($nb/26);
+ }
+ $str = chr(96+$nb).$str;
+
+ return array('arial', false, ($up ? strtoupper($str) : $str).'.');
+
+ case 'upper-roman':
+ case 'lower-roman':
+ $str = $this->listeArab2Rom($nb);
+
+ return array('arial', false, ($up ? strtoupper($str) : $str).'.');
+
+ case 'decimal':
+ return array('arial', false, $nb.'.');
+
+ case 'square':
+ return array('zapfdingbats', true, chr(110));
+
+ case 'circle':
+ return array('zapfdingbats', true, chr(109));
+
+ case 'disc':
+ default:
+ return array('zapfdingbats', true, chr(108));
+ }
+ }
+
+ /**
+ * Ajouter un niveau de liste
+ *
+ * @param string type de liste : ul, ol
+ * @param string style de la liste
+ * @return null
+ */
+ function listeAddLevel($type = 'ul', $style = '', $img = null)
+ {
+ if ($img)
+ {
+ if (preg_match('/^url\(([^)]+)\)$/isU', trim($img), $match))
+ $img = $match[1];
+ else
+ $img = null;
+ }
+ else
+ $img = null;
+
+ if (!in_array($type, array('ul', 'ol'))) $type = 'ul';
+ if (!in_array($style, array('lower-alpha', 'upper-alpha', 'upper-roman', 'lower-roman', 'decimal', 'square', 'circle', 'disc', 'none'))) $style = '';
+
+ if (!$style)
+ {
+ if ($type=='ul') $style = 'disc';
+ else $style = 'decimal';
+ }
+ $this->defLIST[count($this->defLIST)] = array('style' => $style, 'nb' => 0, 'img' => $img);
+ }
+
+ /**
+ * Supprimer un niveau de liste
+ *
+ * @return null
+ */
+ function listeDelLevel()
+ {
+ if (count($this->defLIST))
+ {
+ unset($this->defLIST[count($this->defLIST)-1]);
+ $this->defLIST = array_values($this->defLIST);
+ }
+ }
+
+ /**
+ * traitement d'un code HTML
+ *
+ * @param string code HTML à convertir
+ * @param boolean afficher en pdf (false) ou en html (true)
+ * @return null
+ */
+ function WriteHTML($html, $vue = false)
+ {
+ $html = str_replace('[[page_nb]]', '{nb}', $html);
+
+ $html = str_replace('[[date_y]]', date('Y'), $html);
+ $html = str_replace('[[date_m]]', date('m'), $html);
+ $html = str_replace('[[date_d]]', date('d'), $html);
+
+ $html = str_replace('[[date_h]]', date('H'), $html);
+ $html = str_replace('[[date_i]]', date('i'), $html);
+ $html = str_replace('[[date_s]]', date('s'), $html);
+
+ // si on veut voir le résultat en HTML => on appelle la fonction
+ if ($vue) $this->vueHTML($html);
+
+ // sinon, traitement pour conversion en PDF :
+ // parsing
+ $this->sub_pdf = false;
+ $this->style->readStyle($html);
+ $this->parsing->setHTML($html);
+ $this->parsing->parse();
+ $this->MakeHTMLcode();
+ }
+
+ function MakeHTMLcode()
+ {
+ // pour chaque element identifié par le parsing
+ for($this->parse_pos=0; $this->parse_posparsing->code); $this->parse_pos++)
+ {
+ // récupération de l'élément
+ $todo = $this->parsing->code[$this->parse_pos];
+
+ // si c'est une ouverture de tableau
+ if (in_array($todo['name'], array('table', 'ul', 'ol')) && !$todo['close'])
+ {
+ // on va créer un sous HTML, et on va travailler sur une position temporaire
+ $tag_open = $todo['name'];
+
+ $this->sub_part = true;
+ $this->temp_pos = $this->parse_pos;
+
+ // pour tous les éléments jusqu'à la fermeture de la table afin de préparer les dimensions
+ while(isset($this->parsing->code[$this->temp_pos]) && !($this->parsing->code[$this->temp_pos]['name']==$tag_open && $this->parsing->code[$this->temp_pos]['close']))
+ {
+ $this->loadAction($this->parsing->code[$this->temp_pos]);
+ $this->temp_pos++;
+ }
+ if (isset($this->parsing->code[$this->temp_pos])) $this->loadAction($this->parsing->code[$this->temp_pos]);
+ $this->sub_part = false;
+ }
+
+ // chargement de l'action correspondant à l'élément
+ $this->loadAction($todo);
+ }
+ }
+
+
+
+ /**
+ * affichage en mode HTML du contenu
+ *
+ * @param string contenu
+ * @return null
+ */
+ function vueHTML($content)
+ {
+ $content = preg_replace('/]*)>/isU', ' '.HTML2PDF::textGET('vue01').' : $1', $content);
+ $content = preg_replace('/
]*)>/isU', ' '.HTML2PDF::textGET('vue02').' : $1', $content);
+ $content = preg_replace('/
]*)>/isU', ' '.HTML2PDF::textGET('vue03').' : $1', $content);
+ $content = preg_replace('/<\/page([^>]*)>/isU', '
', $content);
+ $content = preg_replace('/]*)>/isU', ' bookmark : $1 ', $content);
+ $content = preg_replace('/<\/bookmark([^>]*)>/isU', '', $content);
+
+ echo '
+
+
+ '.HTML2PDF::textGET('vue04').' HTML
+
+
+
+'.$content.'
+
+';
+ exit;
+ }
+
+ /**
+ * chargement de l'action correspondante à un element de parsing
+ *
+ * @param array élément de parsing
+ * @return null
+ */
+ function loadAction($row)
+ {
+ // nom de l'action
+ $fnc = ($row['close'] ? 'c_' : 'o_').strtoupper($row['name']);
+
+ // parametres de l'action
+ $param = $row['param'];
+
+ // si aucune page n'est créé, on la créé
+ if ($fnc!='o_PAGE' && $this->FirstPage)
+ {
+ $this->setNewPage();
+ }
+
+ // lancement de l'action
+ if (is_callable(array(&$this, $fnc)))
+ {
+ $res = $this->{$fnc}($param);
+ $this->previousCall = $fnc;
+ return $res;
+ }
+ else
+ {
+ HTML2PDF::makeError(1, __FILE__, __LINE__, strtoupper($row['name']));
+ return false;
+ }
+ }
+
+ /**
+ * balise : PAGE
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_PAGE($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $newPageSet= (!isset($param['pageset']) || $param['pageset']!='old');
+
+ $this->maxH = 0;
+ if ($newPageSet)
+ {
+ $this->subHEADER = array();
+ $this->subFOOTER = array();
+
+ // identification de l'orientation demandée
+ $orientation = '';
+ if (isset($param['orientation']))
+ {
+ $param['orientation'] = strtolower($param['orientation']);
+ if ($param['orientation']=='p') $orientation = 'P';
+ if ($param['orientation']=='portrait') $orientation = 'P';
+
+ if ($param['orientation']=='l') $orientation = 'L';
+ if ($param['orientation']=='paysage') $orientation = 'L';
+ if ($param['orientation']=='landscape') $orientation = 'L';
+ }
+
+ // identification des propriétés du background
+ $background = array();
+ if (isset($param['backimg']))
+ {
+ $background['img'] = isset($param['backimg']) ? $param['backimg'] : ''; // nom de l'image
+ $background['posX'] = isset($param['backimgx']) ? $param['backimgx'] : 'center'; // position horizontale de l'image
+ $background['posY'] = isset($param['backimgy']) ? $param['backimgy'] : 'middle'; // position verticale de l'image
+ $background['width'] = isset($param['backimgw']) ? $param['backimgw'] : '100%'; // taille de l'image (100% = largueur de la feuille)
+
+ // conversion du nom de l'image, en cas de paramètres en _GET
+ $background['img'] = str_replace('&', '&', $background['img']);
+ // conversion des positions
+ if ($background['posX']=='left') $background['posX'] = '0%';
+ if ($background['posX']=='center') $background['posX'] = '50%';
+ if ($background['posX']=='right') $background['posX'] = '100%';
+ if ($background['posY']=='top') $background['posY'] = '0%';
+ if ($background['posY']=='middle') $background['posY'] = '50%';
+ if ($background['posY']=='bottom') $background['posY'] = '100%';
+
+
+ // si il y a une image de précisé
+ if ($background['img'])
+ {
+ // est-ce que c'est une image ?
+ $infos=@GetImageSize($background['img']);
+ if (count($infos)>1)
+ {
+ // taille de l'image, en fonction de la taille spécifiée.
+ $Wi = $this->style->ConvertToMM($background['width'], $this->pdf->w);
+ $Hi = $Wi*$infos[1]/$infos[0];
+
+ // récupération des dimensions et positions de l'image
+ $background['width'] = $Wi;
+ $background['posX'] = $this->style->ConvertToMM($background['posX'], $this->pdf->w - $Wi);
+ $background['posY'] = $this->style->ConvertToMM($background['posY'], $this->pdf->h - $Hi);
+ }
+ else
+ $background = array();
+ }
+ else
+ $background = array();
+ }
+
+ // marges TOP et BOTTOM pour le texte.
+ $background['top'] = isset($param['backtop']) ? $param['backtop'] : '0';
+ $background['bottom'] = isset($param['backbottom']) ? $param['backbottom'] : '0';
+ $background['left'] = isset($param['backleft']) ? $param['backleft'] : '0';
+ $background['right'] = isset($param['backright']) ? $param['backright'] : '0';
+
+ if (preg_match('/^([0-9]*)$/isU', $background['top'])) $background['top'] .= 'mm';
+ if (preg_match('/^([0-9]*)$/isU', $background['bottom'])) $background['bottom'] .= 'mm';
+ if (preg_match('/^([0-9]*)$/isU', $background['left'])) $background['left'] .= 'mm';
+ if (preg_match('/^([0-9]*)$/isU', $background['right'])) $background['right'] .= 'mm';
+
+ $background['top'] = $this->style->ConvertToMM($background['top'], $this->pdf->h);
+ $background['bottom'] = $this->style->ConvertToMM($background['bottom'], $this->pdf->h);
+ $background['left'] = $this->style->ConvertToMM($background['left'], $this->pdf->w);
+ $background['right'] = $this->style->ConvertToMM($background['right'], $this->pdf->w);
+
+ $res = false;
+ $background['color'] = isset($param['backcolor']) ? $this->style->ConvertToRVB($param['backcolor'], $res) : null;
+ if (!$res) $background['color'] = null;
+
+ $this->style->save();
+ $this->style->analyse('PAGE', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ // nouvelle page
+ $this->setNewPage($orientation, $background);
+
+ // footer automatique
+ if (isset($param['footer']))
+ {
+ $lst = explode(';', $param['footer']);
+ foreach($lst as $key => $val) $lst[$key] = trim(strtolower($val));
+ $page = in_array('page', $lst);
+ $date = in_array('date', $lst);
+ $heure = in_array('heure', $lst);
+ $form = in_array('form', $lst);
+ }
+ else
+ {
+ $page = null;
+ $date = null;
+ $heure = null;
+ $form = null;
+ }
+ $this->pdf->SetMyFooter($page, $date, $heure, $form);
+ }
+ else
+ {
+ $this->style->save();
+ $this->style->analyse('PAGE', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ $this->setNewPage();
+ }
+
+ return true;
+ }
+
+ /**
+ * balise : PAGE
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_PAGE($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->maxH = 0;
+
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+
+
+ function o_PAGE_HEADER($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->subHEADER = array();
+ for($this->parse_pos; $this->parse_posparsing->code); $this->parse_pos++)
+ {
+ $todo = $this->parsing->code[$this->parse_pos];
+ if ($todo['name']=='page_header') $todo['name']='page_header_sub';
+ $this->subHEADER[] = $todo;
+ if (strtolower($todo['name'])=='page_header_sub' && $todo['close']) break;
+ }
+
+ $this->SetPageHeader();
+
+ return true;
+ }
+
+ function o_PAGE_FOOTER($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->subFOOTER = array();
+ for($this->parse_pos; $this->parse_posparsing->code); $this->parse_pos++)
+ {
+ $todo = $this->parsing->code[$this->parse_pos];
+ if ($todo['name']=='page_footer') $todo['name']='page_footer_sub';
+ $this->subFOOTER[] = $todo;
+ if (strtolower($todo['name'])=='page_footer_sub' && $todo['close']) break;
+ }
+
+ $this->SetPageFooter();
+
+ return true;
+ }
+
+ function o_PAGE_HEADER_SUB($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->subSTATES = array();
+ $this->subSTATES['x'] = $this->pdf->x;
+ $this->subSTATES['y'] = $this->pdf->y;
+ $this->subSTATES['s'] = $this->style->value;
+ $this->subSTATES['t'] = $this->style->table;
+ $this->subSTATES['ml'] = $this->pdf->lMargin;
+ $this->subSTATES['mr'] = $this->pdf->rMargin;
+ $this->subSTATES['mt'] = $this->pdf->tMargin;
+ $this->subSTATES['mb'] = $this->pdf->bMargin;
+
+ $this->pdf->x = $this->defaultLeft;
+ $this->pdf->y = $this->defaultTop;
+ $this->style->initStyle();
+ $this->style->resetStyle();
+ $this->style->value['width'] = $this->pdf->w - $this->defaultLeft - $this->defaultRight;
+ $this->style->table = array();
+ $this->pdf->lMargin = $this->defaultLeft;
+ $this->pdf->rMargin = $this->defaultRight;
+ $this->pdf->tMargin = $this->defaultTop;
+ $this->pdf->bMargin = $this->defaultBottom;
+ $this->pdf->PageBreakTrigger = $this->pdf->h - $this->pdf->bMargin;
+
+ $this->style->save();
+ $this->style->analyse('page_header_sub', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ function c_PAGE_HEADER_SUB($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->style->load();
+
+ $this->pdf->x = $this->subSTATES['x'];
+ $this->pdf->y = $this->subSTATES['y'];
+ $this->style->value = $this->subSTATES['s'];
+ $this->style->table = $this->subSTATES['t'];
+ $this->pdf->lMargin = $this->subSTATES['ml'];
+ $this->pdf->rMargin = $this->subSTATES['mr'];
+ $this->pdf->tMargin = $this->subSTATES['mt'];
+ $this->pdf->bMargin = $this->subSTATES['mb'];
+ $this->pdf->PageBreakTrigger = $this->pdf->h - $this->pdf->bMargin;
+
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ function o_PAGE_FOOTER_SUB($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->subSTATES = array();
+ $this->subSTATES['x'] = $this->pdf->x;
+ $this->subSTATES['y'] = $this->pdf->y;
+ $this->subSTATES['s'] = $this->style->value;
+ $this->subSTATES['t'] = $this->style->table;
+ $this->subSTATES['ml'] = $this->pdf->lMargin;
+ $this->subSTATES['mr'] = $this->pdf->rMargin;
+ $this->subSTATES['mt'] = $this->pdf->tMargin;
+ $this->subSTATES['mb'] = $this->pdf->bMargin;
+
+ $this->pdf->x = $this->defaultLeft;
+ $this->pdf->y = $this->defaultTop;
+ $this->style->initStyle();
+ $this->style->resetStyle();
+ $this->style->value['width'] = $this->pdf->w - $this->defaultLeft - $this->defaultRight;
+ $this->style->table = array();
+ $this->pdf->lMargin = $this->defaultLeft;
+ $this->pdf->rMargin = $this->defaultRight;
+ $this->pdf->tMargin = $this->defaultTop;
+ $this->pdf->bMargin = $this->defaultBottom;
+ $this->pdf->PageBreakTrigger = $this->pdf->h - $this->pdf->bMargin;
+
+ // on en créé un sous HTML que l'on transforme en PDF
+ // pour récupérer la hauteur
+ // on extrait tout ce qui est contenu dans le FOOTER
+ $sub = null;
+ $res = $this->parsing->getLevel($this->parse_pos);
+ $this->CreateSubHTML($sub);
+ $sub->writeHTML($res[1]);
+ $this->pdf->y = $this->pdf->h - $sub->maxY - $this->defaultBottom - 0.01;
+ unset($sub);
+
+ $this->style->save();
+ $this->style->analyse('page_footer_sub', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ function c_PAGE_FOOTER_SUB($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->style->load();
+
+ $this->pdf->x = $this->subSTATES['x'];
+ $this->pdf->y = $this->subSTATES['y'];
+ $this->style->value = $this->subSTATES['s'];
+ $this->style->table = $this->subSTATES['t'];
+ $this->pdf->lMargin = $this->subSTATES['ml'];
+ $this->pdf->rMargin = $this->subSTATES['mr'];
+ $this->pdf->tMargin = $this->subSTATES['mt'];
+ $this->pdf->bMargin = $this->subSTATES['mb'];
+ $this->pdf->PageBreakTrigger = $this->pdf->h - $this->pdf->bMargin;
+
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : NOBREAK
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_NOBREAK($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->maxH = 0;
+ // on extrait tout ce qui est contenu dans le NOBREAK
+ $res = $this->parsing->getLevel($this->parse_pos);
+
+ // on en créé un sous HTML que l'on transforme en PDF
+ // pour analyse les dimensions
+ // et voir si ca rentre
+ $sub = null;
+ $this->CreateSubHTML($sub);
+ $sub->writeHTML($res[1]);
+
+ $y = $this->pdf->getY();
+ if (
+ $sub->maxY < ($this->pdf->h - $this->pdf->tMargin-$this->pdf->bMargin) &&
+ $y + $sub->maxY>=($this->pdf->h - $this->pdf->bMargin)
+ )
+ $this->setNewPage();
+ unset($sub);
+
+ return true;
+ }
+
+
+ /**
+ * balise : NOBREAK
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_NOBREAK($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->maxH = 0;
+
+ return true;
+ }
+
+ /**
+ * balise : DIV
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_DIV($param, $other = 'div')
+ {
+ if ($this->forOneLine) return false;
+
+ $this->style->save();
+ $this->style->analyse($other, $param);
+ $this->style->FontSet();
+
+ $align_object = null;
+ if ($this->style->value['margin-auto']) $align_object = 'center';
+
+ $marge = array();
+ $marge['l'] = $this->style->value['border']['l']['width'] + $this->style->value['padding']['l']+0.03;
+ $marge['r'] = $this->style->value['border']['r']['width'] + $this->style->value['padding']['r']+0.03;
+ $marge['t'] = $this->style->value['border']['t']['width'] + $this->style->value['padding']['t']+0.03;
+ $marge['b'] = $this->style->value['border']['b']['width'] + $this->style->value['padding']['b']+0.03;
+
+ // on extrait tout ce qui est contenu dans la DIV
+ $res = $this->parsing->getLevel($this->parse_pos);
+
+ // on en créé un sous HTML que l'on transforme en PDF
+ // pour analyse les dimensions
+ $w = 0; $h = 0;
+ if (trim($res[1]))
+ {
+ $sub = null;
+ $this->CreateSubHTML($sub);
+ $sub->writeHTML($res[1]);
+ $w = $sub->maxX;
+ $h = $sub->maxY;
+ unset($sub);
+ }
+
+ $w+= $marge['l']+$marge['r'];
+ $h+= $marge['t']+$marge['b'];
+
+ $this->style->value['width'] = max($w, $this->style->value['width']);
+ $this->style->value['height'] = max($h, $this->style->value['height']);
+
+ if (!$this->style->value['position'])
+ {
+ if (
+ $this->style->value['width'] < ($this->pdf->w - $this->pdf->lMargin-$this->pdf->rMargin) &&
+ $this->pdf->x + $this->style->value['width']>=($this->pdf->w - $this->pdf->rMargin)
+ )
+ $this->o_BR(array());
+
+ if (
+ $this->style->value['height'] < ($this->pdf->h - $this->pdf->tMargin-$this->pdf->bMargin) &&
+ $this->pdf->y + $this->style->value['height']>=($this->pdf->h - $this->pdf->bMargin)
+ )
+ $this->setNewPage();
+
+ // en cas d'alignement => correction
+ $w = $this->style->value['width'];
+ $old = isset($this->style->table[count($this->style->table)-1]) ? $this->style->table[count($this->style->table)-1] : $this->style->value;
+ $parent_w = $old['width'] ? $old['width'] : $this->pdf->w - $this->pdf->lMargin - $this->pdf->rMargin;
+
+ if ($parent_w>$w)
+ {
+ if ($align_object=='center') $this->pdf->x = $this->pdf->x + ($parent_w-$w)*0.5;
+ else if ($align_object=='right') $this->pdf->x = $this->pdf->x + $parent_w-$w;
+ }
+
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ }
+ else
+ {
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->saveMax();
+ $this->saveX = 0;
+ $this->saveY = 0;
+ $this->saveH = 0;
+ }
+
+ // initialisation du style des bordures de la premiere partie de tableau
+ $this->Rectangle(
+ $this->style->value['x'],
+ $this->style->value['y'],
+ $this->style->value['width'],
+ $this->style->value['height'],
+ $this->style->value['border'],
+ $this->style->value['padding'],
+ 0,
+ $this->style->value['background']
+ );
+
+
+ $marge = array();
+ $marge['l'] = $this->style->value['border']['l']['width'] + $this->style->value['padding']['l']+0.03;
+ $marge['r'] = $this->style->value['border']['r']['width'] + $this->style->value['padding']['r']+0.03;
+ $marge['t'] = $this->style->value['border']['t']['width'] + $this->style->value['padding']['t']+0.03;
+ $marge['b'] = $this->style->value['border']['b']['width'] + $this->style->value['padding']['b']+0.03;
+
+ $this->style->value['width'] = $this->style->value['width']-$marge['l']-$marge['r'];
+ $this->style->value['height'] = $this->style->value['height']-$marge['r']-$marge['b'];
+
+ // limitation des marges aux dimensions de la div
+ $mL = $this->style->value['x']+$marge['l'];
+ $mR = $this->pdf->w - $mL - $this->style->value['width'];
+ $this->saveMargin($mL, 0, $mR);
+
+ // positionnement en fonction
+ $h_corr = $this->style->value['height'];
+ $h_reel = $h-$marge['b']-$marge['t'];
+ switch($this->style->value['vertical-align'])
+ {
+ case 'bottom':
+ $y_corr = $h_corr-$h_reel;
+ break;
+
+ case 'middle':
+ $y_corr = ($h_corr-$h_reel)*0.5;
+ break;
+
+ case 'top':
+ default:
+ $y_corr = 0;
+ break;
+ }
+
+ $this->pdf->setX($this->style->value['x']+$marge['l']);
+ $this->pdf->setY($this->style->value['y']+$marge['t']+$y_corr);
+
+ $this->setNewPositionForNewLine();
+
+ return true;
+ }
+ function o_BLOCKQUOTE($param) { return $this->o_DIV($param, 'blockquote'); }
+
+ /**
+ * balise : DIV
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_DIV($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $marge = array();
+ $marge['l'] = $this->style->value['border']['l']['width'] + $this->style->value['padding']['l']+0.03;
+ $marge['r'] = $this->style->value['border']['r']['width'] + $this->style->value['padding']['r']+0.03;
+ $marge['t'] = $this->style->value['border']['t']['width'] + $this->style->value['padding']['t']+0.03;
+ $marge['b'] = $this->style->value['border']['b']['width'] + $this->style->value['padding']['b']+0.03;
+
+ $x = $this->style->value['x'];
+ $y = $this->style->value['y'];
+ $w = $this->style->value['width']+$marge['l']+$marge['r'];
+ $h = $this->style->value['height']+$marge['t']+$marge['b'];
+
+ // correction pour les margins
+ $w+= $this->style->value['margin']['r'];
+ $h+= $this->style->value['margin']['b'];
+
+ if ($this->style->value['position']!='absolute')
+ {
+ // position
+ $this->pdf->x = $x+$w;
+ $this->pdf->y = $y;
+
+ // position MAX
+ $this->maxX = max($this->maxX, $x+$w);
+ $this->maxY = max($this->maxY, $y+$h);
+ $this->maxH = max($this->maxH, $h);
+ }
+ else
+ {
+ // position
+ $this->pdf->x = $this->style->value['xc'];
+ $this->pdf->y = $this->style->value['yc'];
+
+ $this->loadMax();
+ }
+
+ $block = ($this->style->value['display']!='inline' && $this->style->value['position']!='absolute');
+
+ $this->style->load();
+ $this->style->FontSet();
+ $this->loadMargin();
+
+ if ($block) $this->o_BR(array());
+
+ return true;
+ }
+ function c_BLOCKQUOTE($param) { return $this->c_DIV($param); }
+
+ /**
+ * balise : BARCODE
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_BARCODE($param)
+ {
+
+ $lst_barcode = array(
+ 'EAN13' => '0.35mm',
+ 'UPC_A' => '0.35mm',
+ 'CODE39' => '1.00mm',
+ );
+ if (isset($param['type'])) $param['type'] = strtoupper($param['type']);
+
+ if (!isset($param['type']) || !isset($lst_barcode[$param['type']])) $param['type']=='CODE39';
+ if (!isset($param['value'])) $param['value'] = 0;
+ if (!isset($param['bar_w'])) $param['bar_w'] = $lst_barcode[$param['type']];
+ if (!isset($param['bar_h'])) $param['bar_h'] = '10mm';
+
+ if (!isset($param['style']['color'])) $param['style']['color'] = '#000000';
+ $param['style']['background-color'] = $param['style']['color'];
+
+ $this->style->save();
+ $this->style->analyse('barcode', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+
+ $x = $this->pdf->getX();
+ $y = $this->pdf->getY();
+ $w = $this->style->ConvertToMM($param['bar_w']);
+ $h = $this->style->ConvertToMM($param['bar_h']);
+
+ $infos = $this->pdf->{'BARCODE_'.$param['type']}($x, $y, $param['value'], $h, $w);
+
+ // position maximale globale
+ $this->maxX = max($this->maxX, $x+$infos[0]);
+ $this->maxY = max($this->maxY, $y+$infos[1]);
+ $this->maxH = max($this->maxH, $infos[1]);
+
+ $this->pdf->setX($x+$infos[0]);
+
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : BARCODE
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_BARCODE($param)
+ {
+ // completement inutile
+
+ return true;
+ }
+
+ /**
+ * balise : BOOKMARK
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_BOOKMARK($param)
+ {
+ $titre = isset($param['title']) ? trim($param['title']) : '';
+ $level = isset($param['level']) ? floor($param['level']) : 0;
+
+ if ($level<0) $level = 0;
+ if ($titre) $this->pdf->Bookmark($titre, $level, -1);
+
+ return true;
+ }
+
+ /**
+ * balise : BOOKMARK
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_BOOKMARK($param)
+ {
+ // completement inutile
+
+ return true;
+ }
+
+ /**
+ * balise : WRITE
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_WRITE($param)
+ {
+ $fill = ($this->style->value['background']['color']!==null && $this->style->value['background']['image']===null);
+
+ // récupération du texte à écrire, et conversion
+ $txt = $param['txt'];
+ $txt = str_replace('€', '€', $txt);
+
+ if ($this->isAfterFloat)
+ {
+ $txt = preg_replace('/^([\s]*)([^\s])/isU', '$2', $txt);
+ $this->isAfterFloat = false;
+ }
+
+ $txt = html_entity_decode($txt, ENT_QUOTES, 'ISO-8859-15');
+// $txt = utf8_decode(html_entity_decode($txt, ENT_QUOTES, 'UTF-8'));
+
+ $txt = str_replace('[[page_cu]]', $this->pdf->PageNo(), $txt);
+
+ // tailles du texte
+ $h = 1.08*$this->style->value['font-size'];
+ $dh = $h*$this->style->value['mini-decal'];
+
+ $w = $this->pdf->GetStringWidth($txt);
+ // identification de l'alignement
+ $align = 'L';
+
+ if ($this->style->value['text-align']=='li_right')
+ {
+ $w = $this->style->value['width'];
+ $align = 'R';
+ }
+
+ $curr_max = strlen($txt); // taille maxi du texte
+ $maxX = 0; // plus grande largeur du texte apres retour à la ligne
+ $x = $this->pdf->getX(); // position du texte
+ $y = $this->pdf->getY();
+ $w = $this->pdf->GetStringWidth($txt); // largeur du texte
+ list($left, $right) = $this->getMargins($y); // marges autorisees
+ $nb = 0; // nbr de lignes découpées
+
+ // tant que ca ne rentre pas sur la ligne et qu'on a du texte => on découpe
+ while($x+$w>$right && $x<$right && strlen($txt))
+ {
+ // liste des mots
+ $lst = explode(' ', $txt);
+
+ // trouver une phrase qui rentre dans la largeur, en ajoutant les mots 1 à 1
+ $i=0;
+ $old = '';
+ $str = $lst[0];
+ while(($x+$this->pdf->GetStringWidth($str))<$right)
+ {
+ unset($lst[$i]);
+ $old = $str;
+
+ $i++;
+ $str.= ' '.$lst[$i];
+ }
+ $str = $old;
+
+ // si rien de rentre, et que le premier mot ne rentre de toute facon pas dans une ligne, on le force...
+ if ($i==0 && (($left+$this->pdf->GetStringWidth($lst[0]))>=$right))
+ {
+ $str = $lst[0];
+ unset($lst[0]);
+ }
+
+ // récupération des mots restant, et calcul de la largeur
+ $txt = implode(' ', $lst);
+ $w = $this->pdf->GetStringWidth($str);
+
+ // ecriture du bout de phrase extrait et qui rentre
+ $wc = ($align=='L' ? $w : $this->style->value['width']);
+ if ($right - $left<$wc) $wc = $right - $left;
+ if (strlen($str)) $this->pdf->Cell($wc, $h+$dh, $str, 0, 0, $align, $fill, $this->inLink);
+ $this->maxH = max($this->maxH, $this->style->getLineHeight());
+
+ // détermination de la largeur max
+ $maxX = max($maxX, $this->pdf->getX());
+
+ // nouvelle position et nouvelle largeur pour la boucle
+ $w = $this->pdf->GetStringWidth($txt);
+ $y = $this->pdf->getY();
+ $x = $this->pdf->getX();
+
+ // si il reste du text à afficher
+ if (strlen($txt))
+ {
+ if ($this->forOneLine)
+ {
+ $this->maxX = max($this->maxX, $maxX);
+ return false;
+ }
+
+ // retour à la ligne
+ $this->o_BR(array('style' => ''), $curr_max - strlen($txt));
+
+ $y = $this->pdf->getY();
+ $x = $this->pdf->getX();
+
+ // si la prochaine ligne ne rentre pas dans la page => nouvelle page
+ if ($y + $h>$this->pdf->h - $this->pdf->bMargin) $this->setNewPage('', null, $curr_max - strlen($txt));
+
+ // ligne suplémentaire. au bout de 1000 : trop long => erreur
+ $nb++;
+ if ($nb>1000) HTML2PDF::makeError(2, __FILE__, __LINE__, array($txt, $right-$left, $this->pdf->GetStringWidth($txt)));
+
+ list($left, $right) = $this->getMargins($y); // marges autorisees
+ }
+ }
+
+ // si il reste du text apres découpe, c'est qu'il rentre direct => on l'affiche
+ if (strlen($txt))
+ {
+ $this->pdf->Cell(($align=='L' ? $w : $this->style->value['width']), $h+$dh, $txt, 0, 0, $align, $fill, $this->inLink);
+ $this->maxH = max($this->maxH, $this->style->getLineHeight());
+ }
+
+ // détermination des positions MAX
+ $maxX = max($maxX, $this->pdf->getX());
+ $maxY = $this->pdf->getY()+$h;
+
+ // position maximale globale
+ $this->maxX = max($this->maxX, $maxX);
+ $this->maxY = max($this->maxY, $maxY);
+
+ return true;
+ }
+
+ /**
+ * tracer une image
+ *
+ * @param string nom du fichier source
+ * @return null
+ */
+ function Image($src, $sub_li=false)
+ {
+ // est-ce que c'est une image ?
+ $infos=@GetImageSize($src);
+
+ if (count($infos)<2)
+ {
+ HTML2PDF::makeError(6, __FILE__, __LINE__, $src);
+ return false;
+ }
+
+ // récupération des dimensions dans l'unité du PDF
+ $wi = $infos[0]/$this->pdf->k;
+ $hi = $infos[1]/$this->pdf->k;
+
+ // détermination des dimensions d'affichage en fonction du style
+ if ($this->style->value['width'] && $this->style->value['height'])
+ {
+ $w = $this->style->value['width'];
+ $h = $this->style->value['height'];
+ }
+ else if ($this->style->value['width'])
+ {
+ $w = $this->style->value['width'];
+ $h = $hi*$w/$wi;
+
+ }
+ else if ($this->style->value['height'])
+ {
+ $h = $this->style->value['height'];
+ $w = $wi*$h/$hi;
+ }
+ else
+ {
+ $w = 72./96.*$wi;
+ $h = 72./96.*$hi;
+ }
+
+ // detection du float
+ $float = $this->style->getFloat();
+ if ($float && $this->maxH) $this->o_BR(array());
+
+ // position d'affichage
+ $x = $this->pdf->getX();
+ $y = $this->pdf->getY();
+
+ // si l'image ne rentre pas dans la page => nouvelle page
+ if ($y + $h>$this->pdf->h - $this->pdf->bMargin)
+ {
+ $this->setNewPage();
+ $x = $this->pdf->getX();
+ $y = $this->pdf->getY();
+ }
+
+ // correction pour l'affichage d'une puce image
+ $hT = 0.80*$this->style->value['font-size'];
+ if ($sub_li && $h<$hT)
+ {
+ $y+=($hT-$h);
+ }
+
+ $yc = $y-$this->style->value['margin']['t'];
+
+ // détermination de la position réelle d'affichage en fonction du text-align du parent
+ $old = isset($this->style->table[count($this->style->table)-1]) ? $this->style->table[count($this->style->table)-1] : $this->style->value;
+
+ if ( $old['width'])
+ {
+ $parent_w = $old['width'];
+ $parent_x = $x;
+ }
+ else
+ {
+ $parent_w = $this->pdf->w - $this->pdf->lMargin - $this->pdf->rMargin;
+ $parent_x = $this->pdf->lMargin;
+ }
+
+ if ($float)
+ {
+ list($lx, $rx) = $this->getMargins($yc);
+ $parent_x = $lx;
+ $parent_w = $rx-$lx;
+ }
+
+ if ($parent_w>$w && $float!='left')
+ {
+ if ($float=='right' || $this->style->value['text-align']=='li_right') $x = $parent_x + $parent_w - $w-$this->style->value['margin']['r']-$this->style->value['margin']['l'];
+
+// if ($float=='right' || $this->style->value['text-align']=='right') $x = $parent_x + $parent_w - $w-$this->style->value['margin']['r']-$this->style->value['margin']['l'];
+// else if ($this->style->value['text-align']=='center') $x = $parent_x + 0.5*($parent_w - $w);
+ }
+
+ // affichage de l'image, et positionnement à la suite
+ if (!$this->sub_part && !$this->isSubPart) $this->pdf->Image($src, $x, $y, $w, $h, '', $this->inLink);
+
+ $x-= $this->style->value['margin']['l'];
+ $y-= $this->style->value['margin']['t'];
+ $w+= $this->style->value['margin']['l'] + $this->style->value['margin']['r'];
+ $h+= $this->style->value['margin']['t'] + $this->style->value['margin']['b'];
+
+ if ($float=='left')
+ {
+ $this->maxX = max($this->maxX, $x+$w);
+ $this->maxY = max($this->maxY, $y+$h);
+
+ $this->addMargins($float, $x, $y, $x+$w, $y+$h);
+
+ list($lx, $rx) = $this->getMargins($yc);
+ $this->pdf->x = $lx;
+ $this->pdf->y = $yc;
+ }
+ else if ($float=='right')
+ {
+// $this->maxX = max($this->maxX, $x+$w);
+ $this->maxY = max($this->maxY, $y+$h);
+
+ $this->addMargins($float, $x, $y, $x+$w, $y+$h);
+
+ list($lx, $rx) = $this->getMargins($yc);
+ $this->pdf->x = $lx;
+ $this->pdf->y = $yc;
+ }
+ else
+ {
+ $this->pdf->SetX($x+$w);
+ $this->maxX = max($this->maxX, $x+$w);
+ $this->maxY = max($this->maxY, $y+$h);
+ $this->maxH = max($this->maxH, $h);
+ }
+ }
+
+ /**
+ * Tracer un rectanble
+ *
+ * @param float position X
+ * @param float position Y
+ * @param float Largeur
+ * @param float Hauteur
+ * @param array Tableau de style de définition des borders
+ * @param float padding - marge intérieur au rectangle => non utile mais on le passe en paramètre
+ * @param float margin - marge exterieur au rectangle
+ * @param array Tableau de style de définition du background
+ * @return null
+ */
+ function Rectangle($x, $y, $w, $h, $border, $padding, $margin, $background)
+ {
+ if ($this->sub_part || $this->isSubPart) return false;
+ if ($h===null) return false;
+
+ $x+= $margin;
+ $y+= $margin;
+ $w-= $margin*2;
+ $h-= $margin*2;
+
+ // récupération des radius
+ $radius_h = $border['radius'][0];
+ $radius_v = $border['radius'][1];
+
+ // verification des coins en radius
+ $coin_TL = ($radius_h && $radius_v && $radius_v>$border['t']['width'] && $radius_h>$border['l']['width']) ? array($radius_h, $radius_v) : null;
+ $coin_TR = ($radius_h && $radius_v && $radius_v>$border['t']['width'] && $radius_h>$border['r']['width']) ? array($radius_h, $radius_v) : null;
+ $coin_BL = ($radius_h && $radius_v && $radius_v>$border['b']['width'] && $radius_h>$border['l']['width']) ? array($radius_h, $radius_v) : null;
+ $coin_BR = ($radius_h && $radius_v && $radius_v>$border['b']['width'] && $radius_h>$border['r']['width']) ? array($radius_h, $radius_v) : null;
+
+
+
+ // traitement de la couleur de fond
+ $STYLE = '';
+ if ($background['color'])
+ {
+ $this->pdf->SetFillColor($background['color'][0], $background['color'][1], $background['color'][2]);
+ $STYLE.= 'F';
+ }
+
+ if ($STYLE)
+ {
+ $this->pdf->clippingPathOpen($x, $y, $w, $h, $coin_TL,$coin_TR, $coin_BL, $coin_BR);
+ $this->pdf->Rect($x, $y, $w, $h, $STYLE);
+ $this->pdf->clippingPathClose();
+ }
+
+ // traitement de l'image de fond
+ if ($background['image'])
+ {
+ $i_name = $background['image'];
+ $i_position = $background['position']!==null ? $background['position'] : array(0, 0);
+ $i_repeat = $background['repeat']!==null ? $background['repeat'] : array(true, true);
+
+ // taile du fond (il faut retirer les borders
+ $b_x = $x;
+ $b_y = $y;
+ $b_w = $w;
+ $b_h = $h;
+
+ if ($border['b']['width']) { $b_h-= $border['b']['width']; }
+ if ($border['l']['width']) { $b_w-= $border['l']['width']; $b_x+= $border['l']['width']; }
+ if ($border['t']['width']) { $b_h-= $border['t']['width']; $b_y+= $border['t']['width']; }
+ if ($border['r']['width']) { $b_w-= $border['r']['width']; }
+
+ // est-ce que c'est une image ?
+ $i_infos=@GetImageSize($i_name);
+
+ if (count($i_infos)<2)
+ {
+ HTML2PDF::makeError(6, __FILE__, __LINE__, $i_name);
+ return false;
+ }
+
+ // récupération des dimensions dans l'unité du PDF
+ $i_width = 72./96.*$i_infos[0]/$this->pdf->k;
+ $i_height = 72./96.*$i_infos[1]/$this->pdf->k;
+
+ if ($i_repeat[0]) $i_position[0] = $b_x;
+ else if(preg_match('/^([-]?[0-9\.]+)%/isU', $i_position[0], $match)) $i_position[0] = $b_x + $match[1]*($b_w-$i_width)/100;
+ else $i_position[0] = $b_x+$i_position[0];
+
+ if ($i_repeat[1]) $i_position[1] = $b_y;
+ else if(preg_match('/^([-]?[0-9\.]+)%/isU', $i_position[1], $match)) $i_position[1] = $b_y + $match[1]*($b_h-$i_height)/100;
+ else $i_position[1] = $b_y+$i_position[1];
+
+ $i_x_min = $b_x;
+ $i_x_max = $b_x+$b_w;
+ $i_y_min = $b_y;
+ $i_y_max = $b_y+$b_h;
+
+ if (!$i_repeat[0] && !$i_repeat[1])
+ {
+ $i_x_min = $i_position[0]; $i_x_max = $i_position[0]+$i_width;
+ $i_y_min = $i_position[1]; $i_y_max = $i_position[1]+$i_height;
+ }
+ else if ($i_repeat[0] && !$i_repeat[1])
+ {
+ $i_y_min = $i_position[1]; $i_y_max = $i_position[1]+$i_height;
+ }
+ elseif (!$i_repeat[0] && $i_repeat[1])
+ {
+ $i_x_min = $i_position[0]; $i_x_max = $i_position[0]+$i_width;
+ }
+
+ if (is_array($coin_TL)) { $coin_TL[0]-= $border['l']['width']; $coin_TL[1]-= $border['t']['width']; }
+ if (is_array($coin_TR)) { $coin_TR[0]-= $border['r']['width']; $coin_TR[1]-= $border['t']['width']; }
+ if (is_array($coin_BL)) { $coin_BL[0]-= $border['l']['width']; $coin_BL[1]-= $border['b']['width']; }
+ if (is_array($coin_BR)) { $coin_BR[0]-= $border['r']['width']; $coin_BR[1]-= $border['b']['width']; }
+
+ $this->pdf->clippingPathOpen($b_x, $b_y, $b_w, $b_h, $coin_TL, $coin_TR, $coin_BL, $coin_BR);
+ for ($i_y=$i_y_min; $i_y<$i_y_max; $i_y+=$i_height)
+ {
+ for ($i_x=$i_x_min; $i_x<$i_x_max; $i_x+=$i_width)
+ {
+ $c_x = null;
+ $c_y = null;
+ $c_w = $i_width;
+ $c_h = $i_height;
+ if ($i_y_max-$i_y<$i_height)
+ {
+ $c_x = $i_x;
+ $c_y = $i_y;
+ $c_h = $i_y_max-$i_y;
+ }
+ if ($i_x_max-$i_x<$i_width)
+ {
+ $c_x = $i_x;
+ $c_y = $i_y;
+ $c_w = $i_x_max-$i_x;
+ }
+
+ $this->pdf->Image($i_name, $i_x, $i_y, $i_width, $i_height, '', '');
+ }
+ }
+ $this->pdf->clippingPathClose();
+ }
+
+ $x-= 0.01;
+ $y-= 0.01;
+ $w+= 0.02;
+ $h+= 0.02;
+ if ($border['b']['width']) $border['b']['width']+= 0.02;
+ if ($border['l']['width']) $border['l']['width']+= 0.02;
+ if ($border['t']['width']) $border['t']['width']+= 0.02;
+ if ($border['r']['width']) $border['r']['width']+= 0.02;
+
+ if ($border['b']['width'] && $border['b']['color'][0]!==null)
+ {
+ $pt = array();
+ $pt[] = $x+$w; $pt[] = $y+$h;
+ $pt[] = $x+$w-$border['r']['width']; $pt[] = $y+$h;
+ $pt[] = $x+$border['l']['width']; $pt[] = $y+$h;
+ $pt[] = $x; $pt[] = $y+$h;
+ $pt[] = $x+$border['l']['width']; $pt[] = $y+$h-$border['b']['width'];
+ $pt[] = $x+$w-$border['r']['width']; $pt[] = $y+$h-$border['b']['width'];
+
+ $bord = 3;
+ if (is_array($coin_BL))
+ {
+ $bord-=2;
+ $pt[4] += $radius_h-$border['l']['width'];
+ $pt[8] += $radius_h-$border['l']['width'];
+ unset($pt[6]);unset($pt[7]);
+ }
+ if (is_array($coin_BR))
+ {
+ $courbe = array();
+ $courbe[] = $x+$w; $courbe[] = $y+$h-$radius_v;
+ $courbe[] = $x+$w-$radius_h; $courbe[] = $y+$h;
+ $courbe[] = $x+$w-$border['r']['width']; $courbe[] = $y+$h-$radius_v;
+ $courbe[] = $x+$w-$radius_h; $courbe[] = $y+$h-$border['b']['width'];
+ $courbe[] = $x+$w-$radius_h; $courbe[] = $y+$h-$radius_v;
+ $this->Courbe($courbe, $border['b']['color']);
+
+ $bord-=1;
+ $pt[2] -= $radius_h-$border['r']['width'];
+ $pt[10]-= $radius_h-$border['r']['width'];
+ unset($pt[0]);unset($pt[1]);
+
+ }
+
+ $pt = array_values($pt);
+ $this->Line($pt, $border['b']['color'], $border['b']['type'], $border['b']['width'], $bord);
+ }
+
+ if ($border['l']['width'] && $border['l']['color'][0]!==null)
+ {
+ $pt = array();
+ $pt[] = $x; $pt[] = $y+$h;
+ $pt[] = $x; $pt[] = $y+$h-$border['b']['width'];
+ $pt[] = $x; $pt[] = $y+$border['t']['width'];
+ $pt[] = $x; $pt[] = $y;
+ $pt[] = $x+$border['l']['width']; $pt[] = $y+$border['t']['width'];
+ $pt[] = $x+$border['l']['width']; $pt[] = $y+$h-$border['b']['width'];
+
+ $bord = 3;
+ if (is_array($coin_BL))
+ {
+ $courbe = array();
+ $courbe[] = $x+$radius_h; $courbe[] = $y+$h;
+ $courbe[] = $x; $courbe[] = $y+$h-$radius_v;
+ $courbe[] = $x+$radius_h; $courbe[] = $y+$h-$border['b']['width'];
+ $courbe[] = $x+$border['l']['width']; $courbe[] = $y+$h-$radius_v;
+ $courbe[] = $x+$radius_h; $courbe[] = $y+$h-$radius_v;
+ $this->Courbe($courbe, $border['l']['color']);
+
+ $bord-=1;
+ $pt[3] -= $radius_v-$border['b']['width'];
+ $pt[11]-= $radius_v-$border['b']['width'];
+ unset($pt[0]);unset($pt[1]);
+ }
+ if (is_array($coin_TL))
+ {
+ $bord-=2;
+ $pt[5] += $radius_v-$border['t']['width'];
+ $pt[9] += $radius_v-$border['t']['width'];
+ unset($pt[6]);unset($pt[7]);
+ }
+
+ $pt = array_values($pt);
+ $this->Line($pt, $border['l']['color'], $border['l']['type'], $border['l']['width'], $bord);
+ }
+
+ if ($border['t']['width'] && $border['t']['color'][0]!==null)
+ {
+ $pt = array();
+ $pt[] = $x; $pt[] = $y;
+ $pt[] = $x+$border['l']['width']; $pt[] = $y;
+ $pt[] = $x+$w-$border['r']['width']; $pt[] = $y;
+ $pt[] = $x+$w; $pt[] = $y;
+ $pt[] = $x+$w-$border['r']['width']; $pt[] = $y+$border['t']['width'];
+ $pt[] = $x+$border['l']['width']; $pt[] = $y+$border['t']['width'];
+
+ $bord = 3;
+ if (is_array($coin_TL))
+ {
+ $courbe = array();
+ $courbe[] = $x; $courbe[] = $y+$radius_v;
+ $courbe[] = $x+$radius_h; $courbe[] = $y;
+ $courbe[] = $x+$border['l']['width']; $courbe[] = $y+$radius_v;
+ $courbe[] = $x+$radius_h; $courbe[] = $y+$border['t']['width'];
+ $courbe[] = $x+$radius_h; $courbe[] = $y+$radius_v;
+ $this->Courbe($courbe, $border['t']['color']);
+
+ $bord-=1;
+ $pt[2] += $radius_h-$border['l']['width'];
+ $pt[10]+= $radius_h-$border['l']['width'];
+ unset($pt[0]);unset($pt[1]);
+ }
+ if (is_array($coin_TR))
+ {
+ $bord-=2;
+ $pt[4] -= $radius_h-$border['r']['width'];
+ $pt[8] -= $radius_h-$border['r']['width'];
+ unset($pt[6]);unset($pt[7]);
+ }
+
+ $pt = array_values($pt);
+ $this->Line($pt, $border['t']['color'], $border['t']['type'], $border['t']['width'], $bord);
+ }
+
+ if ($border['r']['width'] && $border['r']['color'][0]!==null)
+ {
+ $pt = array();
+ $pt[] = $x+$w; $pt[] = $y;
+ $pt[] = $x+$w; $pt[] = $y+$border['t']['width'];
+ $pt[] = $x+$w; $pt[] = $y+$h-$border['b']['width'];
+ $pt[] = $x+$w; $pt[] = $y+$h;
+ $pt[] = $x+$w-$border['r']['width']; $pt[] = $y+$h-$border['b']['width'];
+ $pt[] = $x+$w-$border['r']['width']; $pt[] = $y+$border['t']['width'];
+
+ $bord = 3;
+ if (is_array($coin_TR))
+ {
+ $courbe = array();
+ $courbe[] = $x+$w-$radius_h; $courbe[] = $y;
+ $courbe[] = $x+$w; $courbe[] = $y+$radius_v;
+ $courbe[] = $x+$w-$radius_h; $courbe[] = $y+$border['t']['width'];
+ $courbe[] = $x+$w-$border['r']['width']; $courbe[] = $y+$radius_v;
+ $courbe[] = $x+$w-$radius_h; $courbe[] = $y+$radius_v;
+ $this->Courbe($courbe, $border['r']['color']);
+
+ $bord-=1;
+ $pt[3] += $radius_v-$border['t']['width'];
+ $pt[11]+= $radius_v-$border['t']['width'];
+ unset($pt[0]);unset($pt[1]);
+ }
+ if (is_array($coin_BR))
+ {
+ $bord-=2;
+ $pt[5] -= $radius_v-$border['b']['width'];
+ $pt[9] -= $radius_v-$border['b']['width'];
+ unset($pt[6]);unset($pt[7]);
+ }
+
+ $pt = array_values($pt);
+ $this->Line($pt, $border['r']['color'], $border['r']['type'], $border['r']['width'], $bord);
+ }
+
+ if ($background) $this->pdf->SetFillColor($background['color'][0], $background['color'][1], $background['color'][2]);
+ }
+
+ function Courbe($pt, $color)
+ {
+ $this->pdf->SetFillColor($color[0], $color[1], $color[2]);
+
+ $this->pdf->drawCourbe($pt[0], $pt[1], $pt[2], $pt[3], $pt[4], $pt[5], $pt[6], $pt[7], $pt[8], $pt[9]);
+ }
+
+ /**
+ * Tracer une ligne epaisse défini par ses points avec des extreminites en biseau
+ *
+ * @param array liste des points definissant le tour de la ligne
+ * @param float couleur RVB
+ * @param string type de ligne
+ * @param float largeur de la ligne
+ * @return null
+ */
+ function Line($pt, $color, $type, $width, $bord=3)
+ {
+ $this->pdf->SetFillColor($color[0], $color[1], $color[2]);
+ if ($type=='dashed' || $type=='dotted')
+ {
+ if ($bord==1)
+ {
+ $tmp = array(); $tmp[]=$pt[0]; $tmp[]=$pt[1]; $tmp[]=$pt[2]; $tmp[]=$pt[3]; $tmp[]=$pt[8]; $tmp[]=$pt[9];
+ $this->pdf->Polygon($tmp, 'F');
+
+ $tmp = array(); $tmp[]=$pt[2]; $tmp[]=$pt[3]; $tmp[]=$pt[4]; $tmp[]=$pt[5]; $tmp[]=$pt[6]; $tmp[]=$pt[7]; $tmp[]=$pt[8]; $tmp[]=$pt[9];
+ $pt = $tmp;
+ }
+ else if ($bord==2)
+ {
+ $tmp = array(); $tmp[]=$pt[2]; $tmp[]=$pt[3]; $tmp[]=$pt[4]; $tmp[]=$pt[5]; $tmp[]=$pt[6]; $tmp[]=$pt[7];
+ $this->pdf->Polygon($tmp, 'F');
+
+ $tmp = array(); $tmp[]=$pt[0]; $tmp[]=$pt[1]; $tmp[]=$pt[2]; $tmp[]=$pt[3]; $tmp[]=$pt[6]; $tmp[]=$pt[7]; $tmp[]=$pt[8]; $tmp[]=$pt[9];
+ $pt = $tmp;
+ }
+ else if ($bord==3)
+ {
+ $tmp = array(); $tmp[]=$pt[0]; $tmp[]=$pt[1]; $tmp[]=$pt[2]; $tmp[]=$pt[3]; $tmp[]=$pt[10]; $tmp[]=$pt[11];
+ $this->pdf->Polygon($tmp, 'F');
+
+ $tmp = array(); $tmp[]=$pt[4]; $tmp[]=$pt[5]; $tmp[]=$pt[6]; $tmp[]=$pt[7]; $tmp[]=$pt[8]; $tmp[]=$pt[9];
+ $this->pdf->Polygon($tmp, 'F');
+
+ $tmp = array(); $tmp[]=$pt[2]; $tmp[]=$pt[3]; $tmp[]=$pt[4]; $tmp[]=$pt[5]; $tmp[]=$pt[8]; $tmp[]=$pt[9]; $tmp[]=$pt[10]; $tmp[]=$pt[11];
+ $pt = $tmp;
+ }
+
+ if ($pt[2]==$pt[0])
+ {
+ $l = abs(($pt[3]-$pt[1])*0.5);
+ $px = 0;
+ $py = $width;
+ $x1 = $pt[0]; $y1 = ($pt[3]+$pt[1])*0.5;
+ $x2 = $pt[6]; $y2 = ($pt[7]+$pt[5])*0.5;
+ }
+ else
+ {
+ $l = abs(($pt[2]-$pt[0])*0.5);
+ $px = $width;
+ $py = 0;
+ $x1 = ($pt[2]+$pt[0])*0.5; $y1 = $pt[1];
+ $x2 = ($pt[6]+$pt[4])*0.5; $y2 = $pt[7];
+ }
+ if ($type=='dashed')
+ {
+ $px = $px*3.;
+ $py = $py*3.;
+ }
+ $mode = ($l/($px+$py)<.5);
+
+ for($i=0; $l-($px+$py)*($i-0.5)>0; $i++)
+ {
+ if (($i%2)==$mode)
+ {
+ $j = $i-0.5;
+ $lx1 = $px*($j); if ($lx1<-$l) $lx1 =-$l;
+ $ly1 = $py*($j); if ($ly1<-$l) $ly1 =-$l;
+ $lx2 = $px*($j+1); if ($lx2>$l) $lx2 = $l;
+ $ly2 = $py*($j+1); if ($ly2>$l) $ly2 = $l;
+
+ $tmp = array();
+ $tmp[] = $x1+$lx1; $tmp[] = $y1+$ly1;
+ $tmp[] = $x1+$lx2; $tmp[] = $y1+$ly2;
+ $tmp[] = $x2+$lx2; $tmp[] = $y2+$ly2;
+ $tmp[] = $x2+$lx1; $tmp[] = $y2+$ly1;
+ $this->pdf->Polygon($tmp, 'F');
+
+ if ($j>0)
+ {
+ $tmp = array();
+ $tmp[] = $x1-$lx1; $tmp[] = $y1-$ly1;
+ $tmp[] = $x1-$lx2; $tmp[] = $y1-$ly2;
+ $tmp[] = $x2-$lx2; $tmp[] = $y2-$ly2;
+ $tmp[] = $x2-$lx1; $tmp[] = $y2-$ly1;
+ $this->pdf->Polygon($tmp, 'F');
+ }
+ }
+ }
+ }
+ else if ($type=='solid')
+ {
+ $this->pdf->Polygon($pt, 'F');
+ }
+ }
+
+ /**
+ * balise : BR
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @param integer position reelle courante si saut de ligne pendant l'ecriture d'un texte
+ * @return null
+ */
+ function o_BR($param, $curr = null)
+ {
+ if ($this->forOneLine) return false;
+
+ $h = $this->style->getLineHeight();
+ $h = max($this->maxH, $h);
+ $y = $this->pdf->getY();
+
+ // si la ligne est vide, la position maximale n'a pas été mise à jour => on la met à jour
+ if ($this->maxH==0) $this->maxY = max($this->maxY, $y+$h);
+
+ // si le saut de ligne rentre => on le prend en compte, sinon nouvelle page
+ if ($y+$h<$this->pdf->h - $this->pdf->bMargin) $this->setNewLine($h, $curr);
+ else $this->setNewPage('', null, $curr);
+
+ $this->maxH = 0;
+
+ return true;
+ }
+
+ /**
+ * balise : HR
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_HR($param)
+ {
+ if ($this->forOneLine) return false;
+ $old_align = $this->style->value['text-align'];
+ $this->style->value['text-align'] = 'left';
+
+ if ($this->maxH) $this->o_BR($param);
+
+ $f_size = $this->style->value['font-size'];
+ $this->style->value['font-size']=$f_size*0.5; $this->o_BR($param);
+ $this->style->value['font-size']=0;
+
+ $param['style']['width'] = '100%';
+
+ $this->style->save();
+ $this->style->value['height']=$this->style->ConvertToMM('1mm');
+
+ $this->style->analyse('hr', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ $h = $this->style->value['height'];
+ if ($h) $h-= $this->style->value['border']['t']['width']+$this->style->value['border']['b']['width'];
+ if ($h<=0) $h = $this->style->value['border']['t']['width']+$this->style->value['border']['b']['width'];
+
+ $this->Rectangle($this->pdf->x, $this->pdf->y, $this->style->value['width'], $h, $this->style->value['border'], 0, 0, $this->style->value['background']);
+ $this->maxH = $h;
+
+ $this->style->load();
+ $this->style->FontSet();
+
+ $this->o_BR($param);
+
+ $this->style->value['font-size']=$f_size*0.5; $this->o_BR($param);
+ $this->style->value['font-size']=$f_size;
+
+ $this->style->value['text-align'] = $old_align;
+ $this->setNewPositionForNewLine();
+
+ return true;
+ }
+
+ /**
+ * balise : B
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_B($param, $other = 'b')
+ {
+ $this->style->save();
+ $this->style->value['font-bold'] = true;
+ $this->style->analyse($other, $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ return true;
+ }
+ function o_STRONG($param) { return $this->o_B($param, 'strong'); }
+
+ /**
+ * balise : B
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_B($param)
+ {
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+ function c_STRONG($param) { return $this->c_B($param); }
+
+ /**
+ * balise : I
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_I($param, $other = 'i')
+ {
+ $this->style->save();
+ $this->style->value['font-italic'] = true;
+ $this->style->analyse($other, $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ return true;
+ }
+ function o_ADDRESS($param) { return $this->o_I($param, 'address'); }
+ function o_CITE($param) { return $this->o_I($param, 'cite'); }
+ function o_EM($param) { return $this->o_I($param, 'em'); }
+ function o_SAMP($param) { return $this->o_I($param, 'samp'); }
+
+ /**
+ * balise : I
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_I($param)
+ {
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+ function c_ADDRESS($param) { return $this->c_I($param); }
+ function c_CITE($param) { return $this->c_I($param); }
+ function c_EM($param) { return $this->c_I($param); }
+ function c_SAMP($param) { return $this->c_I($param); }
+
+ /**
+ * balise : S
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_S($param)
+ {
+ $this->style->save();
+ $this->style->value['font-linethrough'] = true;
+ $this->style->analyse('s', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : S
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_S($param)
+ {
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : U
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_U($param)
+ {
+ $this->style->save();
+ $this->style->value['font-underline'] = true;
+ $this->style->analyse('u', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : U
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_U($param)
+ {
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : A
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_A($param)
+ {
+ $this->inLink = str_replace('&', '&', isset($param['href']) ? $param['href'] : '');
+
+ if (isset($param['name']))
+ {
+ $nom = $param['name'];
+ if (!isset($this->lstAncre[$nom])) $this->lstAncre[$nom] = array($this->pdf->AddLink(), false);
+
+ if (!$this->lstAncre[$nom][1])
+ {
+ $this->lstAncre[$nom][1] = true;
+ $this->pdf->SetLink($this->lstAncre[$nom][0], -1, -1);
+ }
+ }
+
+ if (preg_match('/^#([^#]+)$/isU', $this->inLink, $match))
+ {
+ $nom = $match[1];
+ if (!isset($this->lstAncre[$nom])) $this->lstAncre[$nom] = array($this->pdf->AddLink(), false);
+
+ $this->inLink = $this->lstAncre[$nom][0];
+ }
+
+ $this->style->save();
+ $this->style->value['font-underline'] = true;
+ $this->style->value['color'] = array(20, 20, 250);
+ $this->style->analyse('a', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : A
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_A($param)
+ {
+ $this->inLink = '';
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : H1
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_H1($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->o_BR(array());
+ $this->style->save();
+ $this->style->value['font-bold'] = true;
+ $this->style->value['font-size'] = $this->style->ConvertToMM('28px');
+ $this->style->analyse('h1', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+ $this->setNewPositionForNewLine();
+
+ return true;
+ }
+
+ /**
+ * balise : H1
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_H1($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->o_BR(array());
+ $this->style->load();
+ $this->style->FontSet();
+ $this->o_BR(array());
+
+ return true;
+ }
+
+ /**
+ * balise : H2
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_H2($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->o_BR(array());
+ $this->style->save();
+ $this->style->value['font-bold'] = true;
+ $this->style->value['font-size'] = $this->style->ConvertToMM('24px');
+ $this->style->analyse('h2', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+ $this->setNewPositionForNewLine();
+
+ return true;
+ }
+
+ /**
+ * balise : H2
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_H2($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->o_BR(array());
+ $this->style->load();
+ $this->style->FontSet();
+ $this->o_BR(array());
+
+ return true;
+ }
+
+ /**
+ * balise : H3
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_H3($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->o_BR(array());
+ $this->style->save();
+ $this->style->value['font-bold'] = true;
+ $this->style->value['font-size'] = $this->style->ConvertToMM('20px');
+ $this->style->analyse('h3', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+ $this->setNewPositionForNewLine();
+
+ return true;
+ }
+
+ /**
+ * balise : H3
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_H3($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->o_BR(array());
+ $this->style->load();
+ $this->style->FontSet();
+ $this->o_BR(array());
+
+ return true;
+ }
+
+ /**
+ * balise : H4
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_H4($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->o_BR(array());
+ $this->style->save();
+ $this->style->value['font-bold'] = true;
+ $this->style->value['font-size'] = $this->style->ConvertToMM('16px');
+ $this->style->analyse('h4', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+ $this->setNewPositionForNewLine();
+
+ return true;
+ }
+
+ /**
+ * balise : H4
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_H4($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->o_BR(array());
+ $this->style->load();
+ $this->style->FontSet();
+ $this->o_BR(array());
+
+ return true;
+ }
+
+ /**
+ * balise : H5
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_H5($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->o_BR(array());
+ $this->style->save();
+ $this->style->value['font-bold'] = true;
+ $this->style->value['font-size'] = $this->style->ConvertToMM('12px');
+ $this->style->analyse('h5', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+ $this->setNewPositionForNewLine();
+
+ return true;
+ }
+
+ /**
+ * balise : H5
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_H5($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->o_BR(array());
+ $this->style->load();
+ $this->style->FontSet();
+ $this->o_BR(array());
+
+ return true;
+ }
+
+ /**
+ * balise : H6
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_H6($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->o_BR(array());
+ $this->style->save();
+ $this->style->value['font-bold'] = true;
+ $this->style->value['font-size'] = $this->style->ConvertToMM('9px');
+ $this->style->analyse('h6', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+ $this->setNewPositionForNewLine();
+
+ return true;
+ }
+
+ /**
+ * balise : H6
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_H6($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->o_BR(array());
+ $this->style->load();
+ $this->style->FontSet();
+ $this->o_BR(array());
+
+ return true;
+ }
+
+ /**
+ * balise : SPAN
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_SPAN($param, $other = 'span')
+ {
+ $this->style->save();
+ $this->style->analyse($other, $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ return true;
+ }
+ function o_FONT($param) { return $this->o_SPAN($param, 'font'); }
+
+ /**
+ * balise : SPAN
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_SPAN($param)
+ {
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+ function c_FONT($param) { return $this->c_SPAN($param); }
+
+
+ /**
+ * balise : P
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_P($param)
+ {
+ if ($this->forOneLine) return false;
+
+ if (!in_array($this->previousCall, array('c_P', 'c_UL')))
+ {
+ if ($this->maxH) $this->o_BR(array());
+ $this->o_BR(array());
+ }
+
+ $this->style->save();
+ $this->style->analyse('p', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ if ($this->style->value['text-indent']>0) $this->pdf->x+= $this->style->value['text-indent'];
+
+ return true;
+ }
+
+ /**
+ * balise : P
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_P($param)
+ {
+ if ($this->forOneLine) return false;
+
+ if ($this->maxH) $this->o_BR(array());
+ $this->o_BR(array());
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : PRE
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_PRE($param, $other = 'pre')
+ {
+ if ($other=='pre' && $this->maxH) $this->o_BR(array());
+
+ $this->style->save();
+ $this->style->value['font-family'] = 'courier';
+ $this->style->analyse($other, $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ if ($other=='pre') return $this->o_DIV($param, $other);
+
+ return true;
+ }
+ function o_CODE($param) { return $this->o_PRE($param, 'code'); }
+
+ /**
+ * balise : PRE
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_PRE($param, $other = 'pre')
+ {
+ if ($other=='pre')
+ {
+ if ($this->forOneLine) return false;
+
+ $this->c_DIV($param);
+ $this->o_BR(array());
+ }
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+ function c_CODE($param) { return $this->c_PRE($param, 'code'); }
+
+ /**
+ * balise : BIG
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_BIG($param)
+ {
+ $this->style->save();
+ $this->style->value['mini-decal']-= $this->style->value['mini-size']*0.2;
+ $this->style->value['mini-size'] *= 1.2;
+ $this->style->analyse('big', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : BIG
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_BIG($param)
+ {
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : SMALL
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_SMALL($param)
+ {
+ $this->style->save();
+ $this->style->value['mini-decal']+= $this->style->value['mini-size']*0.18;
+ $this->style->value['mini-size'] *= 0.82;
+ $this->style->analyse('small', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : SMALL
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_SMALL($param)
+ {
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+
+
+ /**
+ * balise : SUP
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_SUP($param)
+ {
+ $this->style->save();
+ $this->style->value['mini-decal']-= $this->style->value['mini-size']*0.25;
+ $this->style->value['mini-size'] *= 0.75;
+ $this->style->analyse('sup', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : SUP
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_SUP($param)
+ {
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : SUB
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_SUB($param)
+ {
+ $this->style->save();
+ $this->style->value['mini-decal']+= $this->style->value['mini-size']*0.25;
+ $this->style->value['mini-size'] *= 0.75;
+ $this->style->analyse('sub', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+ $this->inSub = 1;
+
+ return true;
+ }
+
+ /**
+ * balise : SUB
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_SUB($param)
+ {
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : UL
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_UL($param, $other = 'ul')
+ {
+ if ($this->forOneLine) return false;
+
+ if (!in_array($this->previousCall, array('c_P', 'c_UL')))
+ {
+ if ($this->maxH) $this->o_BR(array());
+ if (!count($this->defLIST)) $this->o_BR(array());
+ }
+
+ if (!isset($param['style']['width'])) $param['allwidth'] = true;
+ $param['cellspacing'] = 0;
+
+ // une liste est traitée comme un tableau
+ $this->o_TABLE($param, $other);
+
+ // ajouter un niveau de liste
+ $this->listeAddLevel($other, $this->style->value['list-style-type'], $this->style->value['list-style-image']);
+
+ return true;
+ }
+ function o_OL($param) { return $this->o_UL($param, 'ol'); }
+
+ /**
+ * balise : UL
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_UL($param)
+ {
+ if ($this->forOneLine) return false;
+
+ // fin du tableau
+ $this->c_TABLE($param);
+
+ // enlever un niveau de liste
+ $this->listeDelLevel();
+
+ if (!$this->sub_part)
+ {
+ if (!count($this->defLIST)) $this->o_BR(array());
+ }
+
+ return true;
+ }
+ function c_OL($param) { return $this->c_UL($param); }
+
+ /**
+ * balise : LI
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_LI($param)
+ {
+ if ($this->forOneLine) return false;
+
+ // ajouter une puce au niveau actuel
+ $this->listeAddLi();
+
+ if (!isset($param['style']['width'])) $param['style']['width'] = '100%';
+
+ // preparation du style de la puce
+ $paramPUCE = $param;
+
+ $inf = $this->listeGetLi();
+ if ($inf[0])
+ {
+ $paramPUCE['style']['font-family'] = $inf[0];
+ $paramPUCE['style']['text-align'] = 'li_right';
+ $paramPUCE['style']['vertical-align'] = 'top';
+ $paramPUCE['style']['width'] = $this->listeGetWidth();
+ $paramPUCE['style']['padding-right'] = $this->listeGetPadding();
+ $paramPUCE['txt'] = $inf[2];
+ }
+ else
+ {
+ $paramPUCE['style']['text-align'] = 'li_right';
+ $paramPUCE['style']['vertical-align'] = 'top';
+ $paramPUCE['style']['width'] = $this->listeGetWidth();
+ $paramPUCE['style']['padding-right'] = $this->listeGetPadding();
+ $paramPUCE['src'] = $inf[2];
+ $paramPUCE['sub_li'] = true;
+ }
+
+ // nouvelle ligne
+ $this->o_TR($param, 'li');
+
+ $this->style->save();
+
+ if ($inf[1])
+ {
+ $this->style->value['mini-decal']+= $this->style->value['mini-size']*0.25;
+ $this->style->value['mini-size'] *= 0.75;
+ }
+
+ // si on est dans un sub_html => preparation, sinon affichage classique
+ if ($this->sub_part)
+ {
+ // TD pour la puce
+ $tmp_pos = $this->temp_pos;
+ $tmp_lst1 = $this->parsing->code[$tmp_pos+1];
+ $tmp_lst2 = $this->parsing->code[$tmp_pos+2];
+ $this->parsing->code[$tmp_pos+1] = array();
+ $this->parsing->code[$tmp_pos+1]['name'] = (isset($paramPUCE['src'])) ? 'img' : 'write';
+ $this->parsing->code[$tmp_pos+1]['param'] = $paramPUCE; unset($this->parsing->code[$tmp_pos+1]['param']['style']['width']);
+ $this->parsing->code[$tmp_pos+1]['close'] = 0;
+ $this->parsing->code[$tmp_pos+2] = array();
+ $this->parsing->code[$tmp_pos+2]['name'] = 'li';
+ $this->parsing->code[$tmp_pos+2]['param'] = $paramPUCE;
+ $this->parsing->code[$tmp_pos+2]['close'] = 1;
+ $this->o_TD($paramPUCE, 'li_sub');
+ $this->c_TD($param);
+ $this->temp_pos = $tmp_pos;
+ $this->parsing->code[$tmp_pos+1] = $tmp_lst1;
+ $this->parsing->code[$tmp_pos+2] = $tmp_lst2;
+ }
+ else
+ {
+ // TD pour la puce
+ $this->o_TD($paramPUCE, 'li_sub');
+ unset($paramPUCE['style']['width']);
+ if (isset($paramPUCE['src'])) $this->o_IMG($paramPUCE);
+ else $this->o_WRITE($paramPUCE);
+ $this->c_TD($paramPUCE);
+ }
+ $this->style->load();
+
+
+ // td pour le contenu
+ $this->o_TD($param, 'li');
+
+ return true;
+ }
+
+ /**
+ * balise : LI
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_LI($param)
+ {
+ if ($this->forOneLine) return false;
+
+ // fin du contenu
+ $this->c_TD($param, 'li');
+
+ // fin de la ligne
+ $this->c_TR($param, 'li');
+
+ return true;
+ }
+
+ /**
+ * balise : TBODY
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_TBODY($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->style->save();
+ $this->style->analyse('tbody', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : TBODY
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_TBODY($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : THEAD
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_THEAD($param)
+ {
+ if ($this->forOneLine) return false;
+
+ global $HTML2PDF_TABLEAU;
+
+ $this->style->save();
+ $this->style->analyse('thead', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ // si on est en mode sub_html : sauvegarde du numéro du TR
+ if ($this->sub_part)
+ {
+ $HTML2PDF_TABLEAU[$param['num']]['thead']['tr'][0] = $HTML2PDF_TABLEAU[$param['num']]['tr_curr'];
+ $HTML2PDF_TABLEAU[$param['num']]['thead']['code'] = array();
+ for($pos=$this->temp_pos; $posparsing->code); $pos++)
+ {
+ $todo = $this->parsing->code[$pos];
+ if (strtolower($todo['name'])=='thead') $todo['name'] = 'thead_sub';
+ $HTML2PDF_TABLEAU[$param['num']]['thead']['code'][] = $todo;
+ if (strtolower($todo['name'])=='thead_sub' && $todo['close']) break;
+ }
+ }
+ else
+ {
+ $res = $this->parsing->getLevel($this->parse_pos);
+ $this->parse_pos = $res[0]-1;
+ $HTML2PDF_TABLEAU[$param['num']]['tr_curr']+= count($HTML2PDF_TABLEAU[$param['num']]['thead']['tr']);
+ }
+
+ return true;
+ }
+
+ /**
+ * balise : THEAD
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_THEAD($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->style->load();
+ $this->style->FontSet();
+
+ // si on est en mode sub_html : sauvegarde du numéro du TR
+ if ($this->sub_part)
+ {
+ global $HTML2PDF_TABLEAU;
+ $min = $HTML2PDF_TABLEAU[$param['num']]['thead']['tr'][0];
+ $max = $HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1;
+ $HTML2PDF_TABLEAU[$param['num']]['thead']['tr'] = range($min, $max);
+ }
+
+ return true;
+ }
+
+ /**
+ * balise : TFOOT
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_TFOOT($param)
+ {
+ if ($this->forOneLine) return false;
+
+ global $HTML2PDF_TABLEAU;
+
+ $this->style->save();
+ $this->style->analyse('tfoot', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ // si on est en mode sub_html : sauvegarde du numéro du TR
+ if ($this->sub_part)
+ {
+ $HTML2PDF_TABLEAU[$param['num']]['tfoot']['tr'][0] = $HTML2PDF_TABLEAU[$param['num']]['tr_curr'];
+ $HTML2PDF_TABLEAU[$param['num']]['tfoot']['code'] = array();
+ for($pos=$this->temp_pos; $posparsing->code); $pos++)
+ {
+ $todo = $this->parsing->code[$pos];
+ if (strtolower($todo['name'])=='tfoot') $todo['name'] = 'tfoot_sub';
+ $HTML2PDF_TABLEAU[$param['num']]['tfoot']['code'][] = $todo;
+ if (strtolower($todo['name'])=='tfoot_sub' && $todo['close']) break;
+ }
+ }
+ else
+ {
+ $res = $this->parsing->getLevel($this->parse_pos+1);
+ $this->parse_pos = $res[0];
+ $HTML2PDF_TABLEAU[$param['num']]['tr_curr']+= count($HTML2PDF_TABLEAU[$param['num']]['tfoot']['tr']);
+ }
+
+ return true;
+ }
+
+ /**
+ * balise : TFOOT
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_TFOOT($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->style->load();
+ $this->style->FontSet();
+
+ // si on est en mode sub_html : sauvegarde du numéro du TR
+ if ($this->sub_part)
+ {
+ global $HTML2PDF_TABLEAU;
+
+ $min = $HTML2PDF_TABLEAU[$param['num']]['tfoot']['tr'][0];
+ $max = $HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1;
+ $HTML2PDF_TABLEAU[$param['num']]['tfoot']['tr'] = range($min, $max);
+ }
+
+ return true;
+ }
+
+ /**
+ * balise : THEAD_SUB
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_THEAD_SUB($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->style->save();
+ $this->style->analyse('thead', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : THEAD_SUB
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_THEAD_SUB($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : TFOOT_SUB
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_TFOOT_SUB($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->style->save();
+ $this->style->analyse('tfoot', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : TFOOT_SUB
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_TFOOT_SUB($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : FORM
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_FORM($param)
+ {
+ $this->style->save();
+ $this->style->analyse('form', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : FORM
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_FORM($param)
+ {
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : TABLE
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_TABLE($param, $other = 'table')
+ {
+ if ($this->forOneLine) return false;
+
+ $this->maxH = 0;
+ // utilisation du tableau des paramétres des tables
+ global $HTML2PDF_TABLEAU;
+
+ $align_object = isset($param['align']) ? strtolower($param['align']) : 'left';
+ if (isset($param['align'])) unset($param['align']);
+ if (!in_array($align_object, array('left', 'center', 'right'))) $align_object = 'left';
+
+ // lecture et initialisation du style
+ $this->style->save();
+ $this->style->analyse($other, $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ if ($this->style->value['margin-auto']) $align_object = 'center';
+
+ // est-on en collapse
+ $collapse = false;
+ if ($other=='table')
+ $collapse = isset($this->style->value['border']['collapse']) ? $this->style->value['border']['collapse'] : false;
+
+ // si oui il faut adapté les borders
+ if ($collapse)
+ {
+ $param['style']['border'] = 'none';
+ $param['cellspacing'] = 0;
+ $none = $this->style->readBorder('none');
+ $this->style->value['border']['t'] = $none;
+ $this->style->value['border']['r'] = $none;
+ $this->style->value['border']['b'] = $none;
+ $this->style->value['border']['l'] = $none;
+ }
+
+ // si on est en mode sub_html : initialisation des dimensions et autres
+ if ($this->sub_part)
+ {
+ $HTML2PDF_TABLEAU[$param['num']] = array();
+ $HTML2PDF_TABLEAU[$param['num']]['cellpadding'] = $this->style->ConvertToMM(isset($param['cellpadding']) ? $param['cellpadding'] : '1px'); // cellpadding du tableau
+ $HTML2PDF_TABLEAU[$param['num']]['cellspacing'] = $this->style->ConvertToMM(isset($param['cellspacing']) ? $param['cellspacing'] : '2px'); // cellspacing du tableau
+ $HTML2PDF_TABLEAU[$param['num']]['cases'] = array(); // liste des propriétés des cases
+ $HTML2PDF_TABLEAU[$param['num']]['td_curr'] = 0; // colonne courante
+ $HTML2PDF_TABLEAU[$param['num']]['tr_curr'] = 0; // ligne courante
+ $HTML2PDF_TABLEAU[$param['num']]['curr_x'] = $this->pdf->getX(); // position courante X
+ $HTML2PDF_TABLEAU[$param['num']]['curr_y'] = $this->pdf->getY(); // position courante Y
+ $HTML2PDF_TABLEAU[$param['num']]['width'] = 0; // largeur globale
+ $HTML2PDF_TABLEAU[$param['num']]['height'] = 0; // hauteur globale
+ $HTML2PDF_TABLEAU[$param['num']]['align'] = $align_object;
+ $HTML2PDF_TABLEAU[$param['num']]['marge'] = array();
+ $HTML2PDF_TABLEAU[$param['num']]['marge']['t'] = $this->style->value['padding']['t']+$this->style->value['border']['t']['width']+$HTML2PDF_TABLEAU[$param['num']]['cellspacing']*0.5;
+ $HTML2PDF_TABLEAU[$param['num']]['marge']['r'] = $this->style->value['padding']['r']+$this->style->value['border']['r']['width']+$HTML2PDF_TABLEAU[$param['num']]['cellspacing']*0.5;
+ $HTML2PDF_TABLEAU[$param['num']]['marge']['b'] = $this->style->value['padding']['b']+$this->style->value['border']['b']['width']+$HTML2PDF_TABLEAU[$param['num']]['cellspacing']*0.5;
+ $HTML2PDF_TABLEAU[$param['num']]['marge']['l'] = $this->style->value['padding']['l']+$this->style->value['border']['l']['width']+$HTML2PDF_TABLEAU[$param['num']]['cellspacing']*0.5;
+ $HTML2PDF_TABLEAU[$param['num']]['page'] = 0; // nombre de pages
+ $HTML2PDF_TABLEAU[$param['num']]['new_page'] = true; // nouvelle page pour le TR courant
+ $HTML2PDF_TABLEAU[$param['num']]['style_value'] = null; // style du tableau
+ $HTML2PDF_TABLEAU[$param['num']]['thead'] = array(); // infos sur le thead
+ $HTML2PDF_TABLEAU[$param['num']]['tfoot'] = array(); // infos sur le tfoot
+ $HTML2PDF_TABLEAU[$param['num']]['thead']['tr'] = array(); // tr du thead
+ $HTML2PDF_TABLEAU[$param['num']]['tfoot']['tr'] = array(); // tr du tfoot
+ $HTML2PDF_TABLEAU[$param['num']]['thead']['height'] = 0; // hauteur du thead
+ $HTML2PDF_TABLEAU[$param['num']]['tfoot']['height'] = 0; // hauteur du tfoot
+ $HTML2PDF_TABLEAU[$param['num']]['thead']['code'] = array(); // contenu HTML du thead
+ $HTML2PDF_TABLEAU[$param['num']]['tfoot']['code'] = array(); // contenu HTML du tfoot
+
+ $this->saveMargin($this->pdf->lMargin, $this->pdf->tMargin, $this->pdf->rMargin);
+
+ // adaptation de la largeur en fonction des marges du tableau
+ $this->style->value['width']-= $HTML2PDF_TABLEAU[$param['num']]['marge']['l'] + $HTML2PDF_TABLEAU[$param['num']]['marge']['r'];
+ }
+ else
+ {
+ // on repart à la premiere page du tableau et à la premiere case
+ $HTML2PDF_TABLEAU[$param['num']]['page'] = 0;
+ $HTML2PDF_TABLEAU[$param['num']]['td_curr'] = 0;
+ $HTML2PDF_TABLEAU[$param['num']]['tr_curr'] = 0;
+ $HTML2PDF_TABLEAU[$param['num']]['td_x'] = $HTML2PDF_TABLEAU[$param['num']]['marge']['l']+$HTML2PDF_TABLEAU[$param['num']]['curr_x'];
+ $HTML2PDF_TABLEAU[$param['num']]['td_y'] = $HTML2PDF_TABLEAU[$param['num']]['marge']['t']+$HTML2PDF_TABLEAU[$param['num']]['curr_y'];
+
+ // initialisation du style des bordures de la premiere partie de tableau
+ $this->Rectangle(
+ $HTML2PDF_TABLEAU[$param['num']]['curr_x'],
+ $HTML2PDF_TABLEAU[$param['num']]['curr_y'],
+ $HTML2PDF_TABLEAU[$param['num']]['width'],
+ isset($HTML2PDF_TABLEAU[$param['num']]['height'][0]) ? $HTML2PDF_TABLEAU[$param['num']]['height'][0] : null,
+ $this->style->value['border'],
+ $this->style->value['padding'],
+ 0,
+ $this->style->value['background']
+ );
+
+ $HTML2PDF_TABLEAU[$param['num']]['style_value'] = $this->style->value;
+ }
+
+ return true;
+ }
+
+ /**
+ * balise : TABLE
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_TABLE($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->maxH = 0;
+ global $HTML2PDF_TABLEAU;
+
+ // restauration du style
+ $this->style->load();
+ $this->style->FontSet();
+
+ // si on est en mode sub_html : initialisation des dimensions et autres
+ if ($this->sub_part)
+ {
+ // ajustement de la taille des cases
+ $this->calculTailleCases($HTML2PDF_TABLEAU[$param['num']]['cases']);
+
+ // calcul de la hauteur du THEAD et du TFOOT
+ $lst = array('thead', 'tfoot');
+ foreach($lst as $mode)
+ {
+ $HTML2PDF_TABLEAU[$param['num']][$mode]['height'] = 0;
+ foreach($HTML2PDF_TABLEAU[$param['num']][$mode]['tr'] as $tr)
+ {
+ // hauteur de la ligne tr
+ $h = 0;
+ for($i=0; $istyle->table[count($this->style->table)-1]) ? $this->style->table[count($this->style->table)-1] : $this->style->value;
+ $parent_w = $old['width'] ? $old['width'] : $this->pdf->w - $this->pdf->lMargin - $this->pdf->rMargin;
+ $x = $HTML2PDF_TABLEAU[$param['num']]['curr_x'];
+ $w = $HTML2PDF_TABLEAU[$param['num']]['width'];
+ if ($parent_w>$w)
+ {
+ if ($HTML2PDF_TABLEAU[$param['num']]['align']=='center')
+ $x = $x + ($parent_w-$w)*0.5;
+ else if ($HTML2PDF_TABLEAU[$param['num']]['align']=='right')
+ $x = $x + $parent_w-$w;
+
+ $HTML2PDF_TABLEAU[$param['num']]['curr_x'] = $x;
+ }
+
+
+ // calcul des dimensions du tableau - hauteur du tableau sur chaque page
+ $HTML2PDF_TABLEAU[$param['num']]['height'] = array();
+
+ $h0 = $HTML2PDF_TABLEAU[$param['num']]['marge']['t'] + $HTML2PDF_TABLEAU[$param['num']]['marge']['b']; // minimum de hauteur à cause des marges
+ $h0+= $HTML2PDF_TABLEAU[$param['num']]['thead']['height'] + $HTML2PDF_TABLEAU[$param['num']]['tfoot']['height']; // et du tfoot et thead
+ $max = $this->pdf->h - $this->pdf->bMargin; // max de hauteur par page
+ $y = $HTML2PDF_TABLEAU[$param['num']]['curr_y']; // position Y actuelle
+ $height = $h0;
+
+ // on va lire les hauteurs de chaque ligne, une à une, et voir si ca rentre sur la page.
+ for($k=0; $k la hauteur sur cette page est trouvée, et on passe à la page d'apres
+ if ($y+$h+$height>$max)
+ {
+ if ($height==$h0) $height = null;
+ $HTML2PDF_TABLEAU[$param['num']]['height'][] = $height;
+ $height = $h0;
+ $y = $this->margeTop;
+ }
+ $height+= $th;
+ }
+ // rajout du reste de tableau (si il existe) à la derniere page
+ if ($height!=$h0 || $k==0) $HTML2PDF_TABLEAU[$param['num']]['height'][] = $height;
+ }
+ else
+ {
+ if (count($HTML2PDF_TABLEAU[$param['num']]['tfoot']['code']))
+ {
+ $tmp_tr = $HTML2PDF_TABLEAU[$param['num']]['tr_curr'];
+ $tmp_td = $HTML2PDF_TABLEAU[$param['num']]['td_curr'];
+ $OLD_parse_pos = $this->parse_pos;
+ $OLD_parse_code = $this->parsing->code;
+
+ $HTML2PDF_TABLEAU[$param['num']]['tr_curr'] = $HTML2PDF_TABLEAU[$param['num']]['tfoot']['tr'][0];
+ $HTML2PDF_TABLEAU[$param['num']]['td_curr'] = 0;
+ $this->parse_pos = 0;
+ $this->parsing->code = $HTML2PDF_TABLEAU[$param['num']]['tfoot']['code'];
+ $this->MakeHTMLcode();
+
+ $this->parse_pos = $OLD_parse_pos;
+ $this->parsing->code = $OLD_parse_code;
+ $HTML2PDF_TABLEAU[$param['num']]['tr_curr'] = $tmp_tr;
+ $HTML2PDF_TABLEAU[$param['num']]['td_curr'] = $tmp_td;
+ }
+
+ // determination des coordonnées de sortie du tableau
+ $x = $HTML2PDF_TABLEAU[$param['num']]['curr_x'] + $HTML2PDF_TABLEAU[$param['num']]['width'];
+ if (count($HTML2PDF_TABLEAU[$param['num']]['height'])>1)
+ $y = $this->margeTop+$HTML2PDF_TABLEAU[$param['num']]['height'][count($HTML2PDF_TABLEAU[$param['num']]['height'])-1];
+ else if (count($HTML2PDF_TABLEAU[$param['num']]['height'])==1)
+ $y = $HTML2PDF_TABLEAU[$param['num']]['curr_y']+$HTML2PDF_TABLEAU[$param['num']]['height'][count($HTML2PDF_TABLEAU[$param['num']]['height'])-1];
+ else
+ $y = $HTML2PDF_TABLEAU[$param['num']]['curr_y'];
+
+ // restauration des marges
+ $this->loadMargin();
+
+ // position de sortie du tableau
+ $this->pdf->setX($x);
+ $this->pdf->setY($y);
+ $this->maxX = max($this->maxX, $x);
+ $this->maxY = max($this->maxY, $y);
+ }
+
+ return true;
+ }
+
+ /**
+ * balise : TR
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_TR($param, $other = 'tr')
+ {
+ if ($this->forOneLine) return false;
+
+ $this->maxH = 0;
+ global $HTML2PDF_TABLEAU;
+
+ // analyse du style
+ $this->style->save();
+ $this->style->analyse($other, $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ // positionnement dans le tableau
+ $HTML2PDF_TABLEAU[$param['num']]['tr_curr']++;
+ $HTML2PDF_TABLEAU[$param['num']]['td_curr']= 0;
+
+ // si on est pas dans un sub_html
+ if (!$this->sub_part)
+ {
+ // Y courant apres la ligne
+ $ty=null;
+ for($ii=0; $ii nouvelle page
+ if (!$this->isInTfoot && $HTML2PDF_TABLEAU[$param['num']]['td_y'] + $HTML2PDF_TABLEAU[$param['num']]['marge']['b'] + $ty +$hfoot> $this->pdf->h - $this->pdf->bMargin)
+ {
+ if (count($HTML2PDF_TABLEAU[$param['num']]['tfoot']['code']))
+ {
+ $tmp_tr = $HTML2PDF_TABLEAU[$param['num']]['tr_curr'];
+ $tmp_td = $HTML2PDF_TABLEAU[$param['num']]['td_curr'];
+ $OLD_parse_pos = $this->parse_pos;
+ $OLD_parse_code = $this->parsing->code;
+
+ $HTML2PDF_TABLEAU[$param['num']]['tr_curr'] = $HTML2PDF_TABLEAU[$param['num']]['tfoot']['tr'][0];
+ $HTML2PDF_TABLEAU[$param['num']]['td_curr'] = 0;
+ $this->parse_pos = 0;
+ $this->parsing->code = $HTML2PDF_TABLEAU[$param['num']]['tfoot']['code'];
+ $this->isInTfoot = true;
+ $this->MakeHTMLcode();
+ $this->isInTfoot = false;
+
+ $this->parse_pos = $OLD_parse_pos;
+ $this->parsing->code = $OLD_parse_code;
+ $HTML2PDF_TABLEAU[$param['num']]['tr_curr'] = $tmp_tr;
+ $HTML2PDF_TABLEAU[$param['num']]['td_curr'] = $tmp_td;
+ }
+
+ $HTML2PDF_TABLEAU[$param['num']]['new_page'] = true;
+ $this->setNewPage();
+
+ $HTML2PDF_TABLEAU[$param['num']]['page']++;
+ $HTML2PDF_TABLEAU[$param['num']]['curr_y'] = $this->pdf->getY();
+ $HTML2PDF_TABLEAU[$param['num']]['td_y'] = $HTML2PDF_TABLEAU[$param['num']]['curr_y']+$HTML2PDF_TABLEAU[$param['num']]['marge']['t'];
+
+ // si la hauteur de cette partie a bien été calculée, on trace le cadre
+ if (isset($HTML2PDF_TABLEAU[$param['num']]['height'][$HTML2PDF_TABLEAU[$param['num']]['page']]))
+ {
+ $old = $this->style->value;
+ $this->style->value = $HTML2PDF_TABLEAU[$param['num']]['style_value'];
+
+ // initialisation du style des bordures de la premiere partie de tableau
+ $this->Rectangle(
+ $HTML2PDF_TABLEAU[$param['num']]['curr_x'],
+ $HTML2PDF_TABLEAU[$param['num']]['curr_y'],
+ $HTML2PDF_TABLEAU[$param['num']]['width'],
+ $HTML2PDF_TABLEAU[$param['num']]['height'][$HTML2PDF_TABLEAU[$param['num']]['page']],
+ $this->style->value['border'],
+ $this->style->value['padding'],
+ $HTML2PDF_TABLEAU[$param['num']]['cellspacing']*0.5,
+ $this->style->value['background']
+ );
+
+ $this->style->value = $old;
+ }
+ }
+
+ if ($HTML2PDF_TABLEAU[$param['num']]['new_page'] && count($HTML2PDF_TABLEAU[$param['num']]['thead']['code']))
+ {
+ $HTML2PDF_TABLEAU[$param['num']]['new_page'] = false;
+ $tmp_tr = $HTML2PDF_TABLEAU[$param['num']]['tr_curr'];
+ $tmp_td = $HTML2PDF_TABLEAU[$param['num']]['td_curr'];
+ $OLD_parse_pos = $this->parse_pos;
+ $OLD_parse_code = $this->parsing->code;
+
+ $HTML2PDF_TABLEAU[$param['num']]['tr_curr'] = $HTML2PDF_TABLEAU[$param['num']]['thead']['tr'][0];
+ $HTML2PDF_TABLEAU[$param['num']]['td_curr'] = 0;
+ $this->parse_pos = 0;
+ $this->parsing->code = $HTML2PDF_TABLEAU[$param['num']]['thead']['code'];
+ $this->MakeHTMLcode();
+
+ $this->parse_pos = $OLD_parse_pos;
+ $this->parsing->code = $OLD_parse_code;
+ $HTML2PDF_TABLEAU[$param['num']]['tr_curr'] = $tmp_tr;
+ $HTML2PDF_TABLEAU[$param['num']]['td_curr'] = $tmp_td;
+ $HTML2PDF_TABLEAU[$param['num']]['new_page'] = true;
+ }
+ }
+ else
+ {
+ $HTML2PDF_TABLEAU[$param['num']]['cases'][$HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1] = array();
+ }
+
+ return true;
+ }
+
+ /**
+ * balise : TR
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_TR($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->maxH = 0;
+ global $HTML2PDF_TABLEAU;
+
+ // restauration du style
+ $this->style->load();
+ $this->style->FontSet();
+
+ // si on est pas dans un sub_html
+ if (!$this->sub_part)
+ {
+ // Y courant apres la ligne
+ $ty=null;
+ for($ii=0; $iiforOneLine) return false;
+
+ $this->maxH = 0;
+ global $HTML2PDF_TABLEAU;
+
+ $param['cellpadding'] = $HTML2PDF_TABLEAU[$param['num']]['cellpadding'].'mm';
+ $param['cellspacing'] = $HTML2PDF_TABLEAU[$param['num']]['cellspacing'].'mm';
+
+ if ($other=='li')
+ {
+ $special_li = true;
+ }
+ else
+ {
+ $special_li = false;
+ if ($other=='li_sub')
+ {
+ $param['style']['border'] = 'none';
+ $param['style']['background-color'] = 'transparent';
+ $param['style']['background-image'] = 'none';
+ $param['style']['background-position'] = '';
+ $param['style']['background-repeat'] = '';
+ $other = 'li';
+ }
+ }
+
+ // est-on en collapse
+ $collapse = false;
+ if (in_array($other, array('td', 'th')))
+ $collapse = isset($this->style->value['border']['collapse']) ? $this->style->value['border']['collapse'] : false;
+
+
+ // analyse du style
+ $this->style->save();
+ $this->style->analyse($other, $param);
+
+ if ($special_li)
+ {
+ $this->style->value['width']-= $this->style->ConvertToMM($this->listeGetWidth());
+ $this->style->value['width']-= $this->style->ConvertToMM($this->listeGetPadding());
+ }
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ // si on est en collapse : modification du style
+ if ($collapse)
+ {
+ if (!$this->sub_part)
+ {
+ if ($HTML2PDF_TABLEAU[$param['num']]['tr_curr']>1 && !$HTML2PDF_TABLEAU[$param['num']]['new_page'])
+ $this->style->value['border']['t'] = $this->style->readBorder('none');
+ }
+
+ if ($HTML2PDF_TABLEAU[$param['num']]['td_curr']>0)
+ $this->style->value['border']['l'] = $this->style->readBorder('none');
+ }
+
+ $marge = array();
+ $marge['t'] = $this->style->value['padding']['t']+0.5*$HTML2PDF_TABLEAU[$param['num']]['cellspacing']+$this->style->value['border']['t']['width'];
+ $marge['r'] = $this->style->value['padding']['r']+0.5*$HTML2PDF_TABLEAU[$param['num']]['cellspacing']+$this->style->value['border']['r']['width'];
+ $marge['b'] = $this->style->value['padding']['b']+0.5*$HTML2PDF_TABLEAU[$param['num']]['cellspacing']+$this->style->value['border']['b']['width'];
+ $marge['l'] = $this->style->value['padding']['l']+0.5*$HTML2PDF_TABLEAU[$param['num']]['cellspacing']+$this->style->value['border']['l']['width'];
+
+ // si on est dans un sub_html
+ if ($this->sub_part)
+ {
+ // on se positionne dans le tableau
+ $HTML2PDF_TABLEAU[$param['num']]['td_curr']++;
+ $HTML2PDF_TABLEAU[$param['num']]['cases'][$HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1][$HTML2PDF_TABLEAU[$param['num']]['td_curr']-1] = array();
+ $HTML2PDF_TABLEAU[$param['num']]['cases'][$HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1][$HTML2PDF_TABLEAU[$param['num']]['td_curr']-1]['w'] = 0;
+ $HTML2PDF_TABLEAU[$param['num']]['cases'][$HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1][$HTML2PDF_TABLEAU[$param['num']]['td_curr']-1]['h'] = 0;
+ $HTML2PDF_TABLEAU[$param['num']]['cases'][$HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1][$HTML2PDF_TABLEAU[$param['num']]['td_curr']-1]['dw'] = 0;
+ $HTML2PDF_TABLEAU[$param['num']]['cases'][$HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1][$HTML2PDF_TABLEAU[$param['num']]['td_curr']-1]['colspan'] = isset($param['colspan']) ? $param['colspan'] : 1;
+ $HTML2PDF_TABLEAU[$param['num']]['cases'][$HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1][$HTML2PDF_TABLEAU[$param['num']]['td_curr']-1]['rowspan'] = isset($param['rowspan']) ? $param['rowspan'] : 1;
+
+ // on extrait tout ce qui est contenu dans le TD
+ $res = $this->parsing->getLevel($this->temp_pos);
+
+ // on en créé un sous HTML que l'on transforme en PDF
+ // pour analyse les dimensions
+ // et les récupérer dans le tableau global.
+ $this->CreateSubHTML($this->sub_html);
+ $this->sub_html->writeHTML($res[1]);
+ $this->temp_pos = $res[0]-2;
+ }
+ else
+ {
+ // on se positionne dans le tableau
+ $HTML2PDF_TABLEAU[$param['num']]['td_curr']++;
+ $HTML2PDF_TABLEAU[$param['num']]['td_x']+= $HTML2PDF_TABLEAU[$param['num']]['cases'][$HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1][$HTML2PDF_TABLEAU[$param['num']]['td_curr']-1]['dw'];
+
+ // initialisation du style des bordures de la premiere partie de tableau
+ $this->Rectangle(
+ $HTML2PDF_TABLEAU[$param['num']]['td_x'],
+ $HTML2PDF_TABLEAU[$param['num']]['td_y'],
+ $HTML2PDF_TABLEAU[$param['num']]['cases'][$HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1][$HTML2PDF_TABLEAU[$param['num']]['td_curr']-1]['w'],
+ $HTML2PDF_TABLEAU[$param['num']]['cases'][$HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1][$HTML2PDF_TABLEAU[$param['num']]['td_curr']-1]['h'],
+ $this->style->value['border'],
+ $this->style->value['padding'],
+ $HTML2PDF_TABLEAU[$param['num']]['cellspacing']*0.5,
+ $this->style->value['background']
+ );
+
+
+ $this->style->value['width'] = $HTML2PDF_TABLEAU[$param['num']]['cases'][$HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1][$HTML2PDF_TABLEAU[$param['num']]['td_curr']-1]['w'] - $marge['l'] - $marge['r'];
+
+ // limitation des marges aux dimensions de la case
+ $mL = $HTML2PDF_TABLEAU[$param['num']]['td_x']+$marge['l'];
+ $mR = $this->pdf->w - $mL - $this->style->value['width'];
+ $this->saveMargin($mL, 0, $mR);
+
+ // positionnement en fonction
+ $h_corr = $HTML2PDF_TABLEAU[$param['num']]['cases'][$HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1][$HTML2PDF_TABLEAU[$param['num']]['td_curr']-1]['h'];
+ $h_reel = $HTML2PDF_TABLEAU[$param['num']]['cases'][$HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1][$HTML2PDF_TABLEAU[$param['num']]['td_curr']-1]['real_h'];
+ switch($this->style->value['vertical-align'])
+ {
+ case 'bottom':
+ $y_corr = $h_corr-$h_reel;
+ break;
+
+ case 'middle':
+ $y_corr = ($h_corr-$h_reel)*0.5;
+ break;
+
+ case 'top':
+ default:
+ $y_corr = 0;
+ break;
+ }
+
+ $this->pdf->setX($HTML2PDF_TABLEAU[$param['num']]['td_x']+$marge['l']);
+ $this->pdf->setY($HTML2PDF_TABLEAU[$param['num']]['td_y']+$marge['t']+$y_corr);
+ $this->setNewPositionForNewLine();
+ }
+
+ return true;
+ }
+
+ /**
+ * balise : TD
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_TD($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->maxH = 0;
+ global $HTML2PDF_TABLEAU;
+
+ // récupération de la marge
+ $marge = array();
+ $marge['t'] = $this->style->value['padding']['t']+0.5*$HTML2PDF_TABLEAU[$param['num']]['cellspacing']+$this->style->value['border']['t']['width'];
+ $marge['r'] = $this->style->value['padding']['r']+0.5*$HTML2PDF_TABLEAU[$param['num']]['cellspacing']+$this->style->value['border']['r']['width'];
+ $marge['b'] = $this->style->value['padding']['b']+0.5*$HTML2PDF_TABLEAU[$param['num']]['cellspacing']+$this->style->value['border']['b']['width'];
+ $marge['l'] = $this->style->value['padding']['l']+0.5*$HTML2PDF_TABLEAU[$param['num']]['cellspacing']+$this->style->value['border']['l']['width'];
+ $marge['t']+= 0.01;
+ $marge['r']+= 0.01;
+ $marge['b']+= 0.01;
+ $marge['l']+= 0.01;
+
+ // si on est dans un sub_html
+ if ($this->sub_part)
+ {
+ if ($this->testTDin1page && $this->sub_html->pdf->page>1) HTML2PDF::makeError(7, __FILE__, __LINE__);
+
+ // dimentions de cette case
+ $w0 = $this->sub_html->maxX + $marge['l'] + $marge['r'];
+ $h0 = $this->sub_html->maxY + $marge['t'] + $marge['b'];
+
+ // dimensions imposées par le style
+ $w2 = $this->style->value['width'] + $marge['l'] + $marge['r'];
+ $h2 = $this->style->value['height'] + $marge['t'] + $marge['b'];
+
+ // dimension finale de la case = max des 2 ci-dessus
+ $HTML2PDF_TABLEAU[$param['num']]['cases'][$HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1][$HTML2PDF_TABLEAU[$param['num']]['td_curr']-1]['w'] = max(array($w0, $w2));
+ $HTML2PDF_TABLEAU[$param['num']]['cases'][$HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1][$HTML2PDF_TABLEAU[$param['num']]['td_curr']-1]['h'] = max(array($h0, $h2));
+
+ $HTML2PDF_TABLEAU[$param['num']]['cases'][$HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1][$HTML2PDF_TABLEAU[$param['num']]['td_curr']-1]['real_w'] = $w0;
+ $HTML2PDF_TABLEAU[$param['num']]['cases'][$HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1][$HTML2PDF_TABLEAU[$param['num']]['td_curr']-1]['real_h'] = $h0;
+
+ // suppresion du sous_html
+ $this->DestroySubHTML();
+ }
+ else
+ {
+ $this->loadMargin();
+ //positionnement
+ $HTML2PDF_TABLEAU[$param['num']]['td_x']+= $HTML2PDF_TABLEAU[$param['num']]['cases'][$HTML2PDF_TABLEAU[$param['num']]['tr_curr']-1][$HTML2PDF_TABLEAU[$param['num']]['td_curr']-1]['w'];
+ }
+
+ // restauration du style
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ function calculTailleCases(&$cases)
+ {
+ // construction d'un tableau de correlation
+ $corr = array();
+
+ // on fait correspondre chaque case d'un tableau normé aux cases réelles, en prennant en compte les colspan et rowspan
+ $Yr=0;
+ for($y=0; $y0) ? '' : array($x, $y, $cases[$y][$x]['colspan'], $cases[$y][$x]['rowspan']);
+ }
+ }
+ $Xr+= $cases[$y][$x]['colspan'];
+ while(isset($corr[$Yr][$Xr])) $Xr++;
+ }
+ $Yr++;
+ }
+
+ if (!isset($corr[0])) return true;
+
+ // on détermine, pour les cases sans colspan, la largeur maximale de chaque colone
+ $sw = array();
+ for($x=0; $x1)
+ {
+ // somme des colonnes correspondant au colspan
+ $s = 0; for($i=0; $i<$corr[$y][$x][2]; $i++) $s+= $sw[$x+$i];
+
+ // si la somme est inférieure à la taille necessaire => règle de 3 pour adapter
+ if ($s>0 && $s<$cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['w'])
+ for($i=0; $i<$corr[$y][$x][2]; $i++)
+ $sw[$x+$i] = $sw[$x+$i]/$s*$cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['w'];
+ }
+ }
+ }
+
+ // on applique les nouvelles largeurs
+ for($x=0; $x1)
+ {
+ // somme des colonnes correspondant au colspan
+ $s = 0; for($i=0; $i<$corr[$y][$x][3]; $i++) $s+= $sh[$y+$i];
+
+ // si la somme est inférieure à la taille necessaire => règle de 3 pour adapter
+ if ($s>0 && $s<$cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['h'])
+ for($i=0; $i<$corr[$y][$x][3]; $i++)
+ $sh[$y+$i] = $sh[$y+$i]/$s*$cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['h'];
+ }
+ }
+ }
+
+
+ // on applique les nouvelles hauteurs
+ for($y=0; $yforOneLine) return false;
+
+ $this->maxH = 0;
+ // identique à TD mais en gras
+ if (!isset($param['style']['font-weight'])) $param['style']['font-weight'] = 'bold';
+ $this->o_TD($param, 'th');
+
+ return true;
+ }
+
+ /**
+ * balise : TH
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_TH($param)
+ {
+ if ($this->forOneLine) return false;
+
+ $this->maxH = 0;
+ // identique à TD
+ $this->c_TD($param);
+
+ return true;
+ }
+
+ /**
+ * balise : IMG
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_IMG($param)
+ {
+ // analyse du style
+ $src = str_replace('&', '&', $param['src']);
+
+ $this->style->save();
+ $this->style->value['width'] = 0;
+ $this->style->value['height'] = 0;
+ $this->style->value['border'] = array(
+ 'type' => 'none',
+ 'width' => 0,
+ 'color' => array(0, 0, 0),
+ );
+ $this->style->value['background'] = array(
+ 'color' => null,
+ 'image' => null,
+ 'position' => null,
+ 'repeat' => null
+ );
+ $this->style->analyse('img', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ // affichage de l'image
+ $this->Image($src, isset($param['sub_li']));
+
+ // restauration du style
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : SELECT
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_SELECT($param)
+ {
+ // preparation du champs
+ if (!isset($param['name'])) $param['name'] = 'champs_pdf_'.(count($this->lstChamps)+1);
+
+ $param['name'] = strtolower($param['name']);
+
+ if (isset($this->champs[$param['name']]))
+ $this->champs[$param['name']]++;
+ else
+ $this->champs[$param['name']] = 1;
+
+ $this->style->save();
+ $this->style->analyse('select', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ $this->lstSelect = array();
+ $this->lstSelect['name'] = $param['name'];
+ $this->lstSelect['multi'] = isset($param['multiple']) ? true : false;
+ $this->lstSelect['size'] = isset($param['size']) ? $param['size'] : 1;
+ $this->lstSelect['options'] = array();
+
+ if ($this->lstSelect['multi'] && $this->lstSelect['size']<3) $this->lstSelect['size'] = 3;
+
+ return true;
+ }
+
+ /**
+ * balise : OPTION
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_OPTION($param)
+ {
+ // on extrait tout ce qui est contenu dans l'option
+ $res = $this->parsing->getLevel($this->parse_pos);
+ $this->parse_pos = $res[0]-2;
+ $texte = $res[1];
+ $value = isset($param['value']) ? $param['value'] : 'auto_opt_'.(count($this->lstSelect)+1);
+
+ $this->lstSelect['options'][$value] = $texte;
+
+ return true;
+ }
+
+ /**
+ * balise : OPTION
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_OPTION($param) { return true; }
+
+ /**
+ * balise : SELECT
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_SELECT()
+ {
+ // position d'affichage
+ $x = $this->pdf->getX();
+ $y = $this->pdf->getY();
+ $f = 1.08*$this->style->value['font-size'];
+
+ $w = $this->style->value['width']; if (!$w) $w = 50;
+ $h = ($f*1.07*$this->lstSelect['size'] + 1);
+ $prop = array();
+ if ($this->lstSelect['multi']) $prop['multipleSelection'] = true;
+ $this->pdf->form_Select($this->lstSelect['name'], $x, $y, $w, $h, $this->lstSelect['options'], $this->lstSelect['size']>1, $prop);
+
+ $this->maxX = max($this->maxX, $x+$w);
+ $this->maxY = max($this->maxY, $y+$h);
+ $this->maxH = max($this->maxH, $h);
+ $this->pdf->setX($x+$w);
+
+ $this->style->load();
+ $this->style->FontSet();
+
+ $this->lstSelect = array();
+
+ return true;
+ }
+
+ /**
+ * balise : TEXTAREA
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_TEXTAREA($param)
+ {
+ // preparation du champs
+ if (!isset($param['name'])) $param['name'] = 'champs_pdf_'.(count($this->lstChamps)+1);
+
+ $param['name'] = strtolower($param['name']);
+
+ if (isset($this->champs[$param['name']]))
+ $this->champs[$param['name']]++;
+ else
+ $this->champs[$param['name']] = 1;
+
+ $this->style->save();
+ $this->style->analyse('textarea', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ // position d'affichage
+ $x = $this->pdf->getX();
+ $y = $this->pdf->getY();
+ $fx = 0.65*$this->style->value['font-size'];
+ $fy = 1.08*$this->style->value['font-size'];
+
+ // on extrait tout ce qui est contenu dans le textarea
+ $res = $this->parsing->getLevel($this->parse_pos);
+ $this->parse_pos = $res[0]-2;
+ $texte = $res[1];
+
+ $w = $fx*(isset($param['cols']) ? $param['cols'] : 22)+1;
+ $h = $fy*1.07*(isset($param['rows']) ? $param['rows'] : 3)+3;
+
+// if ($this->style->value['width']) $w = $this->style->value['width'];
+// if ($this->style->value['height']) $h = $this->style->value['height'];
+
+ $prop = array();
+ $prop['value'] = $texte;
+ $prop['multiline'] = true;
+
+ $this->pdf->form_InputText($param['name'], $x, $y, $w, $h, $prop);
+
+ $this->maxX = max($this->maxX, $x+$w);
+ $this->maxY = max($this->maxY, $y+$h);
+ $this->maxH = max($this->maxH, $h);
+ $this->pdf->setX($x+$w);
+
+ return true;
+ }
+
+ /**
+ * balise : TEXTAREA
+ * mode : FERMETURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function c_TEXTAREA()
+ {
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ /**
+ * balise : INPUT
+ * mode : OUVERTURE
+ *
+ * @param array paramètres de l'élément de parsing
+ * @return null
+ */
+ function o_INPUT($param)
+ {
+ // preparation du champs
+ if (!isset($param['name'])) $param['name'] = 'champs_pdf_'.(count($this->lstChamps)+1);
+ if (!isset($param['value'])) $param['value'] = '';
+ if (!isset($param['type'])) $param['type'] = 'text';
+
+ $param['name'] = strtolower($param['name']);
+ $param['type'] = strtolower($param['type']);
+
+ if (!in_array($param['type'], array('text', 'checkbox', 'radio', 'hidden', 'submit', 'reset', 'button'))) $param['type'] = 'text';
+
+ if (isset($this->champs[$param['name']]))
+ $this->champs[$param['name']]++;
+ else
+ $this->champs[$param['name']] = 1;
+
+ $this->style->save();
+ $this->style->analyse('input', $param);
+ $this->style->setPosition($this->pdf->x, $this->pdf->y);
+ $this->style->FontSet();
+
+ $name = $param['name'];
+
+ // position d'affichage
+ $x = $this->pdf->getX();
+ $y = $this->pdf->getY();
+ $f = 1.08*$this->style->value['font-size'];
+
+ switch($param['type'])
+ {
+ case 'checkbox':
+ $w = 3;
+ $h = $w;
+ if ($h<$f) $y+= ($f-$h)*0.5;
+ $this->pdf->form_InputCheckBox($name, $x, $y, $w, isset($param['checked']));
+ break;
+
+ case 'radio':
+ $w = 3;
+ $h = $w;
+ if ($h<$f) $y+= ($f-$h)*0.5;
+ $this->pdf->form_InputRadio($name, $x, $y, $w);
+ break;
+
+ case 'hidden':
+ $w = 0;
+ $h = 0;
+ $this->pdf->form_InputHidden($name, $param['value']);
+ break;
+
+ case 'text':
+ $w = $this->style->value['width']; if (!$w) $w = 40;
+ $h = $f*1.3;
+ $prop = array();
+ $prop['value'] = $param['value'];
+ $this->pdf->form_InputText($name, $x, $y, $w, $h, $prop);
+ break;
+
+ case 'submit':
+ case 'reset':
+ case 'button':
+ $action = isset($param['onclick']) ? $param['onclick'] : '';
+ $w = $this->style->value['width']; if (!$w) $w = 40;
+ $h = $this->style->value['height']; if (!$h) $h = $f*1.3;
+ $prop = array();
+ $this->pdf->form_InputButton($name, $x, $y, $w, $h, $param['value'], $action, $prop);
+ break;
+
+ default:
+ $w = 0;
+ $h = 0;
+ break;
+ }
+
+ $this->maxX = max($this->maxX, $x+$w);
+ $this->maxY = max($this->maxY, $y+$h);
+ $this->maxH = max($this->maxH, $h);
+ $this->pdf->setX($x+$w);
+
+ $this->style->load();
+ $this->style->FontSet();
+
+ return true;
+ }
+
+ function textLOAD($langue)
+ {
+ if (!preg_match('/^([a-z0-9]+)$/isU', $langue))
+ {
+ echo 'ERROR : language code '.$langue.' incorrect.';
+ exit;
+ }
+
+ $file = dirname(__FILE__).'/langues/'.strtolower($langue).'.txt';
+ if (!is_file($file))
+ {
+ echo 'ERROR : language code '.$langue.' unknown. ';
+ echo 'You can create the translation file '.$file.' and send it to me in order to integrate it into a future version.';
+ exit;
+ }
+
+ $texte = array();
+ $infos = file($file);
+ foreach($infos as $val)
+ {
+ $val = trim($val);
+ $val = explode("\t", $val);
+ if (count($val)<2) continue;
+
+ $t_k = trim($val[0]); unset($val[0]);
+ $t_v = trim(implode(' ', $val));
+ if ($t_k && $t_v) $texte[$t_k] = $t_v;
+ }
+ global $HTML2PDF_TEXTE_FILE;
+ $HTML2PDF_TEXTE_FILE = $texte;
+ }
+
+ function textGET($key)
+ {
+ global $HTML2PDF_TEXTE_FILE;
+ if (!isset($HTML2PDF_TEXTE_FILE[$key])) return '######';
+
+ return $HTML2PDF_TEXTE_FILE[$key];
+ }
+
+ function makeError($err, $file, $line, $other = null)
+ {
+ $msg = '';
+ switch($err)
+ {
+ case 1:
+ $msg = (HTML2PDF::textGET('err01'));
+ $msg = str_replace('[[OTHER]]', $other, $msg);
+ break;
+
+ case 2:
+ $msg = (HTML2PDF::textGET('err02'));
+ $msg = str_replace('[[OTHER_0]]', $other[0], $msg);
+ $msg = str_replace('[[OTHER_1]]', $other[1], $msg);
+ $msg = str_replace('[[OTHER_2]]', $other[2], $msg);
+ break;
+
+ case 3:
+ $msg = (HTML2PDF::textGET('err03'));
+ $msg = str_replace('[[OTHER]]', $other, $msg);
+ break;
+
+ case 4:
+ $msg = (HTML2PDF::textGET('err04'));
+ $msg = str_replace('[[OTHER]]', print_r($other, true), $msg);
+ break;
+
+ case 5:
+ $msg = (HTML2PDF::textGET('err05'));
+ $msg = str_replace('[[OTHER]]', print_r($other, true), $msg);
+ break;
+
+ case 6:
+ $msg = (HTML2PDF::textGET('err06'));
+ $msg = str_replace('[[OTHER]]', $other, $msg);
+ break;
+
+ case 7:
+ $msg = (HTML2PDF::textGET('err07'));
+ break;
+ }
+ echo ''.(HTML2PDF::textGET('txt01')).$err.' ';
+ echo (HTML2PDF::textGET('txt02')).' '.$file.' ';
+ echo (HTML2PDF::textGET('txt03')).' '.$line.' ';
+ echo ' ';
+ echo $msg;
+ exit;
+ }
+ }
+}
+
diff --git a/main/inc/lib/html2pdf/parsingHTML.class.php b/main/inc/lib/html2pdf/parsingHTML.class.php
new file mode 100644
index 0000000000..3f0274505c
--- /dev/null
+++ b/main/inc/lib/html2pdf/parsingHTML.class.php
@@ -0,0 +1,421 @@
+ PDF, utilise fpdf de Olivier PLATHEY
+ * Distribué sous la licence LGPL.
+ *
+ * @author Laurent MINGUET
+ * @version 3.22a - 15/06/2009
+ */
+
+if (!defined('__CLASS_PARSINGHTML__'))
+{
+ define('__CLASS_PARSINGHTML__', true);
+
+ class parsingHTML
+ {
+ var $html = ''; // code HTML à parser
+ var $code = array(); // code HTML parsé
+ var $num = 0; // numéro de table
+ var $level = 0; // niveaux de table
+
+ /**
+ * Constructeur
+ *
+ * @return null
+ */
+ function parsingHTML()
+ {
+ $this->num = 0;
+ $this->level = array($this->num);
+ $this->html = '';
+ $this->code = array();
+ }
+
+ /**
+ * Définir le code HTML à parser
+ *
+ * @param string code html
+ * @return null
+ */
+ function setHTML($html)
+ {
+ $html = preg_replace('//isU', '', $html);
+ $this->html = $html;
+ }
+
+ /**
+ * parser le code HTML
+ *
+ * @return null
+ */
+ function parse()
+ {
+ $parents = array();
+ // récupérer le code à parser
+ $content = $this->html;
+
+ // chercher les balises HTML du code
+ $tmp = array();
+ $this->searchCode($content, $tmp);
+
+ // identifier les balises une à une
+ $pre_in = false;
+ $pre_br = array(
+ 'name' => 'br',
+ 'close' => false,
+ 'param' => array(
+ 'style' => array(),
+ 'num' => 0
+ )
+ );
+
+ $todos = array();
+ foreach($tmp as $part)
+ {
+ // si c'est un texte
+ if ($part[0]=='txt')
+ {
+ // enregistrer l'action correspondante
+ if (!$pre_in)
+ {
+ if (trim($part[1])!=='')
+ {
+ // remplacer tous les espaces, tabulations, saufs de ligne multiples par de simples espaces
+ $part[1] = preg_replace('/([\s]+)/is', ' ', $part[1]);
+
+ $todos[] = array(
+ 'name' => 'write',
+ 'close' => false,
+ 'param' => array('txt' => $part[1]),
+ );
+ }
+ }
+ else
+ {
+ $part[1] = str_replace("\r", '', $part[1]);
+ $part[1] = explode("\n", $part[1]);
+
+ foreach($part[1] as $k => $txt)
+ {
+ $txt = str_replace("\t", ' ', $txt);
+ $txt = str_replace(' ', ' ', $txt);
+ if ($k>0) $todos[] = $pre_br;
+
+ $todos[] = array(
+ 'name' => 'write',
+ 'close' => false,
+ 'param' => array('txt' => $txt),
+ );
+ }
+ }
+ }
+ // sinon, analyser le code
+ else
+ {
+ $res = $this->analiseCode($part[1]);
+ if ($res)
+ {
+ if (!in_array($res['name'], array('br', 'hr', 'img', 'input', 'link', 'option')))
+ {
+ if ($res['close'])
+ {
+ if (count($parents)<1)
+ HTML2PDF::makeError(3, __FILE__, __LINE__, $res['name']);
+ else if ($parents[count($parents)-1]!=$res['name'])
+ HTML2PDF::makeError(4, __FILE__, __LINE__, $parents);
+ else
+ unset($parents[count($parents)-1]);
+ }
+ else
+ {
+ $parents[count($parents)] = $res['name'];
+ }
+ }
+ if ($res['name']=='pre' || $res['name']=='code')
+ {
+ $pre_in = !$res['close'];
+ }
+ $todos[] = $res;
+ }
+ }
+ }
+
+ // pour chaque action identifiée, il faut nettoyer le début et la fin des textes
+ // en fonction des balises qui l'entourent.
+ $nb = count($todos);
+ for($k=0; $k<$nb; $k++)
+ {
+ //si c'est un texte
+ if ($todos[$k]['name']=='write')
+ {
+ // et qu'une balise spécifique le précède => on nettoye les espaces du début du texte
+ if ($k>0 && in_array($todos[$k-1]['name'], array('table', 'tr', 'td', 'th', 'br', 'div', 'hr', 'p', 'ul', 'ol', 'li')))
+ $todos[$k]['param']['txt'] = preg_replace('/^([\s]*)([^\s])/isU', '$2', $todos[$k]['param']['txt']);
+
+ // et qu'une balise spécifique le suit => on nettoye les espaces de la fin du texte
+ if ($kcode = $todos;
+ }
+
+ /**
+ * parser le code HTML
+ *
+ * @param string contenu à parser.
+ * @param &array tableau de retour des données
+ * @return null
+ */
+ function searchCode($content, &$tmp)
+ {
+ // séparer les balises du texte
+ $tmp = array();
+ $reg = '/(<[^>]+>)|([^<]+)+/isU';
+
+ // pour chaque élément trouvé :
+ $str = '';
+ $offset = 0;
+ while(preg_match($reg, $content, $parse, PREG_OFFSET_CAPTURE, $offset))
+ {
+ // si une balise a été détectée
+ if ($parse[1][0])
+ {
+ // sauvegarde du texte précédent si il existe
+ if ($str!=='') $tmp[] = array('txt',$str);
+
+ // sauvegarde de la balise
+ $tmp[] = array('code',trim($parse[1][0]));
+
+ // initialisation du texte suivant
+ $str = '';
+ }
+ else
+ {
+ // ajout du texte à la fin de celui qui est déjà détecté
+ $str.= $parse[2][0];
+ }
+ // Update offset to the end of the match
+ $offset = $parse[0][1] + strlen($parse[0][0]);
+ unset($parse);
+ }
+ // si un texte est présent à la fin, on l'enregistre
+ if ($str!='') $tmp[] = array('txt',$str);
+ unset($str);
+ }
+
+ /**
+ * analyse une balise HTML
+ *
+ * @param string code HTML à identifier
+ * @return array action correspondante
+ */
+ function analiseCode($code)
+ {
+ // nom de la balise et ouverture ou fermeture
+ $balise = '<([\/]{0,1})([_a-z0-9]+)([\/>\s]+)';
+ preg_match('/'.$balise.'/isU', $code, $match);
+ $close = ($match[1]=='/' ? true : false);
+ $name = strtolower($match[2]);
+
+ // paramètres obligatoires en fonction du nom de la balise
+ $param = array();
+ $param['style'] = '';
+ if ($name=='img') { $param['alt'] = ''; $param['src'] = ''; }
+ if ($name=='a') { $param['href'] = ''; }
+
+ // lecture des paramétres du type nom=valeur
+ $prop = '([a-zA-Z0-9_]+)=([^"\'\s>]+)';
+ preg_match_all('/'.$prop.'/is', $code, $match);
+ for($k=0; $k $val)
+ {
+ $key = strtolower($key);
+ switch($key)
+ {
+ case 'width':
+ unset($param[$key]);
+ $param['style'] = 'width: '.$val.'px; '.$param['style'];
+ break;
+
+ case 'align':
+ if ($name!=='table')
+ {
+ unset($param[$key]);
+ $param['style'] = 'text-align: '.$val.'; '.$param['style'];
+ }
+ break;
+
+ case 'valign':
+ unset($param[$key]);
+ $param['style'] = 'vertical-align: '.$val.'; '.$param['style'];
+ break;
+
+ case 'height':
+ unset($param[$key]);
+ $param['style'] = 'height: '.$val.'px; '.$param['style'];
+ break;
+
+ case 'bgcolor':
+ unset($param[$key]);
+ $param['style'] = 'background: '.$val.'; '.$param['style'];
+ break;
+
+ case 'bordercolor':
+ unset($param[$key]);
+ $color = $val;
+ break;
+
+ case 'border':
+ unset($param[$key]);
+ if (preg_match('/^[0-9]$/isU', $val)) $val = $val.'px';
+ $border = $val;
+ break;
+
+ case 'cellpadding':
+ case 'cellspacing':
+ if (preg_match('/^([0-9]+)$/isU', $val)) $param[$key] = $val.'px';
+ break;
+
+ case 'colspan':
+ case 'rowspan':
+ $val = preg_replace('/[^0-9]/isU', '', $val);
+ if (!$val) $val = 1;
+ $param[$key] = $val;
+ break;
+ }
+ }
+ if ($border!==null)
+ {
+ if ($border) $param['style'] = 'border: solid '.$border.' '.$color.'; '.$param['style'];
+ else $param['style'] = 'border: none';
+ }
+
+ // lecture des styles - décomposition
+ $styles = explode(';', $param['style']);
+ $param['style'] = array();
+ foreach($styles as $style)
+ {
+ $tmp = explode(':', $style);
+ if (count($tmp)>1)
+ {
+ $cod = $tmp[0]; unset($tmp[0]); $tmp = implode(':', $tmp);
+ $param['style'][trim(strtolower($cod))] = preg_replace('/[\s]+/isU', ' ', trim($tmp));
+ }
+ }
+
+ // détermination du niveau de table pour les ouverture, avec ajout d'un level
+ if (in_array($name, array('ul', 'ol', 'table')) && !$close)
+ {
+ $this->num++;
+ $this->level[count($this->level)] = $this->num;
+ }
+
+ // attribution du niveau de table où se trouve l'élément
+ if (!isset($param['num'])) $param['num'] = $this->level[count($this->level)-1];
+
+ // pour les fins de table : suppression d'un level
+ if (in_array($name, array('ul', 'ol', 'table')) && $close)
+ {
+ unset($this->level[count($this->level)-1]);
+ }
+
+ // retour de l'action identifiée
+ return array('name' => $name, 'close' => $close ? 1 : 0, 'param' => $param);
+ }
+
+ // récupérer un niveau complet d'HTML entre une ouverture de balise et la fermeture correspondante
+ function getLevel($k)
+ {
+ // si le code n'existe pas : fin
+ if (!isset($this->code[$k])) return '';
+
+ // quelle balise faudra-t-il détecter
+ $detect = $this->code[$k]['name'];
+
+ $level = 0; // niveau de profondeur
+ $end = false; // etat de fin de recherche
+ $code = ''; // code extrait
+
+ // tant que c'est pas fini, on boucle
+ while (!$end)
+ {
+ // action courante
+ $row = $this->code[$k];
+
+ // si write => on ajoute le texte
+ if ($row['name']=='write')
+ {
+ $code.= $row['param']['txt'];
+ }
+ // sinon, c'est une balise html
+ else
+ {
+ $not = false; // indicateur de non prise en compte de la balise courante
+
+ // si c'est la balise que l'on cherche
+ if ($row['name']==$detect)
+ {
+ if ($level==0) { $not = true; } // si on est à la premiere balise : on l'ignore
+ $level+= ($row['close'] ? -1 : 1); // modification du niveau en cours en fonction de l'ouvertre / fermeture
+ if ($level==0) { $not = true; $end = true; } // si on est au niveau 0 : on a fini
+ }
+
+ // si on doit prendre en compte la balise courante
+ if (!$not)
+ {
+ // ecriture du code HTML de la balise
+ $code.= '<'.($row['close'] ? '/' : '').$row['name'];
+ foreach($row['param'] as $key => $val)
+ {
+ if ($key=='style')
+ {
+ $tmp = '';
+ if (isset($val['text-align'])) unset($val['text-align']);
+ foreach($val as $ks => $vs) $tmp.= $ks.':'.$vs.'; ';
+ if (trim($tmp)) $code.= ' '.$key.'="'.$tmp.'"';
+ }
+ else
+ {
+ $code.= ' '.$key.'="'.$val.'"';
+ }
+ }
+ $code.= '>';
+ }
+ }
+
+ // on continue tant qu'il y a du code à analyser...
+ if (isset($this->code[$k+1]))
+ $k++;
+ else
+ $end = true;
+ }
+
+ // retourne la position finale et le code HTML extrait
+ return array($k, $code);
+ }
+ }
+}
+?>
\ No newline at end of file
diff --git a/main/inc/lib/html2pdf/styleHTML.class.php b/main/inc/lib/html2pdf/styleHTML.class.php
new file mode 100644
index 0000000000..272e6c436d
--- /dev/null
+++ b/main/inc/lib/html2pdf/styleHTML.class.php
@@ -0,0 +1,1440 @@
+ PDF, utilise fpdf de Olivier PLATHEY
+ * Distribué sous la licence LGPL.
+ *
+ * @author Laurent MINGUET
+ * @version 3.22a - 15/06/2009
+ */
+
+if (!defined('__CLASS_STYLEHTML__'))
+{
+ define('__CLASS_STYLEHTML__', true);
+
+ class styleHTML
+ {
+ var $css = array(); // tableau des CSS
+ var $css_keys = array(); // tableau des clefs CSS, pour l'ordre d'execution
+ var $value = array(); // valeurs actuelles
+ var $table = array(); // tableau d'empilement pour historisation des niveaux
+ var $pdf = null; // référence au PDF parent
+ var $htmlColor = array(); // liste des couleurs HTML
+ var $onlyLeft = false; // indique si on est dans un sous HTML et qu'on bloque à gauche
+
+ /**
+ * Constructeur
+ *
+ * @param &pdf référence à l'objet HTML2PDF parent
+ * @return null
+ */
+ function styleHTML(&$pdf)
+ {
+ $this->init(); // initialisation
+ $this->pdf = &$pdf;
+ }
+
+ /**
+ * Initialisation du style
+ *
+ * @return null
+ */
+ function init()
+ {
+ $color = array();
+ $color['AliceBlue'] = '#F0F8FF';
+ $color['AntiqueWhite'] = '#FAEBD7';
+ $color['Aqua'] = '#00FFFF';
+ $color['Aquamarine'] = '#7FFFD4';
+ $color['Azure'] = '#F0FFFF';
+ $color['Beige'] = '#F5F5DC';
+ $color['Bisque'] = '#FFE4C4';
+ $color['Black'] = '#000000';
+ $color['BlanchedAlmond'] = '#FFEBCD';
+ $color['Blue'] = '#0000FF';
+ $color['BlueViolet'] = '#8A2BE2';
+ $color['Brown'] = '#A52A2A';
+ $color['BurlyWood'] = '#DEB887';
+ $color['CadetBlue'] = '#5F9EA0';
+ $color['Chartreuse'] = '#7FFF00';
+ $color['Chocolate'] = '#D2691E';
+ $color['Coral'] = '#FF7F50';
+ $color['CornflowerBlue'] = '#6495ED';
+ $color['Cornsilk'] = '#FFF8DC';
+ $color['Crimson'] = '#DC143C';
+ $color['Cyan'] = '#00FFFF';
+ $color['DarkBlue'] = '#00008B';
+ $color['DarkCyan'] = '#008B8B';
+ $color['DarkGoldenRod'] = '#B8860B';
+ $color['DarkGray'] = '#A9A9A9';
+ $color['DarkGrey'] = '#A9A9A9';
+ $color['DarkGreen'] = '#006400';
+ $color['DarkKhaki'] = '#BDB76B';
+ $color['DarkMagenta'] = '#8B008B';
+ $color['DarkOliveGreen'] = '#556B2F';
+ $color['Darkorange'] = '#FF8C00';
+ $color['DarkOrchid'] = '#9932CC';
+ $color['DarkRed'] = '#8B0000';
+ $color['DarkSalmon'] = '#E9967A';
+ $color['DarkSeaGreen'] = '#8FBC8F';
+ $color['DarkSlateBlue'] = '#483D8B';
+ $color['DarkSlateGray'] = '#2F4F4F';
+ $color['DarkSlateGrey'] = '#2F4F4F';
+ $color['DarkTurquoise'] = '#00CED1';
+ $color['DarkViolet'] = '#9400D3';
+ $color['DeepPink'] = '#FF1493';
+ $color['DeepSkyBlue'] = '#00BFFF';
+ $color['DimGray'] = '#696969';
+ $color['DimGrey'] = '#696969';
+ $color['DodgerBlue'] = '#1E90FF';
+ $color['FireBrick'] = '#B22222';
+ $color['FloralWhite'] = '#FFFAF0';
+ $color['ForestGreen'] = '#228B22';
+ $color['Fuchsia'] = '#FF00FF';
+ $color['Gainsboro'] = '#DCDCDC';
+ $color['GhostWhite'] = '#F8F8FF';
+ $color['Gold'] = '#FFD700';
+ $color['GoldenRod'] = '#DAA520';
+ $color['Gray'] = '#808080';
+ $color['Grey'] = '#808080';
+ $color['Green'] = '#008000';
+ $color['GreenYellow'] = '#ADFF2F';
+ $color['HoneyDew'] = '#F0FFF0';
+ $color['HotPink'] = '#FF69B4';
+ $color['IndianRed'] = '#CD5C5C';
+ $color['Indigo'] = '#4B0082';
+ $color['Ivory'] = '#FFFFF0';
+ $color['Khaki'] = '#F0E68C';
+ $color['Lavender'] = '#E6E6FA';
+ $color['LavenderBlush'] = '#FFF0F5';
+ $color['LawnGreen'] = '#7CFC00';
+ $color['LemonChiffon'] = '#FFFACD';
+ $color['LightBlue'] = '#ADD8E6';
+ $color['LightCoral'] = '#F08080';
+ $color['LightCyan'] = '#E0FFFF';
+ $color['LightGoldenRodYellow'] = '#FAFAD2';
+ $color['LightGray'] = '#D3D3D3';
+ $color['LightGrey'] = '#D3D3D3';
+ $color['LightGreen'] = '#90EE90';
+ $color['LightPink'] = '#FFB6C1';
+ $color['LightSalmon'] = '#FFA07A';
+ $color['LightSeaGreen'] = '#20B2AA';
+ $color['LightSkyBlue'] = '#87CEFA';
+ $color['LightSlateGray'] = '#778899';
+ $color['LightSlateGrey'] = '#778899';
+ $color['LightSteelBlue'] = '#B0C4DE';
+ $color['LightYellow'] = '#FFFFE0';
+ $color['Lime'] = '#00FF00';
+ $color['LimeGreen'] = '#32CD32';
+ $color['Linen'] = '#FAF0E6';
+ $color['Magenta'] = '#FF00FF';
+ $color['Maroon'] = '#800000';
+ $color['MediumAquaMarine'] = '#66CDAA';
+ $color['MediumBlue'] = '#0000CD';
+ $color['MediumOrchid'] = '#BA55D3';
+ $color['MediumPurple'] = '#9370D8';
+ $color['MediumSeaGreen'] = '#3CB371';
+ $color['MediumSlateBlue'] = '#7B68EE';
+ $color['MediumSpringGreen'] = '#00FA9A';
+ $color['MediumTurquoise'] = '#48D1CC';
+ $color['MediumVioletRed'] = '#C71585';
+ $color['MidnightBlue'] = '#191970';
+ $color['MintCream'] = '#F5FFFA';
+ $color['MistyRose'] = '#FFE4E1';
+ $color['Moccasin'] = '#FFE4B5';
+ $color['NavajoWhite'] = '#FFDEAD';
+ $color['Navy'] = '#000080';
+ $color['OldLace'] = '#FDF5E6';
+ $color['Olive'] = '#808000';
+ $color['OliveDrab'] = '#6B8E23';
+ $color['Orange'] = '#FFA500';
+ $color['OrangeRed'] = '#FF4500';
+ $color['Orchid'] = '#DA70D6';
+ $color['PaleGoldenRod'] = '#EEE8AA';
+ $color['PaleGreen'] = '#98FB98';
+ $color['PaleTurquoise'] = '#AFEEEE';
+ $color['PaleVioletRed'] = '#D87093';
+ $color['PapayaWhip'] = '#FFEFD5';
+ $color['PeachPuff'] = '#FFDAB9';
+ $color['Peru'] = '#CD853F';
+ $color['Pink'] = '#FFC0CB';
+ $color['Plum'] = '#DDA0DD';
+ $color['PowderBlue'] = '#B0E0E6';
+ $color['Purple'] = '#800080';
+ $color['Red'] = '#FF0000';
+ $color['RosyBrown'] = '#BC8F8F';
+ $color['RoyalBlue'] = '#4169E1';
+ $color['SaddleBrown'] = '#8B4513';
+ $color['Salmon'] = '#FA8072';
+ $color['SandyBrown'] = '#F4A460';
+ $color['SeaGreen'] = '#2E8B57';
+ $color['SeaShell'] = '#FFF5EE';
+ $color['Sienna'] = '#A0522D';
+ $color['Silver'] = '#C0C0C0';
+ $color['SkyBlue'] = '#87CEEB';
+ $color['SlateBlue'] = '#6A5ACD';
+ $color['SlateGray'] = '#708090';
+ $color['SlateGrey'] = '#708090';
+ $color['Snow'] = '#FFFAFA';
+ $color['SpringGreen'] = '#00FF7F';
+ $color['SteelBlue'] = '#4682B4';
+ $color['Tan'] = '#D2B48C';
+ $color['Teal'] = '#008080';
+ $color['Thistle'] = '#D8BFD8';
+ $color['Tomato'] = '#FF6347';
+ $color['Turquoise'] = '#40E0D0';
+ $color['Violet'] = '#EE82EE';
+ $color['Wheat'] = '#F5DEB3';
+ $color['White'] = '#FFFFFF';
+ $color['WhiteSmoke'] = '#F5F5F5';
+ $color['Yellow'] = '#FFFF00';
+ $color['YellowGreen'] = '#9ACD32';
+
+ $this->htmlColor = array();
+ foreach($color as $key => $val) $this->htmlColor[strtolower($key)] = $val;
+ unset($color);
+
+ $this->table = array();
+
+ $this->value = array();
+ $this->initStyle();
+
+ // initialisation des styles sans héritages
+ $this->resetStyle();
+ }
+
+ function initStyle()
+ {
+ $this->value['id_balise'] = 'body'; // balise
+ $this->value['id_name'] = null; // name
+ $this->value['id_id'] = null; // id
+ $this->value['id_class'] = null; // class
+ $this->value['id_lst'] = array('*'); // lst de dependance
+ $this->value['mini-size'] = 1.; // rapport de taille spécifique aux sup, sub
+ $this->value['mini-decal'] = 0; // rapport de position spécifique aux sup, sub
+ $this->value['font-family'] = 'Arial';
+ $this->value['font-bold'] = false;
+ $this->value['font-italic'] = false;
+ $this->value['font-underline'] = false;
+ $this->value['font-overline'] = false;
+ $this->value['font-linethrough'] = false;
+ $this->value['font-size'] = $this->ConvertToMM('10pt');
+ $this->value['text-indent'] = 0;
+ $this->value['text-align'] = 'left';
+ $this->value['vertical-align'] = 'middle';
+ $this->value['line-height'] = 'normal';
+
+ $this->value['position'] = null;
+ $this->value['x'] = null;
+ $this->value['y'] = null;
+ $this->value['width'] = 0;
+ $this->value['height'] = 0;
+ $this->value['top'] = null;
+ $this->value['right'] = null;
+ $this->value['bottom'] = null;
+ $this->value['left'] = null;
+ $this->value['float'] = null;
+ $this->value['display'] = null;
+
+ $this->value['color'] = array(0, 0, 0);
+ $this->value['background'] = array('color' => null, 'image' => null, 'position' => null, 'repeat' => null);
+ $this->value['border'] = array();
+ $this->value['padding'] = array();
+ $this->value['margin'] = array();
+ $this->value['margin-auto'] = false;
+
+ $this->value['list-style-type'] = '';
+ $this->value['list-style-image'] = '';
+
+ $this->value['xc'] = null;
+ $this->value['yc'] = null;
+ }
+
+ /**
+ * Initialisation des styles sans héritages
+ *
+ * @param string balise HTML
+ * @return null
+ */
+ function resetStyle($balise = '')
+ {
+ $collapse = isset($this->value['border']['collapse']) ? $this->value['border']['collapse'] : false;
+ if (!in_array($balise, array('tr', 'td', 'th'))) $collapse = false;
+
+ $this->value['position'] = null;
+ $this->value['x'] = null;
+ $this->value['y'] = null;
+ $this->value['width'] = 0;
+ $this->value['height'] = 0;
+ $this->value['top'] = null;
+ $this->value['right'] = null;
+ $this->value['bottom'] = null;
+ $this->value['left'] = null;
+ $this->value['float'] = null;
+ $this->value['display'] = null;
+ $this->value['background'] = array('color' => null, 'image' => null, 'position' => null, 'repeat' => null);
+ $this->value['border'] = array(
+ 't' => $this->readBorder('none'),
+ 'r' => $this->readBorder('none'),
+ 'b' => $this->readBorder('none'),
+ 'l' => $this->readBorder('none'),
+ 'radius' => array(0, 0),
+ 'collapse' => $collapse,
+ );
+
+ $this->value['margin'] = array(
+ 't' => 0,
+ 'r' => 0,
+ 'b' => 0,
+ 'l' => 0
+ );
+ $this->value['margin-auto'] = false;
+
+ if (in_array($balise, array('div')))
+ $this->value['vertical-align'] = 'top';
+
+ if (in_array($balise, array('ul', 'li')))
+ {
+ $this->value['list-style-type'] = '';
+ $this->value['list-style-image'] = '';
+ }
+
+ if (!in_array($balise, array('tr', 'td')))
+ {
+ $this->value['padding'] = array(
+ 't' => 0,
+ 'r' => 0,
+ 'b' => 0,
+ 'l' => 0
+ );
+ }
+ else
+ {
+ $this->value['padding'] = array(
+ 't' => $this->ConvertToMM('1px'),
+ 'r' => $this->ConvertToMM('1px'),
+ 'b' => $this->ConvertToMM('1px'),
+ 'l' => $this->ConvertToMM('1px')
+ );
+ }
+
+ if ($balise=='hr')
+ {
+ $this->value['border'] = array(
+ 't' => $this->readBorder('solid 1px #000000'),
+ 'r' => $this->readBorder('solid 1px #000000'),
+ 'b' => $this->readBorder('solid 1px #000000'),
+ 'l' => $this->readBorder('solid 1px #000000'),
+ 'radius' => array(0, 0),
+ 'collapse' => false,
+ );
+ $this->ConvertBackground('#FFFFFF', $this->value['background']);
+ }
+
+ $this->value['xc'] = null;
+ $this->value['yc'] = null;
+ }
+
+ /**
+ * Initialisation de la font PDF
+ *
+ * @return null
+ */
+ function FontSet()
+ {
+ $b = ($this->value['font-bold'] ? 'B' : '');
+ $i = ($this->value['font-italic'] ? 'I' : '');
+ $u = ($this->value['font-underline'] ? 'U' : '');
+
+ // taille en mm, à ramener en pt
+ $size = $this->value['font-size'];
+ $size = 72 * $size / 25.4;
+
+ $this->pdf->setOverline($this->value['font-overline']);
+ $this->pdf->setLinethrough($this->value['font-linethrough']);
+
+ // application de la fonte
+ $this->pdf->SetFont($this->value['font-family'], $b.$i.$u, $this->value['mini-size']*$size);
+ $this->pdf->SetTextColor($this->value['color'][0],$this->value['color'][1], $this->value['color'][2]);
+ if ($this->value['background']['color'])
+ $this->pdf->SetFillColor($this->value['background']['color'][0],$this->value['background']['color'][1], $this->value['background']['color'][2]);
+ else
+ $this->pdf->SetFillColor(255);
+ }
+
+ /**
+ * Monter d'un niveau dans l'historisation
+ *
+ * @return null
+ */
+ function save()
+ {
+ $this->table[count($this->table)] = $this->value;
+ }
+
+ /**
+ * Descendre d'un niveau dans l'historisation
+ *
+ * @return null
+ */
+ function load()
+ {
+ if (count($this->table))
+ {
+ $this->value = $this->table[count($this->table)-1];
+ unset($this->table[count($this->table)-1]);
+ }
+ }
+
+ function setPosition(&$current_x, &$current_y)
+ {
+ $this->value['xc'] = $current_x;
+ $this->value['yc'] = $current_y;
+
+ if ($this->value['position']=='relative' || $this->value['position']=='absolute')
+ {
+ if ($this->value['right']!==null)
+ {
+ $x = $this->getLastWidth(true) - $this->value['right'] - $this->value['width'];
+ if ($this->value['margin']['r']) $x-= $this->value['margin']['r'];
+ }
+ else
+ {
+ $x = $this->value['left'];
+ if ($this->value['margin']['l']) $x+= $this->value['margin']['l'];
+ }
+
+ if ($this->value['bottom']!==null)
+ {
+ $y = $this->getLastHeight(true) - $this->value['bottom'] - $this->value['height'];
+ if ($this->value['margin']['b']) $y-= $this->value['margin']['b'];
+ }
+ else
+ {
+ $y = $this->value['top'];
+ if ($this->value['margin']['t']) $y+= $this->value['margin']['t'];
+ }
+
+ if ($this->value['position']=='relative')
+ {
+ $this->value['x'] = $current_x + $x;
+ $this->value['y'] = $current_y + $y;
+ }
+ else
+ {
+ $this->value['x'] = $this->getLastAbsoluteX()+$x;
+ $this->value['y'] = $this->getLastAbsoluteY()+$y;
+ }
+ }
+ else
+ {
+ $this->value['x'] = $current_x;
+ $this->value['y'] = $current_y;
+ if ($this->value['margin']['l']) $this->value['x']+= $this->value['margin']['l'];
+ if ($this->value['margin']['t']) $this->value['y']+= $this->value['margin']['t'];
+ }
+
+ $current_x = $this->value['x'];
+ $current_y = $this->value['y'];
+ }
+
+ /**
+ * Analyse un tableau de style provenant du parseurHTML
+ *
+ * @param string nom de la balise
+ * @param array tableau de style
+ * @return null
+ */
+ function analyse($balise, &$param)
+ {
+ // preparation
+ $balise = strtolower($balise);
+ $id = isset($param['id']) ? strtolower(trim($param['id'])) : null; if (!$id) $id = null;
+ $name = isset($param['name']) ? strtolower(trim($param['name'])) : null; if (!$name) $name = null;
+
+ // lecture de la propriete classe
+ $class = array();
+ $tmp = isset($param['class']) ? preg_replace('/[\s]+/', ' ', strtolower($param['class'])) : '';
+ $tmp = explode(' ', $tmp);
+ foreach($tmp as $k => $v)
+ {
+ $v = trim($v);
+ if ($v) $class[] = $v;
+ }
+
+ // identification de la balise et des styles direct qui pourraient lui être appliqués
+ $this->value['id_balise'] = $balise;
+ $this->value['id_name'] = $name;
+ $this->value['id_id'] = $id;
+ $this->value['id_class'] = $class;
+ $this->value['id_lst'] = array();
+ $this->value['id_lst'][] = '*';
+ $this->value['id_lst'][] = $balise;
+ if (count($class))
+ {
+ foreach($class as $v)
+ {
+ $this->value['id_lst'][] = '*.'.$v;
+ $this->value['id_lst'][] = '.'.$v;
+ $this->value['id_lst'][] = $balise.'.'.$v;
+ }
+ }
+ if ($id)
+ {
+ $this->value['id_lst'][] = '*#'.$id;
+ $this->value['id_lst'][] = '#'.$id;
+ $this->value['id_lst'][] = $id.'#'.$id;
+ }
+
+ // style CSS
+ $styles = $this->getFromCSS();
+
+ // on ajoute le style propre à la balise
+ $styles = array_merge($styles, $param['style']);
+ if (isset($param['allwidth']) && !isset($styles['width'])) $styles['width'] = '100%';
+
+ // mise à zero des styles non hérités
+ $this->resetStyle($balise);
+
+ // interpreration des nouvelles valeurs
+ $correct_width = false;
+ foreach($styles as $nom => $val)
+ {
+ switch($nom)
+ {
+ case 'font-family':
+ $val = explode(',', $val);
+ $val = trim($val[0]);
+
+ if ($val) $this->value['font-family'] = $val;
+ break;
+
+ case 'font-weight':
+ $this->value['font-bold'] = ($val=='bold');
+ break;
+
+ case 'font-style':
+ $this->value['font-italic'] = ($val=='italic');
+ break;
+
+ case 'text-decoration':
+ $val = explode(' ', $val);
+ $this->value['font-underline'] = (in_array('underline', $val));
+ $this->value['font-overline'] = (in_array('overline', $val));
+ $this->value['font-linethrough'] = (in_array('line-through', $val));
+ break;
+
+ case 'text-indent':
+ $this->value['text-indent'] = $this->ConvertToMM($val);
+ break;
+
+ case 'font-size':
+ $val = $this->ConvertToMM($val, $this->value['font-size']);
+ if ($val) $this->value['font-size'] = $val;
+ break;
+
+ case 'color':
+ $res = null;
+ $this->value['color'] = $this->ConvertToRVB($val, $res);
+
+ if ($balise=='hr')
+ {
+ $this->value['border']['l']['color'] = $this->value['color'];
+ $this->value['border']['t']['color'] = $this->value['color'];
+ $this->value['border']['r']['color'] = $this->value['color'];
+ $this->value['border']['b']['color'] = $this->value['color'];
+ }
+ break;
+
+ case 'text-align':
+ $this->value['text-align'] = $val;
+ break;
+
+ case 'vertical-align':
+ $this->value['vertical-align'] = $val;
+ break;
+
+ case 'width':
+ $this->value['width'] = $this->ConvertToMM($val, $this->getLastWidth());
+ if ($this->value['width'] && substr($val, -1)=='%') $correct_width=true;
+ break;
+
+ case 'height':
+ $this->value['height'] = $this->ConvertToMM($val, $this->getLastHeight());
+ break;
+
+ case 'line-height':
+ if (preg_match('/^[0-9\.]+$/isU', $val)) $val = floor($val*100).'%';
+ $this->value['line-height'] = $val;
+ break;
+
+ case 'padding':
+ $val = explode(' ', $val);
+ foreach($val as $k => $v)
+ {
+ $v = trim($v);
+ if ($v!='') $val[$k] = $v;
+ else unset($val[$k]);
+ }
+ $val = array_values($val);
+ if (count($val)!=4)
+ {
+ $val = $this->ConvertToMM($val[0], 0);
+ $this->value['padding']['t'] = $val;
+ $this->value['padding']['r'] = $val;
+ $this->value['padding']['b'] = $val;
+ $this->value['padding']['l'] = $val;
+ }
+ else
+ {
+ $this->value['padding']['t'] = $this->ConvertToMM($val[0], 0);
+ $this->value['padding']['r'] = $this->ConvertToMM($val[1], 0);
+ $this->value['padding']['b'] = $this->ConvertToMM($val[2], 0);
+ $this->value['padding']['l'] = $this->ConvertToMM($val[3], 0);
+ }
+ break;
+
+ case 'padding-top':
+ $this->value['padding']['t'] = $this->ConvertToMM($val, 0);
+ break;
+
+ case 'padding-right':
+ $this->value['padding']['r'] = $this->ConvertToMM($val, 0);
+ break;
+
+ case 'padding-bottom':
+ $this->value['padding']['b'] = $this->ConvertToMM($val, 0);
+ break;
+
+ case 'padding-left':
+ $this->value['padding']['l'] = $this->ConvertToMM($val, 0);
+ break;
+
+ case 'margin':
+ if ($val=='auto')
+ {
+ $this->value['margin-auto'] = true;
+ break;
+ }
+ $val = explode(' ', $val);
+ foreach($val as $k => $v)
+ {
+ $v = trim($v);
+ if ($v!='') $val[$k] = $v;
+ else unset($val[$k]);
+ }
+ $val = array_values($val);
+ if (count($val)!=4)
+ {
+ $val = $this->ConvertToMM($val[0], 0);
+ $this->value['margin']['t'] = $val;
+ $this->value['margin']['r'] = $val;
+ $this->value['margin']['b'] = $val;
+ $this->value['margin']['l'] = $val;
+ }
+ else
+ {
+ $this->value['margin']['t'] = $this->ConvertToMM($val[0], 0);
+ $this->value['margin']['r'] = $this->ConvertToMM($val[1], 0);
+ $this->value['margin']['b'] = $this->ConvertToMM($val[2], 0);
+ $this->value['margin']['l'] = $this->ConvertToMM($val[3], 0);
+ }
+ break;
+
+ case 'margin-top':
+ $this->value['margin']['t'] = $this->ConvertToMM($val, 0);
+ break;
+
+ case 'margin-right':
+ $this->value['margin']['r'] = $this->ConvertToMM($val, 0);
+ break;
+
+ case 'margin-bottom':
+ $this->value['margin']['b'] = $this->ConvertToMM($val, 0);
+ break;
+
+ case 'margin-left':
+ $this->value['margin']['l'] = $this->ConvertToMM($val, 0);
+ break;
+
+ case 'border':
+ $val = $this->readBorder($val);
+ $this->value['border']['t'] = $val;
+ $this->value['border']['r'] = $val;
+ $this->value['border']['b'] = $val;
+ $this->value['border']['l'] = $val;
+ break;
+
+ case 'border-style':
+ $val = explode(' ', $val);
+ foreach($val as $val_k => $val_v)
+ if (!in_array($val_v, array('solid', 'dotted', 'dashed')))
+ $val[$val_k] = null;
+ $this->duplicateBorder($val);
+
+ if ($val[0]) $this->value['border']['t']['type'] = $val[0];
+ if ($val[1]) $this->value['border']['r']['type'] = $val[1];
+ if ($val[2]) $this->value['border']['b']['type'] = $val[2];
+ if ($val[3]) $this->value['border']['l']['type'] = $val[3];
+ break;
+
+ case 'border-top-style':
+ if (in_array($val, array('solid', 'dotted', 'dashed')))
+ $this->value['border']['t']['type'] = $val;
+ break;
+
+ case 'border-right-style':
+ if (in_array($val, array('solid', 'dotted', 'dashed')))
+ $this->value['border']['r']['type'] = $val;
+ break;
+
+ case 'border-bottom-style':
+ if (in_array($val, array('solid', 'dotted', 'dashed')))
+ $this->value['border']['b']['type'] = $val;
+ break;
+
+ case 'border-left-style':
+ if (in_array($val, array('solid', 'dotted', 'dashed')))
+ $this->value['border']['l']['type'] = $val;
+ break;
+
+ case 'border-color':
+ $res = false;
+ $val = preg_replace('/,[\s]+/', ',', $val);
+ $val = explode(' ', $val);
+
+ foreach($val as $val_k => $val_v)
+ {
+ $val[$val_k] = $this->ConvertToRVB($val_v, $res);
+ if (!$res) $val[$val_k] = null;
+ }
+ $this->duplicateBorder($val);
+
+ if (is_array($val[0])) $this->value['border']['t']['color'] = $val[0];
+ if (is_array($val[1])) $this->value['border']['r']['color'] = $val[1];
+ if (is_array($val[2])) $this->value['border']['b']['color'] = $val[2];
+ if (is_array($val[3])) $this->value['border']['l']['color'] = $val[3];
+
+ break;
+
+ case 'border-top-color':
+ $res = false;
+ $val = $this->ConvertToRVB($val, $res);
+ if ($res) $this->value['border']['t']['color'] = $val;
+ break;
+
+ case 'border-right-color':
+ $res = false;
+ $val = $this->ConvertToRVB($val, $res);
+ if ($res) $this->value['border']['r']['color'] = $val;
+ break;
+
+ case 'border-bottom-color':
+ $res = false;
+ $val = $this->ConvertToRVB($val, $res);
+ if ($res) $this->value['border']['b']['color'] = $val;
+ break;
+
+ case 'border-left-color':
+ $res = false;
+ $val = $this->ConvertToRVB($val, $res);
+ if ($res) $this->value['border']['l']['color'] = $val;
+ break;
+
+ case 'border-width':
+ $val = explode(' ', $val);
+ foreach($val as $val_k => $val_v)
+ {
+ $val[$val_k] = $this->ConvertToMM($val_v, 0);
+ }
+ $this->duplicateBorder($val);
+
+ if ($val[0]) $this->value['border']['t']['width'] = $val[0];
+ if ($val[1]) $this->value['border']['r']['width'] = $val[1];
+ if ($val[2]) $this->value['border']['b']['width'] = $val[2];
+ if ($val[3]) $this->value['border']['l']['width'] = $val[3];
+ break;
+
+ case 'border-top-width':
+ $val = $this->ConvertToMM($val, 0);;
+ if ($val) $this->value['border']['t']['width'] = $val;
+ break;
+
+ case 'border-right-width':
+ $val = $this->ConvertToMM($val, 0);;
+ if ($val) $this->value['border']['r']['width'] = $val;
+ break;
+
+ case 'border-bottom-width':
+ $val = $this->ConvertToMM($val, 0);;
+ if ($val) $this->value['border']['b']['width'] = $val;
+ break;
+
+ case 'border-left-width':
+ $val = $this->ConvertToMM($val, 0);;
+ if ($val) $this->value['border']['l']['width'] = $val;
+ break;
+
+ case 'border-collapse':
+ if ($balise=='table') $this->value['border']['collapse'] = ($val=='collapse');
+ break;
+
+ case 'border-radius':
+ // nettoyage des valeurs
+ $val = explode(' ', $val);
+ foreach($val as $k => $v)
+ {
+ $v = trim($v);
+ if ($v)
+ {
+ $v = $this->ConvertToMM($v, 0);
+ if ($v) $val[$k] = $v;
+ else unset($val[$k]);
+ }
+ else unset($val[$k]);
+ }
+ $val = array_values($val);
+
+ if (!isset($val[1]) && isset($val[0])) $val[1] = $val[0];
+ if (count($val)==2)
+ $this->value['border']['radius'] = array($val[0], $val[1]);
+
+ break;
+
+ case 'border-top':
+ $this->value['border']['t'] = $this->readBorder($val);
+ break;
+
+ case 'border-right':
+ $this->value['border']['r'] = $this->readBorder($val);
+ break;
+
+ case 'border-bottom':
+ $this->value['border']['b'] = $this->readBorder($val);
+ break;
+
+ case 'border-left':
+ $this->value['border']['l'] = $this->readBorder($val);
+ break;
+
+ case 'background-color':
+ $this->value['background']['color'] = $this->ConvertBackgroundColor($val);
+ break;
+
+ case 'background-image':
+ $this->value['background']['image'] = $this->ConvertBackgroundImage($val);
+ break;
+
+ case 'background-position':
+ $res = null;
+ $this->value['background']['position'] = $this->ConvertBackgroundPosition($val, $res);
+ break;
+
+ case 'background-repeat':
+ $this->value['background']['repeat'] = $this->ConvertBackgroundRepeat($val);
+ break;
+
+ case 'background':
+ $this->ConvertBackground($val, $this->value['background']);
+ break;
+
+ case 'position':
+ if ($val=='absolute') $this->value['position'] = 'absolute';
+ else if ($val=='relative') $this->value['position'] = 'relative';
+ else $this->value['position'] = null;
+ break;
+
+ case 'float':
+ if ($val=='left') $this->value['float'] = 'left';
+ else if ($val=='right') $this->value['float'] = 'right';
+ else $this->value['float'] = null;
+ break;
+
+ case 'display':
+ if ($val=='inline') $this->value['display'] = 'inline';
+ else if ($val=='block') $this->value['display'] = 'block';
+ else if ($val=='none') $this->value['display'] = 'none';
+ else $this->value['display'] = null;
+ break;
+
+ case 'top':
+ case 'bottom':
+ case 'left':
+ case 'right':
+ $this->value[$nom] = $val;
+ break;
+
+ case 'list-style':
+ case 'list-style-type':
+ case 'list-style-image':
+ if ($nom=='list-style') $nom = 'list-style-type';
+ $this->value[$nom] = $val;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if ($this->onlyLeft) $this->value['text-align'] = 'left';
+
+ // correction de la largeur pour correspondre au modèle de boite quick
+ if ($correct_width)
+ {
+ if (!in_array($balise, array('table', 'div', 'hr')))
+ {
+ $this->value['width']-= $this->value['padding']['l'] + $this->value['padding']['r'];
+ $this->value['width']-= $this->value['border']['l']['width'] + $this->value['border']['r']['width'];
+ }
+ if (in_array($balise, array('th', 'td')))
+ {
+ $this->value['width']-= $this->ConvertToMM(isset($param['cellspacing']) ? $param['cellspacing'] : '2px');
+ }
+ if ($this->value['width']<0) $this->value['width']=0;
+ }
+ else
+ {
+ if ($this->value['width'])
+ {
+ if ($this->value['border']['l']['width']) $this->value['width'] += $this->value['border']['l']['width'];
+ if ($this->value['border']['r']['width']) $this->value['width'] += $this->value['border']['r']['width'];
+ if ($this->value['padding']['l']) $this->value['width'] += $this->value['padding']['l'];
+ if ($this->value['padding']['r']) $this->value['width'] += $this->value['padding']['r'];
+ }
+ }
+ if ($this->value['height'])
+ {
+ if ($this->value['border']['b']['width']) { $this->value['height'] += $this->value['border']['b']['width']; }
+ if ($this->value['border']['t']['width']) { $this->value['height'] += $this->value['border']['t']['width']; }
+ if ($this->value['padding']['b']) $this->value['height'] += $this->value['padding']['b'];
+ if ($this->value['padding']['t']) $this->value['height'] += $this->value['padding']['t'];
+ }
+
+ if ($this->value['top']!=null) $this->value['top'] = $this->ConvertToMM($this->value['top'], $this->getLastHeight(true));
+ if ($this->value['bottom']!=null) $this->value['bottom'] = $this->ConvertToMM($this->value['bottom'], $this->getLastHeight(true));
+ if ($this->value['left']!=null) $this->value['left'] = $this->ConvertToMM($this->value['left'], $this->getLastWidth(true));
+ if ($this->value['right']!=null) $this->value['right'] = $this->ConvertToMM($this->value['right'], $this->getLastWidth(true));
+
+ if ($this->value['top'] && $this->value['bottom'] && $this->value['height']) $this->value['bottom'] = null;
+ if ($this->value['left'] && $this->value['right'] && $this->value['width']) $this->value['right'] = null;
+ }
+
+ /**
+ * Récupération de la hauteur de ligne courante
+ *
+ * @return float hauteur en mm
+ */
+ function getLineHeight()
+ {
+ $val = $this->value['line-height'];
+ if ($val=='normal') $val = '108%';
+ return $this->ConvertToMM($val, $this->value['font-size']);
+ }
+
+ /**
+ * Récupération de la largeur de l'objet parent
+ *
+ * @return float largeur
+ */
+ function getLastWidth($mode = false)
+ {
+ for($k=count($this->table); $k>0; $k--)
+ {
+ if ($this->table[$k-1]['width'])
+ {
+ $w = $this->table[$k-1]['width'];
+ if ($mode)
+ {
+ $w+= $this->table[$k-1]['border']['l']['width'] + $this->table[$k-1]['padding']['l']+0.02;
+ $w+= $this->table[$k-1]['border']['r']['width'] + $this->table[$k-1]['padding']['r']+0.02;
+ }
+ return $w;
+ }
+ }
+ return $this->pdf->w - $this->pdf->lMargin - $this->pdf->rMargin;
+ }
+
+ /**
+ * Récupération de la hauteur de l'objet parent
+ *
+ * @return float hauteur
+ */
+ function getLastHeight($mode = false)
+ {
+ for($k=count($this->table); $k>0; $k--)
+ {
+ if ($this->table[$k-1]['height'])
+ {
+ $h = $this->table[$k-1]['height'];
+ if ($mode)
+ {
+ $h+= $this->table[$k-1]['border']['t']['width'] + $this->table[$k-1]['padding']['t']+0.02;
+ $h+= $this->table[$k-1]['border']['b']['width'] + $this->table[$k-1]['padding']['b']+0.02;
+ }
+ return $h;
+ }
+ }
+ return $this->pdf->h - $this->pdf->tMargin - $this->pdf->bMargin;
+ }
+
+ function getFloat()
+ {
+ if ($this->value['float']=='left') return 'left';
+ if ($this->value['float']=='right') return 'right';
+ return null;
+ }
+
+ function getLastAbsoluteX()
+ {
+ for($k=count($this->table); $k>0; $k--)
+ {
+ if ($this->table[$k-1]['x'] && $this->table[$k-1]['position']) return $this->table[$k-1]['x'];
+ }
+ return $this->pdf->lMargin;
+ }
+
+ function getLastAbsoluteY()
+ {
+ for($k=count($this->table); $k>0; $k--)
+ {
+ if ($this->table[$k-1]['y'] && $this->table[$k-1]['position']) return $this->table[$k-1]['y'];
+ }
+ return $this->pdf->tMargin;
+ }
+
+ /**
+ * Récupération des propriétés CSS de la balise en cours
+ *
+ * @return array() tableau des propriétés CSS
+ */
+ function getFromCSS()
+ {
+ $styles = array(); // style à appliquer
+ $getit = array(); // styles à récuperer
+
+ // identification des styles direct, et ceux des parents
+ $lst = array();
+ $lst[] = $this->value['id_lst'];
+ for($i=count($this->table)-1; $i>=0; $i--) $lst[] = $this->table[$i]['id_lst'];
+
+ // identification des styles à récuperer
+ foreach($this->css_keys as $key => $num)
+ if ($this->getReccursiveStyle($key, $lst))
+ $getit[$key] = $num;
+
+ // si des styles sont à recuperer
+ if (count($getit))
+ {
+ // on les récupère, mais dans l'odre de définition, afin de garder les priorités
+ asort($getit);
+ foreach($getit as $key => $val) $styles = array_merge($styles, $this->css[$key]);
+ }
+
+ return $styles;
+ }
+
+ /**
+ * Identification des styles à récuperer, en fonction de la balise et de ses parents
+ *
+ * @param string clef CSS à analyser
+ * @param array() tableau des styles direct, et ceux des parents
+ * @param string prochaine etape
+ * @return boolean clef autorisée ou non
+ */
+ function getReccursiveStyle($key, $lst, $next = null)
+ {
+ // si propchaine etape, on construit les valeurs
+ if ($next!==null)
+ {
+ if ($next) $key = trim(substr($key, 0, -strlen($next))); // on elève cette etape
+ unset($lst[0]);
+ if (!count($lst)) return false; // pas d'etape possible
+ $lst = array_values($lst);
+ }
+
+ // pour chaque style direct possible de l'etape en cours
+ foreach($lst[0] as $nom)
+ {
+ if ($key==$nom) return true; // si la clef conrrespond => ok
+ if (substr($key, -strlen(' '.$nom))==' '.$nom && $this->getReccursiveStyle($key, $lst, $nom)) return true; // si la clef est la fin, on analyse ce qui précède
+ }
+
+ // si on est pas à la premiere etape, on doit analyse toutes les sous etapes
+ if ($next!==null && $this->getReccursiveStyle($key, $lst, '')) return true;
+
+ // aucun style trouvé
+ return false;
+ }
+
+ /**
+ * Analyse d'une propriété Border
+ *
+ * @param string propriété border
+ * @return array() propriété décodée
+ */
+ function readBorder($val)
+ {
+ $none = array('type' => 'none', 'width' => 0, 'color' => array(0, 0, 0));
+
+ // valeurs par défault
+ $type = 'solid';
+ $width = $this->ConvertToMM('1pt');
+ $color = array(0, 0, 0);
+
+ // nettoyage des valeurs
+ $val = explode(' ', $val);
+ foreach($val as $k => $v)
+ {
+ $v = trim($v);
+ if ($v) $val[$k] = $v;
+ else unset($val[$k]);
+ }
+ $val = array_values($val);
+ // identification des valeurs
+ $res = null;
+ foreach($val as $key)
+ {
+ if ($key=='none' || $key=='hidden') return $none;
+
+ if ($this->ConvertToMM($key)!==null) $width = $this->ConvertToMM($key);
+ else if (in_array($key, array('solid', 'dotted', 'dashed'))) $type = $key;
+ else
+ {
+ $tmp = $this->ConvertToRVB($key, $res);
+ if ($res) $color = $tmp;
+ }
+ }
+ if (!$width) return $none;
+ return array('type' => $type, 'width' => $width, 'color' => $color);
+ }
+
+ function duplicateBorder(&$val)
+ {
+ if (count($val)==1)
+ {
+ $val[1] = $val[0];
+ $val[2] = $val[0];
+ $val[3] = $val[0];
+ }
+ else if (count($val)==2)
+ {
+ $val[2] = $val[0];
+ $val[3] = $val[1];
+ }
+ else if (count($val)==3)
+ {
+ $val[3] = $val[1];
+ }
+ }
+
+ function ConvertBackground($stl, &$res)
+ {
+ // Image
+ $text = '/url\(([^)]*)\)/isU';
+ if (preg_match($text, $stl, $match))
+ {
+ $res['image'] = $this->ConvertBackgroundImage($match[0]);
+ $stl = preg_replace($text, '', $stl);
+ $stl = preg_replace('/[\s]+/', ' ', $stl);
+ }
+
+ // protection des espaces
+ $stl = preg_replace('/,[\s]+/', ',', $stl);
+ $lst = explode(' ', $stl);
+
+ $pos = '';
+ foreach($lst as $val)
+ {
+ $ok = false;
+ $color = $this->ConvertToRVB($val, $ok);
+
+ if ($ok)
+ {
+ $res['color'] = $color;
+ }
+ else if ($val=='transparent')
+ {
+ $res['color'] = null;
+ }
+ else
+ {
+ $repeat = $this->ConvertBackgroundRepeat($val);
+ if ($repeat)
+ {
+ $res['repeat'] = $repeat;
+ }
+ else
+ {
+ $pos.= ($pos ? ' ' : '').$val;
+ }
+ }
+ }
+ if ($pos)
+ {
+ $pos = $this->ConvertBackgroundPosition($pos, $ok);
+ if ($ok) $res['position'] = $pos;
+ }
+ }
+
+ function ConvertBackgroundColor($val)
+ {
+ $res = null;
+ if ($val=='transparent') return null;
+ else return $this->ConvertToRVB($val, $res);
+ }
+
+ function ConvertBackgroundImage($val)
+ {
+ if ($val=='none')
+ return null;
+ else if (preg_match('/^url\(([^)]*)\)$/isU', $val, $match))
+ return $match[1];
+ else
+ return null;
+ }
+
+ function ConvertBackgroundPosition($val, &$res)
+ {
+ $val = explode(' ', $val);
+ if (count($val)<2)
+ {
+ if (!$val[0]) return null;
+ $val[1] = 'center';
+ }
+ if (count($val)>2) return null;
+
+ $x = 0;
+ $y = 0;
+ $res = true;
+
+ if ($val[0]=='left') $x = '0%';
+ else if ($val[0]=='center') $x = '50%';
+ else if ($val[0]=='right') $x = '100%';
+ else if ($val[0]=='top') $y = '0%';
+ else if ($val[0]=='bottom') $y = '100%';
+ else if (preg_match('/^[-]?[0-9\.]+%$/isU', $val[0])) $x = $val[0];
+ else if ($this->ConvertToMM($val[0])) $x = $this->ConvertToMM($val[0]);
+ else $res = false;
+
+ if ($val[1]=='left') $x = '0%';
+ else if ($val[1]=='right') $x = '100%';
+ else if ($val[1]=='top') $y = '0%';
+ else if ($val[1]=='center') $y = '50%';
+ else if ($val[1]=='bottom') $y = '100%';
+ else if (preg_match('/^[-]?[0-9\.]+%$/isU', $val[1])) $y = $val[1];
+ else if ($this->ConvertToMM($val[1])) $y = $this->ConvertToMM($val[1]);
+ else $res = false;
+
+ $val[0] = $x;
+ $val[1] = $y;
+
+ return $val;
+ }
+
+ function ConvertBackgroundRepeat($val)
+ {
+ switch($val)
+ {
+ case 'repeat':
+ return array(true, true);
+ case 'repeat-x':
+ return array(true, false);
+ case 'repeat-y':
+ return array(false, true);
+ case 'no-repeat':
+ return array(false, false);
+ }
+ return null;
+ }
+ /**
+ * Convertir une longueur en mm
+ *
+ * @param string longueur, avec unité, à convertir
+ * @param float longueur du parent
+ * @return float longueur exprimée en mm
+ */
+ function ConvertToMM($val, $old=0.)
+ {
+ $val = trim($val);
+ if (preg_match('/^[0-9\.\-]+$/isU', $val)) $val.= 'px';
+ if (preg_match('/^[0-9\.\-]+px$/isU', $val)) $val = 25.4/96. * str_replace('px', '', $val);
+ else if (preg_match('/^[0-9\.\-]+pt$/isU', $val)) $val = 25.4/72. * str_replace('pt', '', $val);
+ else if (preg_match('/^[0-9\.\-]+in$/isU', $val)) $val = 25.4 * str_replace('in', '', $val);
+ else if (preg_match('/^[0-9\.\-]+mm$/isU', $val)) $val = 1.*str_replace('mm', '', $val);
+ else if (preg_match('/^[0-9\.\-]+%$/isU', $val)) $val = 1.*$old*str_replace('%', '', $val)/100.;
+ else $val = null;
+
+ return $val;
+ }
+
+ /**
+ * Décomposition d'un code couleur HTML
+ *
+ * @param string couleur au format CSS
+ * @return array(r, v, b) couleur exprimé par ses comporantes R, V, B, de 0 à 255.
+ */
+ function ConvertToRVB($val, &$res)
+ {
+ $val = trim($val);
+ $res = true;
+
+ if (strtolower($val)=='transparent') return array(null, null, null);
+ if (isset($this->htmlColor[strtolower($val)])) $val = $this->htmlColor[strtolower($val)];
+
+ if (preg_match('/rgb\([\s]*([0-9%]+)[\s]*,[\s]*([0-9%]+)[\s]*,[\s]*([0-9%]+)[\s]*\)/isU', $val, $match))
+ {
+ $r =$match[1]; if (substr($r, -1)=='%') $r = floor(255*substr($r, 0, -1)/100);
+ $v =$match[2]; if (substr($v, -1)=='%') $v = floor(255*substr($v, 0, -1)/100);
+ $b =$match[3]; if (substr($b, -1)=='%') $b = floor(255*substr($b, 0, -1)/100);
+ }
+ else if (strlen($val)==7 && substr($val, 0, 1)=='#')
+ {
+ $r = hexdec(substr($val, 1, 2));
+ $v = hexdec(substr($val, 3, 2));
+ $b = hexdec(substr($val, 5, 2));
+ }
+ else if (strlen($val)==4 && substr($val, 0, 1)=='#')
+ {
+ $r = hexdec(substr($val, 1, 1).substr($val, 1, 1));
+ $v = hexdec(substr($val, 2, 1).substr($val, 2, 1));
+ $b = hexdec(substr($val, 3, 1).substr($val, 3, 1));
+ }
+ else
+ {
+ $r=0;
+ $v=0;
+ $b=0;
+ $res = false;
+ }
+ return array(floor($r), floor($v), floor($b));
+ }
+
+ /**
+ * Analyser une feuille de style
+ *
+ * @param string code CSS
+ * @return null
+ */
+ function analyseStyle(&$code)
+ {
+ // on remplace tous les espaces, tab, \r, \n, par des espaces uniques
+ $code = preg_replace('/[\s]+/', ' ', $code);
+
+ // on enlève les commentaires
+ $code = preg_replace('/\/\*.*?\*\//s', '', $code);
+
+ // on analyse chaque style
+ preg_match_all('/([^{}]+){([^}]*)}/isU', $code, $match);
+ for($k=0; $k on remplie le tableau correspondant
+ $styles = trim($match[2][$k]);
+ $styles = explode(';', $styles);
+ $stl = array();
+ foreach($styles as $style)
+ {
+ $tmp = explode(':', $style);
+ if (count($tmp)>1)
+ {
+ $cod = $tmp[0]; unset($tmp[0]); $tmp = implode(':', $tmp);
+ $stl[trim(strtolower($cod))] = trim($tmp);
+ }
+ }
+
+ // décomposition des noms par les ,
+ $noms = explode(',', $noms);
+ foreach($noms as $nom)
+ {
+ $nom = trim($nom);
+ // Si il a une fonction spécifique, comme :hover => on zap
+ if (strpos($nom, ':')!==false) continue;
+ if (!isset($this->css[$nom]))
+ $this->css[$nom] = $stl;
+ else
+ $this->css[$nom] = array_merge($this->css[$nom], $stl);
+
+ }
+ }
+
+ $this->css_keys = array_flip(array_keys($this->css));
+ }
+
+ /**
+ * Extraction des feuille de style du code HTML
+ *
+ * @param string code HTML
+ * @return null
+ */
+ function readStyle(&$html)
+ {
+ $style = ' ';
+
+ // extraction des balises link, et suppression de celles-ci dans le code HTML
+ preg_match_all('/ ]*)>/isU', $html, $match);
+ $html = preg_replace('/ ]*>/isU', '', $html);
+ $html = preg_replace('/<\/link[^>]*>/isU', '', $html);
+
+ // analyse de chaque balise
+ foreach($match[1] as $code)
+ {
+ $tmp = array();
+ // lecture des paramétres du type nom=valeur
+ $prop = '([a-zA-Z0-9_]+)=([^"\'\s>]+)';
+ preg_match_all('/'.$prop.'/is', $code, $match);
+ for($k=0; $k on garde
+ if (isset($tmp['type']) && strtolower($tmp['type'])=='text/css' && isset($tmp['href']))
+ {
+ $content = @file_get_contents($tmp['href']);
+ $url = $tmp['href'];
+ if (strpos($url, 'http://')!==false)
+ {
+ $url = str_replace('http://', '', $url);
+ $url = explode('/', $url);
+ $url_main = 'http://'.$url[0].'/';
+ $url_self = $url; unset($url_self[count($url_self)-1]); $url_self = 'http://'.implode('/', $url_self).'/';
+
+ $content = preg_replace('/url\(([^\\\\][^)]*)\)/isU', 'url('.$url_self.'$1)', $content);
+ $content = preg_replace('/url\((\\\\[^)]*)\)/isU', 'url('.$url_main.'$1)', $content);
+ }
+
+ $style.= $content."\n";
+ }
+ }
+
+
+ // extraction des balises style, et suppression de celles-ci dans le code HTML
+ preg_match_all('/