Browse Source

FINAL suepr merge step : added all modules to this super repos

Bachir Soussi Chiadmi 9 years ago
parent
commit
f2b8ace9b7
100 changed files with 20464 additions and 0 deletions
  1. 18 0
      modules/simpletest/tests/psr_0_test/lib/Drupal/psr_0_test/Tests/Nested/NestedExampleTest.php
  2. 7 0
      sites/all/README.txt
  3. 112 0
      sites/all/libraries/FirePHPCore/FirePHPCore/CHANGELOG
  4. 12 0
      sites/all/libraries/FirePHPCore/FirePHPCore/CREDITS
  5. 32 0
      sites/all/libraries/FirePHPCore/FirePHPCore/README
  6. 10 0
      sites/all/libraries/FirePHPCore/FirePHPCore/build.properties
  7. 115 0
      sites/all/libraries/FirePHPCore/FirePHPCore/build.xml
  8. 29 0
      sites/all/libraries/FirePHPCore/FirePHPCore/demo/LICENSE
  9. 89 0
      sites/all/libraries/FirePHPCore/FirePHPCore/demo/oo.php
  10. 79 0
      sites/all/libraries/FirePHPCore/FirePHPCore/demo/oo.php4
  11. 86 0
      sites/all/libraries/FirePHPCore/FirePHPCore/demo/procedural.php
  12. 76 0
      sites/all/libraries/FirePHPCore/FirePHPCore/demo/procedural.php4
  13. 1544 0
      sites/all/libraries/FirePHPCore/FirePHPCore/lib/FirePHPCore/FirePHP.class.php
  14. 1292 0
      sites/all/libraries/FirePHPCore/FirePHPCore/lib/FirePHPCore/FirePHP.class.php4
  15. 29 0
      sites/all/libraries/FirePHPCore/FirePHPCore/lib/FirePHPCore/LICENSE
  16. 261 0
      sites/all/libraries/FirePHPCore/FirePHPCore/lib/FirePHPCore/fb.php
  17. 251 0
      sites/all/libraries/FirePHPCore/FirePHPCore/lib/FirePHPCore/fb.php4
  18. 52 0
      sites/all/libraries/FirePHPCore/FirePHPCore/pear.package.tpl.xml
  19. 379 0
      sites/all/libraries/MPDF54/CHANGELOG.txt
  20. 92 0
      sites/all/libraries/MPDF54/CREDITS.txt
  21. 164 0
      sites/all/libraries/MPDF54/FONT INFO.txt
  22. 340 0
      sites/all/libraries/MPDF54/LICENSE.txt
  23. 148 0
      sites/all/libraries/MPDF54/README.txt
  24. 1721 0
      sites/all/libraries/MPDF54/classes/barcode.php
  25. 248 0
      sites/all/libraries/MPDF54/classes/bmp.php
  26. 371 0
      sites/all/libraries/MPDF54/classes/directw.php
  27. 1263 0
      sites/all/libraries/MPDF54/classes/form.php
  28. 700 0
      sites/all/libraries/MPDF54/classes/gif.php
  29. 723 0
      sites/all/libraries/MPDF54/classes/grad.php
  30. 264 0
      sites/all/libraries/MPDF54/classes/indic.php
  31. 2596 0
      sites/all/libraries/MPDF54/classes/svg.php
  32. 42 0
      sites/all/libraries/MPDF54/classes/tocontents.php
  33. 2373 0
      sites/all/libraries/MPDF54/classes/ttfontsuni.php
  34. 236 0
      sites/all/libraries/MPDF54/classes/wmf.php
  35. 172 0
      sites/all/libraries/MPDF54/compress.php
  36. 499 0
      sites/all/libraries/MPDF54/config.php
  37. 153 0
      sites/all/libraries/MPDF54/config_cp.php
  38. 302 0
      sites/all/libraries/MPDF54/config_fonts.php
  39. BIN
      sites/all/libraries/MPDF54/examples/alpha.gif
  40. BIN
      sites/all/libraries/MPDF54/examples/alpha.png
  41. BIN
      sites/all/libraries/MPDF54/examples/alpha3.png
  42. BIN
      sites/all/libraries/MPDF54/examples/bayeux1.jpg
  43. BIN
      sites/all/libraries/MPDF54/examples/bg.jpg
  44. BIN
      sites/all/libraries/MPDF54/examples/bgbarcode.png
  45. BIN
      sites/all/libraries/MPDF54/examples/bgrock.jpg
  46. BIN
      sites/all/libraries/MPDF54/examples/borders2FF.jpg
  47. BIN
      sites/all/libraries/MPDF54/examples/borders2IE.jpg
  48. BIN
      sites/all/libraries/MPDF54/examples/borders3FF.jpg
  49. BIN
      sites/all/libraries/MPDF54/examples/borders3IE.jpg
  50. BIN
      sites/all/libraries/MPDF54/examples/borders4FF.jpg
  51. BIN
      sites/all/libraries/MPDF54/examples/borders4IE.jpg
  52. BIN
      sites/all/libraries/MPDF54/examples/bordersFF.jpg
  53. BIN
      sites/all/libraries/MPDF54/examples/bordersIE.jpg
  54. BIN
      sites/all/libraries/MPDF54/examples/bordersMPDF2.jpg
  55. BIN
      sites/all/libraries/MPDF54/examples/clematis.jpg
  56. 11 0
      sites/all/libraries/MPDF54/examples/example01_basic.php
  57. 11 0
      sites/all/libraries/MPDF54/examples/example02_CSS_styles.php
  58. 71 0
      sites/all/libraries/MPDF54/examples/example03_backgrounds_and_borders.php
  59. 207 0
      sites/all/libraries/MPDF54/examples/example04_images.php
  60. 412 0
      sites/all/libraries/MPDF54/examples/example05_tables.php
  61. 93 0
      sites/all/libraries/MPDF54/examples/example06_tables_nested.php
  62. 500 0
      sites/all/libraries/MPDF54/examples/example07_tables_borders.php
  63. 137 0
      sites/all/libraries/MPDF54/examples/example08_lists.php
  64. 13 0
      sites/all/libraries/MPDF54/examples/example09_forms.php
  65. 75 0
      sites/all/libraries/MPDF54/examples/example10_floating_and_fixed_position_elements.php
  66. 8 0
      sites/all/libraries/MPDF54/examples/example11_overflow_auto.php
  67. 40 0
      sites/all/libraries/MPDF54/examples/example12_paging_html.php
  68. 26 0
      sites/all/libraries/MPDF54/examples/example13_paging_css.php
  69. 5 0
      sites/all/libraries/MPDF54/examples/example14_page_numbers_ToC_Index_Bookmarks.php
  70. 48 0
      sites/all/libraries/MPDF54/examples/example15_headers_method_1.php
  71. 37 0
      sites/all/libraries/MPDF54/examples/example16_headers_method_2.php
  72. 26 0
      sites/all/libraries/MPDF54/examples/example17_headers_method_3.php
  73. 51 0
      sites/all/libraries/MPDF54/examples/example18_headers_method_4.php
  74. 59 0
      sites/all/libraries/MPDF54/examples/example19_page_sizes.php
  75. 41 0
      sites/all/libraries/MPDF54/examples/example20_justify.php
  76. 8 0
      sites/all/libraries/MPDF54/examples/example21_hyphenation.php
  77. 15 0
      sites/all/libraries/MPDF54/examples/example22_columns.php
  78. 7 0
      sites/all/libraries/MPDF54/examples/example23_orientation.php
  79. 7 0
      sites/all/libraries/MPDF54/examples/example24_orientation_2.php
  80. 13 0
      sites/all/libraries/MPDF54/examples/example26_RTL.php
  81. 20 0
      sites/all/libraries/MPDF54/examples/example27_CJK_using_Adobe_fonts.php
  82. 20 0
      sites/all/libraries/MPDF54/examples/example28_CJK_using_embedded_fonts.php
  83. 113 0
      sites/all/libraries/MPDF54/examples/example29_multilingual_autofont.php
  84. 11 0
      sites/all/libraries/MPDF54/examples/example30_arabic.php
  85. 14 0
      sites/all/libraries/MPDF54/examples/example32_indic.php
  86. 5 0
      sites/all/libraries/MPDF54/examples/example35_watermarks.php
  87. 9 0
      sites/all/libraries/MPDF54/examples/example36_annotations_and_Attached_files.php
  88. 437 0
      sites/all/libraries/MPDF54/examples/example37_barcodes.php
  89. 32 0
      sites/all/libraries/MPDF54/examples/example38_dot_tab.php
  90. 32 0
      sites/all/libraries/MPDF54/examples/example39_PDFA_compliance.php
  91. 20 0
      sites/all/libraries/MPDF54/examples/example40_MPDFI_thumbnails.php
  92. 36 0
      sites/all/libraries/MPDF54/examples/example41_MPDFI_template.php
  93. 35 0
      sites/all/libraries/MPDF54/examples/example42_MPDFI_templatedoc.php
  94. 14 0
      sites/all/libraries/MPDF54/examples/example43_MPDFI_booklet.php
  95. 30 0
      sites/all/libraries/MPDF54/examples/example44_MPDFI_yearbook.php
  96. 236 0
      sites/all/libraries/MPDF54/examples/example46_progress_bars_simple.php
  97. 236 0
      sites/all/libraries/MPDF54/examples/example47_progress_bars_simple_custom.php
  98. 236 0
      sites/all/libraries/MPDF54/examples/example48_progress_bars_advanced.php
  99. 41 0
      sites/all/libraries/MPDF54/examples/example49_changelog.php
  100. 86 0
      sites/all/libraries/MPDF54/examples/example50_new_mPDF_3_features.php

+ 18 - 0
modules/simpletest/tests/psr_0_test/lib/Drupal/psr_0_test/Tests/Nested/NestedExampleTest.php

@@ -0,0 +1,18 @@
+<?php
+
+namespace Drupal\psr_0_test\Tests\Nested;
+
+class NestedExampleTest extends \DrupalWebTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'PSR0 example test: PSR-0 in nested subfolders.',
+      'description' => 'We want to assert that this PSR-0 test case is being discovered.',
+      'group' => 'SimpleTest',
+    );
+  }
+
+  function testArithmetics() {
+    $this->assert(1 + 1 == 2, '1 + 1 == 2');
+  }
+}

+ 7 - 0
sites/all/README.txt

@@ -0,0 +1,7 @@
+
+This directory should be used to place downloaded and custom modules
+and themes which are common to all sites. Keeping contributed and
+custom modules and themes in the sites directory will aid in upgrading
+Drupal core files. Place contributed and custom modules and themes in
+the sites/all/modules and sites/all/themes directories respectively.
+

+ 112 - 0
sites/all/libraries/FirePHPCore/FirePHPCore/CHANGELOG

@@ -0,0 +1,112 @@
+
+  - (Issue 112) Error Predefined Constants Not available for PHP 5.x versions
+
+2008-06-14 - Release Version: 0.3.1
+
+  - (Issue 108) ignore class name case in object filter
+
+2009-05-11 - Release Version: 0.3
+2009-05-01 - Release Version: 0.3.rc.1
+
+  - (Issue 90) PHP4 compatible version of FirePHPCore
+  - (Issue 98) Thrown exceptions don't send an HTTP 500 if the FirePHP exception handler is enabled
+  - (Issue 85) Support associative arrays in encodeTable method in FirePHP.class.php
+  - (Issue 66) Add a new getOptions() public method in API
+  - (Issue 82) Define $this->options outside of __construct
+  - (Issue 72) Message error if group name is null
+  - (Issue 68) registerErrorHandler() and registerExceptionHandler() should returns previous handlers defined
+  - (Issue 69) Add the missing register handler in the triumvirate (error, exception, assert)
+  - (Issue 75) [Error & Exception Handling] Option to not exit script execution
+  - (Issue 83) Exception handler can't throw exceptions
+  - (Issue 80) Auto/Pre collapsing groups AND Custom group row colors
+
+2008-11-09 - Release Version: 0.2.1
+
+  - (Issue 70) Problem when logging resources
+
+2008-10-21 - Release Version: 0.2.0
+
+	- Updated version to 0.2.0
+	- Switched to using __sleep instead of __wakeup
+	- Added support to exclude object members when encoding
+  - Add support to enable/disable logging
+
+2008-10-17 - Release Version: 0.2.b.8
+  
+  - New implementation for is_utf8()
+  - (Issue 55) maxObjectDepth Option not working correctly when using TABLE and EXCEPTION Type
+  - Bugfix for max[Object|Array]Depth when encoding nested array/object graphs
+  - Bugfix for FB::setOptions()
+
+2008-10-16 - Release Version: 0.2.b.7
+
+  - (Issue 45) Truncate dump when string have non utf8 cars
+  - (Issue 52) logging will not work when firephp object gets stored in the session.
+
+2008-10-16 - Release Version: 0.2.b.6
+
+  - (Issue 37) Display file and line information for each log message
+  - (Issue 51) Limit output of object graphs
+  - Bugfix for encoding object members set to NULL|false|''
+
+2008-10-14 - Release Version: 0.2.b.5
+
+  - Updated JsonStream wildfire protocol to be more robust
+  - (Issue 33) PHP error notices running demos
+  - (Issue 48) Warning: ReflectionProperty::getValue() expects exactly 1 parameter, 0 given
+
+2008-10-08 - Release Version: 0.2.b.4
+
+	- Bugfix for logging objects with recursion
+
+2008-10-08 - Release Version: 0.2.b.3
+
+  - (Issue 43) Notice message in 0.2b2
+  - Added support for PHP's native json_encode() if available
+  - Revised object encoder to detect object recursion
+
+2008-10-07 - Release Version: 0.2.b.2
+
+  - (Issue 28) Need solution for logging private and protected object variables
+  - Added trace() and table() aliases in FirePHP class
+  - (Issue 41) Use PHP doc in FirePHP
+  - (Issue 39) Static logging method for object oriented API
+
+2008-10-01 - Release Version: 0.2.b.1
+
+  - Added support for error and exception handling
+  - Updated min PHP version for PEAR package to 5.2
+  - Added version constant for library
+  - Gave server library it's own wildfire plugin namespace
+  - Migrated communication protocol to Wildfire JsonStream
+  - Added support for console groups using "group" and "groupEnd"
+  - Added support for log, info, warn and error logging aliases
+  - (Issue 29) problem with TRACE when using with error_handler
+  - (Issue 33) PHP error notices running demos
+  - (Issue 12) undefined index php notice
+  - Removed closing ?> php tags
+  - (Issue 13) the code in the fb() function has a second return statement that will never be reached
+
+2008-07-30 - Release Version: 0.1.1.3
+
+	- Include __className property in JSON string if variable was an object
+	- Bugfix - Mis-spelt "Exception" in JSON encoding code
+
+2008-06-13 - Release Version: 0.1.1.1
+
+	- Bugfix - Standardize windows paths in stack traces
+	- Bugfix - Display correct stack trace info in windows environments
+	- Bugfix - Check $_SERVER['HTTP_USER_AGENT'] before returning
+
+2008-06-13 - Release Version: 0.1.1
+
+	- Added support for FirePHP::TRACE log style
+	- Changed license to New BSD License
+
+2008-06-06 - Release Version: 0.0.2
+
+  - Bugfix - Added usleep() to header writing loop to ensure unique index
+  - Bugfix - Ensure chunk_split does not generate trailing "\n" with empty data header
+  - Added support for FirePHP::TABLE log style
+  
+ 

+ 12 - 0
sites/all/libraries/FirePHPCore/FirePHPCore/CREDITS

@@ -0,0 +1,12 @@
+                         _______________________________
+                         F  i  r  e  P  H  P  C  o  r  e
+                         
+  Current Development
+  -------------------
+    
+  Christoph Dorn <christoph@christophdorn.com>
+  Michael Day    <manveru.alma@gmail.com>
+
+  If you've done work on FirePHPCore and you are not listed here,
+  please feel free to add yourself.
+

+ 32 - 0
sites/all/libraries/FirePHPCore/FirePHPCore/README

@@ -0,0 +1,32 @@
+
+Version: ##Version####Release##
+
+------------------------------------------------------
+	Requirements
+------------------------------------------------------
+
+Client Side:
+
+	- Firefox - http://www.getfirefox.com/
+	- Firebug - http://www.getfirebug.com/
+	- FirePHP - http://www.firephp.org/
+
+Server Side:
+	
+	- PHP 5 (complete functionality)
+	- PHP 4 (most functionality)
+
+
+------------------------------------------------------
+	Install Tutorial
+------------------------------------------------------
+	
+	http://www.firephp.org/HQ/Install.htm
+	
+	
+------------------------------------------------------
+	Support
+------------------------------------------------------
+	
+	http://forum.firephp.org/
+	

+ 10 - 0
sites/all/libraries/FirePHPCore/FirePHPCore/build.properties

@@ -0,0 +1,10 @@
+
+version = 0.3
+release = .1
+
+pear.stability = stable
+
+
+upload.server = 
+upload.user = 
+upload.path = 

+ 115 - 0
sites/all/libraries/FirePHPCore/FirePHPCore/build.xml

@@ -0,0 +1,115 @@
+<?xml version="1.0"?>
+
+<project name="org.firephp.package.FirePHPCore" default="package" basedir=".">
+
+    <property file="build.local.properties" />
+    <property file="build.properties" />
+
+    <target name="prepare">
+      
+        <echo msg="Making directory ./build" />
+        <delete dir="./build" includeemptydirs="true" verbose="false" failonerror="true" />
+        <mkdir dir="./build" />
+        
+    </target>
+
+    <target name="build" depends="prepare">
+        <echo msg="Copying files to build directory..." />
+
+        <copy file="./CHANGELOG" tofile="./build/FirePHPCore-${version}${release}/CHANGELOG"/>
+        <copy file="./CREDITS" tofile="./build/FirePHPCore-${version}${release}/CREDITS"/>
+
+        <copy file="./README" tofile="./build/FirePHPCore-${version}${release}/README">
+          <filterchain>
+            <replacetokens begintoken="##" endtoken="##">
+              <token key="Version" value="${version}" />
+              <token key="Release" value="${release}" />
+            </replacetokens>
+          </filterchain>          
+        </copy>
+
+        <copy todir="./build/FirePHPCore-${version}${release}/lib" >
+          <fileset dir="./lib"/>
+          <filterchain>
+            <replacetokens begintoken="##" endtoken="##">
+              <token key="Version" value="${version}" />
+            </replacetokens>
+          </filterchain>          
+        </copy>
+
+        <copy todir="./build/pear" >
+          <fileset dir="./lib/FirePHPCore"/>
+          <filterchain>
+            <replacetokens begintoken="##" endtoken="##">
+              <token key="Version" value="${version}" />
+            </replacetokens>
+          </filterchain>          
+        </copy>
+
+    </target>
+
+
+
+
+    <target name="dist" depends="build">
+
+        <phingcall target="package-default"/>
+        <phingcall target="package-pear"/>
+
+        <echo msg="Do not forget to tag the release!"/>
+    
+    </target>
+    
+
+    <target name="package-default">
+        
+        <echo msg="Creating archive..." />
+
+        <exec command="zip -vr FirePHPCore.zip FirePHPCore-${version}${release}/*" dir="${project.basedir}/build/" passthru="true" />
+
+        <echo msg="Files copied and compressed in build directory OK!" />
+            
+        <echo msg="Renaming package archive to FirePHPCore-${version}${release}.zip."/>        
+      
+        <move file="./build/FirePHPCore.zip" tofile="./build/FirePHPLibrary-FirePHPCore-${version}${release}.zip" overwrite="true"/>
+
+    </target>
+    
+    <target name="package-pear">
+        
+        <php function="date" returnProperty="date">
+          <param value="Y-m-d"/>
+        </php> 
+
+        <copy file="pear.package.tpl.xml" tofile="./build/pear/package.xml" overwrite="true">
+         
+          <filterchain>
+            <replacetokens begintoken="##" endtoken="##">
+              <token key="Date" value="${date}" />
+              <token key="Version" value="${version}" />
+              <token key="Release" value="${release}" />
+              <token key="Stability" value="${pear.stability}" />
+            </replacetokens>
+          </filterchain>          
+        
+        </copy>
+        
+        <exec command="pear channel-discover pear.firephp.org" passthru="true"/>
+        <exec command="pear package package.xml" dir="./build/pear" passthru="true"/>
+                  
+    </target>    
+    
+    <target name="tag">
+
+        <exec command="svn copy --username christoph@christophdorn.com -m 'Tag ${version}${release} for FirePHPCore' 'https://firephp.googlecode.com/svn/branches/Library-FirePHPCore-${version}' 'https://firephp.googlecode.com/svn/tags/Library-FirePHPCore-${version}${release}'" passthru="true"/>
+
+    </target>
+    
+    
+    <target name="upload">
+      
+        <exec command="scp ./build/FirePHPLibrary-FirePHPCore-${version}${release}.zip ${upload.user}@${upload.server}:${upload.path}" passthru="true"/>
+       
+    </target>
+
+</project>

+ 29 - 0
sites/all/libraries/FirePHPCore/FirePHPCore/demo/LICENSE

@@ -0,0 +1,29 @@
+Software License Agreement (New BSD License)
+
+Copyright (c) 2006-2009, Christoph Dorn
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+
+    * Neither the name of Christoph Dorn nor the names of its
+      contributors may be used to endorse or promote products derived from this
+      software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 89 - 0
sites/all/libraries/FirePHPCore/FirePHPCore/demo/oo.php

@@ -0,0 +1,89 @@
+<?php
+
+/* ***** BEGIN LICENSE BLOCK *****
+ *  
+ * This file is part of FirePHP (http://www.firephp.org/).
+ * 
+ * Software License Agreement (New BSD License)
+ * 
+ * Copyright (c) 2006-2009, Christoph Dorn
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ * 
+ *     * Redistributions in binary form must reproduce the above copyright notice,
+ *       this list of conditions and the following disclaimer in the documentation
+ *       and/or other materials provided with the distribution.
+ * 
+ *     * Neither the name of Christoph Dorn nor the names of its
+ *       contributors may be used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * ***** END LICENSE BLOCK ***** */
+
+
+/* NOTE: You must have the FirePHPCore library in your include path */
+
+set_include_path('./../lib/'.PATH_SEPARATOR.get_include_path());
+ 
+
+require('FirePHPCore/FirePHP.class.php');
+
+/* NOTE: You must have Output Buffering enabled via
+         ob_start() or output_buffering ini directive. */
+
+
+$firephp = FirePHP::getInstance(true);
+
+
+$firephp->fb('Hello World'); /* Defaults to FirePHP::LOG */
+
+$firephp->fb('Log message'  ,FirePHP::LOG);
+$firephp->fb('Info message' ,FirePHP::INFO);
+$firephp->fb('Warn message' ,FirePHP::WARN);
+$firephp->fb('Error message',FirePHP::ERROR);
+
+$firephp->fb('Message with label','Label',FirePHP::LOG);
+
+$firephp->fb(array('key1'=>'val1',
+         'key2'=>array(array('v1','v2'),'v3')),
+   'TestArray',FirePHP::LOG);
+
+function test($Arg1) {
+  throw new Exception('Test Exception');
+}
+try {
+  test(array('Hello'=>'World'));
+} catch(Exception $e) {
+  /* Log exception including stack trace & variables */
+  $firephp->fb($e);
+}
+
+$firephp->fb('Backtrace to here',FirePHP::TRACE);
+
+$firephp->fb(array('2 SQL queries took 0.06 seconds',array(
+   array('SQL Statement','Time','Result'),
+   array('SELECT * FROM Foo','0.02',array('row1','row2')),
+   array('SELECT * FROM Bar','0.04',array('row1','row2'))
+  )),FirePHP::TABLE);
+
+/* Will show only in "Server" tab for the request */
+$firephp->fb(apache_request_headers(),'RequestHeaders',FirePHP::DUMP);
+
+
+print 'Hello World';

+ 79 - 0
sites/all/libraries/FirePHPCore/FirePHPCore/demo/oo.php4

@@ -0,0 +1,79 @@
+<?php
+
+/* ***** BEGIN LICENSE BLOCK *****
+ *  
+ * This file is part of FirePHP (http://www.firephp.org/).
+ * 
+ * Software License Agreement (New BSD License)
+ * 
+ * Copyright (c) 2006-2009, Christoph Dorn
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ * 
+ *     * Redistributions in binary form must reproduce the above copyright notice,
+ *       this list of conditions and the following disclaimer in the documentation
+ *       and/or other materials provided with the distribution.
+ * 
+ *     * Neither the name of Christoph Dorn nor the names of its
+ *       contributors may be used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * ***** END LICENSE BLOCK ***** */
+
+
+/* NOTE: You must have the FirePHPCore library in your include path */
+
+set_include_path('./../lib/'.PATH_SEPARATOR.get_include_path());
+ 
+
+require('FirePHPCore/FirePHP.class.php4');
+
+/* NOTE: You must have Output Buffering enabled via
+         ob_start() or output_buffering ini directive. */
+
+
+$firephp =& FirePHP::getInstance(true);
+
+
+$firephp->fb('Hello World'); /* Defaults to FirePHP::LOG */
+
+$firephp->fb('Log message'  ,FirePHP_LOG);
+$firephp->fb('Info message' ,FirePHP_INFO);
+$firephp->fb('Warn message' ,FirePHP_WARN);
+$firephp->fb('Error message',FirePHP_ERROR);
+
+$firephp->fb('Message with label','Label',FirePHP_LOG);
+
+$firephp->fb(array('key1'=>'val1',
+         'key2'=>array(array('v1','v2'),'v3')),
+   'TestArray',FirePHP_LOG);
+
+$firephp->fb('Backtrace to here',FirePHP_TRACE);
+
+$firephp->fb(array('2 SQL queries took 0.06 seconds',array(
+   array('SQL Statement','Time','Result'),
+   array('SELECT * FROM Foo','0.02',array('row1','row2')),
+   array('SELECT * FROM Bar','0.04',array('row1','row2'))
+  )),FirePHP_TABLE);
+
+/* Will show only in "Server" tab for the request */
+$firephp->fb(apache_request_headers(),'RequestHeaders',FirePHP_DUMP);
+
+
+print 'Hello World';

+ 86 - 0
sites/all/libraries/FirePHPCore/FirePHPCore/demo/procedural.php

@@ -0,0 +1,86 @@
+<?php
+
+/* ***** BEGIN LICENSE BLOCK *****
+ *  
+ * This file is part of FirePHP (http://www.firephp.org/).
+ * 
+ * Software License Agreement (New BSD License)
+ * 
+ * Copyright (c) 2006-2009, Christoph Dorn
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ * 
+ *     * Redistributions in binary form must reproduce the above copyright notice,
+ *       this list of conditions and the following disclaimer in the documentation
+ *       and/or other materials provided with the distribution.
+ * 
+ *     * Neither the name of Christoph Dorn nor the names of its
+ *       contributors may be used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * ***** END LICENSE BLOCK ***** */
+
+
+/* NOTE: You must have the FirePHPCore library in your include path */
+
+set_include_path('./../lib/'.PATH_SEPARATOR.get_include_path());
+ 
+
+require('FirePHPCore/fb.php');
+
+/* NOTE: You must have Output Buffering enabled via
+         ob_start() or output_buffering ini directive. */
+
+fb('Hello World'); /* Defaults to FirePHP::LOG */
+
+fb('Log message'  ,FirePHP::LOG);
+fb('Info message' ,FirePHP::INFO);
+fb('Warn message' ,FirePHP::WARN);
+fb('Error message',FirePHP::ERROR);
+
+fb('Message with label','Label',FirePHP::LOG);
+
+fb(array('key1'=>'val1',
+         'key2'=>array(array('v1','v2'),'v3')),
+   'TestArray',FirePHP::LOG);
+
+function test($Arg1) {
+  throw new Exception('Test Exception');
+}
+try {
+  test(array('Hello'=>'World'));
+} catch(Exception $e) {
+  /* Log exception including stack trace & variables */
+  fb($e);
+}
+
+fb('Backtrace to here',FirePHP::TRACE);
+
+fb(array('2 SQL queries took 0.06 seconds',array(
+   array('SQL Statement','Time','Result'),
+   array('SELECT * FROM Foo','0.02',array('row1','row2')),
+   array('SELECT * FROM Bar','0.04',array('row1','row2'))
+  )),FirePHP::TABLE);
+
+/* Will show only in "Server" tab for the request */
+fb(apache_request_headers(),'RequestHeaders',FirePHP::DUMP);
+
+
+print 'Hello World';
+

+ 76 - 0
sites/all/libraries/FirePHPCore/FirePHPCore/demo/procedural.php4

@@ -0,0 +1,76 @@
+<?php
+
+/* ***** BEGIN LICENSE BLOCK *****
+ *  
+ * This file is part of FirePHP (http://www.firephp.org/).
+ * 
+ * Software License Agreement (New BSD License)
+ * 
+ * Copyright (c) 2006-2009, Christoph Dorn
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ * 
+ *     * Redistributions in binary form must reproduce the above copyright notice,
+ *       this list of conditions and the following disclaimer in the documentation
+ *       and/or other materials provided with the distribution.
+ * 
+ *     * Neither the name of Christoph Dorn nor the names of its
+ *       contributors may be used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * ***** END LICENSE BLOCK ***** */
+
+
+/* NOTE: You must have the FirePHPCore library in your include path */
+
+set_include_path('./../lib/'.PATH_SEPARATOR.get_include_path());
+ 
+
+require('FirePHPCore/fb.php');
+
+/* NOTE: You must have Output Buffering enabled via
+         ob_start() or output_buffering ini directive. */
+
+fb('Hello World'); /* Defaults to FirePHP::LOG */
+
+fb('Log message'  ,FirePHP_LOG);
+fb('Info message' ,FirePHP_INFO);
+fb('Warn message' ,FirePHP_WARN);
+fb('Error message',FirePHP_ERROR);
+
+fb('Message with label','Label',FirePHP_LOG);
+
+fb(array('key1'=>'val1',
+         'key2'=>array(array('v1','v2'),'v3')),
+   'TestArray',FirePHP_LOG);
+
+fb('Backtrace to here',FirePHP_TRACE);
+
+fb(array('2 SQL queries took 0.06 seconds',array(
+   array('SQL Statement','Time','Result'),
+   array('SELECT * FROM Foo','0.02',array('row1','row2')),
+   array('SELECT * FROM Bar','0.04',array('row1','row2'))
+  )),FirePHP_TABLE);
+
+/* Will show only in "Server" tab for the request */
+fb(apache_request_headers(),'RequestHeaders',FirePHP_DUMP);
+
+
+print 'Hello World';
+

+ 1544 - 0
sites/all/libraries/FirePHPCore/FirePHPCore/lib/FirePHPCore/FirePHP.class.php

@@ -0,0 +1,1544 @@
+<?php
+/**
+ * *** BEGIN LICENSE BLOCK *****
+ *  
+ * This file is part of FirePHP (http://www.firephp.org/).
+ * 
+ * Software License Agreement (New BSD License)
+ * 
+ * Copyright (c) 2006-2009, Christoph Dorn
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ * 
+ *     * Redistributions in binary form must reproduce the above copyright notice,
+ *       this list of conditions and the following disclaimer in the documentation
+ *       and/or other materials provided with the distribution.
+ * 
+ *     * Neither the name of Christoph Dorn nor the names of its
+ *       contributors may be used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * ***** END LICENSE BLOCK *****
+ * 
+ * @copyright   Copyright (C) 2007-2009 Christoph Dorn
+ * @author      Christoph Dorn <christoph@christophdorn.com>
+ * @license     http://www.opensource.org/licenses/bsd-license.php
+ * @package     FirePHP
+ */
+
+/**
+ * @see http://code.google.com/p/firephp/issues/detail?id=112
+ */
+if(!defined('E_STRICT')) {
+  define('E_STRICT', 2048);
+}
+if(!defined('E_RECOVERABLE_ERROR')) {
+  define('E_RECOVERABLE_ERROR', 4096);
+}
+if(!defined('E_DEPRECATED')) {
+  define('E_DEPRECATED', 8192);
+}
+if(!defined('E_USER_DEPRECATED')) {
+  define('E_USER_DEPRECATED', 16384);
+} 
+ 
+/**
+ * Sends the given data to the FirePHP Firefox Extension.
+ * The data can be displayed in the Firebug Console or in the
+ * "Server" request tab.
+ * 
+ * For more information see: http://www.firephp.org/
+ * 
+ * @copyright   Copyright (C) 2007-2009 Christoph Dorn
+ * @author      Christoph Dorn <christoph@christophdorn.com>
+ * @license     http://www.opensource.org/licenses/bsd-license.php
+ * @package     FirePHP
+ */
+class FirePHP {
+  
+  /**
+   * FirePHP version
+   *
+   * @var string
+   */
+  const VERSION = '0.3';
+  
+  /**
+   * Firebug LOG level
+   *
+   * Logs a message to firebug console.
+   * 
+   * @var string
+   */
+  const LOG = 'LOG';
+  
+  /**
+   * Firebug INFO level
+   *
+   * Logs a message to firebug console and displays an info icon before the message.
+   * 
+   * @var string
+   */
+  const INFO = 'INFO';
+  
+  /**
+   * Firebug WARN level
+   *
+   * Logs a message to firebug console, displays an warning icon before the message and colors the line turquoise.
+   * 
+   * @var string
+   */
+  const WARN = 'WARN';
+  
+  /**
+   * Firebug ERROR level
+   *
+   * Logs a message to firebug console, displays an error icon before the message and colors the line yellow. Also increments the firebug error count.
+   * 
+   * @var string
+   */
+  const ERROR = 'ERROR';
+  
+  /**
+   * Dumps a variable to firebug's server panel
+   *
+   * @var string
+   */
+  const DUMP = 'DUMP';
+  
+  /**
+   * Displays a stack trace in firebug console
+   *
+   * @var string
+   */
+  const TRACE = 'TRACE';
+  
+  /**
+   * Displays an exception in firebug console
+   * 
+   * Increments the firebug error count.
+   *
+   * @var string
+   */
+  const EXCEPTION = 'EXCEPTION';
+  
+  /**
+   * Displays an table in firebug console
+   *
+   * @var string
+   */
+  const TABLE = 'TABLE';
+  
+  /**
+   * Starts a group in firebug console
+   * 
+   * @var string
+   */
+  const GROUP_START = 'GROUP_START';
+  
+  /**
+   * Ends a group in firebug console
+   * 
+   * @var string
+   */
+  const GROUP_END = 'GROUP_END';
+  
+  /**
+   * Singleton instance of FirePHP
+   *
+   * @var FirePHP
+   */
+  protected static $instance = null;
+  
+  /**
+   * Flag whether we are logging from within the exception handler
+   * 
+   * @var boolean
+   */
+  protected $inExceptionHandler = false;
+  
+  /**
+   * Flag whether to throw PHP errors that have been converted to ErrorExceptions
+   * 
+   * @var boolean
+   */
+  protected $throwErrorExceptions = true;
+  
+  /**
+   * Flag whether to convert PHP assertion errors to Exceptions
+   * 
+   * @var boolean
+   */
+  protected $convertAssertionErrorsToExceptions = true;
+  
+  /**
+   * Flag whether to throw PHP assertion errors that have been converted to Exceptions
+   * 
+   * @var boolean
+   */
+  protected $throwAssertionExceptions = false;
+  
+  /**
+   * Wildfire protocol message index
+   *
+   * @var int
+   */
+  protected $messageIndex = 1;
+    
+  /**
+   * Options for the library
+   * 
+   * @var array
+   */
+  protected $options = array('maxObjectDepth' => 10,
+                             'maxArrayDepth' => 20,
+                             'useNativeJsonEncode' => true,
+                             'includeLineNumbers' => true);
+
+  /**
+   * Filters used to exclude object members when encoding
+   * 
+   * @var array
+   */
+  protected $objectFilters = array();
+  
+  /**
+   * A stack of objects used to detect recursion during object encoding
+   * 
+   * @var object
+   */
+  protected $objectStack = array();
+  
+  /**
+   * Flag to enable/disable logging
+   * 
+   * @var boolean
+   */
+  protected $enabled = true;
+
+  /**
+   * The object constructor
+   */
+  function __construct() {
+  }
+
+  /**
+   * When the object gets serialized only include specific object members.
+   * 
+   * @return array
+   */  
+  public function __sleep() {
+    return array('options','objectFilters','enabled');
+  }
+    
+  /**
+   * Gets singleton instance of FirePHP
+   *
+   * @param boolean $AutoCreate
+   * @return FirePHP
+   */
+  public static function getInstance($AutoCreate=false) {
+    if($AutoCreate===true && !self::$instance) {
+      self::init();
+    }
+    return self::$instance;
+  }
+   
+  /**
+   * Creates FirePHP object and stores it for singleton access
+   *
+   * @return FirePHP
+   */
+  public static function init() {
+    return self::$instance = new self();
+  }
+  
+  /**
+   * Enable and disable logging to Firebug
+   * 
+   * @param boolean $Enabled TRUE to enable, FALSE to disable
+   * @return void
+   */
+  public function setEnabled($Enabled) {
+    $this->enabled = $Enabled;
+  }
+  
+  /**
+   * Check if logging is enabled
+   * 
+   * @return boolean TRUE if enabled
+   */
+  public function getEnabled() {
+    return $this->enabled;
+  }
+  
+  /**
+   * Specify a filter to be used when encoding an object
+   * 
+   * Filters are used to exclude object members.
+   * 
+   * @param string $Class The class name of the object
+   * @param array $Filter An array of members to exclude
+   * @return void
+   */
+  public function setObjectFilter($Class, $Filter) {
+    $this->objectFilters[strtolower($Class)] = $Filter;
+  }
+  
+  /**
+   * Set some options for the library
+   * 
+   * Options:
+   *  - maxObjectDepth: The maximum depth to traverse objects (default: 10)
+   *  - maxArrayDepth: The maximum depth to traverse arrays (default: 20)
+   *  - useNativeJsonEncode: If true will use json_encode() (default: true)
+   *  - includeLineNumbers: If true will include line numbers and filenames (default: true)
+   * 
+   * @param array $Options The options to be set
+   * @return void
+   */
+  public function setOptions($Options) {
+    $this->options = array_merge($this->options,$Options);
+  }
+  
+  /**
+   * Get options from the library
+   *
+   * @return array The currently set options
+   */
+  public function getOptions() {
+    return $this->options;
+  }
+  
+  /**
+   * Register FirePHP as your error handler
+   * 
+   * Will throw exceptions for each php error.
+   * 
+   * @return mixed Returns a string containing the previously defined error handler (if any)
+   */
+  public function registerErrorHandler($throwErrorExceptions=true)
+  {
+    //NOTE: The following errors will not be caught by this error handler:
+    //      E_ERROR, E_PARSE, E_CORE_ERROR,
+    //      E_CORE_WARNING, E_COMPILE_ERROR,
+    //      E_COMPILE_WARNING, E_STRICT
+    
+    $this->throwErrorExceptions = $throwErrorExceptions;
+    
+    return set_error_handler(array($this,'errorHandler'));     
+  }
+
+  /**
+   * FirePHP's error handler
+   * 
+   * Throws exception for each php error that will occur.
+   *
+   * @param int $errno
+   * @param string $errstr
+   * @param string $errfile
+   * @param int $errline
+   * @param array $errcontext
+   */
+  public function errorHandler($errno, $errstr, $errfile, $errline, $errcontext)
+  {
+    // Don't throw exception if error reporting is switched off
+    if (error_reporting() == 0) {
+      return;
+    }
+    // Only throw exceptions for errors we are asking for
+    if (error_reporting() & $errno) {
+
+      $exception = new ErrorException($errstr, 0, $errno, $errfile, $errline);
+      if($this->throwErrorExceptions) {
+        throw $exception;
+      } else {
+        $this->fb($exception);
+      }
+    }
+  }
+  
+  /**
+   * Register FirePHP as your exception handler
+   * 
+   * @return mixed Returns the name of the previously defined exception handler,
+   *               or NULL on error.
+   *               If no previous handler was defined, NULL is also returned.
+   */
+  public function registerExceptionHandler()
+  {
+    return set_exception_handler(array($this,'exceptionHandler'));     
+  }
+  
+  /**
+   * FirePHP's exception handler
+   * 
+   * Logs all exceptions to your firebug console and then stops the script.
+   *
+   * @param Exception $Exception
+   * @throws Exception
+   */
+  function exceptionHandler($Exception) {
+    
+    $this->inExceptionHandler = true;
+
+    header('HTTP/1.1 500 Internal Server Error');
+
+    $this->fb($Exception);
+    
+    $this->inExceptionHandler = false;
+  }
+  
+  /**
+   * Register FirePHP driver as your assert callback
+   * 
+   * @param boolean $convertAssertionErrorsToExceptions
+   * @param boolean $throwAssertionExceptions
+   * @return mixed Returns the original setting or FALSE on errors
+   */
+  public function registerAssertionHandler($convertAssertionErrorsToExceptions=true, $throwAssertionExceptions=false)
+  {
+    $this->convertAssertionErrorsToExceptions = $convertAssertionErrorsToExceptions;
+    $this->throwAssertionExceptions = $throwAssertionExceptions;
+    
+    if($throwAssertionExceptions && !$convertAssertionErrorsToExceptions) {
+      throw $this->newException('Cannot throw assertion exceptions as assertion errors are not being converted to exceptions!');
+    }
+    
+    return assert_options(ASSERT_CALLBACK, array($this, 'assertionHandler'));
+  }
+  
+  /**
+   * FirePHP's assertion handler
+   *
+   * Logs all assertions to your firebug console and then stops the script.
+   *
+   * @param string $file File source of assertion
+   * @param int    $line Line source of assertion
+   * @param mixed  $code Assertion code
+   */
+  public function assertionHandler($file, $line, $code)
+  {
+
+    if($this->convertAssertionErrorsToExceptions) {
+      
+      $exception = new ErrorException('Assertion Failed - Code[ '.$code.' ]', 0, null, $file, $line);
+
+      if($this->throwAssertionExceptions) {
+        throw $exception;
+      } else {
+        $this->fb($exception);
+      }
+    
+    } else {
+    
+      $this->fb($code, 'Assertion Failed', FirePHP::ERROR, array('File'=>$file,'Line'=>$line));
+    
+    }
+  }  
+  
+  /**
+   * Set custom processor url for FirePHP
+   *
+   * @param string $URL
+   */    
+  public function setProcessorUrl($URL)
+  {
+    $this->setHeader('X-FirePHP-ProcessorURL', $URL);
+  }
+
+  /**
+   * Set custom renderer url for FirePHP
+   *
+   * @param string $URL
+   */
+  public function setRendererUrl($URL)
+  {
+    $this->setHeader('X-FirePHP-RendererURL', $URL);
+  }
+  
+  /**
+   * Start a group for following messages.
+   * 
+   * Options:
+   *   Collapsed: [true|false]
+   *   Color:     [#RRGGBB|ColorName]
+   *
+   * @param string $Name
+   * @param array $Options OPTIONAL Instructions on how to log the group
+   * @return true
+   * @throws Exception
+   */
+  public function group($Name, $Options=null) {
+    
+    if(!$Name) {
+      throw $this->newException('You must specify a label for the group!');
+    }
+    
+    if($Options) {
+      if(!is_array($Options)) {
+        throw $this->newException('Options must be defined as an array!');
+      }
+      if(array_key_exists('Collapsed', $Options)) {
+        $Options['Collapsed'] = ($Options['Collapsed'])?'true':'false';
+      }
+    }
+    
+    return $this->fb(null, $Name, FirePHP::GROUP_START, $Options);
+  }
+  
+  /**
+   * Ends a group you have started before
+   *
+   * @return true
+   * @throws Exception
+   */
+  public function groupEnd() {
+    return $this->fb(null, null, FirePHP::GROUP_END);
+  }
+
+  /**
+   * Log object with label to firebug console
+   *
+   * @see FirePHP::LOG
+   * @param mixes $Object
+   * @param string $Label
+   * @return true
+   * @throws Exception
+   */
+  public function log($Object, $Label=null) {
+    return $this->fb($Object, $Label, FirePHP::LOG);
+  } 
+
+  /**
+   * Log object with label to firebug console
+   *
+   * @see FirePHP::INFO
+   * @param mixes $Object
+   * @param string $Label
+   * @return true
+   * @throws Exception
+   */
+  public function info($Object, $Label=null) {
+    return $this->fb($Object, $Label, FirePHP::INFO);
+  } 
+
+  /**
+   * Log object with label to firebug console
+   *
+   * @see FirePHP::WARN
+   * @param mixes $Object
+   * @param string $Label
+   * @return true
+   * @throws Exception
+   */
+  public function warn($Object, $Label=null) {
+    return $this->fb($Object, $Label, FirePHP::WARN);
+  } 
+
+  /**
+   * Log object with label to firebug console
+   *
+   * @see FirePHP::ERROR
+   * @param mixes $Object
+   * @param string $Label
+   * @return true
+   * @throws Exception
+   */
+  public function error($Object, $Label=null) {
+    return $this->fb($Object, $Label, FirePHP::ERROR);
+  } 
+
+  /**
+   * Dumps key and variable to firebug server panel
+   *
+   * @see FirePHP::DUMP
+   * @param string $Key
+   * @param mixed $Variable
+   * @return true
+   * @throws Exception
+   */
+  public function dump($Key, $Variable) {
+    return $this->fb($Variable, $Key, FirePHP::DUMP);
+  }
+  
+  /**
+   * Log a trace in the firebug console
+   *
+   * @see FirePHP::TRACE
+   * @param string $Label
+   * @return true
+   * @throws Exception
+   */
+  public function trace($Label) {
+    return $this->fb($Label, FirePHP::TRACE);
+  } 
+
+  /**
+   * Log a table in the firebug console
+   *
+   * @see FirePHP::TABLE
+   * @param string $Label
+   * @param string $Table
+   * @return true
+   * @throws Exception
+   */
+  public function table($Label, $Table) {
+    return $this->fb($Table, $Label, FirePHP::TABLE);
+  }
+  
+  /**
+   * Check if FirePHP is installed on client
+   *
+   * @return boolean
+   */
+  public function detectClientExtension() {
+    /* Check if FirePHP is installed on client */
+    if(!@preg_match_all('/\sFirePHP\/([\.|\d]*)\s?/si',$this->getUserAgent(),$m) ||
+       !version_compare($m[1][0],'0.0.6','>=')) {
+      return false;
+    }
+    return true;    
+  }
+ 
+  /**
+   * Log varible to Firebug
+   * 
+   * @see http://www.firephp.org/Wiki/Reference/Fb
+   * @param mixed $Object The variable to be logged
+   * @return true Return TRUE if message was added to headers, FALSE otherwise
+   * @throws Exception
+   */
+  public function fb($Object) {
+  
+    if(!$this->enabled) {
+      return false;
+    }
+  
+    if (headers_sent($filename, $linenum)) {
+      // If we are logging from within the exception handler we cannot throw another exception
+      if($this->inExceptionHandler) {
+        // Simply echo the error out to the page
+        echo '<div style="border: 2px solid red; font-family: Arial; font-size: 12px; background-color: lightgray; padding: 5px;"><span style="color: red; font-weight: bold;">FirePHP ERROR:</span> Headers already sent in <b>'.$filename.'</b> on line <b>'.$linenum.'</b>. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.</div>';
+      } else {
+        throw $this->newException('Headers already sent in '.$filename.' on line '.$linenum.'. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.');
+      }
+    }
+  
+    $Type = null;
+    $Label = null;
+    $Options = array();
+  
+    if(func_num_args()==1) {
+    } else
+    if(func_num_args()==2) {
+      switch(func_get_arg(1)) {
+        case self::LOG:
+        case self::INFO:
+        case self::WARN:
+        case self::ERROR:
+        case self::DUMP:
+        case self::TRACE:
+        case self::EXCEPTION:
+        case self::TABLE:
+        case self::GROUP_START:
+        case self::GROUP_END:
+          $Type = func_get_arg(1);
+          break;
+        default:
+          $Label = func_get_arg(1);
+          break;
+      }
+    } else
+    if(func_num_args()==3) {
+      $Type = func_get_arg(2);
+      $Label = func_get_arg(1);
+    } else
+    if(func_num_args()==4) {
+      $Type = func_get_arg(2);
+      $Label = func_get_arg(1);
+      $Options = func_get_arg(3);
+    } else {
+      throw $this->newException('Wrong number of arguments to fb() function!');
+    }
+  
+  
+    if(!$this->detectClientExtension()) {
+      return false;
+    }
+  
+    $meta = array();
+    $skipFinalObjectEncode = false;
+  
+    if($Object instanceof Exception) {
+
+      $meta['file'] = $this->_escapeTraceFile($Object->getFile());
+      $meta['line'] = $Object->getLine();
+      
+      $trace = $Object->getTrace();
+      if($Object instanceof ErrorException
+         && isset($trace[0]['function'])
+         && $trace[0]['function']=='errorHandler'
+         && isset($trace[0]['class'])
+         && $trace[0]['class']=='FirePHP') {
+           
+        $severity = false;
+        switch($Object->getSeverity()) {
+          case E_WARNING: $severity = 'E_WARNING'; break;
+          case E_NOTICE: $severity = 'E_NOTICE'; break;
+          case E_USER_ERROR: $severity = 'E_USER_ERROR'; break;
+          case E_USER_WARNING: $severity = 'E_USER_WARNING'; break;
+          case E_USER_NOTICE: $severity = 'E_USER_NOTICE'; break;
+          case E_STRICT: $severity = 'E_STRICT'; break;
+          case E_RECOVERABLE_ERROR: $severity = 'E_RECOVERABLE_ERROR'; break;
+          case E_DEPRECATED: $severity = 'E_DEPRECATED'; break;
+          case E_USER_DEPRECATED: $severity = 'E_USER_DEPRECATED'; break;
+        }
+           
+        $Object = array('Class'=>get_class($Object),
+                        'Message'=>$severity.': '.$Object->getMessage(),
+                        'File'=>$this->_escapeTraceFile($Object->getFile()),
+                        'Line'=>$Object->getLine(),
+                        'Type'=>'trigger',
+                        'Trace'=>$this->_escapeTrace(array_splice($trace,2)));
+        $skipFinalObjectEncode = true;
+      } else {
+        $Object = array('Class'=>get_class($Object),
+                        'Message'=>$Object->getMessage(),
+                        'File'=>$this->_escapeTraceFile($Object->getFile()),
+                        'Line'=>$Object->getLine(),
+                        'Type'=>'throw',
+                        'Trace'=>$this->_escapeTrace($trace));
+        $skipFinalObjectEncode = true;
+      }
+      $Type = self::EXCEPTION;
+      
+    } else
+    if($Type==self::TRACE) {
+      
+      $trace = debug_backtrace();
+      if(!$trace) return false;
+      for( $i=0 ; $i<sizeof($trace) ; $i++ ) {
+
+        if(isset($trace[$i]['class'])
+           && isset($trace[$i]['file'])
+           && ($trace[$i]['class']=='FirePHP'
+               || $trace[$i]['class']=='FB')
+           && (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php'
+               || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) {
+          /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */
+        } else
+        if(isset($trace[$i]['class'])
+           && isset($trace[$i+1]['file'])
+           && $trace[$i]['class']=='FirePHP'
+           && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') {
+          /* Skip fb() */
+        } else
+        if($trace[$i]['function']=='fb'
+           || $trace[$i]['function']=='trace'
+           || $trace[$i]['function']=='send') {
+          $Object = array('Class'=>isset($trace[$i]['class'])?$trace[$i]['class']:'',
+                          'Type'=>isset($trace[$i]['type'])?$trace[$i]['type']:'',
+                          'Function'=>isset($trace[$i]['function'])?$trace[$i]['function']:'',
+                          'Message'=>$trace[$i]['args'][0],
+                          'File'=>isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'',
+                          'Line'=>isset($trace[$i]['line'])?$trace[$i]['line']:'',
+                          'Args'=>isset($trace[$i]['args'])?$this->encodeObject($trace[$i]['args']):'',
+                          'Trace'=>$this->_escapeTrace(array_splice($trace,$i+1)));
+
+          $skipFinalObjectEncode = true;
+          $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'';
+          $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:'';
+          break;
+        }
+      }
+
+    } else
+    if($Type==self::TABLE) {
+      
+      if(isset($Object[0]) && is_string($Object[0])) {
+        $Object[1] = $this->encodeTable($Object[1]);
+      } else {
+        $Object = $this->encodeTable($Object);
+      }
+
+      $skipFinalObjectEncode = true;
+      
+    } else
+    if($Type==self::GROUP_START) {
+      
+      if(!$Label) {
+        throw $this->newException('You must specify a label for the group!');
+      }
+      
+    } else {
+      if($Type===null) {
+        $Type = self::LOG;
+      }
+    }
+    
+    if($this->options['includeLineNumbers']) {
+      if(!isset($meta['file']) || !isset($meta['line'])) {
+
+        $trace = debug_backtrace();
+        for( $i=0 ; $trace && $i<sizeof($trace) ; $i++ ) {
+  
+          if(isset($trace[$i]['class'])
+             && isset($trace[$i]['file'])
+             && ($trace[$i]['class']=='FirePHP'
+                 || $trace[$i]['class']=='FB')
+             && (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php'
+                 || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) {
+            /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */
+          } else
+          if(isset($trace[$i]['class'])
+             && isset($trace[$i+1]['file'])
+             && $trace[$i]['class']=='FirePHP'
+             && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') {
+            /* Skip fb() */
+          } else
+          if(isset($trace[$i]['file'])
+             && substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php') {
+            /* Skip FB::fb() */
+          } else {
+            $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'';
+            $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:'';
+            break;
+          }
+        }      
+      
+      }
+    } else {
+      unset($meta['file']);
+      unset($meta['line']);
+    }
+
+  	$this->setHeader('X-Wf-Protocol-1','http://meta.wildfirehq.org/Protocol/JsonStream/0.2');
+  	$this->setHeader('X-Wf-1-Plugin-1','http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/'.self::VERSION);
+ 
+    $structure_index = 1;
+    if($Type==self::DUMP) {
+      $structure_index = 2;
+    	$this->setHeader('X-Wf-1-Structure-2','http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1');
+    } else {
+    	$this->setHeader('X-Wf-1-Structure-1','http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1');
+    }
+  
+    if($Type==self::DUMP) {
+    	$msg = '{"'.$Label.'":'.$this->jsonEncode($Object, $skipFinalObjectEncode).'}';
+    } else {
+      $msg_meta = $Options;
+      $msg_meta['Type'] = $Type;
+      if($Label!==null) {
+        $msg_meta['Label'] = $Label;
+      }
+      if(isset($meta['file']) && !isset($msg_meta['File'])) {
+        $msg_meta['File'] = $meta['file'];
+      }
+      if(isset($meta['line']) && !isset($msg_meta['Line'])) {
+        $msg_meta['Line'] = $meta['line'];
+      }
+    	$msg = '['.$this->jsonEncode($msg_meta).','.$this->jsonEncode($Object, $skipFinalObjectEncode).']';
+    }
+    
+    $parts = explode("\n",chunk_split($msg, 5000, "\n"));
+
+    for( $i=0 ; $i<count($parts) ; $i++) {
+        
+        $part = $parts[$i];
+        if ($part) {
+            
+            if(count($parts)>2) {
+              // Message needs to be split into multiple parts
+              $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex,
+                               (($i==0)?strlen($msg):'')
+                               . '|' . $part . '|'
+                               . (($i<count($parts)-2)?'\\':''));
+            } else {
+              $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex,
+                               strlen($part) . '|' . $part . '|');
+            }
+            
+            $this->messageIndex++;
+            
+            if ($this->messageIndex > 99999) {
+                throw $this->newException('Maximum number (99,999) of messages reached!');             
+            }
+        }
+    }
+
+  	$this->setHeader('X-Wf-1-Index',$this->messageIndex-1);
+
+    return true;
+  }
+  
+  /**
+   * Standardizes path for windows systems.
+   *
+   * @param string $Path
+   * @return string
+   */
+  protected function _standardizePath($Path) {
+    return preg_replace('/\\\\+/','/',$Path);    
+  }
+  
+  /**
+   * Escape trace path for windows systems
+   *
+   * @param array $Trace
+   * @return array
+   */
+  protected function _escapeTrace($Trace) {
+    if(!$Trace) return $Trace;
+    for( $i=0 ; $i<sizeof($Trace) ; $i++ ) {
+      if(isset($Trace[$i]['file'])) {
+        $Trace[$i]['file'] = $this->_escapeTraceFile($Trace[$i]['file']);
+      }
+      if(isset($Trace[$i]['args'])) {
+        $Trace[$i]['args'] = $this->encodeObject($Trace[$i]['args']);
+      }
+    }
+    return $Trace;    
+  }
+  
+  /**
+   * Escape file information of trace for windows systems
+   *
+   * @param string $File
+   * @return string
+   */
+  protected function _escapeTraceFile($File) {
+    /* Check if we have a windows filepath */
+    if(strpos($File,'\\')) {
+      /* First strip down to single \ */
+      
+      $file = preg_replace('/\\\\+/','\\',$File);
+      
+      return $file;
+    }
+    return $File;
+  }
+
+  /**
+   * Send header
+   *
+   * @param string $Name
+   * @param string_type $Value
+   */
+  protected function setHeader($Name, $Value) {
+    return header($Name.': '.$Value);
+  }
+
+  /**
+   * Get user agent
+   *
+   * @return string|false
+   */
+  protected function getUserAgent() {
+    if(!isset($_SERVER['HTTP_USER_AGENT'])) return false;
+    return $_SERVER['HTTP_USER_AGENT'];
+  }
+
+  /**
+   * Returns a new exception
+   *
+   * @param string $Message
+   * @return Exception
+   */
+  protected function newException($Message) {
+    return new Exception($Message);
+  }
+  
+  /**
+   * Encode an object into a JSON string
+   * 
+   * Uses PHP's jeson_encode() if available
+   * 
+   * @param object $Object The object to be encoded
+   * @return string The JSON string
+   */
+  public function jsonEncode($Object, $skipObjectEncode=false)
+  {
+    if(!$skipObjectEncode) {
+      $Object = $this->encodeObject($Object);
+    }
+    
+    if(function_exists('json_encode')
+       && $this->options['useNativeJsonEncode']!=false) {
+
+      return json_encode($Object);
+    } else {
+      return $this->json_encode($Object);
+    }
+  }
+
+  /**
+   * Encodes a table by encoding each row and column with encodeObject()
+   * 
+   * @param array $Table The table to be encoded
+   * @return array
+   */  
+  protected function encodeTable($Table) {
+    
+    if(!$Table) return $Table;
+    
+    $new_table = array();
+    foreach($Table as $row) {
+  
+      if(is_array($row)) {
+        $new_row = array();
+        
+        foreach($row as $item) {
+          $new_row[] = $this->encodeObject($item);
+        }
+        
+        $new_table[] = $new_row;
+      }
+    }
+    
+    return $new_table;
+  }
+
+  /**
+   * Encodes an object including members with
+   * protected and private visibility
+   * 
+   * @param Object $Object The object to be encoded
+   * @param int $Depth The current traversal depth
+   * @return array All members of the object
+   */
+  protected function encodeObject($Object, $ObjectDepth = 1, $ArrayDepth = 1)
+  {
+    $return = array();
+
+    if (is_resource($Object)) {
+
+      return '** '.(string)$Object.' **';
+
+    } else    
+    if (is_object($Object)) {
+
+        if ($ObjectDepth > $this->options['maxObjectDepth']) {
+          return '** Max Object Depth ('.$this->options['maxObjectDepth'].') **';
+        }
+        
+        foreach ($this->objectStack as $refVal) {
+            if ($refVal === $Object) {
+                return '** Recursion ('.get_class($Object).') **';
+            }
+        }
+        array_push($this->objectStack, $Object);
+                
+        $return['__className'] = $class = get_class($Object);
+        $class_lower = strtolower($class);
+
+        $reflectionClass = new ReflectionClass($class);  
+        $properties = array();
+        foreach( $reflectionClass->getProperties() as $property) {
+          $properties[$property->getName()] = $property;
+        }
+            
+        $members = (array)$Object;
+            
+        foreach( $properties as $raw_name => $property ) {
+          
+          $name = $raw_name;
+          if($property->isStatic()) {
+            $name = 'static:'.$name;
+          }
+          if($property->isPublic()) {
+            $name = 'public:'.$name;
+          } else
+          if($property->isPrivate()) {
+            $name = 'private:'.$name;
+            $raw_name = "\0".$class."\0".$raw_name;
+          } else
+          if($property->isProtected()) {
+            $name = 'protected:'.$name;
+            $raw_name = "\0".'*'."\0".$raw_name;
+          }
+          
+          if(!(isset($this->objectFilters[$class_lower])
+               && is_array($this->objectFilters[$class_lower])
+               && in_array($raw_name,$this->objectFilters[$class_lower]))) {
+
+            if(array_key_exists($raw_name,$members)
+               && !$property->isStatic()) {
+              
+              $return[$name] = $this->encodeObject($members[$raw_name], $ObjectDepth + 1, 1);      
+            
+            } else {
+              if(method_exists($property,'setAccessible')) {
+                $property->setAccessible(true);
+                $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1);
+              } else
+              if($property->isPublic()) {
+                $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1);
+              } else {
+                $return[$name] = '** Need PHP 5.3 to get value **';
+              }
+            }
+          } else {
+            $return[$name] = '** Excluded by Filter **';
+          }
+        }
+        
+        // Include all members that are not defined in the class
+        // but exist in the object
+        foreach( $members as $raw_name => $value ) {
+          
+          $name = $raw_name;
+          
+          if ($name{0} == "\0") {
+            $parts = explode("\0", $name);
+            $name = $parts[2];
+          }
+          
+          if(!isset($properties[$name])) {
+            $name = 'undeclared:'.$name;
+              
+            if(!(isset($this->objectFilters[$class_lower])
+                 && is_array($this->objectFilters[$class_lower])
+                 && in_array($raw_name,$this->objectFilters[$class_lower]))) {
+              
+              $return[$name] = $this->encodeObject($value, $ObjectDepth + 1, 1);
+            } else {
+              $return[$name] = '** Excluded by Filter **';
+            }
+          }
+        }
+        
+        array_pop($this->objectStack);
+        
+    } elseif (is_array($Object)) {
+
+        if ($ArrayDepth > $this->options['maxArrayDepth']) {
+          return '** Max Array Depth ('.$this->options['maxArrayDepth'].') **';
+        }
+      
+        foreach ($Object as $key => $val) {
+          
+          // Encoding the $GLOBALS PHP array causes an infinite loop
+          // if the recursion is not reset here as it contains
+          // a reference to itself. This is the only way I have come up
+          // with to stop infinite recursion in this case.
+          if($key=='GLOBALS'
+             && is_array($val)
+             && array_key_exists('GLOBALS',$val)) {
+            $val['GLOBALS'] = '** Recursion (GLOBALS) **';
+          }
+          
+          $return[$key] = $this->encodeObject($val, 1, $ArrayDepth + 1);
+        }
+    } else {
+      if(self::is_utf8($Object)) {
+        return $Object;
+      } else {
+        return utf8_encode($Object);
+      }
+    }
+    return $return;
+  }
+
+  /**
+   * Returns true if $string is valid UTF-8 and false otherwise.
+   *
+   * @param mixed $str String to be tested
+   * @return boolean
+   */
+  protected static function is_utf8($str) {
+    $c=0; $b=0;
+    $bits=0;
+    $len=strlen($str);
+    for($i=0; $i<$len; $i++){
+        $c=ord($str[$i]);
+        if($c > 128){
+            if(($c >= 254)) return false;
+            elseif($c >= 252) $bits=6;
+            elseif($c >= 248) $bits=5;
+            elseif($c >= 240) $bits=4;
+            elseif($c >= 224) $bits=3;
+            elseif($c >= 192) $bits=2;
+            else return false;
+            if(($i+$bits) > $len) return false;
+            while($bits > 1){
+                $i++;
+                $b=ord($str[$i]);
+                if($b < 128 || $b > 191) return false;
+                $bits--;
+            }
+        }
+    }
+    return true;
+  } 
+
+  /**
+   * Converts to and from JSON format.
+   *
+   * JSON (JavaScript Object Notation) is a lightweight data-interchange
+   * format. It is easy for humans to read and write. It is easy for machines
+   * to parse and generate. It is based on a subset of the JavaScript
+   * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
+   * This feature can also be found in  Python. JSON is a text format that is
+   * completely language independent but uses conventions that are familiar
+   * to programmers of the C-family of languages, including C, C++, C#, Java,
+   * JavaScript, Perl, TCL, and many others. These properties make JSON an
+   * ideal data-interchange language.
+   *
+   * This package provides a simple encoder and decoder for JSON notation. It
+   * is intended for use with client-side Javascript applications that make
+   * use of HTTPRequest to perform server communication functions - data can
+   * be encoded into JSON notation for use in a client-side javascript, or
+   * decoded from incoming Javascript requests. JSON format is native to
+   * Javascript, and can be directly eval()'ed with no further parsing
+   * overhead
+   *
+   * All strings should be in ASCII or UTF-8 format!
+   *
+   * LICENSE: Redistribution and use in source and binary forms, with or
+   * without modification, are permitted provided that the following
+   * conditions are met: Redistributions of source code must retain the
+   * above copyright notice, this list of conditions and the following
+   * disclaimer. Redistributions in binary form must reproduce the above
+   * copyright notice, this list of conditions and the following disclaimer
+   * in the documentation and/or other materials provided with the
+   * distribution.
+   *
+   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+   * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+   * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+   * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+   * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+   * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+   * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+   * DAMAGE.
+   *
+   * @category
+   * @package     Services_JSON
+   * @author      Michal Migurski <mike-json@teczno.com>
+   * @author      Matt Knapp <mdknapp[at]gmail[dot]com>
+   * @author      Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
+   * @author      Christoph Dorn <christoph@christophdorn.com>
+   * @copyright   2005 Michal Migurski
+   * @version     CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
+   * @license     http://www.opensource.org/licenses/bsd-license.php
+   * @link        http://pear.php.net/pepr/pepr-proposal-show.php?id=198
+   */
+   
+     
+  /**
+   * Keep a list of objects as we descend into the array so we can detect recursion.
+   */
+  private $json_objectStack = array();
+
+
+ /**
+  * convert a string from one UTF-8 char to one UTF-16 char
+  *
+  * Normally should be handled by mb_convert_encoding, but
+  * provides a slower PHP-only method for installations
+  * that lack the multibye string extension.
+  *
+  * @param    string  $utf8   UTF-8 character
+  * @return   string  UTF-16 character
+  * @access   private
+  */
+  private function json_utf82utf16($utf8)
+  {
+      // oh please oh please oh please oh please oh please
+      if(function_exists('mb_convert_encoding')) {
+          return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
+      }
+
+      switch(strlen($utf8)) {
+          case 1:
+              // this case should never be reached, because we are in ASCII range
+              // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+              return $utf8;
+
+          case 2:
+              // return a UTF-16 character from a 2-byte UTF-8 char
+              // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+              return chr(0x07 & (ord($utf8{0}) >> 2))
+                   . chr((0xC0 & (ord($utf8{0}) << 6))
+                       | (0x3F & ord($utf8{1})));
+
+          case 3:
+              // return a UTF-16 character from a 3-byte UTF-8 char
+              // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+              return chr((0xF0 & (ord($utf8{0}) << 4))
+                       | (0x0F & (ord($utf8{1}) >> 2)))
+                   . chr((0xC0 & (ord($utf8{1}) << 6))
+                       | (0x7F & ord($utf8{2})));
+      }
+
+      // ignoring UTF-32 for now, sorry
+      return '';
+  }
+
+ /**
+  * encodes an arbitrary variable into JSON format
+  *
+  * @param    mixed   $var    any number, boolean, string, array, or object to be encoded.
+  *                           see argument 1 to Services_JSON() above for array-parsing behavior.
+  *                           if var is a strng, note that encode() always expects it
+  *                           to be in ASCII or UTF-8 format!
+  *
+  * @return   mixed   JSON string representation of input var or an error if a problem occurs
+  * @access   public
+  */
+  private function json_encode($var)
+  {
+    
+    if(is_object($var)) {
+      if(in_array($var,$this->json_objectStack)) {
+        return '"** Recursion **"';
+      }
+    }
+          
+      switch (gettype($var)) {
+          case 'boolean':
+              return $var ? 'true' : 'false';
+
+          case 'NULL':
+              return 'null';
+
+          case 'integer':
+              return (int) $var;
+
+          case 'double':
+          case 'float':
+              return (float) $var;
+
+          case 'string':
+              // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
+              $ascii = '';
+              $strlen_var = strlen($var);
+
+             /*
+              * Iterate over every character in the string,
+              * escaping with a slash or encoding to UTF-8 where necessary
+              */
+              for ($c = 0; $c < $strlen_var; ++$c) {
+
+                  $ord_var_c = ord($var{$c});
+
+                  switch (true) {
+                      case $ord_var_c == 0x08:
+                          $ascii .= '\b';
+                          break;
+                      case $ord_var_c == 0x09:
+                          $ascii .= '\t';
+                          break;
+                      case $ord_var_c == 0x0A:
+                          $ascii .= '\n';
+                          break;
+                      case $ord_var_c == 0x0C:
+                          $ascii .= '\f';
+                          break;
+                      case $ord_var_c == 0x0D:
+                          $ascii .= '\r';
+                          break;
+
+                      case $ord_var_c == 0x22:
+                      case $ord_var_c == 0x2F:
+                      case $ord_var_c == 0x5C:
+                          // double quote, slash, slosh
+                          $ascii .= '\\'.$var{$c};
+                          break;
+
+                      case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
+                          // characters U-00000000 - U-0000007F (same as ASCII)
+                          $ascii .= $var{$c};
+                          break;
+
+                      case (($ord_var_c & 0xE0) == 0xC0):
+                          // characters U-00000080 - U-000007FF, mask 110XXXXX
+                          // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                          $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
+                          $c += 1;
+                          $utf16 = $this->json_utf82utf16($char);
+                          $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                          break;
+
+                      case (($ord_var_c & 0xF0) == 0xE0):
+                          // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+                          // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                          $char = pack('C*', $ord_var_c,
+                                       ord($var{$c + 1}),
+                                       ord($var{$c + 2}));
+                          $c += 2;
+                          $utf16 = $this->json_utf82utf16($char);
+                          $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                          break;
+
+                      case (($ord_var_c & 0xF8) == 0xF0):
+                          // characters U-00010000 - U-001FFFFF, mask 11110XXX
+                          // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                          $char = pack('C*', $ord_var_c,
+                                       ord($var{$c + 1}),
+                                       ord($var{$c + 2}),
+                                       ord($var{$c + 3}));
+                          $c += 3;
+                          $utf16 = $this->json_utf82utf16($char);
+                          $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                          break;
+
+                      case (($ord_var_c & 0xFC) == 0xF8):
+                          // characters U-00200000 - U-03FFFFFF, mask 111110XX
+                          // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                          $char = pack('C*', $ord_var_c,
+                                       ord($var{$c + 1}),
+                                       ord($var{$c + 2}),
+                                       ord($var{$c + 3}),
+                                       ord($var{$c + 4}));
+                          $c += 4;
+                          $utf16 = $this->json_utf82utf16($char);
+                          $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                          break;
+
+                      case (($ord_var_c & 0xFE) == 0xFC):
+                          // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+                          // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                          $char = pack('C*', $ord_var_c,
+                                       ord($var{$c + 1}),
+                                       ord($var{$c + 2}),
+                                       ord($var{$c + 3}),
+                                       ord($var{$c + 4}),
+                                       ord($var{$c + 5}));
+                          $c += 5;
+                          $utf16 = $this->json_utf82utf16($char);
+                          $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                          break;
+                  }
+              }
+
+              return '"'.$ascii.'"';
+
+          case 'array':
+             /*
+              * As per JSON spec if any array key is not an integer
+              * we must treat the the whole array as an object. We
+              * also try to catch a sparsely populated associative
+              * array with numeric keys here because some JS engines
+              * will create an array with empty indexes up to
+              * max_index which can cause memory issues and because
+              * the keys, which may be relevant, will be remapped
+              * otherwise.
+              *
+              * As per the ECMA and JSON specification an object may
+              * have any string as a property. Unfortunately due to
+              * a hole in the ECMA specification if the key is a
+              * ECMA reserved word or starts with a digit the
+              * parameter is only accessible using ECMAScript's
+              * bracket notation.
+              */
+
+              // treat as a JSON object
+              if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
+                  
+                  $this->json_objectStack[] = $var;
+
+                  $properties = array_map(array($this, 'json_name_value'),
+                                          array_keys($var),
+                                          array_values($var));
+
+                  array_pop($this->json_objectStack);
+
+                  foreach($properties as $property) {
+                      if($property instanceof Exception) {
+                          return $property;
+                      }
+                  }
+
+                  return '{' . join(',', $properties) . '}';
+              }
+
+              $this->json_objectStack[] = $var;
+
+              // treat it like a regular array
+              $elements = array_map(array($this, 'json_encode'), $var);
+
+              array_pop($this->json_objectStack);
+
+              foreach($elements as $element) {
+                  if($element instanceof Exception) {
+                      return $element;
+                  }
+              }
+
+              return '[' . join(',', $elements) . ']';
+
+          case 'object':
+              $vars = self::encodeObject($var);
+
+              $this->json_objectStack[] = $var;
+
+              $properties = array_map(array($this, 'json_name_value'),
+                                      array_keys($vars),
+                                      array_values($vars));
+
+              array_pop($this->json_objectStack);
+              
+              foreach($properties as $property) {
+                  if($property instanceof Exception) {
+                      return $property;
+                  }
+              }
+                     
+              return '{' . join(',', $properties) . '}';
+
+          default:
+              return null;
+      }
+  }
+
+ /**
+  * array-walking function for use in generating JSON-formatted name-value pairs
+  *
+  * @param    string  $name   name of key to use
+  * @param    mixed   $value  reference to an array element to be encoded
+  *
+  * @return   string  JSON-formatted name-value pair, like '"name":value'
+  * @access   private
+  */
+  private function json_name_value($name, $value)
+  {
+      // Encoding the $GLOBALS PHP array causes an infinite loop
+      // if the recursion is not reset here as it contains
+      // a reference to itself. This is the only way I have come up
+      // with to stop infinite recursion in this case.
+      if($name=='GLOBALS'
+         && is_array($value)
+         && array_key_exists('GLOBALS',$value)) {
+        $value['GLOBALS'] = '** Recursion **';
+      }
+    
+      $encoded_value = $this->json_encode($value);
+
+      if($encoded_value instanceof Exception) {
+          return $encoded_value;
+      }
+
+      return $this->json_encode(strval($name)) . ':' . $encoded_value;
+  }
+}

+ 1292 - 0
sites/all/libraries/FirePHPCore/FirePHPCore/lib/FirePHPCore/FirePHP.class.php4

@@ -0,0 +1,1292 @@
+<?php
+/**
+ * *** BEGIN LICENSE BLOCK *****
+ *  
+ * This file is part of FirePHP (http://www.firephp.org/).
+ * 
+ * Software License Agreement (New BSD License)
+ * 
+ * Copyright (c) 2006-2009, Christoph Dorn
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ * 
+ *     * Redistributions in binary form must reproduce the above copyright notice,
+ *       this list of conditions and the following disclaimer in the documentation
+ *       and/or other materials provided with the distribution.
+ * 
+ *     * Neither the name of Christoph Dorn nor the names of its
+ *       contributors may be used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * ***** END LICENSE BLOCK *****
+ * 
+ * This verion of FirePHPCore is for use with PHP4. If you do not require PHP4 
+ * compatibility, it is suggested you use FirePHPCore.class.php instead.
+ * 
+ * @copyright   Copyright (C) 2007-2009 Christoph Dorn
+ * @author      Christoph Dorn <christoph@christophdorn.com>
+ * @author      Michael Day <manveru.alma@gmail.com>
+ * @license     http://www.opensource.org/licenses/bsd-license.php
+ * @package     FirePHP
+ */
+ 
+/**
+ * FirePHP version
+ * 
+ * @var string
+ */
+define('FirePHP_VERSION', '0.3');
+
+/**
+ * Firebug LOG level
+ * 
+ * Logs a message to firebug console
+ * 
+ * @var string
+ */
+define('FirePHP_LOG', 'LOG');
+
+/**
+ * Firebug INFO level
+ * 
+ * Logs a message to firebug console and displays an info icon before the message
+ *
+ * @var string
+ */
+define('FirePHP_INFO', 'INFO');
+
+/**
+ * Firebug WARN level
+ * 
+ * Logs a message to firebug console, displays a warning icon before the message and colors the line turquoise
+ *
+ * @var string
+ */
+define('FirePHP_WARN', 'WARN');
+
+/**
+ * Firebug ERROR level
+ * 
+ * Logs a message to firebug console, displays an error icon before the message and colors the line yellow. Also increments the firebug error count.
+ *
+ * @var string
+ */
+define('FirePHP_ERROR', 'ERROR');
+
+/**
+ * Dumps a variable to firebug's server panel
+ *
+ * @var string
+ */
+define('FirePHP_DUMP', 'DUMP');
+
+/**
+ * Displays a stack trace in firebug console
+ * 
+ * @var string
+ */
+define('FirePHP_TRACE', 'TRACE');
+
+/**
+ * Displays a table in firebug console
+ *
+ * @var string
+ */
+define('FirePHP_TABLE', 'TABLE');
+ 
+/**
+ * Starts a group in firebug console
+ *
+ * @var string
+ */
+define('FirePHP_GROUP_START', 'GROUP_START');
+
+/**
+ * Ends a group in firebug console
+ * 
+ * @var string
+ */
+define('FirePHP_GROUP_END', 'GROUP_END');
+
+/**
+ * Sends the given data to the FirePHP Firefox Extension.
+ * The data can be displayed in the Firebug Console or in the
+ * "Server" request tab.
+ * 
+ * For more information see: http://www.firephp.org/
+ * 
+ * @copyright   Copyright (C) 2007-2009 Christoph Dorn
+ * @author      Christoph Dorn <christoph@christophdorn.com>
+ * @author      Michael Day <manveru.alma@gmail.com>
+ * @license     http://www.opensource.org/licenses/bsd-license.php
+ * @package     FirePHP
+ */
+class FirePHP {
+  /**
+   * Wildfire protocol message index
+   *
+   * @var int
+   */
+  var $messageIndex = 1;
+    
+  /**
+   * Options for the library
+   * 
+   * @var array
+   */
+  var $options = array('maxObjectDepth' => 10,
+                       'maxArrayDepth' => 20,
+                       'useNativeJsonEncode' => true,
+                       'includeLineNumbers' => true);
+
+  /**
+   * Filters used to exclude object members when encoding
+   * 
+   * @var array
+   */
+  var $objectFilters = array();
+  
+  /**
+   * A stack of objects used to detect recursion during object encoding
+   * 
+   * @var object
+   */
+  var $objectStack = array();
+  
+  /**
+   * Flag to enable/disable logging
+   * 
+   * @var boolean
+   */
+  var $enabled = true;
+
+  /**
+   * The object constructor
+   */
+  function FirePHP() {
+  }
+
+    
+  /**
+   * When the object gets serialized only include specific object members.
+   * 
+   * @return array
+   */  
+  function __sleep() {
+    return array('options','objectFilters','enabled');
+  }
+
+  /**
+   * Gets singleton instance of FirePHP
+   *
+   * @param boolean $AutoCreate
+   * @return FirePHP
+   */
+  function &getInstance($AutoCreate=false) {
+  	global $FirePHP_Instance;
+  	
+  	if($AutoCreate===true && !$FirePHP_Instance) {
+  		$FirePHP_Instance = new FirePHP();
+  	}
+  	
+  	return $FirePHP_Instance;
+  }
+    
+  /**
+   * Enable and disable logging to Firebug
+   * 
+   * @param boolean $Enabled TRUE to enable, FALSE to disable
+   * @return void
+   */
+  function setEnabled($Enabled) {
+    $this->enabled = $Enabled;
+  }
+  
+  /**
+   * Check if logging is enabled
+   * 
+   * @return boolean TRUE if enabled
+   */
+  function getEnabled() {
+    return $this->enabled;
+  }
+  
+  /**
+   * Specify a filter to be used when encoding an object
+   * 
+   * Filters are used to exclude object members.
+   * 
+   * @param string $Class The class name of the object
+   * @param array $Filter An array of members to exclude
+   * @return void
+   */
+  function setObjectFilter($Class, $Filter) {
+    $this->objectFilters[strtolower($Class)] = $Filter;
+  }
+  
+  /**
+   * Set some options for the library
+   * 
+   * Options:
+   *  - maxObjectDepth: The maximum depth to traverse objects (default: 10)
+   *  - maxArrayDepth: The maximum depth to traverse arrays (default: 20)
+   *  - useNativeJsonEncode: If true will use json_encode() (default: true)
+   *  - includeLineNumbers: If true will include line numbers and filenames (default: true)
+   * 
+   * @param array $Options The options to be set
+   * @return void
+   */
+  function setOptions($Options) {
+    $this->options = array_merge($this->options,$Options);
+  }
+  
+  /**
+   * Get options from the library
+   *
+   * @return array The currently set options
+   */
+  function getOptions() {
+    return $this->options;
+  }
+  
+  /**
+   * Register FirePHP as your error handler
+   * 
+   * Will use FirePHP to log each php error.
+   *
+   * @return mixed Returns a string containing the previously defined error handler (if any)
+   */
+  function registerErrorHandler()
+  {
+    //NOTE: The following errors will not be caught by this error handler:
+    //      E_ERROR, E_PARSE, E_CORE_ERROR,
+    //      E_CORE_WARNING, E_COMPILE_ERROR,
+    //      E_COMPILE_WARNING, E_STRICT
+    
+    return set_error_handler(array($this,'errorHandler'));     
+  }
+
+  /**
+   * FirePHP's error handler
+   * 
+   * Logs each php error that will occur.
+   *
+   * @param int $errno
+   * @param string $errstr
+   * @param string $errfile
+   * @param int $errline
+   * @param array $errcontext
+   */
+  function errorHandler($errno, $errstr, $errfile, $errline, $errcontext)
+  {
+  	global $FirePHP_Instance;
+    // Don't log error if error reporting is switched off
+    if (error_reporting() == 0) {
+      return;
+    }
+    // Only log error for errors we are asking for
+    if (error_reporting() & $errno) {
+      $FirePHP_Instance->group($errstr);
+      $FirePHP_Instance->error("{$errfile}, line $errline");
+      $FirePHP_Instance->groupEnd();
+    }
+  }
+  
+  /**
+   * Register FirePHP driver as your assert callback
+   * 
+   * @return mixed Returns the original setting
+   */
+  function registerAssertionHandler()
+  {
+    return assert_options(ASSERT_CALLBACK, array($this, 'assertionHandler'));
+  }
+  
+  /**
+   * FirePHP's assertion handler
+   *
+   * Logs all assertions to your firebug console and then stops the script.
+   *
+   * @param string $file File source of assertion
+   * @param int    $line Line source of assertion
+   * @param mixed  $code Assertion code
+   */
+  function assertionHandler($file, $line, $code)
+  {
+    $this->fb($code, 'Assertion Failed', FirePHP_ERROR, array('File'=>$file,'Line'=>$line));
+  }  
+  
+  /**
+   * Set custom processor url for FirePHP
+   *
+   * @param string $URL
+   */    
+  function setProcessorUrl($URL)
+  {
+    $this->setHeader('X-FirePHP-ProcessorURL', $URL);
+  }
+
+  /**
+   * Set custom renderer url for FirePHP
+   *
+   * @param string $URL
+   */
+  function setRendererUrl($URL)
+  {
+    $this->setHeader('X-FirePHP-RendererURL', $URL);
+  }
+  
+  /**
+   * Start a group for following messages.
+   * 
+   * Options:
+   *   Collapsed: [true|false]
+   *   Color:     [#RRGGBB|ColorName]
+   *
+   * @param string $Name
+   * @param array $Options OPTIONAL Instructions on how to log the group
+   * @return true
+   * @throws Exception
+   */
+  function group($Name, $Options=null) {
+    
+    if(!$Name) {
+      trigger_error('You must specify a label for the group!');
+    }
+    
+    if($Options) {
+      if(!is_array($Options)) {
+        trigger_error('Options must be defined as an array!');
+      }
+      if(array_key_exists('Collapsed', $Options)) {
+        $Options['Collapsed'] = ($Options['Collapsed'])?'true':'false';
+      }
+    }
+    
+    return $this->fb(null, $Name, FirePHP_GROUP_START, $Options);
+  }
+  
+  /**
+   * Ends a group you have started before
+   *
+   * @return true
+   * @throws Exception
+   */
+  function groupEnd() {
+    return $this->fb(null, null, FirePHP_GROUP_END);
+  }
+
+  /**
+   * Log object with label to firebug console
+   *
+   * @see FirePHP::LOG
+   * @param mixes $Object
+   * @param string $Label
+   * @return true
+   * @throws Exception
+   */
+  function log($Object, $Label=null) {
+    return $this->fb($Object, $Label, FirePHP_LOG);
+  } 
+
+  /**
+   * Log object with label to firebug console
+   *
+   * @see FirePHP::INFO
+   * @param mixes $Object
+   * @param string $Label
+   * @return true
+   * @throws Exception
+   */
+  function info($Object, $Label=null) {
+    return $this->fb($Object, $Label, FirePHP_INFO);
+  } 
+
+  /**
+   * Log object with label to firebug console
+   *
+   * @see FirePHP::WARN
+   * @param mixes $Object
+   * @param string $Label
+   * @return true
+   * @throws Exception
+   */
+  function warn($Object, $Label=null) {
+    return $this->fb($Object, $Label, FirePHP_WARN);
+  } 
+
+  /**
+   * Log object with label to firebug console
+   *
+   * @see FirePHP::ERROR
+   * @param mixes $Object
+   * @param string $Label
+   * @return true
+   * @throws Exception
+   */
+  function error($Object, $Label=null) {
+    return $this->fb($Object, $Label, FirePHP_ERROR);
+  } 
+
+  /**
+   * Dumps key and variable to firebug server panel
+   *
+   * @see FirePHP::DUMP
+   * @param string $Key
+   * @param mixed $Variable
+   * @return true
+   * @throws Exception
+   */
+  function dump($Key, $Variable) {
+    return $this->fb($Variable, $Key, FirePHP_DUMP);
+  }
+  
+  /**
+   * Log a trace in the firebug console
+   *
+   * @see FirePHP::TRACE
+   * @param string $Label
+   * @return true
+   * @throws Exception
+   */
+  function trace($Label) {
+    return $this->fb($Label, FirePHP_TRACE);
+  } 
+
+  /**
+   * Log a table in the firebug console
+   *
+   * @see FirePHP::TABLE
+   * @param string $Label
+   * @param string $Table
+   * @return true
+   * @throws Exception
+   */
+  function table($Label, $Table) {
+    return $this->fb($Table, $Label, FirePHP_TABLE);
+  }
+  
+  /**
+   * Check if FirePHP is installed on client
+   *
+   * @return boolean
+   */
+  function detectClientExtension() {
+    /* Check if FirePHP is installed on client */
+    if(!@preg_match_all('/\sFirePHP\/([\.|\d]*)\s?/si',$this->getUserAgent(),$m) ||
+       !version_compare($m[1][0],'0.0.6','>=')) {
+      return false;
+    }
+    return true;    
+  }
+ 
+  /**
+   * Log varible to Firebug
+   * 
+   * @see http://www.firephp.org/Wiki/Reference/Fb
+   * @param mixed $Object The variable to be logged
+   * @return true Return TRUE if message was added to headers, FALSE otherwise
+   * @throws Exception
+   */
+  function fb($Object) {
+  
+    if(!$this->enabled) {
+      return false;
+    }
+  
+    if (headers_sent($filename, $linenum)) {
+        trigger_error('Headers already sent in '.$filename.' on line '.$linenum.'. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.');
+    }
+  
+    $Type = null;
+    $Label = null;
+    $Options = array();
+  
+    if(func_num_args()==1) {
+    } else
+    if(func_num_args()==2) {
+      switch(func_get_arg(1)) {
+        case FirePHP_LOG:
+        case FirePHP_INFO:
+        case FirePHP_WARN:
+        case FirePHP_ERROR:
+        case FirePHP_DUMP:
+        case FirePHP_TRACE:
+        case FirePHP_TABLE:
+        case FirePHP_GROUP_START:
+        case FirePHP_GROUP_END:
+          $Type = func_get_arg(1);
+          break;
+        default:
+          $Label = func_get_arg(1);
+          break;
+      }
+    } else
+    if(func_num_args()==3) {
+      $Type = func_get_arg(2);
+      $Label = func_get_arg(1);
+    } else
+    if(func_num_args()==4) {
+      $Type = func_get_arg(2);
+      $Label = func_get_arg(1);
+      $Options = func_get_arg(3);
+    } else {
+      trigger_error('Wrong number of arguments to fb() function!');
+    }
+  
+  
+    if(!$this->detectClientExtension()) {
+      return false;
+    }
+  
+    $meta = array();
+    $skipFinalObjectEncode = false;
+  
+    if($Type==FirePHP_TRACE) {
+      
+      $trace = debug_backtrace();
+      if(!$trace) return false;
+      for( $i=0 ; $i<sizeof($trace) ; $i++ ) {
+
+        if(isset($trace[$i]['class'])
+           && isset($trace[$i]['file'])
+           && ($trace[$i]['class']=='FirePHP'
+               || $trace[$i]['class']=='FB')
+           && (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php'
+               || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) {
+          /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */
+        } else
+        if(isset($trace[$i]['class'])
+           && isset($trace[$i+1]['file'])
+           && $trace[$i]['class']=='FirePHP'
+           && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') {
+          /* Skip fb() */
+        } else
+        if($trace[$i]['function']=='fb'
+           || $trace[$i]['function']=='trace'
+           || $trace[$i]['function']=='send') {
+          $Object = array('Class'=>isset($trace[$i]['class'])?$trace[$i]['class']:'',
+                          'Type'=>isset($trace[$i]['type'])?$trace[$i]['type']:'',
+                          'Function'=>isset($trace[$i]['function'])?$trace[$i]['function']:'',
+                          'Message'=>$trace[$i]['args'][0],
+                          'File'=>isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'',
+                          'Line'=>isset($trace[$i]['line'])?$trace[$i]['line']:'',
+                          'Args'=>isset($trace[$i]['args'])?$this->encodeObject($trace[$i]['args']):'',
+                          'Trace'=>$this->_escapeTrace(array_splice($trace,$i+1)));
+
+          $skipFinalObjectEncode = true;
+          $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'';
+          $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:'';
+          break;
+        }
+      }
+
+    } else
+    if($Type==FirePHP_TABLE) {
+      
+      if(isset($Object[0]) && is_string($Object[0])) {
+        $Object[1] = $this->encodeTable($Object[1]);
+      } else {
+        $Object = $this->encodeTable($Object);
+      }
+
+      $skipFinalObjectEncode = true;
+      
+    } else
+    if($Type==FirePHP_GROUP_START) {
+      
+      if(!$Label) {
+        trigger_error('You must specify a label for the group!');
+      }
+    } else {
+      if($Type===null) {
+        $Type = FirePHP_LOG;
+      }
+    }
+    
+    if($this->options['includeLineNumbers']) {
+      if(!isset($meta['file']) || !isset($meta['line'])) {
+
+        $trace = debug_backtrace();
+        for( $i=0 ; $trace && $i<sizeof($trace) ; $i++ ) {
+  
+          if(isset($trace[$i]['class'])
+             && isset($trace[$i]['file'])
+             && ($trace[$i]['class']=='FirePHP'
+                 || $trace[$i]['class']=='FB')
+             && (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php'
+                 || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) {
+            /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */
+          } else
+          if(isset($trace[$i]['class'])
+             && isset($trace[$i+1]['file'])
+             && $trace[$i]['class']=='FirePHP'
+             && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') {
+            /* Skip fb() */
+          } else
+          if(isset($trace[$i]['file'])
+             && substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php') {
+            /* Skip FB::fb() */
+          } else {
+            $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'';
+            $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:'';
+            break;
+          }
+        }      
+      
+      }
+    } else {
+      unset($meta['file']);
+      unset($meta['line']);
+    }
+
+  	$this->setHeader('X-Wf-Protocol-1','http://meta.wildfirehq.org/Protocol/JsonStream/0.2');
+  	$this->setHeader('X-Wf-1-Plugin-1','http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/'.FirePHP_VERSION);
+ 
+    $structure_index = 1;
+    if($Type==FirePHP_DUMP) {
+      $structure_index = 2;
+    	$this->setHeader('X-Wf-1-Structure-2','http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1');
+    } else {
+    	$this->setHeader('X-Wf-1-Structure-1','http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1');
+    }
+  
+    if($Type==FirePHP_DUMP) {
+    	$msg = '{"'.$Label.'":'.$this->jsonEncode($Object, $skipFinalObjectEncode).'}';
+    } else {
+      $msg_meta = $Options;
+      $msg_meta['Type'] = $Type;
+      if($Label!==null) {
+        $msg_meta['Label'] = $Label;
+      }
+      if(isset($meta['file']) && !isset($msg_meta['File'])) {
+        $msg_meta['File'] = $meta['file'];
+      }
+      if(isset($meta['line']) && !isset($msg_meta['Line'])) {
+        $msg_meta['Line'] = $meta['line'];
+      }
+    	$msg = '['.$this->jsonEncode($msg_meta).','.$this->jsonEncode($Object, $skipFinalObjectEncode).']';
+    }
+    
+    $parts = explode("\n",chunk_split($msg, 5000, "\n"));
+
+    for( $i=0 ; $i<count($parts) ; $i++) {
+        
+        $part = $parts[$i];
+        if ($part) {
+            
+            if(count($parts)>2) {
+              // Message needs to be split into multiple parts
+              $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex,
+                               (($i==0)?strlen($msg):'')
+                               . '|' . $part . '|'
+                               . (($i<count($parts)-2)?'\\':''));
+            } else {
+              $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex,
+                               strlen($part) . '|' . $part . '|');
+            }
+            
+            $this->messageIndex++;
+            
+            if ($this->messageIndex > 99999) {
+                trigger_error('Maximum number (99,999) of messages reached!');             
+            }
+        }
+    }
+
+  	$this->setHeader('X-Wf-1-Index',$this->messageIndex-1);
+
+    return true;
+  }
+  
+  
+  /**
+   * Standardizes path for windows systems.
+   *
+   * @param string $Path
+   * @return string
+   */
+   function _standardizePath($Path) {
+    return preg_replace('/\\\\+/','/',$Path);    
+  }
+  
+  /**
+   * Escape trace path for windows systems
+   *
+   * @param array $Trace
+   * @return array
+   */
+   function _escapeTrace($Trace) {
+    if(!$Trace) return $Trace;
+    for( $i=0 ; $i<sizeof($Trace) ; $i++ ) {
+      if(isset($Trace[$i]['file'])) {
+        $Trace[$i]['file'] = $this->_escapeTraceFile($Trace[$i]['file']);
+      }
+      if(isset($Trace[$i]['args'])) {
+        $Trace[$i]['args'] = $this->encodeObject($Trace[$i]['args']);
+      }
+    }
+    return $Trace;    
+  }
+  
+  /**
+   * Escape file information of trace for windows systems
+   *
+   * @param string $File
+   * @return string
+   */
+   function _escapeTraceFile($File) {
+    /* Check if we have a windows filepath */
+    if(strpos($File,'\\')) {
+      /* First strip down to single \ */
+      
+      $file = preg_replace('/\\\\+/','\\',$File);
+      
+      return $file;
+    }
+    return $File;
+  }
+
+  /**
+   * Send header
+   *
+   * @param string $Name
+   * @param string_type $Value
+   */
+   function setHeader($Name, $Value) {
+    return header($Name.': '.$Value);
+  }
+
+  /**
+   * Get user agent
+   *
+   * @return string|false
+   */
+   function getUserAgent() {
+    if(!isset($_SERVER['HTTP_USER_AGENT'])) return false;
+    return $_SERVER['HTTP_USER_AGENT'];
+  }
+
+  /**
+   * Encode an object into a JSON string
+   * 
+   * Uses PHP's jeson_encode() if available
+   * 
+   * @param object $Object The object to be encoded
+   * @return string The JSON string
+   */
+   function jsonEncode($Object, $skipObjectEncode=false)
+  {
+    if(!$skipObjectEncode) {
+      $Object = $this->encodeObject($Object);
+    }
+    
+    if(function_exists('json_encode')
+       && $this->options['useNativeJsonEncode']!=false) {
+
+      return json_encode($Object);
+    } else {
+      return $this->json_encode($Object);
+    }
+  }
+  
+  /**
+   * Encodes a table by encoding each row and column with encodeObject()
+   * 
+   * @param array $Table The table to be encoded
+   * @return array
+   */  
+   function encodeTable($Table) {
+    
+    if(!$Table) return $Table;
+    
+    $new_table = array();
+    foreach($Table as $row) {
+  
+      if(is_array($row)) {
+        $new_row = array();
+        
+        foreach($row as $item) {
+          $new_row[] = $this->encodeObject($item);
+        }
+        
+        $new_table[] = $new_row;
+      }
+    }
+    
+    return $new_table;
+  }
+  
+  /**
+   * Encodes an object
+   * 
+   * @param Object $Object The object to be encoded
+   * @param int $Depth The current traversal depth
+   * @return array All members of the object
+   */
+   function encodeObject($Object, $ObjectDepth = 1, $ArrayDepth = 1)
+  {
+    $return = array();
+
+    if (is_resource($Object)) {
+
+      return '** '.(string)$Object.' **';
+
+    } else    
+    if (is_object($Object)) {
+
+        if ($ObjectDepth > $this->options['maxObjectDepth']) {
+          return '** Max Object Depth ('.$this->options['maxObjectDepth'].') **';
+        }
+        
+        foreach ($this->objectStack as $refVal) {
+            if ($refVal === $Object) {
+                return '** Recursion ('.get_class($Object).') **';
+            }
+        }
+        array_push($this->objectStack, $Object);
+                
+        $return['__className'] = $class = get_class($Object);
+        $class_lower = strtolower($class);
+
+        $members = (array)$Object;
+            
+        // Include all members that are not defined in the class
+        // but exist in the object
+        foreach( $members as $raw_name => $value ) {
+          
+          $name = $raw_name;
+          
+          if ($name{0} == "\0") {
+            $parts = explode("\0", $name);
+            $name = $parts[2];
+          }
+          
+          if(!isset($properties[$name])) {
+            $name = 'undeclared:'.$name;
+              
+            if(!(isset($this->objectFilters[$class_lower])
+                 && is_array($this->objectFilters[$class_lower])
+                 && in_array($raw_name,$this->objectFilters[$class_lower]))) {
+              
+              $return[$name] = $this->encodeObject($value, $ObjectDepth + 1, 1);
+            } else {
+              $return[$name] = '** Excluded by Filter **';
+            }
+          }
+        }
+        
+        array_pop($this->objectStack);
+        
+    } elseif (is_array($Object)) {
+
+        if ($ArrayDepth > $this->options['maxArrayDepth']) {
+          return '** Max Array Depth ('.$this->options['maxArrayDepth'].') **';
+        }
+      
+        foreach ($Object as $key => $val) {
+          
+          // Encoding the $GLOBALS PHP array causes an infinite loop
+          // if the recursion is not reset here as it contains
+          // a reference to itself. This is the only way I have come up
+          // with to stop infinite recursion in this case.
+          if($key=='GLOBALS'
+             && is_array($val)
+             && array_key_exists('GLOBALS',$val)) {
+            $val['GLOBALS'] = '** Recursion (GLOBALS) **';
+          }
+          
+          $return[$key] = $this->encodeObject($val, 1, $ArrayDepth + 1);
+        }
+    } else {
+      if($this->is_utf8($Object)) {
+        return $Object;
+      } else {
+        return utf8_encode($Object);
+      }
+    }
+    return $return;
+  	
+  }
+
+  /**
+   * Returns true if $string is valid UTF-8 and false otherwise.
+   *
+   * @param mixed $str String to be tested
+   * @return boolean
+   */
+   function is_utf8($str) {
+    $c=0; $b=0;
+    $bits=0;
+    $len=strlen($str);
+    for($i=0; $i<$len; $i++){
+        $c=ord($str[$i]);
+        if($c > 128){
+            if(($c >= 254)) return false;
+            elseif($c >= 252) $bits=6;
+            elseif($c >= 248) $bits=5;
+            elseif($c >= 240) $bits=4;
+            elseif($c >= 224) $bits=3;
+            elseif($c >= 192) $bits=2;
+            else return false;
+            if(($i+$bits) > $len) return false;
+            while($bits > 1){
+                $i++;
+                $b=ord($str[$i]);
+                if($b < 128 || $b > 191) return false;
+                $bits--;
+            }
+        }
+    }
+    return true;
+  } 
+
+  /**
+   * Converts to and from JSON format.
+   *
+   * JSON (JavaScript Object Notation) is a lightweight data-interchange
+   * format. It is easy for humans to read and write. It is easy for machines
+   * to parse and generate. It is based on a subset of the JavaScript
+   * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
+   * This feature can also be found in  Python. JSON is a text format that is
+   * completely language independent but uses conventions that are familiar
+   * to programmers of the C-family of languages, including C, C++, C#, Java,
+   * JavaScript, Perl, TCL, and many others. These properties make JSON an
+   * ideal data-interchange language.
+   *
+   * This package provides a simple encoder and decoder for JSON notation. It
+   * is intended for use with client-side Javascript applications that make
+   * use of HTTPRequest to perform server communication functions - data can
+   * be encoded into JSON notation for use in a client-side javascript, or
+   * decoded from incoming Javascript requests. JSON format is native to
+   * Javascript, and can be directly eval()'ed with no further parsing
+   * overhead
+   *
+   * All strings should be in ASCII or UTF-8 format!
+   *
+   * LICENSE: Redistribution and use in source and binary forms, with or
+   * without modification, are permitted provided that the following
+   * conditions are met: Redistributions of source code must retain the
+   * above copyright notice, this list of conditions and the following
+   * disclaimer. Redistributions in binary form must reproduce the above
+   * copyright notice, this list of conditions and the following disclaimer
+   * in the documentation and/or other materials provided with the
+   * distribution.
+   *
+   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+   * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+   * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+   * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+   * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+   * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+   * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+   * DAMAGE.
+   *
+   * @category
+   * @package     Services_JSON
+   * @author      Michal Migurski <mike-json@teczno.com>
+   * @author      Matt Knapp <mdknapp[at]gmail[dot]com>
+   * @author      Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
+   * @author      Christoph Dorn <christoph@christophdorn.com>
+   * @copyright   2005 Michal Migurski
+   * @version     CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
+   * @license     http://www.opensource.org/licenses/bsd-license.php
+   * @link        http://pear.php.net/pepr/pepr-proposal-show.php?id=198
+   */
+   
+     
+  /**
+   * Keep a list of objects as we descend into the array so we can detect recursion.
+   */
+  var $json_objectStack = array();
+
+
+ /**
+  * convert a string from one UTF-8 char to one UTF-16 char
+  *
+  * Normally should be handled by mb_convert_encoding, but
+  * provides a slower PHP-only method for installations
+  * that lack the multibye string extension.
+  *
+  * @param    string  $utf8   UTF-8 character
+  * @return   string  UTF-16 character
+  * @access   private
+  */
+  function json_utf82utf16($utf8)
+  {
+      // oh please oh please oh please oh please oh please
+      if(function_exists('mb_convert_encoding')) {
+          return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
+      }
+
+      switch(strlen($utf8)) {
+          case 1:
+              // this case should never be reached, because we are in ASCII range
+              // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+              return $utf8;
+
+          case 2:
+              // return a UTF-16 character from a 2-byte UTF-8 char
+              // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+              return chr(0x07 & (ord($utf8{0}) >> 2))
+                   . chr((0xC0 & (ord($utf8{0}) << 6))
+                       | (0x3F & ord($utf8{1})));
+
+          case 3:
+              // return a UTF-16 character from a 3-byte UTF-8 char
+              // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+              return chr((0xF0 & (ord($utf8{0}) << 4))
+                       | (0x0F & (ord($utf8{1}) >> 2)))
+                   . chr((0xC0 & (ord($utf8{1}) << 6))
+                       | (0x7F & ord($utf8{2})));
+      }
+
+      // ignoring UTF-32 for now, sorry
+      return '';
+  }
+
+ /**
+  * encodes an arbitrary variable into JSON format
+  *
+  * @param    mixed   $var    any number, boolean, string, array, or object to be encoded.
+  *                           see argument 1 to Services_JSON() above for array-parsing behavior.
+  *                           if var is a strng, note that encode() always expects it
+  *                           to be in ASCII or UTF-8 format!
+  *
+  * @return   mixed   JSON string representation of input var or an error if a problem occurs
+  * @access   public
+  */
+  function json_encode($var)
+  {
+    
+    if(is_object($var)) {
+      if(in_array($var,$this->json_objectStack)) {
+        return '"** Recursion **"';
+      }
+    }
+          
+      switch (gettype($var)) {
+          case 'boolean':
+              return $var ? 'true' : 'false';
+
+          case 'NULL':
+              return 'null';
+
+          case 'integer':
+              return (int) $var;
+
+          case 'double':
+          case 'float':
+              return (float) $var;
+
+          case 'string':
+              // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
+              $ascii = '';
+              $strlen_var = strlen($var);
+
+             /*
+              * Iterate over every character in the string,
+              * escaping with a slash or encoding to UTF-8 where necessary
+              */
+              for ($c = 0; $c < $strlen_var; ++$c) {
+
+                  $ord_var_c = ord($var{$c});
+
+                  switch (true) {
+                      case $ord_var_c == 0x08:
+                          $ascii .= '\b';
+                          break;
+                      case $ord_var_c == 0x09:
+                          $ascii .= '\t';
+                          break;
+                      case $ord_var_c == 0x0A:
+                          $ascii .= '\n';
+                          break;
+                      case $ord_var_c == 0x0C:
+                          $ascii .= '\f';
+                          break;
+                      case $ord_var_c == 0x0D:
+                          $ascii .= '\r';
+                          break;
+
+                      case $ord_var_c == 0x22:
+                      case $ord_var_c == 0x2F:
+                      case $ord_var_c == 0x5C:
+                          // double quote, slash, slosh
+                          $ascii .= '\\'.$var{$c};
+                          break;
+
+                      case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
+                          // characters U-00000000 - U-0000007F (same as ASCII)
+                          $ascii .= $var{$c};
+                          break;
+
+                      case (($ord_var_c & 0xE0) == 0xC0):
+                          // characters U-00000080 - U-000007FF, mask 110XXXXX
+                          // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                          $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
+                          $c += 1;
+                          $utf16 = $this->json_utf82utf16($char);
+                          $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                          break;
+
+                      case (($ord_var_c & 0xF0) == 0xE0):
+                          // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+                          // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                          $char = pack('C*', $ord_var_c,
+                                       ord($var{$c + 1}),
+                                       ord($var{$c + 2}));
+                          $c += 2;
+                          $utf16 = $this->json_utf82utf16($char);
+                          $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                          break;
+
+                      case (($ord_var_c & 0xF8) == 0xF0):
+                          // characters U-00010000 - U-001FFFFF, mask 11110XXX
+                          // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                          $char = pack('C*', $ord_var_c,
+                                       ord($var{$c + 1}),
+                                       ord($var{$c + 2}),
+                                       ord($var{$c + 3}));
+                          $c += 3;
+                          $utf16 = $this->json_utf82utf16($char);
+                          $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                          break;
+
+                      case (($ord_var_c & 0xFC) == 0xF8):
+                          // characters U-00200000 - U-03FFFFFF, mask 111110XX
+                          // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                          $char = pack('C*', $ord_var_c,
+                                       ord($var{$c + 1}),
+                                       ord($var{$c + 2}),
+                                       ord($var{$c + 3}),
+                                       ord($var{$c + 4}));
+                          $c += 4;
+                          $utf16 = $this->json_utf82utf16($char);
+                          $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                          break;
+
+                      case (($ord_var_c & 0xFE) == 0xFC):
+                          // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+                          // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                          $char = pack('C*', $ord_var_c,
+                                       ord($var{$c + 1}),
+                                       ord($var{$c + 2}),
+                                       ord($var{$c + 3}),
+                                       ord($var{$c + 4}),
+                                       ord($var{$c + 5}));
+                          $c += 5;
+                          $utf16 = $this->json_utf82utf16($char);
+                          $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                          break;
+                  }
+              }
+
+              return '"'.$ascii.'"';
+
+          case 'array':
+             /*
+              * As per JSON spec if any array key is not an integer
+              * we must treat the the whole array as an object. We
+              * also try to catch a sparsely populated associative
+              * array with numeric keys here because some JS engines
+              * will create an array with empty indexes up to
+              * max_index which can cause memory issues and because
+              * the keys, which may be relevant, will be remapped
+              * otherwise.
+              *
+              * As per the ECMA and JSON specification an object may
+              * have any string as a property. Unfortunately due to
+              * a hole in the ECMA specification if the key is a
+              * ECMA reserved word or starts with a digit the
+              * parameter is only accessible using ECMAScript's
+              * bracket notation.
+              */
+
+              // treat as a JSON object
+              if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
+                  
+                  $this->json_objectStack[] = $var;
+
+                  $properties = array_map(array($this, 'json_name_value'),
+                                          array_keys($var),
+                                          array_values($var));
+
+                  array_pop($this->json_objectStack);
+
+                  return '{' . join(',', $properties) . '}';
+              }
+
+              $this->json_objectStack[] = $var;
+
+              // treat it like a regular array
+              $elements = array_map(array($this, 'json_encode'), $var);
+
+              array_pop($this->json_objectStack);
+
+              return '[' . join(',', $elements) . ']';
+
+          case 'object':
+              $vars = FirePHP::encodeObject($var);
+
+              $this->json_objectStack[] = $var;
+
+              $properties = array_map(array($this, 'json_name_value'),
+                                      array_keys($vars),
+                                      array_values($vars));
+
+              array_pop($this->json_objectStack);
+              
+              return '{' . join(',', $properties) . '}';
+
+          default:
+              return null;
+      }
+  }
+
+ /**
+  * array-walking function for use in generating JSON-formatted name-value pairs
+  *
+  * @param    string  $name   name of key to use
+  * @param    mixed   $value  reference to an array element to be encoded
+  *
+  * @return   string  JSON-formatted name-value pair, like '"name":value'
+  * @access   private
+  */
+  function json_name_value($name, $value)
+  {
+      // Encoding the $GLOBALS PHP array causes an infinite loop
+      // if the recursion is not reset here as it contains
+      // a reference to itself. This is the only way I have come up
+      // with to stop infinite recursion in this case.
+      if($name=='GLOBALS'
+         && is_array($value)
+         && array_key_exists('GLOBALS',$value)) {
+        $value['GLOBALS'] = '** Recursion **';
+      }
+    
+      $encoded_value = $this->json_encode($value);
+
+      return $this->json_encode(strval($name)) . ':' . $encoded_value;
+  }
+}
+

+ 29 - 0
sites/all/libraries/FirePHPCore/FirePHPCore/lib/FirePHPCore/LICENSE

@@ -0,0 +1,29 @@
+Software License Agreement (New BSD License)
+
+Copyright (c) 2006-2009, Christoph Dorn
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+
+    * Neither the name of Christoph Dorn nor the names of its
+      contributors may be used to endorse or promote products derived from this
+      software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 261 - 0
sites/all/libraries/FirePHPCore/FirePHPCore/lib/FirePHPCore/fb.php

@@ -0,0 +1,261 @@
+<?php
+
+/* ***** BEGIN LICENSE BLOCK *****
+ *  
+ * This file is part of FirePHP (http://www.firephp.org/).
+ * 
+ * Software License Agreement (New BSD License)
+ * 
+ * Copyright (c) 2006-2009, Christoph Dorn
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ * 
+ *     * Redistributions in binary form must reproduce the above copyright notice,
+ *       this list of conditions and the following disclaimer in the documentation
+ *       and/or other materials provided with the distribution.
+ * 
+ *     * Neither the name of Christoph Dorn nor the names of its
+ *       contributors may be used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * ***** END LICENSE BLOCK *****
+ * 
+ * @copyright   Copyright (C) 2007-2009 Christoph Dorn
+ * @author      Christoph Dorn <christoph@christophdorn.com>
+ * @license     http://www.opensource.org/licenses/bsd-license.php
+ * @package     FirePHP
+ */
+
+require_once dirname(__FILE__).'/FirePHP.class.php';
+
+/**
+ * Sends the given data to the FirePHP Firefox Extension.
+ * The data can be displayed in the Firebug Console or in the
+ * "Server" request tab.
+ * 
+ * @see http://www.firephp.org/Wiki/Reference/Fb
+ * @param mixed $Object
+ * @return true
+ * @throws Exception
+ */
+function fb()
+{
+  $instance = FirePHP::getInstance(true);
+  
+  $args = func_get_args();
+  return call_user_func_array(array($instance,'fb'),$args);
+}
+
+
+class FB
+{
+  /**
+   * Enable and disable logging to Firebug
+   * 
+   * @see FirePHP->setEnabled()
+   * @param boolean $Enabled TRUE to enable, FALSE to disable
+   * @return void
+   */
+  public static function setEnabled($Enabled) {
+    $instance = FirePHP::getInstance(true);
+    $instance->setEnabled($Enabled);
+  }
+  
+  /**
+   * Check if logging is enabled
+   * 
+   * @see FirePHP->getEnabled()
+   * @return boolean TRUE if enabled
+   */
+  public static function getEnabled() {
+    $instance = FirePHP::getInstance(true);
+    return $instance->getEnabled();
+  }  
+  
+  /**
+   * Specify a filter to be used when encoding an object
+   * 
+   * Filters are used to exclude object members.
+   * 
+   * @see FirePHP->setObjectFilter()
+   * @param string $Class The class name of the object
+   * @param array $Filter An array or members to exclude
+   * @return void
+   */
+  public static function setObjectFilter($Class, $Filter) {
+    $instance = FirePHP::getInstance(true);
+    $instance->setObjectFilter($Class, $Filter);
+  }
+  
+  /**
+   * Set some options for the library
+   * 
+   * @see FirePHP->setOptions()
+   * @param array $Options The options to be set
+   * @return void
+   */
+  public static function setOptions($Options) {
+    $instance = FirePHP::getInstance(true);
+    $instance->setOptions($Options);
+  }
+
+  /**
+   * Get options for the library
+   * 
+   * @see FirePHP->getOptions()
+   * @return array The options
+   */
+  public static function getOptions() {
+    $instance = FirePHP::getInstance(true);
+    return $instance->getOptions();
+  }
+
+  /**
+   * Log object to firebug
+   * 
+   * @see http://www.firephp.org/Wiki/Reference/Fb
+   * @param mixed $Object
+   * @return true
+   * @throws Exception
+   */
+  public static function send()
+  {
+    $instance = FirePHP::getInstance(true);
+    $args = func_get_args();
+    return call_user_func_array(array($instance,'fb'),$args);
+  }
+
+  /**
+   * Start a group for following messages
+   * 
+   * Options:
+   *   Collapsed: [true|false]
+   *   Color:     [#RRGGBB|ColorName]
+   *
+   * @param string $Name
+   * @param array $Options OPTIONAL Instructions on how to log the group
+   * @return true
+   */
+  public static function group($Name, $Options=null) {
+    $instance = FirePHP::getInstance(true);
+    return $instance->group($Name, $Options);
+  }
+
+  /**
+   * Ends a group you have started before
+   *
+   * @return true
+   * @throws Exception
+   */
+  public static function groupEnd() {
+    return self::send(null, null, FirePHP::GROUP_END);
+  }
+
+  /**
+   * Log object with label to firebug console
+   *
+   * @see FirePHP::LOG
+   * @param mixes $Object
+   * @param string $Label
+   * @return true
+   * @throws Exception
+   */
+  public static function log($Object, $Label=null) {
+    return self::send($Object, $Label, FirePHP::LOG);
+  } 
+
+  /**
+   * Log object with label to firebug console
+   *
+   * @see FirePHP::INFO
+   * @param mixes $Object
+   * @param string $Label
+   * @return true
+   * @throws Exception
+   */
+  public static function info($Object, $Label=null) {
+    return self::send($Object, $Label, FirePHP::INFO);
+  } 
+
+  /**
+   * Log object with label to firebug console
+   *
+   * @see FirePHP::WARN
+   * @param mixes $Object
+   * @param string $Label
+   * @return true
+   * @throws Exception
+   */
+  public static function warn($Object, $Label=null) {
+    return self::send($Object, $Label, FirePHP::WARN);
+  } 
+
+  /**
+   * Log object with label to firebug console
+   *
+   * @see FirePHP::ERROR
+   * @param mixes $Object
+   * @param string $Label
+   * @return true
+   * @throws Exception
+   */
+  public static function error($Object, $Label=null) {
+    return self::send($Object, $Label, FirePHP::ERROR);
+  } 
+
+  /**
+   * Dumps key and variable to firebug server panel
+   *
+   * @see FirePHP::DUMP
+   * @param string $Key
+   * @param mixed $Variable
+   * @return true
+   * @throws Exception
+   */
+  public static function dump($Key, $Variable) {
+    return self::send($Variable, $Key, FirePHP::DUMP);
+  } 
+
+  /**
+   * Log a trace in the firebug console
+   *
+   * @see FirePHP::TRACE
+   * @param string $Label
+   * @return true
+   * @throws Exception
+   */
+  public static function trace($Label) {
+    return self::send($Label, FirePHP::TRACE);
+  } 
+
+  /**
+   * Log a table in the firebug console
+   *
+   * @see FirePHP::TABLE
+   * @param string $Label
+   * @param string $Table
+   * @return true
+   * @throws Exception
+   */
+  public static function table($Label, $Table) {
+    return self::send($Table, $Label, FirePHP::TABLE);
+  } 
+
+}
+

+ 251 - 0
sites/all/libraries/FirePHPCore/FirePHPCore/lib/FirePHPCore/fb.php4

@@ -0,0 +1,251 @@
+<?php
+
+/* ***** BEGIN LICENSE BLOCK *****
+ *  
+ * This file is part of FirePHP (http://www.firephp.org/).
+ * 
+ * Software License Agreement (New BSD License)
+ * 
+ * Copyright (c) 2006-2009, Christoph Dorn
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ * 
+ *     * Redistributions in binary form must reproduce the above copyright notice,
+ *       this list of conditions and the following disclaimer in the documentation
+ *       and/or other materials provided with the distribution.
+ * 
+ *     * Neither the name of Christoph Dorn nor the names of its
+ *       contributors may be used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * ***** END LICENSE BLOCK *****
+ * 
+ * @copyright   Copyright (C) 2007-2009 Christoph Dorn
+ * @author      Christoph Dorn <christoph@christophdorn.com>
+ * @author      Michael Day <manveru.alma@gmail.com>
+ * @license     http://www.opensource.org/licenses/bsd-license.php
+ * @package     FirePHP
+ */
+
+require_once dirname(__FILE__).'/FirePHP.class.php4';
+
+/**
+ * Sends the given data to the FirePHP Firefox Extension.
+ * The data can be displayed in the Firebug Console or in the
+ * "Server" request tab.
+ * 
+ * @see http://www.firephp.org/Wiki/Reference/Fb
+ * @param mixed $Object
+ * @return true
+ * @throws Exception
+ */
+function fb()
+{
+  $instance =& FirePHP::getInstance(true);
+
+  $args = func_get_args();
+  return call_user_func_array(array(&$instance,'fb'),$args);
+}
+
+
+class FB
+{
+  /**
+   * Enable and disable logging to Firebug
+   * 
+   * @see FirePHP->setEnabled()
+   * @param boolean $Enabled TRUE to enable, FALSE to disable
+   * @return void
+   */
+  function setEnabled($Enabled) {
+    $instance =& FirePHP::getInstance(true);
+    $instance->setEnabled($Enabled);
+  }
+  
+  /**
+   * Check if logging is enabled
+   * 
+   * @see FirePHP->getEnabled()
+   * @return boolean TRUE if enabled
+   */
+  function getEnabled() {
+    $instance =& FirePHP::getInstance(true);
+    return $instance->getEnabled();
+  }  
+  
+  /**
+   * Specify a filter to be used when encoding an object
+   * 
+   * Filters are used to exclude object members.
+   * 
+   * @see FirePHP->setObjectFilter()
+   * @param string $Class The class name of the object
+   * @param array $Filter An array or members to exclude
+   * @return void
+   */
+  function setObjectFilter($Class, $Filter) {
+    $instance =& FirePHP::getInstance(true);
+    $instance->setObjectFilter($Class, $Filter);
+  }
+  
+  /**
+   * Set some options for the library
+   * 
+   * @see FirePHP->setOptions()
+   * @param array $Options The options to be set
+   * @return void
+   */
+  function setOptions($Options) {
+    $instance =& FirePHP::getInstance(true);
+    $instance->setOptions($Options);
+  }
+
+  /**
+   * Get options for the library
+   * 
+   * @see FirePHP->getOptions()
+   * @return array The options
+   */
+  function getOptions() {
+    $instance =& FirePHP::getInstance(true);
+    return $instance->getOptions();
+  }
+
+  /**
+   * Log object to firebug
+   * 
+   * @see http://www.firephp.org/Wiki/Reference/Fb
+   * @param mixed $Object
+   * @return true
+   */
+  function send()
+  {
+    $instance =& FirePHP::getInstance(true);
+    $args = func_get_args();
+    return call_user_func_array(array(&$instance,'fb'),$args);
+  }
+
+  /**
+   * Start a group for following messages
+   * 
+   * Options:
+   *   Collapsed: [true|false]
+   *   Color:     [#RRGGBB|ColorName]
+   *
+   * @param string $Name
+   * @param array $Options OPTIONAL Instructions on how to log the group
+   * @return true
+   */
+  function group($Name, $Options=null) {
+    $instance =& FirePHP::getInstance(true);
+    return $instance->group($Name, $Options);
+  }
+
+  /**
+   * Ends a group you have started before
+   *
+   * @return true
+   */
+  function groupEnd() {
+    return FB::send(null, null, FirePHP_GROUP_END);
+  }
+
+  /**
+   * Log object with label to firebug console
+   *
+   * @see FirePHP::LOG
+   * @param mixes $Object
+   * @param string $Label
+   * @return true
+   */
+  function log($Object, $Label=null) {
+    return FB::send($Object, $Label, FirePHP_LOG);
+  } 
+
+  /**
+   * Log object with label to firebug console
+   *
+   * @see FirePHP::INFO
+   * @param mixes $Object
+   * @param string $Label
+   * @return true
+   */
+  function info($Object, $Label=null) {
+    return FB::send($Object, $Label, FirePHP_INFO);
+  } 
+
+  /**
+   * Log object with label to firebug console
+   *
+   * @see FirePHP::WARN
+   * @param mixes $Object
+   * @param string $Label
+   * @return true
+   */
+  function warn($Object, $Label=null) {
+    return FB::send($Object, $Label, FirePHP_WARN);
+  } 
+
+  /**
+   * Log object with label to firebug console
+   *
+   * @see FirePHP::ERROR
+   * @param mixes $Object
+   * @param string $Label
+   * @return true
+   */
+  function error($Object, $Label=null) {
+    return FB::send($Object, $Label, FirePHP_ERROR);
+  } 
+
+  /**
+   * Dumps key and variable to firebug server panel
+   *
+   * @see FirePHP::DUMP
+   * @param string $Key
+   * @param mixed $Variable
+   * @return true
+   */
+  function dump($Key, $Variable) {
+    return FB::send($Variable, $Key, FirePHP_DUMP);
+  } 
+
+  /**
+   * Log a trace in the firebug console
+   *
+   * @see FirePHP::TRACE
+   * @param string $Label
+   * @return true
+   */
+  function trace($Label) {
+    return FB::send($Label, FirePHP_TRACE);
+  } 
+
+  /**
+   * Log a table in the firebug console
+   *
+   * @see FirePHP::TABLE
+   * @param string $Label
+   * @param string $Table
+   * @return true
+   */
+  function table($Label, $Table) {
+    return FB::send($Table, $Label, FirePHP_TABLE);
+  } 
+}

+ 52 - 0
sites/all/libraries/FirePHPCore/FirePHPCore/pear.package.tpl.xml

@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package packagerversion="1.7.1" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0                http://pear.php.net/dtd/tasks-1.0.xsd                http://pear.php.net/dtd/package-2.0                http://pear.php.net/dtd/package-2.0.xsd">
+  
+ <name>FirePHPCore</name>
+ <channel>pear.firephp.org</channel>
+ <summary>Core feature and communication library</summary>
+ <description>Handles all communication between the PHP code on the server and the FirePHP Firefox client extension. Also implements all core FirePHP features.</description>
+ <lead>
+  <name>Christoph Dorn</name>
+  <user>cadorn</user>
+  <email>christoph@christophdorn.com</email>
+  <active>yes</active>
+ </lead>
+ 
+ <date>##Date##</date>
+ <version>
+  <release>##Version####Release##</release>
+  <api>0.1</api>
+ </version>
+ 
+ <stability>
+  <release>##Stability##</release>
+  <api>stable</api>
+ </stability>
+ 
+ <license>New BSD</license>
+ 
+ <notes>No Notes</notes>
+ 
+ <contents>
+  <dir name="/" baseinstalldir="FirePHPCore">
+
+   <file name="fb.php" role="php"/>
+   <file name="fb.php4" role="php"/>
+
+   <file name="FirePHP.class.php" role="php"/>
+   <file name="FirePHP.class.php4" role="php"/>
+
+  </dir>
+ </contents>
+ <dependencies>
+  <required>
+   <php>
+    <min>4.0</min>
+   </php>
+   <pearinstaller>
+    <min>1.4.5</min>
+   </pearinstaller>
+  </required>
+ </dependencies>
+ <phprelease />
+</package>

+ 379 - 0
sites/all/libraries/MPDF54/CHANGELOG.txt

@@ -0,0 +1,379 @@
+===========================
+mPDF 5.4
+14/02/2012
+===========================
+
+
+Files changed
+-------------
+mpdf.php
+config.php
+compress.php
+classes/ttfontsuni.php
+classes/barcode.php
+classes/indic.php
+classes/svg.php
+examples/show_code.php	-----  SECURITY RISK**
+examples/example49_changelog.php
+examples/example57_new_mPDF_v5-3_active_forms_b (replace example57_new_mPDF_v5-3_active_forms)
+includes/out.php
+mpdfi/fpdi_pdf_parser.php
+
+Files added
+-----------
+classes/bmp.php
+classes/directw.php
+classes/form.php
+classes/grad.php
+classes/tocontents.php
+classes/wmf.php
+examples/example58_new_mPDF_v5-4_features
+
+config.php changes
+------------------
+Edited: $this->allowedCSStags, $this->innerblocktags, $this->defaultCSS;  (CAPTION added in each case)
+Moved: Numerous $form_.. variables are now in /classes/form.php
+
+New config variables 
+--------------------
+$this->bookmarkStyles = array();
+$this->cacheTables = true;
+	
+New methods
+-----------
+function CircularText()
+function SetVisibility()
+
+New/Extended CSS
+----------------
+box-shadow (block elements - does NOT support "inset")
+text-shadow (all text elements - does NOT support "blur")
+visibility: visible|hidden|printonly|screenonly (block-level elements and images IMG only)
+text-transform: capitalize|uppercase|lowercase (extended to support TD/TH)
+tr|td|th:nth-child(odd|even|2n+1)
+color, strikethrough, underline and background-color (extended to support rotated TD/TH)
+underline and strike-through (extended to support TD/TH)
+underline (line colour)  (extended to work correctly in watermark)
+page-break-after: left|right|always (block elements and tables)
+	NB respects $mpdf->restoreBlockPagebreaks = true; i.e. will make pagebreak act like formfeed
+background[-color]: extended to support rgba|cmyka|cmyk|hsla|hsl|spot
+border(extended to support inline elements)
+
+
+New HTML
+--------
+<caption>
+<textcircle />
+
+
+New features / Improvements
+---------------------------
+Tables - Zebra Stripes
+Tables: overlapping rowspans (partially) supported
+Tables - Disk caching
+Using progress bars (or $showStats) now reports 'real' memory usage i.e. get_memory_usage(true)
+Support for query string in the URLs for external stylesheets e.g. @import url("style.css?ltcyy7");
+Table caption partially supported
+CircularText
+BookMark styling
+Spread tables i.e. can split table (columns) across several pages width.
+Can use chelvetica, ctimes and ccourier to specify core fonts in a non-core font document
+Spread tables i.e. can split table (columns) across several pages width.
+{colsum} in <tfoot> cell will insert a column total per page.
+SVG embedded as island in HTML supported
+Active Forms
+	textarea and input (text types) now accept javascript as:
+	onKeystroke, onValidate, onCalculate and onFormat
+	onChange is depracated but works as onCalculate (for textarea and input)
+	(PS Select still accepts onChange cf. 5.3.37)
+Ledger and Tabloid added as page formats recognised. NB Ledger is same as tabloid but landscape. In mPDF, both give the same size (portrait)
+so need to add -L e.g. Ledger-L for landscape.
+
+
+Internal script changes
+-----------------------
+Changed this->k to _MPDFK throughout all scripts
+Changes to color (packed binary data in string rather than array) to reduce memory usage esp in tables
+Internal variables Removed
+	$usetableheader;
+	$tableheadernrows;
+	$tablefooternrows;
+vars $ChangePage, $p_bottom_border, $img_margin_top(+) $issetcolor + other similar  removed
+
+Removed a whole load of // comments
+Updates to remove some more Warning Notices (not all marked in text)
+Border set on TR - changed so set on each cell, rather than retrospectively at end of TR
+All references to table['text'] removed as not needed - uses ['textbuffer'] instead
+OpenTag(TD) changes to reduce memory usage with tables
+Includes different method to set a default timezone
+fn _smallCaps does not need (undefined) $space
+this->chrs and this->ords replaced by chr() and ord()
+Headers in out.php updated to match those used in Output()
+Change to SetFont() to improve performance time
+Change to GetStringWidth() to improve performance time
+Corrected copying of Glyphs 0,1,2, to all subset fonts (non-SMP/SIP), and only setting 32->127 in subset
+Subset fonts (non-SMP/SIP) have additionally Unicode CMap tables (0,0,4 and 0,3,4) as well as Microsoft (3,1,4)
+Subset fonts (SMP/SIP) have CMap tables (1,0,6 and 3,0,4) - rather than 1,0,6 and 3,0,6
+Subset fonts (SMP/SIP) have 'name' table changed to give 1,0 and 3,0. As it is a symbol font (not Unicode encoded) :
+	needs to have a name entry in 3,0 (e.g. symbol) - original font will have 3,1 (i.e. Unicode)
+Automatically checks for HTML code length > 100000 characters and gives error warning if
+	 PHP < 5.2.0 (as not configurable) or increases pcre.backtrack_limit if PHP < 5.3.7
+
+Removed/Depracated
+------------------
+function UseTableHeader($opt=true)	fn removed / depracated
+function UsePRE($opt=true) removed
+$attr['REPEAT_HEADER'] == true		CSS removed / depracated
+$this->usepre=true; removed / depracated as never needed - always respects PRE whitespace
+
+ToC: NB Values can no longer be set directly e.g. as in example
+	$mpdf->TOCheader = array();	// array as for setting header/footer
+	$mpdf->TOCfooter = array();	// array as for setting header/footer
+	$mpdf->TOCpreHTML = '<h2>Contents - Portrait</h2>';	// HTML text to appear before table of contents
+	$mpdf->TOCpostHTML = '';	// HTML text to appear after table of contents
+	$mpdf->TOCbookmarkText = 'Content list';	// Text as it will appear in the Bookmarks (leave blank for none)
+Need to use TOCpagebreak either direct (or array version) or as HTML
+OR if absolutley necessary, could use:
+	$mpdf->tocontents->TOCheader = array();	// array as for setting header/footer
+	$mpdf->tocontents->TOCfooter = array();	// array as for setting header/footer
+	$mpdf->tocontents->TOCpreHTML = '<h2>Contents - Portrait</h2>';	// HTML text to appear before table of contents
+	$mpdf->tocontents->TOCpostHTML = '';	// HTML text to appear after table of contents
+	$mpdf->tocontents->TOCbookmarkText = 'Content list';	// Text as it will appear in the Bookmarks (leave blank for none)
+
+
+
+Further Details
+===============
+
+CSS border on inline elements
+-----------------------------
+Support for CSS border (and variants) on inline elements e.g. <span style="border-bottom: 1px dashed #000000;">
+Border styles solid|dotted|dashed|double only are supported. Border radius not supported.
+Nested inline elements will have repeat left|right borders on the nested content (unlike browsers)
+
+Tables - Zebra Stripes
+----------------------
+TABLE - striped rows cf. http://dev.opera.com/articles/view/zebra-striping-tables-with-css3/
+tr:nth-child(odd) { background-color: #99ff99; }
+thead tr:nth-child(3n+2) { background-color: #FFBBFF; }
+td:nth-child(2n+1) { background-color: #BBBBFF; }
+table.zebraTable td:nth-child(2n+1) { background-color: #BBBBFF; }
+table.zebraTable th:nth-child(2n+1) { background-color: #BBBBFF; }
+
+NB mPDF does NOT correctly apply specificity to all CSS
+table.zebra tbody tr:nth-child(2n+1) td { background-color: #FFFFBB; }
+table.zebra tbody td:nth-child(odd) { background-color: #BBBBFF; }
+
+should make every odd row yellow, and every odd coloumn blue, but with the row/yellow overriding the column/blue.
+In mPDF the td:nth-child(odd) trumps the plain td, so the column colour wins out. You can force the effect you want by using
+table.zebra tbody tr:nth-child(2n+1) td:nth-child(1n+0) { background-color: #FFFFBB; }
+
+(The :nth-child(1n+0) selector just selects every td cell.)
+
+
+
+Tables - Disk caching
+---------------------
+TABLES: using disk caching
+// Using disk to cache table data can reduce memory usage dramatically, but at a cost of increased 
+// executon time and disk access (read and write)
+$this->cacheTables = true;
+NB		$this->packTableData will be overridden to => true;	// required for cacheTables
+		$this->simpleTables will be overridden to => false;  // Cannot co-exist with cacheTables
+
+
+Table caption
+-------------
+Must come immediately after <table...>
+CSS caption-side and HTML align attribute of top|bottom supported (not attribute left|right)
+Handled as a separate block element brought outside the table, so:
+	CSS will not cascade correctly on the table
+	width of caption block is that of page or of the block element containing the table
+	so alignment will be to the page-width not the table width
+	if table page-break-after: always, the caption will follow the pagebreak.
+This does work:
+<style>
+.tablecaption { caption-side: bottom; text-align: left; font-weight: bold; color: green; }
+</style>
+...
+<table>
+<caption class="tablecaption">Caption title here</caption>
+<tbody>
+
+CSS visibility: printonly, screenonly
+-------------------------------------
+Roughly based on CSS
+
+Works on Block elements P, DIV etc, or Image
+Cannot nest / layer.
+Inner blocks/image with set visibility are ignored if already set on enclosing block element.
+(Block element) does not work inside table (image does)
+So 'visible' does nothing but is set as default
+(NB Changes output to PDF version 1.5)
+Incompatible with PDFA / PDFX
+
+'visibility'
+    Value:  	visible | hidden | (collapse | inherit)
+    Initial:  	visible
+    Applies to:  	all elements
+    Inherited:  	yes
+
+The 'visibility' property specifies whether the boxes generated by an element are rendered.
+Invisible boxes still affect layout (set the 'display' property to 'none' to suppress box generation altogether).
+Values have the following meanings:
+
+visible
+    The generated box is visible.
+hidden
+    The generated box is invisible (fully transparent, nothing is drawn), but still affects layout.
+	Furthermore, descendants of the element will be visible if they have 'visibility: visible'.
+collapse | inherit
+    NOT supported in mPDF
+
+CUSTOM:
+printonly | screenonly
+
+
+Added VISIBILITY function
+$mpdf->SetVisibility('screenonly'); or 'printonly' 'visible' or 'hidden'
+(NB Changes output to PDF version 1.5)
+Incompatible with PDFA / PDFX
+
+CircularText
+------------
+function CircularText($x, $y, $r, $text, $align='top', $kerning=120, $fontwidth=100) {
+x: abscissa of center
+y: ordinate of center
+r: radius of circle
+text: text to be printed
+align: text alignment: top or bottom. Default value: top
+kerning: spacing between letters in percentage. Default value: 120. Zero is not allowed.
+fontwidth: width of letters in percentage. Default value: 100. Zero is not allowed
+
+- now uses Kerning between letters if useKerning == true (set manually see example)
+
+BookMark styling
+----------------
+New configurable variable to control appearance of Bookmarks e.g.
+$this->bookmarkStyles = array(
+	0 => array('color'=> array(0,64,128), 'style'=>'B'),
+	1 => array('color'=> array(128,0,0), 'style'=>''),
+	2 => array('color'=> array(0,128,0), 'style'=>'I'),
+);
+	
+Column sums
+-----------
+(Also changed some preg_replace to str_replace to improve performance)
+To use: just add {colsum} to any cells of the table footer <tfoot>
+Add a number to specify a fixed number of decimal points e.g. <td>£{colsum2}</td>  will give you £123.40
+The width of the column will be calculated using the actual string {colsum} as a placeholder.
+If you need the column to be wider, use underscores "_" to pad it e.g. {colsum2_____}
+
+
+Spread tables
+-------------
+i.e. can split table (columns) across several pages width.
+CSS <table style="overflow: visible">
+Cannot use with: 
+$this->kwt - ignored
+$this->table_rotate - ignored
+$this->table_keep_together - ignored
+$this->ColActive  - cancels spread tables
+
+Messes up with:
+$mpdf->forcePortraitHeaders = true;
+$mpdf->forcePortraitMargins = true;
+Problems with CJK, and RTL
+
+Will do no resizing of fonts at all.
+Maximum width of column = page width i.e. will not split columns across pages - NB will keep colspan>1 on one page
+If table row too high for page will die with error message.
+Will override some specs for width if this creates conflicts
+Recommended to specify absolute value of width on each column.
+
+
+
+
+Bug fixes
+=========
+Dottab - if text after dottab is hyperlinked <a></a> then dots are underlined
+
+page-break-before now respects $mpdf->restoreBlockPagebreaks = true; i.e. will make pagebreak act like formfeed
+Annotation() function called directly with colorarray(r,g,b)
+
+Added urldecode to _getImage to cope with ../name%20of%20image.jpg
+Added urldecode AND htmlspecials_decode to href in <a> link e.g. https://www.google.com/search?hl=en&amp;q=mpdf&amp;filename=name%20of%20file
+[barcode.php] Allow &nbsp; in C39 codes - will be changed to spaces
+
+<table> inside a <div position:fixed, left:300px;> not calculating table width correctly
+	- leading to either upside down table or error width less than 1 character
+
+Depracated magic_quotes_runtime() in compress.php
+
+DIRECTW included twice in compress.php
+FORMS mark up for compress.php corrected
+
+double backslashes not preserved inside <pre> or <textarea>
+
+font-weight and font-style not recognised in <pageheader>
+
+Progress bars causing corrupt PDF file (out.php) changed fopen from "r" mode to "rb" (binary)
+Target around image - <a href="#internaltarget"><img ... /></a> - not working
+
+SmallCaps in <thead> error
+
+Fonts with "name" table in format 1 not recognised correctly
+Rotated table which does not fit on remaining page, forces a new page even if already at top of page
+
+Locale causing problems - all instances of sprintf() using %.3f changed to %.3F so not locale aware
+
+CSS border radius not implemented on fixed/absolute positioned block element
+
+Background color in rotated table extending way beyond bottom of table
+
+Nested table containing <thead> or <tfoot> was confused with <thead> or <tfoot> of parent table
+
+Correct handling of spaces, < or & in textarea
+
+<option> and <input ..> attributes value/title decoded with fn lesser_entity_decode instead of htmlspecialchars_decode to include &apos;
+
+line width not restored to correct value after "line-through" text in Cell()
+
+Kannada - incorrect positioning of Reph
+
+Forms - In <input> or <option> (select) not correctly handling HTML named entities e.g. &lt; in value or title
+Active forms - &nbsp; as Value or Title incorrectly showing as Euro - PDFDocEncoding fixed
+
+Unicode data in embedded fonts not encrypted when doc encrypted 
+
+Nested block elements which are empty including innermost one, top margin of innermost block was ignored
+
+font-size: xx% inside a block was setting on block's parent font-size
+
+Active forms - radio buttons (removed name from Widget - leave on Radio group)
+	causing problems accessing field for radio buttons
+
+When using simple tables and border-collapse, if table border set, but cell borders not set, should display table border (fixed)
+position:fixed block - if neither top nor bottom nor height specified, was positioned incorrectly (y)
+Leave - if top, bottom, margin-top, margiin-bottom and height are all left unspecified (or auto), will centre vertically
+on the page (specific to mPDF - not consistent with CSS2.1)
+But if any one of them are specified (including e.g. margin-top=0), follows CSS spec, so top is the current "static" position
+
+background-image-opacity=0 not working on BODY or BLOCK
+
+Lists - if LI continues after a nested List, would add as a new LI item (should continue as part of earlier LI item)
+
+fn WriteCell() converts to 'windows-1252' when required
+if multiple calls to mPDF used, cannot redefine function cmp()
+internal link targets <a name="xx" /> in ToC not moved when using: page-break-inside:avoid
+internal link targets <a name="xx" /> not moved when using: columns, page-break-inside:avoid, keep-with-table or table rotate
+
+Active Forms - onChange not working for SELECT (cf. 5.3.25) Example 57 only worked by chance as JS was carried over from Select to Text field
+Bug is fixed, but example file needed updating to onCalculate for the display field.
+
+Table cell: if height set as %, currently sets it as % of page-width; instead this now ignores it.
+
+Bengali letter Khanda Ta (U+09CE) character not recognised; was added in Unicode v4.1 and prior to this, (U+09A4 U+09CD U+200D)
+	so mPDF converts to this string and seems to work.
+
+OCR characters wrong size in barcodes if using different ocr font

+ 92 - 0
sites/all/libraries/MPDF54/CREDITS.txt

@@ -0,0 +1,92 @@
+
+
+/*******************************************************************************
+* Software: FPDF                                                               *
+* Version:  1.53                                                               *
+* Date:     2004-12-31                                                         *
+* Author:   Olivier PLATHEY                                                    *
+* License:  Freeware                                                           *
+*                                                                              *
+* You may use and modify this software as you wish.                            *
+*******************************************************************************/
+
+/*******************************************************************************
+* HTML2FPDF is a php script to read a HTML text and generate a PDF file.       *
+* Copyright (C) 2004-2005 Renato Coelho                                        *
+*	                          					       *
+* html2fpdf.php, htmltoolkit.php                                               *
+*******************************************************************************/
+
+CREDITS From HTML2FPDF:
+
+-Olivier Plathey for the fpdf.php class [http://www.fpdf.org]
+-Damon Kohler for the Flowing Block script [mailto:damonkohler@yahoo.com]
+-Clément Lavoillotte for HTML-oriented FPDF idea
+-Yamasoft for the gif.php class [http://www.yamasoft.com/]
+-Jérôme Fenal for the _parsegif() function
+-"VIETCOM" for the PDFTable code [http://www.freepgs.com/vietcom/tool/pdftable/] [mailto:vncommando@yahoo.com]
+-Yukihiro O. for the SetDash() function [mailto:yukihiro_o@infoseek.jp]
+-Ron Korving for the WordWrap() function
+-Michel Poulain for the DisplayPreferences() function
+-Patrick Benny for the MultiCellBlt() function idea [no longer in use]
+-Seb for the _SetTextRendering() and SetTextOutline() functions [mailto:captainseb@wanadoo.fr]
+-MorphSoft for the colornames list idea
+-W3SCHOOLS for HTML-related reference info [http://www.w3schools.com/]
+
+
+
+/****************************************************************************
+* Software: FPDF_Protection                                                 *
+* Version:  1.02                                                            *
+* Date:     2005/05/08                                                      *
+* Author:   Klemen VODOPIVEC                                                *
+* License:  Freeware                                                        *
+*                                                                           *
+* You may use and modify this software as you wish as stated in original    *
+* FPDF package.                                                             *
+****************************************************************************/
+
+/****************************************************************************
+//  FPDI - Version 1.2
+//
+//    Copyright 2004-2007 Setasign - Jan Slabon
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+****************************************************************************/
+
+/****************************************************************************
+   * @copyright Khaled Al-Shamaa 2008
+   * @link http://www.ar-php.org
+   * @author Khaled Al-Shamaa <khaled@ar-php.org>
+   * @desc   Set of PHP5 / UTF-8 Classes developed to enhance Arabic web
+   *         applications by providing set of tools includes stem-based searching, 
+   *         translitiration, soundex, Hijri calendar, charset detection and
+   *         converter, spell numbers, keyboard language, Muslim prayer time, 
+   *         auto-summarization, and more...
+   * @package Arabic
+   *    
+   * @version 1.8 released in Feb 15, 2009
+   * 
+   * @license LGPL
+****************************************************************************/
+
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation;
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+[http://www.opensource.org/licenses/lgpl-license.php]
+

+ 164 - 0
sites/all/libraries/MPDF54/FONT INFO.txt

@@ -0,0 +1,164 @@
+
+=================
+Open Source Fonts
+=================
+mPDF should be able to read most TrueType Unicode font files with a .ttf extension
+Truetype fonts with .ttf or .otf extension and .ttc TrueType collections should also work OK.
+
+You will probably therefore have access to any number of fonts, but here are some useful sources for 
+open-source or free-use fonts. Many of these were included with earlier versions of mPDF:
+
+General collections
+-------------------
+- DejaVu font collection from: http://dejavu-fonts.org/wiki/Main_Page (included in the release)
+- GNU FreeFont from: http://www.gnu.org/software/freefont/
+- Linux Libertine from: http://www.linuxlibertine.org (use the .ttf files - not the .otf)
+- Liberation Fonts from: https://fedorahosted.org/liberation-fonts/ or directly https://fedorahosted.org/releases/l/i/liberation-fonts/
+
+Thai fonts
+----------
+- Collection of Thai fonts from: ftp://linux.thai.net/pub/thailinux/software/thai-ttf/
+
+
+OCR-B
+-----
+OCRB (ocrb10) font: http://ansuz.sooke.bc.ca/software/ocrb.php
+	Useful for barcodes (included in the release)
+
+Pan-Unicode fonts (fonts containing most characters defined in Unicode)
+-----------------------------------------------------------------------
+- BitStream Cyberbit from: http://aol-4.vo.llnwd.net/pub/communicator/extras/fonts/windows/
+	Cyberbit.ZIP (or just Google it)
+	(NB if run with $debug_fonts gives warning of invalid table checksum - just turn it off!)
+- Code2000 (NB shareware) from: http://www.code2000.net/code2000_page.htm
+- Quivira from: http://www.quivira-font.com/ (combining diacritics are not placed correctly, but has a very full set of glyphs)
+
+
+CJK (Chinese-Japanese-Korean)
+-----------------------------
+HanNomA and B from: http://vietunicode.sourceforge.net/fonts/fonts_hannom.html
+unBatang_0613 from: http://people.ktug.or.kr/~nomos/mine/UnBatang_0613.ttf
+Sun-ExtA and Sun-ExtB from: http://www.alanwood.net/unicode/fonts-east-asian.html
+	(http://www.alanwood.net/downloads/index.html)
+Fonts which contain both Unicode BMP and SIP (Supplementary Ideographic Plane) 
+	characters in one file e.g. "AR PL UMing" and "AR PL UKai" 
+	from: http://www.freedesktop.org  
+	http://www.freedesktop.org/wiki/Software/CJKUnifonts/Download
+[MS Windows fonts such as MS Mincho and MingLiU also work] 
+Japanese IPA fonts: http://ossipedia.ipa.go.jp/ipafont/index.html
+
+Arabic/Eastern fonts
+--------------------
+- XW Zar fonts can be downloaded from: http://www.redlers.com/downloadfont.html
+	(2 of these fonts are included in the release)
+	(original site in Farsi: http://wiki.irmug.org/index.php/XWZar)
+- See below for more details and font names of the fonts used in mPDF 4.x
+
+
+Other sources
+-------------
+http://www.unifont.org/fontguide/
+http://www.alanwood.net/unicode/fonts.html
+http://cooltext.com (e.g. http://cooltext.com/Fonts-Unicode+Arabic)
+ApparatusSIL, DoulosSIL, Padauk from SIL: http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&cat_id=FontDownloads
+DaiBanna (Tai Le) 
+
+Mediaeval & Ancient Scripts
+---------------------------
+Junicode: http://junicode.sourceforge.net/
+Cardo: http://scholarsfonts.net/cardofnt.html
+
+Syriac fonts
+------------
+http://www.bethmardutho.org/meltho/
+
+
+
+
+============
+ARABIC FONTS
+============
+You can use any appropriate Unicode-encoded .ttf or .ttc font file for arabic text, but
+the font file must include the Arabic Presentation Forms-B (U+FE70–U+FEFF).
+2 of the XW Zar fonts are included in the release.
+
+
+
+===========
+INDIC FONTS
+===========
+Indic scripts e.g. Hindi, Bengali etc. use conjuct forms which have no Unicode assignment. You 
+cannot therefore use any standard .ttf font files with mPDF.
+
+A set of fonts has been adapted to use specifically with mPDF. They are based on a set of fonts from:
+
+http://www.cdacmumbai.in/projects/indix/e_introduction.shtml
+
+NB These fonts are released under GNU GPL Version 2 license
+
+You need these adapted fonts (ind_bn_1_001.ttf etc.) to work with mPDF, as the glyphs have been 
+assigned to Unicode values in the Private Use area (U+E000 ->). These are included in the 
+mPDF download.
+
+
+
+Users of mPDF v4.x
+------------------
+The original indic font files do not contain a full set of even basic ASCII
+characters. The fonts supplied have been "fixed" to include those extra
+characters. This now works whether the font is subset or not.
+
+
+
+=========
+CJK Fonts
+=========
+
+
+Supplemental Ideographic Plane
+==============================
+SIP = Supplemental Ideographic Plane ( = Plane 2) = U+20000 - U+2FFFF  (131072 - 196607)
+These characters are required for the HKSCS Hong Kong Supplementary Character Set. Fonts with 
+SIP characters are commonly divided into a second file e.g. MingLiU and MingLiU-ExtB
+
+mPDF requires 2 fonts and they should be cross-referenced in config_fonts.php e.g.
+	"sun-exta" => array(
+		'R' => "Sun-ExtA.ttf",
+		'sip-ext' => 'sun-extb',
+		),
+	"sun-extb" => array(
+		'R' => "Sun-ExtB.ttf",
+		),
+
+--OR--
+(NB these ones also define the font number within the TTC Collection as TTCfontID)
+	'mingliu' => array (
+		'R' => 'mingliu.ttc',
+		'TTCfontID' => array (
+			'R' => 1,
+		),
+		'sip-ext' => 'mingliu-extb',
+	),
+	'mingliu-extb' => array (
+		'R' => 'mingliub.ttc',
+		'TTCfontID' => array (
+			'R' => 1,
+		),
+	),
+	'mingliu_hkscs' => array (
+		'R' => 'mingliu.ttc',
+		'TTCfontID' => array (
+			'R' => 3,
+		),
+		'sip-ext' => 'mingliu_hkscs-extb',
+	),
+	'mingliu_hkscs-extb' => array (
+		'R' => 'mingliub.ttc',
+		'TTCfontID' => array (
+			'R' => 3,
+		),
+	),
+
+
+
+

+ 340 - 0
sites/all/libraries/MPDF54/LICENSE.txt

@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the 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 Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.

+ 148 - 0
sites/all/libraries/MPDF54/README.txt

@@ -0,0 +1,148 @@
+Installation
+============
+    * Download the .zip file and unzip it
+    * Create a folder e.g. /mpdf on your server
+    * Upload all of the files to the server, maintaining the folders as they are
+    * Ensure that you have write permissions set (CHMOD 6xx or 7xx) for the following folders:
+	 /ttfontdata/ - used to cache font data; improves performance a lot
+	 /tmp/ - used for some images and ProgressBar
+	 /graph_cache/ - if you are using JpGraph in conjunction with mPDF
+
+To test the installation, point your browser to the basic example file : [path_to_mpdf_folder]/mpdf/examples/example_basic.php
+
+If you wish to define a different folder for temporary files rather than /tmp/ see the note on 'Folder for temporary files' in 
+ the section on Installation & Setup in the manual (http://mpdf1.com/manual/).
+
+If you have problems, please read the section on troubleshooting in the manual.
+
+
+Fonts
+=====
+I will refer to font names in 2 ways:
+"CSS font-family name" - mPDF is designed primarily to read HTML and CSS. This is the name used in CSS e.g.
+	<p style="font-family: 'Trebuchet MS';">
+
+"mPDF font-family name" - the name used internally to process fonts. This could be anything you like,
+	but by default mPDF will convert CSS font-family names by removing any spaces and changing
+	to lowercase. Reading the name above, mPDF will look for a "mPDF font-family name" of
+	'trebuchetms'.
+
+The configurable values referred to below are set in the config_fonts.php file
+
+When parsing HTML/CSS, mPDF will read the CSS font-family name (e.g. 'Trebuchet MS') and convert 
+by removing any spaces and changing to lowercase, to look for a mPDF font-family name (trebuchetms). 
+
+Next it will look for a translation (if set) e.g.:
+$this->fonttrans = array(
+	'trebuchetms' => 'trebuchet'
+)
+
+Now the mPDF font-family name to be used is 'trebuchet'
+
+If you wish to make this font available, you need to specify the Truetype .ttf font files for each variant.
+These should be defined in the array:
+$this->fontdata = array(
+	"trebuchet" => array(
+		'R' => "trebuc.ttf",
+		'B' => "trebucbd.ttf",
+		'I' => "trebucit.ttf",
+		'BI' => "trebucbi.ttf",
+		)
+)
+
+This is the array which determines whether a font is available to mPDF. Each font-family must have a
+Regular ['R'] file defined - the others (bold, italic, bold-italic) are optional.
+
+mPDF will try to load the font-file. If you have defined _MPDF_SYSTEM_TTFONTS at the top of the 
+config_fonts.php file, it will first look for the font-file there. This is useful if you are running 
+mPDF on a computer which already has a folder with TTF fonts in (e.g. on Windows)
+
+If the font-file is not there, or _MPDF_SYSTEM_TTFONTS is not defined, mPDF will look in the folder
+/[your_path_to_mpdf]/ttfonts/
+
+Note that the font-file names are case-sensitive and can contain capitals.
+
+If the folder /ttfontdata/ is writeable (CHMOD 644 or 755), mPDF will save files there which it can 
+re-use next time it accesses a particular font. This will significantly improve processing time
+and is strongly recommended. 
+
+mPDF should be able to read most TrueType Unicode font files with a .ttf extension
+Truetype fonts with .ttf extension that are OpenType also work OK.
+TrueType collections (.ttc) will also work if they contain TrueType Unicode fonts.
+
+
+Character substitution
+----------------------
+Most people will have access to a Pan-Unicode font with most Unicode characters in it such as 
+Arial Unicode MS. Set $this->backupSubsFont = array('arialunicodems'); at the top of the config_fonts.php file
+to use this font when substituting any characters not found in the specific font being used.
+
+Example:
+You can set $mpdf->useSubstitutions = true; at runtime
+or $this->useSubstitutions = true; in the config.php file
+
+<p style="font-family: 'Comic Sans MS'">This text contains a Thai character &#3617; which does not exist
+in the Comic Sans MS font file</p>
+
+When useSubstitutions is true, mPDF will try to find substitutions for any missing characters:
+1) firstly looks if the character is available in the inbuilt Symbols or ZapfDingbats fonts;
+2) [If defined] looks in each of the the font(s) set by $this->backupSubsFont array
+
+NB There is an increase in processing time when using substitutions, and even more so if
+a backupSubsFont is defined.
+
+Controlling mPDF mode
+=====================
+The first parameter of new mPDF('') works as follows:
+new mPDF('c') - forces mPDF to only use the built-in [c]ore Adobe fonts (Helvetica, Times etc)
+
+new mPDF('') - default - font subsetting behaviour is determined by the configurable variables
+	$this->maxTTFFilesize and $this->percentSubset (see below)
+	Default values are set so that: 1) very large font files are always subset
+	2) Fonts are embedded as subsets if < 30% of the characters are used
+
+new mPDF('..-x') - used together with a language or language/country code, this will cause
+	mPDF to use only in-built core fonts (Helvetica, Times) if the language specified is appropiate; 
+	otherwise it will force subsetting (equivalent to using "")
+	e.g. new mPDF('de-x') or new mPDF('pt-BR-x') will use in-built core fonts
+	and new mPDF('ru-x') will use subsets of any available TrueType fonts
+	The languages that use core fonts are defined in config_cp.php (using the value $coreSuitable).
+
+new mPDF('..+aCJK')  new mPDF('+aCJK')
+new mPDF('..-aCJK')  new mPDF('-aCJK')
+	 - used optionally together with a language or language/country code, +aCJK will force mPDF
+	to use the Adobe non-embedded CJK fonts when a passage is marked with e.g. "lang: ja"
+	This can be used at runtime to override the value set for $mpdf->useAdobeCJK in config.php
+	Use in conjunction with settings in config_cp.php
+
+For backwards compatibility, new mPDF('-s') and new mPDF('s') will force subsetting by 
+	setting $this->percentSubset=100 (see below)
+	new mPDF('utf-8-s') and new mPDF('ar-s') are also recognised
+
+Language/Country (ll-cc)
+------------------------
+You can use a language code ('en') or language/country code ('en-GB') to control which 
+mode/fonts are used. The behaviour is set up in config_cp.php file.
+The default settings show some of the things you can do:
+new mPDF('de') - as German is a Western European langauge, it is suitable to use the Adobe core fonts.
+	Using 'de' alone will do nothing, but if you use ('de-x'), this will use core fonts.
+new mPDF('th') - many fonts do not contain the characters necessary for Thai script. The value $unifonts 
+	defines a restricted list of fonts available for mPDF to use.
+
+NB <html dir="rtl"> or <body dir="rtl"> are supported.
+
+
+
+Configuration variables changed
+===============================
+Configuration variables are documented in the on-line manual (http://mpdf1.com/manual/).
+
+
+Font folders
+============
+If you wish to define your own font file folders (perhaps to share),
+you can define the 2 constants in your script before including the mpdf.php script e.g.:
+
+define('_MPDF_TTFONTPATH','your_path/ttfonts/'); 		
+define('_MPDF_TTFONTDATAPATH','your_path/ttfontdata/'); 	// should be writeable
+

File diff suppressed because it is too large
+ 1721 - 0
sites/all/libraries/MPDF54/classes/barcode.php


+ 248 - 0
sites/all/libraries/MPDF54/classes/bmp.php

@@ -0,0 +1,248 @@
+<?php
+
+class bmp {
+
+var $mpdf = null;
+
+function bmp(&$mpdf) {
+	$this->mpdf = $mpdf;
+}
+
+
+function _getBMPimage($data, $file) {
+	$info = array();
+		// Adapted from script by Valentin Schmidt
+		// http://staff.dasdeck.de/valentin/fpdf/fpdf_bmp/
+		$bfOffBits=$this->_fourbytes2int_le(substr($data,10,4));
+		$width=$this->_fourbytes2int_le(substr($data,18,4));
+		$height=$this->_fourbytes2int_le(substr($data,22,4));
+		$flip = ($height<0);
+		if ($flip) $height =-$height;
+		$biBitCount=$this->_twobytes2int_le(substr($data,28,2));
+		$biCompression=$this->_fourbytes2int_le(substr($data,30,4)); 
+		$info = array('w'=>$width, 'h'=>$height);
+		if ($biBitCount<16){
+			$info['cs'] = 'Indexed';
+			$info['bpc'] = $biBitCount;
+			$palStr = substr($data,54,($bfOffBits-54));
+			$pal = '';
+			$cnt = strlen($palStr)/4;
+			for ($i=0;$i<$cnt;$i++){
+				$n = 4*$i;
+				$pal .= $palStr[$n+2].$palStr[$n+1].$palStr[$n];
+			}
+			$info['pal'] = $pal;
+		}
+		else{
+			$info['cs'] = 'DeviceRGB';
+			$info['bpc'] = 8;
+		}
+
+		if ($this->mpdf->restrictColorSpace==1 || $this->mpdf->PDFX || $this->mpdf->restrictColorSpace==3) {
+			if (($this->mpdf->PDFA && !$this->mpdf->PDFAauto) || ($this->mpdf->PDFX && !$this->mpdf->PDFXauto)) { $this->mpdf->PDFAXwarnings[] = "Image cannot be converted to suitable colour space for PDFA or PDFX file - ".$file." - (Image replaced by 'no-image'.)"; }
+			return array('error' => "BMP Image cannot be converted to suitable colour space - ".$file." - (Image replaced by 'no-image'.)"); 
+		}
+
+		$biXPelsPerMeter=$this->_fourbytes2int_le(substr($data,38,4));	// horizontal pixels per meter, usually set to zero
+		//$biYPelsPerMeter=$this->_fourbytes2int_le(substr($data,42,4));	// vertical pixels per meter, usually set to zero
+		$biXPelsPerMeter=round($biXPelsPerMeter/1000 *25.4);
+		//$biYPelsPerMeter=round($biYPelsPerMeter/1000 *25.4);
+		$info['set-dpi'] = $biXPelsPerMeter; 
+
+		switch ($biCompression){
+		  case 0:
+			$str = substr($data,$bfOffBits);
+			break;
+		  case 1: # BI_RLE8
+			$str = $this->rle8_decode(substr($data,$bfOffBits), $width);
+			break;
+		  case 2: # BI_RLE4
+			$str = $this->rle4_decode(substr($data,$bfOffBits), $width);
+			break;
+		}
+		$bmpdata = '';
+		$padCnt = (4-ceil(($width/(8/$biBitCount)))%4)%4;
+		switch ($biBitCount){
+		  case 1:
+		  case 4:
+		  case 8:
+			$w = floor($width/(8/$biBitCount)) + ($width%(8/$biBitCount)?1:0);
+			$w_row = $w + $padCnt;
+			if ($flip){
+				for ($y=0;$y<$height;$y++){
+					$y0 = $y*$w_row;
+					for ($x=0;$x<$w;$x++)
+						$bmpdata .= $str[$y0+$x];
+				}
+			}else{
+				for ($y=$height-1;$y>=0;$y--){
+					$y0 = $y*$w_row;
+					for ($x=0;$x<$w;$x++)
+						$bmpdata .= $str[$y0+$x];
+				}
+			}
+			break;
+
+		  case 16:
+			$w_row = $width*2 + $padCnt;
+			if ($flip){
+				for ($y=0;$y<$height;$y++){
+					$y0 = $y*$w_row;
+					for ($x=0;$x<$width;$x++){
+						$n = (ord( $str[$y0 + 2*$x + 1])*256 +    ord( $str[$y0 + 2*$x]));
+						$b = ($n & 31)<<3; $g = ($n & 992)>>2; $r = ($n & 31744)>>7128;
+						$bmpdata .= chr($r) . chr($g) . chr($b);
+					}
+				}
+			}else{
+				for ($y=$height-1;$y>=0;$y--){
+					$y0 = $y*$w_row;
+					for ($x=0;$x<$width;$x++){
+						$n = (ord( $str[$y0 + 2*$x + 1])*256 +    ord( $str[$y0 + 2*$x]));
+						$b = ($n & 31)<<3; $g = ($n & 992)>>2; $r = ($n & 31744)>>7;
+						$bmpdata .= chr($r) . chr($g) . chr($b);
+					}
+				}
+			}
+			break;
+
+		  case 24:
+		  case 32:
+			$byteCnt = $biBitCount/8;
+			$w_row = $width*$byteCnt + $padCnt;
+
+			if ($flip){
+				for ($y=0;$y<$height;$y++){
+					$y0 = $y*$w_row;
+					for ($x=0;$x<$width;$x++){
+						$i = $y0 + $x*$byteCnt ; # + 1
+						$bmpdata .= $str[$i+2].$str[$i+1].$str[$i];
+					}
+				}
+			}else{
+				for ($y=$height-1;$y>=0;$y--){
+					$y0 = $y*$w_row;
+					for ($x=0;$x<$width;$x++){
+						$i = $y0 + $x*$byteCnt ; # + 1
+						$bmpdata .= $str[$i+2].$str[$i+1].$str[$i];
+					}
+				}
+			}
+			break;
+
+		  default:
+			return array('error' => 'Error parsing BMP image - Unsupported image biBitCount'); 
+		}
+		if ($this->mpdf->compress) {
+			$bmpdata=gzcompress($bmpdata);
+			$info['f']='FlateDecode';
+		} 
+		$info['data']=$bmpdata;
+		$info['type']='bmp';
+		return $info;
+}
+
+function _fourbytes2int_le($s) {
+	//Read a 4-byte integer from string
+	return (ord($s[3])<<24) + (ord($s[2])<<16) + (ord($s[1])<<8) + ord($s[0]);
+}
+
+function _twobytes2int_le($s) {
+	//Read a 2-byte integer from string
+	return (ord(substr($s, 1, 1))<<8) + ord(substr($s, 0, 1));
+}
+
+
+# Decoder for RLE8 compression in windows bitmaps
+# see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_6x0u.asp
+function rle8_decode ($str, $width){
+    $lineWidth = $width + (3 - ($width-1) % 4);
+    $out = '';
+    $cnt = strlen($str);
+    for ($i=0;$i<$cnt;$i++){
+        $o = ord($str[$i]);
+        switch ($o){
+            case 0: # ESCAPE
+                $i++;
+                switch (ord($str[$i])){
+                    case 0: # NEW LINE
+                         $padCnt = $lineWidth - strlen($out)%$lineWidth;
+                        if ($padCnt<$lineWidth) $out .= str_repeat(chr(0), $padCnt); # pad line
+                        break;
+                    case 1: # END OF FILE
+                        $padCnt = $lineWidth - strlen($out)%$lineWidth;
+                        if ($padCnt<$lineWidth) $out .= str_repeat(chr(0), $padCnt); # pad line
+                         break 3;
+                    case 2: # DELTA
+                        $i += 2;
+                        break;
+                    default: # ABSOLUTE MODE
+                        $num = ord($str[$i]);
+                        for ($j=0;$j<$num;$j++)
+                            $out .= $str[++$i];
+                        if ($num % 2) $i++;
+             }
+                break;
+            default:
+                $out .= str_repeat($str[++$i], $o);
+        }
+    }
+    return $out;
+}
+
+# Decoder for RLE4 compression in windows bitmaps
+# see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_6x0u.asp
+function rle4_decode ($str, $width){
+    $w = floor($width/2) + ($width % 2);
+    $lineWidth = $w + (3 - ( ($width-1) / 2) % 4);    
+    $pixels = array();
+    $cnt = strlen($str);
+    for ($i=0;$i<$cnt;$i++){
+        $o = ord($str[$i]);
+        switch ($o){
+            case 0: # ESCAPE
+                $i++;
+                switch (ord($str[$i])){
+                    case 0: # NEW LINE                        
+                        while (count($pixels)%$lineWidth!=0)
+                            $pixels[]=0;
+                        break;
+                    case 1: # END OF FILE
+                        while (count($pixels)%$lineWidth!=0)
+                            $pixels[]=0;
+                        break 3;
+                    case 2: # DELTA
+                        $i += 2;
+                        break;
+                    default: # ABSOLUTE MODE
+                        $num = ord($str[$i]);
+                        for ($j=0;$j<$num;$j++){
+                            if ($j%2==0){
+                                $c = ord($str[++$i]);
+                              $pixels[] = ($c & 240)>>4;
+                             } else
+                              $pixels[] = $c & 15;
+                        }
+                        if ($num % 2) $i++;
+             }
+                break;
+            default:
+                $c = ord($str[++$i]);
+                for ($j=0;$j<$o;$j++)
+                    $pixels[] = ($j%2==0 ? ($c & 240)>>4 : $c & 15);
+        }
+    }
+    
+    $out = '';
+    if (count($pixels)%2) $pixels[]=0;
+    $cnt = count($pixels)/2;
+    for ($i=0;$i<$cnt;$i++)
+        $out .= chr(16*$pixels[2*$i] + $pixels[2*$i+1]);
+    return $out;
+} 
+
+
+
+}
+
+?>

+ 371 - 0
sites/all/libraries/MPDF54/classes/directw.php

@@ -0,0 +1,371 @@
+<?php
+
+class directw {
+
+var $mpdf = null;
+
+function directw(&$mpdf) {
+	$this->mpdf = $mpdf;
+}
+
+
+function Write($h,$txt,$currentx=0,$link='',$directionality='ltr',$align='') {
+	if (!$align) { 
+		if ($directionality=='rtl') { $align = 'R'; }
+		else { $align = 'L'; }
+	}
+	if ($h == 0) { $this->mpdf->SetLineHeight(); $h = $this->mpdf->lineheight; }
+	//Output text in flowing mode
+	$w = $this->mpdf->w - $this->mpdf->rMargin - $this->mpdf->x; 
+
+	$wmax = ($w - ($this->mpdf->cMarginL+$this->mpdf->cMarginR));
+	$s=str_replace("\r",'',$txt);
+	if ($this->mpdf->usingCoreFont)  { $nb=strlen($s); }
+	else {
+		$nb=mb_strlen($s, $this->mpdf->mb_enc );
+		// handle single space character
+		if(($nb==1) && $s == " ") {
+			$this->mpdf->x += $this->mpdf->GetStringWidth($s);
+			return;
+		}
+	}
+	$sep=-1;
+	$i=0;
+	$j=0;
+	$l=0;
+	$nl=1;
+	if (!$this->mpdf->usingCoreFont) {
+		if (preg_match("/([".$this->mpdf->pregRTLchars."])/u", $txt)) { $this->mpdf->biDirectional = true; }	// *RTL*
+		$checkCursive=false;
+		if ($this->mpdf->biDirectional) {  $checkCursive=true; }	// *RTL*
+		else if (isset($this->mpdf->CurrentFont['indic']) && $this->mpdf->CurrentFont['indic']) {  $checkCursive=true; }	// *INDIC*
+		while($i<$nb) {
+			//Get next character
+			$c = mb_substr($s,$i,1,$this->mpdf->mb_enc );
+			if($c == "\n") {
+				// WORD SPACING
+				$this->mpdf->ResetSpacing();
+				//Explicit line break
+				$tmp = rtrim(mb_substr($s,$j,$i-$j,$this->mpdf->mb_enc));
+				if ($directionality == 'rtl' && $align == 'J') { $align = 'R'; }	// *RTL*
+				$this->mpdf->magic_reverse_dir($tmp, true, $directionality);	// *RTL*
+				$this->mpdf->Cell($w, $h, $tmp, 0, 2, $align, $fill, $link);
+				$i++;
+				$sep = -1;
+				$j = $i;
+				$l = 0;
+				if($nl == 1) {
+					if ($currentx != 0) $this->mpdf->x=$currentx;
+					else $this->mpdf->x=$this->mpdf->lMargin;
+					$w = $this->mpdf->w - $this->mpdf->rMargin - $this->mpdf->x;
+					$wmax = ($w - ($this->mpdf->cMarginL+$this->mpdf->cMarginR));
+				}
+				$nl++;
+				continue;
+			}
+			if($c == " ") { $sep= $i; }
+			$l += $this->mpdf->GetCharWidthNonCore($c);	// mPDF 5.3.04
+			if($l > $wmax) {
+				//Automatic line break (word wrapping)
+				if($sep == -1) {
+					// WORD SPACING
+					$this->mpdf->ResetSpacing();
+					if($this->mpdf->x > $this->mpdf->lMargin) {
+						//Move to next line
+						if ($currentx != 0) $this->mpdf->x=$currentx;
+						else $this->mpdf->x=$this->mpdf->lMargin;
+						$this->mpdf->y+=$h;
+						$w=$this->mpdf->w-$this->mpdf->rMargin-$this->mpdf->x;
+						$wmax = ($w - ($this->mpdf->cMarginL+$this->mpdf->cMarginR));
+						$i++;
+						$nl++;
+						continue;
+					}
+					if($i==$j) { $i++; }
+					$tmp = rtrim(mb_substr($s,$j,$i-$j,$this->mpdf->mb_enc));
+					if ($directionality == 'rtl' && $align == 'J') { $align = 'R'; }	// *RTL*
+					$this->mpdf->magic_reverse_dir($tmp, true, $directionality);	// *RTL*
+					$this->mpdf->Cell($w, $h, $tmp, 0, 2, $align, $fill, $link);
+				}
+				else {
+					$tmp = rtrim(mb_substr($s,$j,$sep-$j,$this->mpdf->mb_enc));
+					if ($directionality == 'rtl' && $align == 'J') { $align = 'R'; }	// *RTL*
+					$this->mpdf->magic_reverse_dir($tmp, true, $directionality);	// *RTL*
+
+					if($align=='J') {
+						//////////////////////////////////////////
+						// JUSTIFY J using Unicode fonts (Word spacing doesn't work)
+						// WORD SPACING
+						// Change NON_BREAKING SPACE to spaces so they are 'spaced' properly
+					      $tmp = str_replace(chr(194).chr(160),chr(32),$tmp ); 
+						$len_ligne = $this->mpdf->GetStringWidth($tmp );
+						$nb_carac = mb_strlen( $tmp , $this->mpdf->mb_enc ) ;  
+						$nb_spaces = mb_substr_count( $tmp ,' ', $this->mpdf->mb_enc ) ;  
+						$inclCursive=false;
+						if ($checkCursive) {
+							if (preg_match("/([".$this->mpdf->pregRTLchars."])/u", $tmp)) { $inclCursive = true; }	// *RTL*
+							if (preg_match("/([".$this->mpdf->pregHIchars.$this->mpdf->pregBNchars.$this->mpdf->pregPAchars."])/u", $tmp)) { $inclCursive = true; }	// *INDIC*
+						}
+						list($charspacing,$ws) = $this->mpdf->GetJspacing($nb_carac,$nb_spaces,((($w-2) - $len_ligne) * _MPDFK),$inclCursive);
+						$this->mpdf->SetSpacing($charspacing,$ws);
+						//////////////////////////////////////////
+					}
+					$this->mpdf->Cell($w, $h, $tmp, 0, 2, $align, $fill, $link);
+					$i=$sep+1;
+				}
+				$sep = -1;
+				$j = $i;
+				$l = 0;
+				if($nl==1) {
+					if ($currentx != 0) $this->mpdf->x=$currentx;
+					else $this->mpdf->x=$this->mpdf->lMargin;
+					$w=$this->mpdf->w-$this->mpdf->rMargin-$this->mpdf->x;
+					$wmax = ($w - ($this->mpdf->cMarginL+$this->mpdf->cMarginR));
+				}
+				$nl++;
+			}
+			else { $i++; }
+		}
+		//Last chunk
+		// WORD SPACING
+		$this->mpdf->ResetSpacing();
+	}
+	else {
+		while($i<$nb) {
+			//Get next character
+			$c=$s[$i];
+			if($c == "\n") {
+				//Explicit line break
+				// WORD SPACING
+				$this->mpdf->ResetSpacing();
+				$this->mpdf->Cell($w, $h, substr($s, $j, $i-$j), 0, 2, $align, $fill, $link);
+				$i++;
+				$sep = -1;
+				$j = $i;
+				$l = 0;
+				if($nl == 1) {
+					if ($currentx != 0) $this->mpdf->x=$currentx;
+					else $this->mpdf->x=$this->mpdf->lMargin;
+					$w = $this->mpdf->w - $this->mpdf->rMargin - $this->mpdf->x;
+					$wmax=$w-($this->mpdf->cMarginL+$this->mpdf->cMarginR);
+				}
+				$nl++;
+				continue;
+			}
+			if($c == " ") { $sep= $i; }
+			$l += $this->mpdf->GetCharWidthCore($c);	// mPDF 5.3.04
+			if($l > $wmax) {
+				//Automatic line break (word wrapping)
+				if($sep == -1) {
+					// WORD SPACING
+					$this->mpdf->ResetSpacing();
+					if($this->mpdf->x > $this->mpdf->lMargin) {
+						//Move to next line
+						if ($currentx != 0) $this->mpdf->x=$currentx;
+						else $this->mpdf->x=$this->mpdf->lMargin;
+						$this->mpdf->y+=$h;
+						$w=$this->mpdf->w-$this->mpdf->rMargin-$this->mpdf->x;
+						$wmax=$w-($this->mpdf->cMarginL+$this->mpdf->cMarginR);
+						$i++;
+						$nl++;
+						continue;
+					}
+					if($i==$j) { $i++; }
+					$this->mpdf->Cell($w, $h, substr($s, $j, $i-$j), 0, 2, $align, $fill, $link);
+				}
+				else {
+					$tmp = substr($s, $j, $sep-$j);
+					if($align=='J') {
+						//////////////////////////////////////////
+						// JUSTIFY J using Unicode fonts (Word spacing doesn't work)
+						// WORD SPACING
+						// Change NON_BREAKING SPACE to spaces so they are 'spaced' properly
+					      $tmp = str_replace(chr(160),chr(32),$tmp );
+						$len_ligne = $this->mpdf->GetStringWidth($tmp );
+						$nb_carac = strlen( $tmp ) ;  
+						$nb_spaces = substr_count( $tmp ,' ' ) ;  
+						list($charspacing,$ws) = $this->mpdf->GetJspacing($nb_carac,$nb_spaces,((($w-2) - $len_ligne) * _MPDFK),$false);
+						$this->mpdf->SetSpacing($charspacing,$ws);
+						//////////////////////////////////////////
+					}
+					$this->mpdf->Cell($w, $h, $tmp, 0, 2, $align, $fill, $link);
+					$i=$sep+1;
+				}
+				$sep = -1;
+				$j = $i;
+				$l = 0;
+				if($nl==1) {
+					if ($currentx != 0) $this->mpdf->x=$currentx;
+					else $this->mpdf->x=$this->mpdf->lMargin;
+					$w=$this->mpdf->w-$this->mpdf->rMargin-$this->mpdf->x;
+					$wmax=$w-($this->mpdf->cMarginL+$this->mpdf->cMarginR);
+				}
+				$nl++;
+			}
+			else {
+				$i++;
+			}
+		}
+		// WORD SPACING
+		$this->mpdf->ResetSpacing();
+	}
+	//Last chunk
+	if($i!=$j) {
+		if ($currentx != 0) $this->mpdf->x=$currentx;
+		else $this->mpdf->x=$this->mpdf->lMargin;	
+		if ($this->mpdf->usingCoreFont) { $tmp = substr($s,$j,$i-$j); }
+		else {
+			$tmp = mb_substr($s,$j,$i-$j,$this->mpdf->mb_enc);
+			if ($directionality == 'rtl' && $align == 'J') { $align = 'R'; }	// *RTL*
+			$this->mpdf->magic_reverse_dir($tmp, true, $directionality);	// *RTL*
+		}
+		$this->mpdf->Cell($w,$h,$tmp,0,0,$align,$fill,$link);
+	}
+}
+
+
+function CircularText($x, $y, $r, $text, $align='top', $fontfamily='', $fontsizePt=0, $fontstyle='', $kerning=120, $fontwidth=100) {
+	if ($font || $fontstyle || $fontsizePt) $this->mpdf->SetFont($fontfamily,$fontstyle,$fontsizePt);
+	$kerning/=100;
+	$fontwidth/=100;        
+	if($kerning==0) $this->mpdf->Error('Please use values unequal to zero for kerning (CircularText)');
+	if($fontwidth==0) $this->mpdf->Error('Please use values unequal to zero for font width (CircularText)');        
+	$t=0;
+	$text=str_replace("\r",'',$text);
+	if ($this->mpdf->usingCoreFont)  {
+		$nb=strlen($text); 
+		for($i=0; $i<$nb; $i++){
+			$w[$i]=$this->mpdf->GetStringWidth($text[$i]);
+			$w[$i]*=$kerning*$fontwidth;
+			$t+=$w[$i];
+		}
+	}
+	else { 
+		$nb=mb_strlen($text, $this->mpdf->mb_enc ); 
+		$lastchar = '';
+		$unicode = $this->mpdf->UTF8StringToArray($text);
+		for($i=0; $i<$nb; $i++){
+			$c = mb_substr($text,$i,1,$this->mpdf->mb_enc );
+			$w[$i]=$this->mpdf->GetStringWidth($c);
+			$w[$i]*=$kerning*$fontwidth;
+			$char = $unicode[$i];
+			if ($this->mpdf->useKerning && $lastchar) {
+				if (isset($this->mpdf->CurrentFont['kerninfo'][$lastchar][$char])) { 
+					$tk = $this->mpdf->CurrentFont['kerninfo'][$lastchar][$char] * ($this->mpdf->FontSize/ 1000) * $kerning * $fontwidth; 
+					$w[$i] += $tk/2;
+					$w[$i-1] += $tk/2;
+					$t+=$tk;
+				}
+			}
+			$lastchar = $char;
+			$t+=$w[$i];
+		}
+	}
+	//circumference
+	$u=($r*2)*M_PI;
+	//total width of string in degrees
+	$d=($t/$u)*360;
+
+	$this->mpdf->StartTransform();
+	// rotate matrix for the first letter to center the text
+	// (half of total degrees)
+	if($align=='top'){
+		$this->mpdf->transformRotate(-$d/2, $x, $y);
+	}
+	else{
+		$this->mpdf->transformRotate($d/2, $x, $y);
+	}
+	//run through the string
+	for($i=0; $i<$nb; $i++){
+		if($align=='top'){
+			//rotate matrix half of the width of current letter + half of the width of preceding letter
+			if($i==0){
+				$this->mpdf->transformRotate((($w[$i]/2)/$u)*360, $x, $y);
+			}
+			else{
+				$this->mpdf->transformRotate((($w[$i]/2+$w[$i-1]/2)/$u)*360, $x, $y);
+			}
+			if($fontwidth!=1){
+				$this->mpdf->StartTransform();
+				$this->mpdf->transformScale($fontwidth*100, 100, $x, $y);
+			}
+			$this->mpdf->SetXY($x-$w[$i]/2, $y-$r);
+		}
+		else{
+			//rotate matrix half of the width of current letter + half of the width of preceding letter
+			if($i==0){
+				$this->mpdf->transformRotate(-(($w[$i]/2)/$u)*360, $x, $y);
+			}
+			else{
+				$this->mpdf->transformRotate(-(($w[$i]/2+$w[$i-1]/2)/$u)*360, $x, $y);
+			}
+			if($fontwidth!=1){
+				$this->mpdf->StartTransform();
+				$this->mpdf->transformScale($fontwidth*100, 100, $x, $y);
+			}
+			$this->mpdf->SetXY($x-$w[$i]/2, $y+$r-($this->mpdf->FontSize));
+		}
+		if ($this->mpdf->usingCoreFont) { $c=$text[$i]; }
+		else { $c = mb_substr($text,$i,1,$this->mpdf->mb_enc ); }
+		$this->mpdf->Cell(($w[$i]),$this->mpdf->FontSize,$c,0,0,'C');	// mPDF 5.3.53
+		if($fontwidth!=1){
+			$this->mpdf->StopTransform();
+		}
+	}
+	$this->mpdf->StopTransform();
+}
+
+function Shaded_box( $text,$font='',$fontstyle='B',$szfont='',$width='70%',$style='DF',$radius=2.5,$fill='#FFFFFF',$color='#000000',$pad=2 )
+{
+// F (shading - no line),S (line, no shading),DF (both)
+	if (!$font) { $font= $this->mpdf->default_font; }
+	if (!$szfont) { $szfont = ($this->mpdf->default_font_size * 1.8); }
+
+	$text = $this->mpdf->purify_utf8_text($text);
+	if ($this->mpdf->text_input_as_HTML) {
+		$text = $this->mpdf->all_entities_to_utf8($text);
+	}
+	if ($this->mpdf->usingCoreFont) { $text = mb_convert_encoding($text,$this->mpdf->mb_enc,'UTF-8'); }
+	// DIRECTIONALITY
+	$this->mpdf->magic_reverse_dir($text, true, $this->mpdf->directionality);	// *RTL*
+	// Font-specific ligature substitution for Indic fonts
+	if (isset($this->mpdf->CurrentFont['indic']) && $this->mpdf->CurrentFont['indic']) $this->mpdf->ConvertIndic($text);	// *INDIC*
+	$text = ' '.$text.' ';
+	if (!$width) { $width = $this->mpdf->pgwidth; } else { $width=$this->mpdf->ConvertSize($width,$this->mpdf->pgwidth); }
+	$midpt = $this->mpdf->lMargin+($this->mpdf->pgwidth/2);
+	$r1  = $midpt-($width/2);	//($this->mpdf->w / 2) - 40;
+	$r2  = $r1 + $width; 		//$r1 + 80;
+	$y1  = $this->mpdf->y;
+
+
+	$mid = ($r1 + $r2 ) / 2;
+	$loop   = 0;
+    
+	while ( $loop == 0 )
+	{
+		$this->mpdf->SetFont( $font, $fontstyle, $szfont );
+		$sz = $this->mpdf->GetStringWidth( $text );
+		if ( ($r1+$sz) > $r2 )
+			$szfont --;
+		else
+			$loop ++;
+	}
+
+	$y2  = $this->mpdf->FontSize+($pad*2);
+
+	$this->mpdf->SetLineWidth(0.1);
+	$fc = $this->mpdf->ConvertColor($fill);
+	$tc = $this->mpdf->ConvertColor($color);
+	$this->mpdf->SetFColor($fc);
+	$this->mpdf->SetTColor($tc);
+	$this->mpdf->RoundedRect($r1, $y1, ($r2 - $r1), $y2, $radius, $style);
+	$this->mpdf->SetX( $r1);
+	$this->mpdf->Cell($r2-$r1, $y2, $text, 0, 1, "C" );
+	$this->mpdf->SetY($y1+$y2+2);	// +2 = mm margin below shaded box
+	$this->mpdf->Reset();
+}
+
+
+}
+
+?>

File diff suppressed because it is too large
+ 1263 - 0
sites/all/libraries/MPDF54/classes/form.php


+ 700 - 0
sites/all/libraries/MPDF54/classes/gif.php

@@ -0,0 +1,700 @@
+<?php
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 2009-12-22 Adapted for mPDF 4.2
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// GIF Util - (C) 2003 Yamasoft (S/C)
+// http://www.yamasoft.com
+// All Rights Reserved
+// This file can be freely copied, distributed, modified, updated by anyone under the only
+// condition to leave the original address (Yamasoft, http://www.yamasoft.com) and this header.
+///////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 2009-12-22 Adapted INB 
+// Functions calling functionname($x, $len = 0) were not working on PHP5.1.5 as pass by reference
+// All edited to $len = 0; then call function.
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class CGIFLZW
+{
+	var $MAX_LZW_BITS;
+	var $Fresh, $CodeSize, $SetCodeSize, $MaxCode, $MaxCodeSize, $FirstCode, $OldCode;
+	var $ClearCode, $EndCode, $Next, $Vals, $Stack, $sp, $Buf, $CurBit, $LastBit, $Done, $LastByte;
+
+	///////////////////////////////////////////////////////////////////////////
+
+	// CONSTRUCTOR
+	function CGIFLZW()
+	{
+		$this->MAX_LZW_BITS = 12;
+		unSet($this->Next);
+		unSet($this->Vals);
+		unSet($this->Stack);
+		unSet($this->Buf);
+
+		$this->Next  = range(0, (1 << $this->MAX_LZW_BITS)       - 1);
+		$this->Vals  = range(0, (1 << $this->MAX_LZW_BITS)       - 1);
+		$this->Stack = range(0, (1 << ($this->MAX_LZW_BITS + 1)) - 1);
+		$this->Buf   = range(0, 279);
+	}
+
+	///////////////////////////////////////////////////////////////////////////
+
+	function deCompress($data, &$datLen)
+	{
+		$stLen  = strlen($data);
+		$datLen = 0;
+		$ret    = "";
+		$dp = 0; 	// data pointer
+
+		// INITIALIZATION
+		$this->LZWCommandInit($data, $dp);
+
+		while(($iIndex = $this->LZWCommand($data, $dp)) >= 0) {
+			$ret .= chr($iIndex);
+		}
+
+		$datLen = $dp;
+
+		if($iIndex != -2) {
+			return false;
+		}
+
+		return $ret;
+	}
+
+	///////////////////////////////////////////////////////////////////////////
+	function LZWCommandInit(&$data, &$dp)
+	{
+			$this->SetCodeSize = ord($data[0]);
+			$dp += 1;
+
+			$this->CodeSize    = $this->SetCodeSize + 1;
+			$this->ClearCode   = 1 << $this->SetCodeSize;
+			$this->EndCode     = $this->ClearCode + 1;
+			$this->MaxCode     = $this->ClearCode + 2;
+			$this->MaxCodeSize = $this->ClearCode << 1;
+
+			$this->GetCodeInit($data, $dp);
+
+			$this->Fresh = 1;
+			for($i = 0; $i < $this->ClearCode; $i++) {
+				$this->Next[$i] = 0;
+				$this->Vals[$i] = $i;
+			}
+
+			for(; $i < (1 << $this->MAX_LZW_BITS); $i++) {
+				$this->Next[$i] = 0;
+				$this->Vals[$i] = 0;
+			}
+
+			$this->sp = 0;
+			return 1;
+	}
+
+	function LZWCommand(&$data, &$dp)
+	{
+		if($this->Fresh) {
+			$this->Fresh = 0;
+			do {
+				$this->FirstCode = $this->GetCode($data, $dp);
+				$this->OldCode   = $this->FirstCode;
+			}
+			while($this->FirstCode == $this->ClearCode);
+
+			return $this->FirstCode;
+		}
+
+		if($this->sp > 0) {
+			$this->sp--;
+			return $this->Stack[$this->sp];
+		}
+
+		while(($Code = $this->GetCode($data, $dp)) >= 0) {
+			if($Code == $this->ClearCode) {
+				for($i = 0; $i < $this->ClearCode; $i++) {
+					$this->Next[$i] = 0;
+					$this->Vals[$i] = $i;
+				}
+
+				for(; $i < (1 << $this->MAX_LZW_BITS); $i++) {
+					$this->Next[$i] = 0;
+					$this->Vals[$i] = 0;
+				}
+
+				$this->CodeSize    = $this->SetCodeSize + 1;
+				$this->MaxCodeSize = $this->ClearCode << 1;
+				$this->MaxCode     = $this->ClearCode + 2;
+				$this->sp          = 0;
+				$this->FirstCode   = $this->GetCode($data, $dp);
+				$this->OldCode     = $this->FirstCode;
+
+				return $this->FirstCode;
+			}
+
+			if($Code == $this->EndCode) {
+				return -2;
+			}
+
+			$InCode = $Code;
+			if($Code >= $this->MaxCode) {
+				$this->Stack[$this->sp++] = $this->FirstCode;
+				$Code = $this->OldCode;
+			}
+
+			while($Code >= $this->ClearCode) {
+				$this->Stack[$this->sp++] = $this->Vals[$Code];
+
+				if($Code == $this->Next[$Code]) // Circular table entry, big GIF Error!
+					return -1;
+
+				$Code = $this->Next[$Code];
+			}
+
+			$this->FirstCode = $this->Vals[$Code];
+			$this->Stack[$this->sp++] = $this->FirstCode;
+
+			if(($Code = $this->MaxCode) < (1 << $this->MAX_LZW_BITS)) {
+				$this->Next[$Code] = $this->OldCode;
+				$this->Vals[$Code] = $this->FirstCode;
+				$this->MaxCode++;
+
+				if(($this->MaxCode >= $this->MaxCodeSize) && ($this->MaxCodeSize < (1 << $this->MAX_LZW_BITS))) {
+					$this->MaxCodeSize *= 2;
+					$this->CodeSize++;
+				}
+			}
+
+			$this->OldCode = $InCode;
+			if($this->sp > 0) {
+				$this->sp--;
+				return $this->Stack[$this->sp];
+			}
+		}
+
+		return $Code;
+	}
+
+	///////////////////////////////////////////////////////////////////////////
+
+	function GetCodeInit(&$data, &$dp)
+	{
+			$this->CurBit   = 0;
+			$this->LastBit  = 0;
+			$this->Done     = 0;
+			$this->LastByte = 2;
+			return 1;
+	}
+
+	function GetCode(&$data, &$dp)
+	{
+		if(($this->CurBit + $this->CodeSize) >= $this->LastBit) {
+			if($this->Done) {
+				if($this->CurBit >= $this->LastBit) {
+					// Ran off the end of my bits
+					return 0;
+				}
+				return -1;
+			}
+
+			$this->Buf[0] = $this->Buf[$this->LastByte - 2];
+			$this->Buf[1] = $this->Buf[$this->LastByte - 1];
+
+			$Count = ord($data[$dp]);
+			$dp += 1;
+
+			if($Count) {
+				for($i = 0; $i < $Count; $i++) {
+					$this->Buf[2 + $i] = ord($data[$dp+$i]);
+				}
+				$dp += $Count;
+			}
+			else {
+				$this->Done = 1;
+			}
+
+			$this->LastByte = 2 + $Count;
+			$this->CurBit   = ($this->CurBit - $this->LastBit) + 16;
+			$this->LastBit  = (2 + $Count) << 3;
+		}
+
+		$iRet = 0;
+		for($i = $this->CurBit, $j = 0; $j < $this->CodeSize; $i++, $j++) {
+			$iRet |= (($this->Buf[intval($i / 8)] & (1 << ($i % 8))) != 0) << $j;
+		}
+
+		$this->CurBit += $this->CodeSize;
+		return $iRet;
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class CGIFCOLORTABLE
+{
+	var $m_nColors;
+	var $m_arColors;
+
+	///////////////////////////////////////////////////////////////////////////
+
+	// CONSTRUCTOR
+	function CGIFCOLORTABLE()
+	{
+		unSet($this->m_nColors);
+		unSet($this->m_arColors);
+	}
+
+	///////////////////////////////////////////////////////////////////////////
+
+	function load($lpData, $num)
+	{
+		$this->m_nColors  = 0;
+		$this->m_arColors = array();
+
+		for($i = 0; $i < $num; $i++) {
+			$rgb = substr($lpData, $i * 3, 3);
+			if(strlen($rgb) < 3) {
+				return false;
+			}
+
+			$this->m_arColors[] = (ord($rgb[2]) << 16) + (ord($rgb[1]) << 8) + ord($rgb[0]);
+			$this->m_nColors++;
+		}
+
+		return true;
+	}
+
+	///////////////////////////////////////////////////////////////////////////
+
+	function toString()
+	{
+		$ret = "";
+
+		for($i = 0; $i < $this->m_nColors; $i++) {
+			$ret .=
+				chr(($this->m_arColors[$i] & 0x000000FF))       . // R
+				chr(($this->m_arColors[$i] & 0x0000FF00) >>  8) . // G
+				chr(($this->m_arColors[$i] & 0x00FF0000) >> 16);  // B
+		}
+
+		return $ret;
+	}
+
+
+	///////////////////////////////////////////////////////////////////////////
+
+	function colorIndex($rgb)
+	{
+		$rgb  = intval($rgb) & 0xFFFFFF;
+		$r1   = ($rgb & 0x0000FF);
+		$g1   = ($rgb & 0x00FF00) >>  8;
+		$b1   = ($rgb & 0xFF0000) >> 16;
+		$idx  = -1;
+
+		for($i = 0; $i < $this->m_nColors; $i++) {
+			$r2 = ($this->m_arColors[$i] & 0x000000FF);
+			$g2 = ($this->m_arColors[$i] & 0x0000FF00) >>  8;
+			$b2 = ($this->m_arColors[$i] & 0x00FF0000) >> 16;
+			$d  = abs($r2 - $r1) + abs($g2 - $g1) + abs($b2 - $b1);
+
+			if(($idx == -1) || ($d < $dif)) {
+				$idx = $i;
+				$dif = $d;
+			}
+		}
+
+		return $idx;
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class CGIFFILEHEADER
+{
+	var $m_lpVer;
+	var $m_nWidth;
+	var $m_nHeight;
+	var $m_bGlobalClr;
+	var $m_nColorRes;
+	var $m_bSorted;
+	var $m_nTableSize;
+	var $m_nBgColor;
+	var $m_nPixelRatio;
+	var $m_colorTable;
+
+	///////////////////////////////////////////////////////////////////////////
+
+	// CONSTRUCTOR
+	function CGIFFILEHEADER()
+	{
+		unSet($this->m_lpVer);
+		unSet($this->m_nWidth);
+		unSet($this->m_nHeight);
+		unSet($this->m_bGlobalClr);
+		unSet($this->m_nColorRes);
+		unSet($this->m_bSorted);
+		unSet($this->m_nTableSize);
+		unSet($this->m_nBgColor);
+		unSet($this->m_nPixelRatio);
+		unSet($this->m_colorTable);
+	}
+
+	///////////////////////////////////////////////////////////////////////////
+
+	function load($lpData, &$hdrLen)
+	{
+		$hdrLen = 0;
+
+		$this->m_lpVer = substr($lpData, 0, 6);
+		if(($this->m_lpVer <> "GIF87a") && ($this->m_lpVer <> "GIF89a")) {
+			return false;
+		}
+
+		$this->m_nWidth  = $this->w2i(substr($lpData, 6, 2));
+		$this->m_nHeight = $this->w2i(substr($lpData, 8, 2));
+		if(!$this->m_nWidth || !$this->m_nHeight) {
+			return false;
+		}
+
+		$b = ord(substr($lpData, 10, 1));
+		$this->m_bGlobalClr  = ($b & 0x80) ? true : false;
+		$this->m_nColorRes   = ($b & 0x70) >> 4;
+		$this->m_bSorted     = ($b & 0x08) ? true : false;
+		$this->m_nTableSize  = 2 << ($b & 0x07);
+		$this->m_nBgColor    = ord(substr($lpData, 11, 1));
+		$this->m_nPixelRatio = ord(substr($lpData, 12, 1));
+		$hdrLen = 13;
+
+		if($this->m_bGlobalClr) {
+			$this->m_colorTable = new CGIFCOLORTABLE();
+			if(!$this->m_colorTable->load(substr($lpData, $hdrLen), $this->m_nTableSize)) {
+				return false;
+			}
+			$hdrLen += 3 * $this->m_nTableSize;
+		}
+
+		return true;
+	}
+
+	///////////////////////////////////////////////////////////////////////////
+
+	function w2i($str)
+	{
+		return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8);
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class CGIFIMAGEHEADER
+{
+	var $m_nLeft;
+	var $m_nTop;
+	var $m_nWidth;
+	var $m_nHeight;
+	var $m_bLocalClr;
+	var $m_bInterlace;
+	var $m_bSorted;
+	var $m_nTableSize;
+	var $m_colorTable;
+
+	///////////////////////////////////////////////////////////////////////////
+
+	// CONSTRUCTOR
+	function CGIFIMAGEHEADER()
+	{
+		unSet($this->m_nLeft);
+		unSet($this->m_nTop);
+		unSet($this->m_nWidth);
+		unSet($this->m_nHeight);
+		unSet($this->m_bLocalClr);
+		unSet($this->m_bInterlace);
+		unSet($this->m_bSorted);
+		unSet($this->m_nTableSize);
+		unSet($this->m_colorTable);
+	}
+
+	///////////////////////////////////////////////////////////////////////////
+
+	function load($lpData, &$hdrLen)
+	{
+		$hdrLen = 0;
+
+		$this->m_nLeft   = $this->w2i(substr($lpData, 0, 2));
+		$this->m_nTop    = $this->w2i(substr($lpData, 2, 2));
+		$this->m_nWidth  = $this->w2i(substr($lpData, 4, 2));
+		$this->m_nHeight = $this->w2i(substr($lpData, 6, 2));
+
+		if(!$this->m_nWidth || !$this->m_nHeight) {
+			return false;
+		}
+
+		$b = ord($lpData{8});
+		$this->m_bLocalClr  = ($b & 0x80) ? true : false;
+		$this->m_bInterlace = ($b & 0x40) ? true : false;
+		$this->m_bSorted    = ($b & 0x20) ? true : false;
+		$this->m_nTableSize = 2 << ($b & 0x07);
+		$hdrLen = 9;
+
+		if($this->m_bLocalClr) {
+			$this->m_colorTable = new CGIFCOLORTABLE();
+			if(!$this->m_colorTable->load(substr($lpData, $hdrLen), $this->m_nTableSize)) {
+				return false;
+			}
+			$hdrLen += 3 * $this->m_nTableSize;
+		}
+
+		return true;
+	}
+
+	///////////////////////////////////////////////////////////////////////////
+
+	function w2i($str)
+	{
+		return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8);
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class CGIFIMAGE
+{
+	var $m_disp;
+	var $m_bUser;
+	var $m_bTrans;
+	var $m_nDelay;
+	var $m_nTrans;
+	var $m_lpComm;
+	var $m_gih;
+	var $m_data;
+	var $m_lzw;
+
+	///////////////////////////////////////////////////////////////////////////
+
+	function CGIFIMAGE()
+	{
+		unSet($this->m_disp);
+		unSet($this->m_bUser);
+		unSet($this->m_bTrans);
+		unSet($this->m_nDelay);
+		unSet($this->m_nTrans);
+		unSet($this->m_lpComm);
+		unSet($this->m_data);
+		$this->m_gih = new CGIFIMAGEHEADER();
+		$this->m_lzw = new CGIFLZW();
+	}
+
+	///////////////////////////////////////////////////////////////////////////
+
+	function load($data, &$datLen)
+	{
+		$datLen = 0;
+
+		while(true) {
+			$b = ord($data[0]);
+			$data = substr($data, 1);
+			$datLen++;
+
+			switch($b) {
+			case 0x21: // Extension
+				$len = 0;
+				if(!$this->skipExt($data, $len)) {
+					return false;
+				}
+				$datLen += $len;
+				break;
+
+			case 0x2C: // Image
+				// LOAD HEADER & COLOR TABLE
+				$len = 0;
+				if(!$this->m_gih->load($data, $len)) {
+					return false;
+				}
+				$data = substr($data, $len);
+				$datLen += $len;
+
+				// ALLOC BUFFER
+				$len = 0;
+
+				if(!($this->m_data = $this->m_lzw->deCompress($data, $len))) {
+					return false;
+				}
+
+				$data = substr($data, $len);
+				$datLen += $len;
+
+				if($this->m_gih->m_bInterlace) {
+					$this->deInterlace();
+				}
+
+				return true;
+
+			case 0x3B: // EOF
+			default:
+				return false;
+			}
+		}
+		return false;
+	}
+
+	///////////////////////////////////////////////////////////////////////////
+
+	function skipExt(&$data, &$extLen)
+	{
+		$extLen = 0;
+
+		$b = ord($data[0]);
+		$data = substr($data, 1);
+		$extLen++;
+
+		switch($b) {
+		case 0xF9: // Graphic Control
+			$b = ord($data[1]);
+			$this->m_disp   = ($b & 0x1C) >> 2;
+			$this->m_bUser  = ($b & 0x02) ? true : false;
+			$this->m_bTrans = ($b & 0x01) ? true : false;
+			$this->m_nDelay = $this->w2i(substr($data, 2, 2));
+			$this->m_nTrans = ord($data[4]);
+			break;
+
+		case 0xFE: // Comment
+			$this->m_lpComm = substr($data, 1, ord($data[0]));
+			break;
+
+		case 0x01: // Plain text
+			break;
+
+		case 0xFF: // Application
+			break;
+		}
+
+		// SKIP DEFAULT AS DEFS MAY CHANGE
+		$b = ord($data[0]);
+		$data = substr($data, 1);
+		$extLen++;
+		while($b > 0) {
+			$data = substr($data, $b);
+			$extLen += $b;
+			$b    = ord($data[0]);
+			$data = substr($data, 1);
+			$extLen++;
+		}
+		return true;
+	}
+
+	///////////////////////////////////////////////////////////////////////////
+
+	function w2i($str)
+	{
+		return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8);
+	}
+
+	///////////////////////////////////////////////////////////////////////////
+
+	function deInterlace()
+	{
+		$data = $this->m_data;
+
+		for($i = 0; $i < 4; $i++) {
+			switch($i) {
+			case 0:
+				$s = 8;
+				$y = 0;
+				break;
+
+			case 1:
+				$s = 8;
+				$y = 4;
+				break;
+
+			case 2:
+				$s = 4;
+				$y = 2;
+				break;
+
+			case 3:
+				$s = 2;
+				$y = 1;
+				break;
+			}
+
+			for(; $y < $this->m_gih->m_nHeight; $y += $s) {
+				$lne = substr($this->m_data, 0, $this->m_gih->m_nWidth);
+				$this->m_data = substr($this->m_data, $this->m_gih->m_nWidth);
+
+				$data =
+					substr($data, 0, $y * $this->m_gih->m_nWidth) .
+					$lne .
+					substr($data, ($y + 1) * $this->m_gih->m_nWidth);
+			}
+		}
+
+		$this->m_data = $data;
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class CGIF
+{
+	var $m_gfh;
+	var $m_lpData;
+	var $m_img;
+	var $m_bLoaded;
+
+	///////////////////////////////////////////////////////////////////////////
+
+	// CONSTRUCTOR
+	function CGIF()
+	{
+		$this->m_gfh     = new CGIFFILEHEADER();
+		$this->m_img     = new CGIFIMAGE();
+		$this->m_lpData  = "";
+		$this->m_bLoaded = false;
+	}
+
+	///////////////////////////////////////////////////////////////////////////
+	function ClearData() {
+		$this->m_lpData = '';
+		unSet($this->m_img->m_data);
+		unSet($this->m_img->m_lzw->Next);
+		unSet($this->m_img->m_lzw->Vals);
+		unSet($this->m_img->m_lzw->Stack);
+		unSet($this->m_img->m_lzw->Buf);
+	}
+
+	function loadFile(&$data, $iIndex)
+	{
+		if($iIndex < 0) {
+			return false;
+		}
+		$this->m_lpData = $data;
+
+		// GET FILE HEADER
+		$len = 0;
+		if(!$this->m_gfh->load($this->m_lpData, $len)) {
+			return false;
+		}
+
+		$this->m_lpData = substr($this->m_lpData, $len);
+
+		do {
+			$imgLen = 0;
+			if(!$this->m_img->load($this->m_lpData, $imgLen)) {
+				return false;
+			}
+			$this->m_lpData = substr($this->m_lpData, $imgLen);
+		}
+		while($iIndex-- > 0);
+
+		$this->m_bLoaded = true;
+		return true;
+	}
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+?>

+ 723 - 0
sites/all/libraries/MPDF54/classes/grad.php

@@ -0,0 +1,723 @@
+<?php
+
+class grad {
+
+var $mpdf = null;
+
+function grad(&$mpdf) {
+	$this->mpdf = $mpdf;
+}
+
+// mPDF 5.3.A1
+function CoonsPatchMesh($x, $y, $w, $h, $patch_array=array(), $x_min=0, $x_max=1, $y_min=0, $y_max=1, $colspace='RGB', $return=false){
+	$s=' q ';
+	$s.=sprintf(' %.3F %.3F %.3F %.3F re W n ', $x*_MPDFK, ($this->mpdf->h-$y)*_MPDFK, $w*_MPDFK, -$h*_MPDFK);
+	$s.=sprintf(' %.3F 0 0 %.3F %.3F %.3F cm ', $w*_MPDFK, $h*_MPDFK, $x*_MPDFK, ($this->mpdf->h-($y+$h))*_MPDFK);
+	$n = count($this->mpdf->gradients)+1;
+	$this->mpdf->gradients[$n]['type'] = 6; //coons patch mesh
+	$this->mpdf->gradients[$n]['colorspace'] = $colspace; //coons patch mesh
+	$bpcd=65535; //16 BitsPerCoordinate
+	$trans = false;
+	$this->mpdf->gradients[$n]['stream']='';
+	for($i=0;$i<count($patch_array);$i++){
+		$this->mpdf->gradients[$n]['stream'].=chr($patch_array[$i]['f']); //start with the edge flag as 8 bit
+		for($j=0;$j<count($patch_array[$i]['points']);$j++){
+			//each point as 16 bit
+			if (($j % 2) == 1) {	// Y coordinate (adjusted as input is From top left)
+				$patch_array[$i]['points'][$j]=(($patch_array[$i]['points'][$j]-$y_min)/($y_max-$y_min))*$bpcd;
+				$patch_array[$i]['points'][$j]=$bpcd-$patch_array[$i]['points'][$j];
+			}
+			else {
+				$patch_array[$i]['points'][$j]=(($patch_array[$i]['points'][$j]-$x_min)/($x_max-$x_min))*$bpcd;
+			}
+			if($patch_array[$i]['points'][$j]<0) $patch_array[$i]['points'][$j]=0;
+			if($patch_array[$i]['points'][$j]>$bpcd) $patch_array[$i]['points'][$j]=$bpcd;
+			$this->mpdf->gradients[$n]['stream'].=chr(floor($patch_array[$i]['points'][$j]/256));
+			$this->mpdf->gradients[$n]['stream'].=chr(floor($patch_array[$i]['points'][$j]%256));
+		}
+		for($j=0;$j<count($patch_array[$i]['colors']);$j++){
+			//each color component as 8 bit
+			if ($colspace=='RGB') {
+				$this->mpdf->gradients[$n]['stream'].=($patch_array[$i]['colors'][$j][1]);
+				$this->mpdf->gradients[$n]['stream'].=($patch_array[$i]['colors'][$j][2]);
+				$this->mpdf->gradients[$n]['stream'].=($patch_array[$i]['colors'][$j][3]);
+				if (isset($patch_array[$i]['colors'][$j][4]) && ord($patch_array[$i]['colors'][$j][4])<100) { $trans = true; }
+			}
+			else if ($colspace=='CMYK') {
+				$this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][1])*2.55);
+				$this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][2])*2.55);
+				$this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][3])*2.55);
+				$this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][4])*2.55);
+				if (isset($patch_array[$i]['colors'][$j][5]) && ord($patch_array[$i]['colors'][$j][5])<100) { $trans = true; }
+			}
+			else if ($colspace=='Gray') {
+				$this->mpdf->gradients[$n]['stream'].=($patch_array[$i]['colors'][$j][1]);
+				if ($patch_array[$i]['colors'][$j][2]==1) { $trans = true; }	// transparency converted from rgba or cmyka()
+			}
+		}
+	}
+	// TRANSPARENCY
+	if ($trans) { 
+		$this->mpdf->gradients[$n]['stream_trans']='';
+		for($i=0;$i<count($patch_array);$i++){
+			$this->mpdf->gradients[$n]['stream_trans'].=chr($patch_array[$i]['f']);
+			for($j=0;$j<count($patch_array[$i]['points']);$j++){
+				//each point as 16 bit
+				$this->mpdf->gradients[$n]['stream_trans'].=chr(floor($patch_array[$i]['points'][$j]/256));
+				$this->mpdf->gradients[$n]['stream_trans'].=chr(floor($patch_array[$i]['points'][$j]%256));
+			}
+			for($j=0;$j<count($patch_array[$i]['colors']);$j++){
+				//each color component as 8 bit // OPACITY
+				if ($colspace=='RGB') {
+					$this->mpdf->gradients[$n]['stream_trans'].=chr(intval(ord($patch_array[$i]['colors'][$j][4])*2.55));
+				}
+				else if ($colspace=='CMYK') {
+					$this->mpdf->gradients[$n]['stream_trans'].=chr(intval(ord($patch_array[$i]['colors'][$j][5])*2.55));
+				}
+				else if ($colspace=='Gray') {
+					$this->mpdf->gradients[$n]['stream_trans'].=chr(intval(ord($patch_array[$i]['colors'][$j][3])*2.55));
+				}
+			}
+		}
+		$this->mpdf->gradients[$n]['trans'] = true;	
+		$s .= ' /TGS'.$n.' gs ';
+	}
+	//paint the gradient
+	$s .= '/Sh'.$n.' sh'."\n";
+	//restore previous Graphic State
+	$s .= 'Q'."\n";
+	if ($return) { return $s; }
+	else { $this->mpdf->_out($s); }
+}
+
+
+// type = linear:2; radial: 3;
+// Linear: $coords - array of the form (x1, y1, x2, y2) which defines the gradient vector (see linear_gradient_coords.jpg). 
+//    The default value is from left to right (x1=0, y1=0, x2=1, y2=0).
+// Radial: $coords - array of the form (fx, fy, cx, cy, r) where (fx, fy) is the starting point of the gradient with color1, 
+//    (cx, cy) is the center of the circle with color2, and r is the radius of the circle (see radial_gradient_coords.jpg). 
+//    (fx, fy) should be inside the circle, otherwise some areas will not be defined
+// $col = array(R,G,B/255); or array(G/255); or array(C,M,Y,K/100)
+// $stops = array('col'=>$col [, 'opacity'=>0-1] [, 'offset'=>0-1])
+function Gradient($x, $y, $w, $h, $type, $stops=array(), $colorspace='RGB', $coords='', $extend='', $return=false, $is_mask=false) {
+	if (strtoupper(substr($type,0,1)) == 'L') { $type = 2; }	// linear
+	else if (strtoupper(substr($type,0,1)) == 'R') { $type = 3; }	// radial
+	if ($colorspace != 'CMYK' && $colorspace != 'Gray') {
+		$colorspace = 'RGB';
+	}
+	$bboxw = $w;
+	$bboxh = $h;
+	$usex = $x;
+	$usey = $y;
+	$usew = $bboxw;
+	$useh = $bboxh;
+	if ($type < 1) { $type = 2; }
+	if ($coords[0]!==false && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$coords[0],$m)) { 
+		$tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
+		if ($tmp) { $coords[0] = $tmp/$w; }
+	}
+	if ($coords[1]!==false && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$coords[1],$m)) { 
+		$tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
+		if ($tmp) { $coords[1] = 1-($tmp/$h); }
+	}
+	// LINEAR
+	if ($type == 2) { 
+		$angle = $coords[4];
+		$repeat = $coords[5];
+		// ALL POINTS SET (default for custom mPDF linear gradient) - no -moz
+		if ($coords[0]!==false && $coords[1]!==false && $coords[2]!==false && $coords[3]!==false) {
+			// do nothing - coords used as they are
+		}
+
+		// If both a <point> and <angle> are defined, the gradient axis starts from the point and runs along the angle. The end point is 
+		// defined as before - in this case start points may not be in corners, and axis may not correctly fall in the right quadrant.
+		// NO end points (Angle defined & Start points)
+		else if ($angle!==false && $coords[0]!==false && $coords[1]!==false && $coords[2]===false && $coords[3]===false) {
+		  if ($angle==0 || $angle==360) { $coords[3]=$coords[1]; if ($coords[0]==1) $coords[2]=2; else $coords[2]=1; }
+		  else if ($angle==90) { $coords[2]=$coords[0]; $coords[3]=1; if ($coords[1]==1) $coords[3]=2; else $coords[3]=1; }
+		  else if ($angle==180) { if ($coords[4]==0) $coords[2]=-1; else $coords[2]=0; $coords[3]=$coords[1]; }
+		  else if ($angle==270) { $coords[2]=$coords[0]; if ($coords[1]==0) $coords[3]=-1; else $coords[3]=0; }
+		  else {
+			$endx=1; $endy=1; 
+			if ($angle <=90) { 
+				if ($angle <=45) { $endy=tan(deg2rad($angle)); }
+				else { $endx=tan(deg2rad(90-$angle)); }
+				$b = atan2(($endy*$bboxh), ($endx*$bboxw));
+				$ny = 1 - $coords[1] - (tan($b) * (1-$coords[0]));
+				$tx = sin($b) * cos($b) * $ny;
+				$ty = cos($b) * cos($b) * $ny;
+				$coords[2] = 1+$tx; $coords[3] = 1-$ty; 
+			}
+			else if ($angle <=180) { 
+				if ($angle <=135) { $endx=tan(deg2rad($angle-90)); }
+				else { $endy=tan(deg2rad(180-$angle)); }
+				$b = atan2(($endy*$bboxh), ($endx*$bboxw));
+				$ny = 1 - $coords[1] - (tan($b) * ($coords[0]));
+				$tx = sin($b) * cos($b) * $ny;
+				$ty = cos($b) * cos($b) * $ny;
+				$coords[2] =  -$tx; $coords[3] = 1-$ty;
+			}
+			else if ($angle <=270) { 
+				if ($angle <=225) { $endy=tan(deg2rad($angle-180)); }
+				else { $endx=tan(deg2rad(270-$angle)); }
+				$b = atan2(($endy*$bboxh), ($endx*$bboxw));
+				$ny = $coords[1] - (tan($b) * ($coords[0]));
+				$tx = sin($b) * cos($b) * $ny;
+				$ty = cos($b) * cos($b) * $ny;
+				$coords[2] = -$tx; $coords[3] = $ty; 
+			}
+			else { 
+				if ($angle <=315) { $endx=tan(deg2rad($angle-270)); }
+				else { $endy=tan(deg2rad(360-$angle));  }
+				$b = atan2(($endy*$bboxh), ($endx*$bboxw));
+				$ny = $coords[1] - (tan($b) * (1-$coords[0]));
+				$tx = sin($b) * cos($b) * $ny;
+				$ty = cos($b) * cos($b) * $ny;
+				$coords[2] = 1+$tx; $coords[3] = $ty; 
+
+			}
+		  }
+		}
+
+		// -moz If the first parameter is only an <angle>, the gradient axis starts from the box's corner that would ensure the 
+		// axis goes through the box. The axis runs along the specified angle. The end point of the axis is defined such that the 
+		// farthest corner of the box from the starting point is perpendicular to the gradient axis at that point.
+		// NO end points or Start points (Angle defined)
+		else if ($angle!==false && $coords[0]===false && $coords[1]===false) {
+		  if ($angle==0 || $angle==360) { $coords[0]=0; $coords[1]=0; $coords[2]=1; $coords[3]=0; }
+		  else if ($angle==90) { $coords[0]=0; $coords[1]=0; $coords[2]=0; $coords[3]=1; }
+		  else if ($angle==180) { $coords[0]=1; $coords[1]=0; $coords[2]=0; $coords[3]=0; }
+		  else if ($angle==270) { $coords[0]=0; $coords[1]=1; $coords[2]=0; $coords[3]=0; }
+		  else {
+			if ($angle <=90) { 
+				$coords[0]=0; $coords[1]=0; 
+				if ($angle <=45) { $endx=1; $endy=tan(deg2rad($angle)); }
+				else { $endx=tan(deg2rad(90-$angle)); $endy=1; }
+			}
+			else if ($angle <=180) { 
+				$coords[0]=1; $coords[1]=0; 
+				if ($angle <=135) { $endx=tan(deg2rad($angle-90)); $endy=1; }
+				else { $endx=1; $endy=tan(deg2rad(180-$angle)); }
+			}
+			else if ($angle <=270) { 
+				$coords[0]=1; $coords[1]=1; 
+				if ($angle <=225) { $endx=1; $endy=tan(deg2rad($angle-180)); }
+				else { $endx=tan(deg2rad(270-$angle)); $endy=1; }
+			}
+			else { 
+				$coords[0]=0; $coords[1]=1; 
+				if ($angle <=315) { $endx=tan(deg2rad($angle-270)); $endy=1; }
+				else { $endx=1; $endy=tan(deg2rad(360-$angle));  }
+			}
+			$b = atan2(($endy*$bboxh), ($endx*$bboxw));
+			$h2 = $bboxh - ($bboxh * tan($b));
+			$px = $bboxh + ($h2 * sin($b) * cos($b));
+			$py = ($bboxh * tan($b)) + ($h2 * sin($b) * sin($b));
+			$x1 = $px / $bboxh;
+			$y1 = $py / $bboxh;
+			if ($angle <=90) { $coords[2] = $x1; $coords[3] = $y1; }
+			else if ($angle <=180) { $coords[2] = 1-$x1; $coords[3] = $y1; }
+			else if ($angle <=270) { $coords[2] = 1-$x1; $coords[3] = 1-$y1; }
+			else { $coords[2] = $x1; $coords[3] = 1-$y1; }
+		  }
+		}
+		// -moz If the first parameter to the gradient function is only a <point>, the gradient axis starts from the specified point, 
+		// and ends at the point you would get if you rotated the starting point by 180 degrees about the center of the box that the 
+		// gradient is to be applied to.
+		// NO angle and NO end points (Start points defined)
+		else if ((!isset($angle) || $angle===false) && $coords[0]!==false && $coords[1]!==false) { 	// should have start and end defined
+		  $coords[2] = 1-$coords[0]; $coords[3] = 1-$coords[1];
+		  $angle = rad2deg(atan2($coords[3]-$coords[1],$coords[2]-$coords[0]));
+		  if ($angle < 0) { $angle += 360; }
+		  else if ($angle > 360) { $angle -= 360; }
+		  if ($angle!=0 && $angle!=360 && $angle!=90 && $angle!=180 && $angle!=270) { 
+		    if ($w >= $h) {
+			$coords[1] *= $h/$w ;
+			$coords[3] *= $h/$w ;
+			$usew = $useh = $bboxw;
+			$usey -= ($w-$h);
+		    }
+		    else {
+			$coords[0] *= $w/$h ;
+			$coords[2] *= $w/$h ;
+			$usew = $useh = $bboxh;
+		    }
+		  }
+		}
+
+		// -moz If neither a <point> or <angle> is specified, i.e. the entire function consists of only <stop> values, the gradient 
+		// axis starts from the top of the box and runs vertically downwards, ending at the bottom of the box.
+		else {	// default values T2B
+			// All values are set in parseMozGradient - so won't appear here
+			$coords = array(0,0,1,0);	// default for original linear gradient (L2R)
+		}
+		$s = ' q';
+		$s .= sprintf(' %.3F %.3F %.3F %.3F re W n', $x*_MPDFK, ($this->mpdf->h-$y)*_MPDFK, $w*_MPDFK, -$h*_MPDFK)."\n";
+		$s .= sprintf(' %.3F 0 0 %.3F %.3F %.3F cm', $usew*_MPDFK, $useh*_MPDFK, $usex*_MPDFK, ($this->mpdf->h-($usey+$useh))*_MPDFK)."\n";
+	}
+
+	// RADIAL
+	else if ($type == 3) { 
+		$radius = $coords[4];
+		$angle = $coords[5];	// ?? no effect
+		$shape = $coords[6];
+		$size = $coords[7];
+		$repeat = $coords[8];
+		// ALL POINTS AND RADIUS SET (default for custom mPDF radial gradient) - no -moz
+		if ($coords[0]!==false && $coords[1]!==false && $coords[2]!==false && $coords[3]!==false && $coords[4]!==false) {
+			// do nothing - coords used as they are
+		}
+		// If a <point> is defined
+		else if ($shape!==false && $size!==false) {
+		   if ($coords[2]==false) { $coords[2] = $coords[0]; }
+		   if ($coords[3]==false) { $coords[3] = $coords[1]; }
+		   // ELLIPSE
+		   if ($shape=='ellipse') {
+			$corner1 = sqrt(pow($coords[0],2) + pow($coords[1],2));
+			$corner2 = sqrt(pow($coords[0],2) + pow((1-$coords[1]),2));
+			$corner3 = sqrt(pow((1-$coords[0]),2) + pow($coords[1],2));
+			$corner4 = sqrt(pow((1-$coords[0]),2) + pow((1-$coords[1]),2));
+			if ($size=='closest-side') { $radius = min($coords[0], $coords[1], (1-$coords[0]), (1-$coords[1])); }
+			else if ($size=='closest-corner') { $radius = min($corner1, $corner2, $corner3, $corner4); }
+			else if ($size=='farthest-side') { $radius = max($coords[0], $coords[1], (1-$coords[0]), (1-$coords[1])); }
+			else { $radius = max($corner1, $corner2, $corner3, $corner4); }	// farthest corner (default)
+		   }
+		   // CIRCLE
+		   else if ($shape=='circle') {
+		    if ($w >= $h) {
+			$coords[1] = $coords[3] = ($coords[1] * $h/$w) ;
+			$corner1 = sqrt(pow($coords[0],2) + pow($coords[1],2));
+			$corner2 = sqrt(pow($coords[0],2) + pow((($h/$w)-$coords[1]),2));
+			$corner3 = sqrt(pow((1-$coords[0]),2) + pow($coords[1],2));
+			$corner4 = sqrt(pow((1-$coords[0]),2) + pow((($h/$w)-$coords[1]),2));
+			if ($size=='closest-side') { $radius = min($coords[0], $coords[1], (1-$coords[0]), (($h/$w)-$coords[1])); }
+			else if ($size=='closest-corner') { $radius = min($corner1, $corner2, $corner3, $corner4); }
+			else if ($size=='farthest-side') { $radius = max($coords[0], $coords[1], (1-$coords[0]), (($h/$w)-$coords[1])); }
+			else if ($size=='farthest-corner') { $radius = max($corner1, $corner2, $corner3, $corner4); }	// farthest corner (default)
+			$usew = $useh = $bboxw;
+			$usey -= ($w-$h);
+		    }
+		    else {
+			$coords[0] = $coords[2] = ($coords[0] * $w/$h) ;
+			$corner1 = sqrt(pow($coords[0],2) + pow($coords[1],2));
+			$corner2 = sqrt(pow($coords[0],2) + pow((1-$coords[1]),2));
+			$corner3 = sqrt(pow((($w/$h)-$coords[0]),2) + pow($coords[1],2));
+			$corner4 = sqrt(pow((($w/$h)-$coords[0]),2) + pow((1-$coords[1]),2));
+			if ($size=='closest-side') { $radius = min($coords[0], $coords[1], (($w/$h)-$coords[0]), (1-$coords[1])); }
+			else if ($size=='closest-corner') { $radius = min($corner1, $corner2, $corner3, $corner4); }
+			else if ($size=='farthest-side') { $radius = max($coords[0], $coords[1], (($w/$h)-$coords[0]), (1-$coords[1])); }
+			else if ($size=='farthest-corner') { $radius = max($corner1, $corner2, $corner3, $corner4); }	// farthest corner (default)
+			$usew = $useh = $bboxh;
+		    }
+		   }
+		   if ($radius==0) { $radius=0.001; }	// to prevent error
+		   $coords[4] = $radius; 
+		}
+
+		// -moz If entire function consists of only <stop> values
+		else {	// default values 
+			// All values are set in parseMozGradient - so won't appear here
+			$coords = array(0.5,0.5,0.5,0.5);	// default for radial gradient (centred)
+		}
+		$s = ' q';
+		$s .= sprintf(' %.3F %.3F %.3F %.3F re W n', $x*_MPDFK, ($this->mpdf->h-$y)*_MPDFK, $w*_MPDFK, -$h*_MPDFK)."\n";
+		$s .= sprintf(' %.3F 0 0 %.3F %.3F %.3F cm', $usew*_MPDFK, $useh*_MPDFK, $usex*_MPDFK, ($this->mpdf->h-($usey+$useh))*_MPDFK)."\n";
+	}
+
+	$n = count($this->mpdf->gradients) + 1;
+	$this->mpdf->gradients[$n]['type'] = $type;
+	$this->mpdf->gradients[$n]['colorspace'] = $colorspace;
+	$trans = false;
+	$this->mpdf->gradients[$n]['is_mask'] = $is_mask;
+	if ($is_mask) { $trans = true; }
+	if (count($stops) == 1) { $stops[1] = $stops[0]; }
+	if (!isset($stops[0]['offset'])) { $stops[0]['offset'] = 0; }
+	if (!isset($stops[(count($stops)-1)]['offset'])) { $stops[(count($stops)-1)]['offset'] = 1; }
+
+	// Fix stop-offsets set as absolute lengths
+	if ($type==2) {
+		$axisx = ($coords[2]-$coords[0])*$usew;
+		$axisy = ($coords[3]-$coords[1])*$useh;
+		$axis_length = sqrt(pow($axisx,2) + pow($axisy,2));
+	}
+	else { $axis_length = $coords[4]*$usew; }	// Absolute lengths are meaningless for an ellipse - Firefox uses Width as reference
+
+	for($i=0;$i<count($stops);$i++) {
+	  if (isset($stops[$i]['offset']) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$stops[$i]['offset'],$m)) { 
+		$tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
+		$stops[$i]['offset'] = $tmp/$axis_length;
+	  }
+	}
+
+
+	if (isset($stops[0]['offset']) && $stops[0]['offset']>0) { 
+		$firststop = $stops[0]; 
+		$firststop['offset'] = 0;
+		array_unshift($stops, $firststop); 
+	}
+	if (!$repeat && isset($stops[(count($stops)-1)]['offset']) && $stops[(count($stops)-1)]['offset']<1) {
+		$endstop = $stops[(count($stops)-1)]; 
+		$endstop['offset'] = 1;
+		$stops[] = $endstop; 
+	}
+	if ($stops[0]['offset'] > $stops[(count($stops)-1)]['offset']) { 
+		$stops[0]['offset'] = 0;
+		$stops[(count($stops)-1)]['offset'] = 1;
+	}
+
+	for($i=0;$i<count($stops);$i++) {
+		// mPDF 5.3.74
+		if ($colorspace == 'CMYK') {
+			$this->mpdf->gradients[$n]['stops'][$i]['col'] = sprintf('%.3F %.3F %.3F %.3F', (ord($stops[$i]['col']{1})/100), (ord($stops[$i]['col']{2})/100), (ord($stops[$i]['col']{3})/100), (ord($stops[$i]['col']{4})/100));
+		}
+		else if ($colorspace == 'Gray') {
+			$this->mpdf->gradients[$n]['stops'][$i]['col'] = sprintf('%.3F', (ord($stops[$i]['col']{1})/255));
+		}
+		else {
+			$this->mpdf->gradients[$n]['stops'][$i]['col'] = sprintf('%.3F %.3F %.3F', (ord($stops[$i]['col']{1})/255), (ord($stops[$i]['col']{2})/255), (ord($stops[$i]['col']{3})/255));
+		}
+		if (!isset($stops[$i]['opacity'])) { $stops[$i]['opacity'] = 1; } 
+		else if ($stops[$i]['opacity'] > 1 || $stops[$i]['opacity'] < 0) { $stops[$i]['opacity'] = 1; } 
+		else if ($stops[$i]['opacity'] < 1) { 
+			$trans = true; 
+		}
+		$this->mpdf->gradients[$n]['stops'][$i]['opacity'] = $stops[$i]['opacity'];
+		// OFFSET
+		if ($i>0 && $i<(count($stops)-1)) {
+		  if (!isset($stops[$i]['offset']) || (isset($stops[$i+1]['offset']) && $stops[$i]['offset']>$stops[$i+1]['offset']) || $stops[$i]['offset']<$stops[$i-1]['offset']) { 
+			if (isset($stops[$i-1]['offset']) && isset($stops[$i+1]['offset'])) { 
+				$stops[$i]['offset'] = ($stops[$i-1]['offset']+$stops[$i+1]['offset'])/2; 
+			}
+			else {
+				for($j=($i+1);$j<count($stops);$j++) {
+					if(isset($stops[$j]['offset'])) { break; }
+				}
+				$int = ($stops[$j]['offset'] - $stops[($i-1)]['offset'])/($j-$i+1);
+				for($f=0;$f<($j-$i-1);$f++) {
+					$stops[($i+$f)]['offset'] = $stops[($i+$f-1)]['offset'] + ($int);
+				}
+			}
+		  }
+		}
+		$this->mpdf->gradients[$n]['stops'][$i]['offset'] = $stops[$i]['offset'];
+		$this->mpdf->gradients[$n]['stops'][$i]['offset'] = $stops[$i]['offset'];
+	}
+
+	if ($repeat) {
+		$ns = count($this->mpdf->gradients[$n]['stops']);
+		$offs = array();
+		for($i=0;$i<$ns;$i++) {
+			$offs[$i] = $this->mpdf->gradients[$n]['stops'][$i]['offset'];
+		}
+		$gp = 0;
+		$inside=true;
+		while($inside) {
+		   $gp++;
+		   for($i=0;$i<$ns;$i++) {
+			$this->mpdf->gradients[$n]['stops'][(($ns*$gp)+$i)] = $this->mpdf->gradients[$n]['stops'][(($ns*($gp-1))+$i)];
+			$tmp = $this->mpdf->gradients[$n]['stops'][(($ns*($gp-1))+($ns-1))]['offset']+$offs[$i] ;
+			if ($tmp < 1) { $this->mpdf->gradients[$n]['stops'][(($ns*$gp)+$i)]['offset'] = $tmp; }
+			else {
+				$this->mpdf->gradients[$n]['stops'][(($ns*$gp)+$i)]['offset'] = 1;
+				$inside = false;
+				break(2);
+			}
+		   }
+		}
+	}
+
+	if ($trans) { 
+		$this->mpdf->gradients[$n]['trans'] = true;	
+		$s .= ' /TGS'.$n.' gs ';
+	}
+	if (!is_array($extend) || count($extend) <1) { 
+		$extend=array('true', 'true');	// These are supposed to be quoted - appear in PDF file as text
+	}
+	$this->mpdf->gradients[$n]['coords'] = $coords;
+	$this->mpdf->gradients[$n]['extend'] = $extend;
+	//paint the gradient
+	$s .= '/Sh'.$n.' sh '."\n";
+	//restore previous Graphic State
+	$s .= ' Q '."\n";
+	if ($return) { return $s; }
+	else { $this->mpdf->_out($s); }
+}
+
+
+function parseMozGradient($bg) {
+   //	background[-image]: -moz-linear-gradient(left, #c7Fdde 20%, #FF0000 ); 
+   //	background[-image]: linear-gradient(left, #c7Fdde 20%, #FF0000 ); // CSS3
+   if (preg_match('/repeating-/',$bg)) { $repeat = true; }
+   else { $repeat = false; }
+   if (preg_match('/linear-gradient\((.*)\)/',$bg,$m)) {
+	$g = array();
+	$g['type'] = 2;
+	$g['colorspace'] = 'RGB';
+	$g['extend'] = array('true','true');
+	$v = trim($m[1]);
+	// Change commas inside e.g. rgb(x,x,x)
+	while(preg_match('/(\([^\)]*?),/',$v)) { $v = preg_replace('/(\([^\)]*?),/','\\1@',$v); }
+	// Remove spaces inside e.g. rgb(x, x, x)
+	while(preg_match('/(\([^\)]*?)[ ]/',$v)) { $v = preg_replace('/(\([^\)]*?)[ ]/','\\1',$v); }
+	$bgr = preg_split('/\s*,\s*/',$v);
+	for($i=0;$i<count($bgr);$i++) { $bgr[$i] = preg_replace('/@/', ',', $bgr[$i]); }
+	// Is first part $bgr[0] a valid point/angle?
+	$first = preg_split('/\s+/',trim($bgr[0]));
+	if (preg_match('/(left|center|right|bottom|top|deg|grad|rad)/i',$bgr[0]) && !preg_match('/(<#|rgb|rgba|hsl|hsla)/i',$bgr[0])) {
+		$startStops = 1; 
+	}
+	else if (trim($first[(count($first)-1)]) === "0") {
+		$startStops = 1;
+	}
+	else {
+		$check = $this->mpdf->ConvertColor($first[0]);
+		if ($check) $startStops = 0; 
+		else $startStops = 1; 
+	}
+	// first part a valid point/angle?
+	if ($startStops == 1) {	// default values
+		// [<point> || <angle>,] = [<% em px left center right bottom top> || <deg grad rad 0>,]
+		if (preg_match('/([\-]*[0-9\.]+)(deg|grad|rad)/i',$bgr[0],$m)) {
+			$angle = $m[1] + 0;
+			if (strtolower($m[2])=='deg') { $angle = $angle; }
+			else if (strtolower($m[2])=='grad') { $angle *= (360/400); }
+			else if (strtolower($m[2])=='rad') { $angle = rad2deg($angle); }
+			while($angle < 0) { $angle += 360; }
+			$angle = ($angle % 360);
+		}
+		else if (trim($first[(count($first)-1)]) === "0") { $angle = 0; }
+		if (preg_match('/left/i',$bgr[0])) { $startx = 0; }
+		else if (preg_match('/right/i',$bgr[0])) { $startx = 1; }
+		if (preg_match('/top/i',$bgr[0])) { $starty = 1; }
+		else if (preg_match('/bottom/i',$bgr[0])) { $starty = 0; }
+		// Check for %? ?% or %%
+		if (preg_match('/(\d+)[%]/i',$first[0],$m)) { $startx = $m[1]/100; }
+		else if (!isset($startx) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$first[0],$m)) { 
+			$tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
+			if ($tmp) { $startx = $m[1]; }
+		}
+		if (isset($first[1]) && preg_match('/(\d+)[%]/i',$first[1],$m)) { $starty = 1 - ($m[1]/100); }
+		else if (!isset($starty) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$first[1],$m)) { 
+			$tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
+			if ($tmp) { $starty = $m[1]; }
+		}
+		if (isset($startx) && !isset($starty)) { $starty = 0.5; }
+		if (!isset($startx) && isset($starty)) { $startx = 0.5; }
+
+	}
+	// If neither a <point> or <angle> is specified, i.e. the entire function consists of only <stop> values, the gradient axis starts from the top of the box and runs vertically downwards, ending at the bottom of the box.
+	else {	// default values T2B
+		$starty = 1; $startx = 0.5;
+		$endy = 0; $endx = 0.5;
+	}
+	$coords = array();
+	if (!isset($startx)) { $startx = false; }
+	if (!isset($starty)) { $starty = false; }
+	if (!isset($endx)) { $endx = false; }
+	if (!isset($endy)) { $endy = false; }
+	if (!isset($angle)) { $angle = false; }
+	$g['coords'] = array($startx ,$starty ,$endx ,$endy, $angle, $repeat );
+	$g['stops'] = array();
+	for($i=$startStops;$i<count($bgr);$i++) {
+		$stop = array();
+		// parse stops
+		$el = preg_split('/\s+/',trim($bgr[$i]));
+		// mPDF 5.3.74
+		$col = $this->mpdf->ConvertColor($el[0]);
+		if ($col) { $stop['col'] = $col; }
+		else { $stop['col'] = $col = $this->mpdf->ConvertColor(255); }
+		if ($col{0}==1) $g['colorspace'] = 'Gray';
+		else if ($col{0}==4 || $col{0}==6) $g['colorspace'] = 'CMYK';
+		if ($col{0}==5) { $stop['opacity'] = ord($col{4})/100; }	// transparency from rgba()
+		else if ($col{0}==6) { $stop['opacity'] = ord($col{5})/100; }	// transparency from cmyka()
+		else if ($col{0}==1 && $col{2}==1) { $stop['opacity'] = ord($col{3})/100; }	// transparency converted from rgba or cmyka()
+
+		if (isset($el[1]) && preg_match('/(\d+)[%]/',$el[1],$m)) { 
+			$stop['offset'] = $m[1]/100;
+			if ($stop['offset']>1) { unset($stop['offset']); }
+		}
+		else if (isset($el[1]) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$el[1],$m)) { 
+			$tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
+			if ($tmp) { $stop['offset'] = $m[1]; }
+		}
+		$g['stops'][] = $stop;
+	}
+	if (count($g['stops'] )) { return $g; }
+   }
+   else if (preg_match('/radial-gradient\((.*)\)/',$bg,$m)) {
+	$g = array();
+	$g['type'] = 3;
+	$g['colorspace'] = 'RGB';
+	$g['extend'] = array('true','true');
+	$v = trim($m[1]);
+	// Change commas inside e.g. rgb(x,x,x)
+	while(preg_match('/(\([^\)]*?),/',$v)) { $v = preg_replace('/(\([^\)]*?),/','\\1@',$v); }
+	// Remove spaces inside e.g. rgb(x, x, x)
+	while(preg_match('/(\([^\)]*?)[ ]/',$v)) { $v = preg_replace('/(\([^\)]*?)[ ]/','\\1',$v); }
+	$bgr = preg_split('/\s*,\s*/',$v);
+	for($i=0;$i<count($bgr);$i++) { $bgr[$i] = preg_replace('/@/', ',', $bgr[$i]); }
+
+	// Is first part $bgr[0] a valid point/angle?
+	$startStops = 0; 
+	$pos_angle = false;
+	$shape_size = false;
+	$first = preg_split('/\s+/',trim($bgr[0]));
+	$checkCol = $this->mpdf->ConvertColor($first[0]);
+	if (preg_match('/(left|center|right|bottom|top|deg|grad|rad)/i',$bgr[0]) && !preg_match('/(<#|rgb|rgba|hsl|hsla)/i',$bgr[0])) {
+		$startStops=1; 
+		$pos_angle = $bgr[0];
+	}
+	else if (trim($first[(count($first)-1)]) === "0") {
+		$startStops=1;
+		$pos_angle = $bgr[0];
+	}
+	else if (preg_match('/(circle|ellipse|closest-side|closest-corner|farthest-side|farthest-corner|contain|cover)/i',$bgr[0])) {
+		$startStops=1; 
+		$shape_size = $bgr[0];
+	}
+	else if (!$checkCol) {
+		$startStops=1;
+ 		$pos_angle = $bgr[0];
+	}
+	if (preg_match('/(circle|ellipse|closest-side|closest-corner|farthest-side|farthest-corner|contain|cover)/i',$bgr[1])) {
+		$startStops=2; 
+		$shape_size = $bgr[1];
+	}
+
+	// If valid point/angle?
+	if ($pos_angle) {	// default values
+		// [<point> || <angle>,] = [<% em px left center right bottom top> || <deg grad rad 0>,]
+		if (preg_match('/left/i',$pos_angle)) { $startx = 0; }
+		else if (preg_match('/right/i',$pos_angle)) { $startx = 1; }
+		if (preg_match('/top/i',$pos_angle)) { $starty = 1; }
+		else if (preg_match('/bottom/i',$pos_angle)) { $starty = 0; }
+		// Check for %? ?% or %%
+		if (preg_match('/(\d+)[%]/i',$first[0],$m)) { $startx = $m[1]/100; }
+		else if (!isset($startx) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$first[0],$m)) { 
+			$tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
+			if ($tmp) { $startx = $m[1]; }
+		}
+		if (isset($first[1]) && preg_match('/(\d+)[%]/i',$first[1],$m)) { $starty = 1 - ($m[1]/100); }
+		else if (!isset($starty) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$first[1],$m)) { 
+			$tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
+			if ($tmp) { $starty = $m[1]; }
+		}
+
+/*
+		// ?? Angle has no effect in radial gradient (does not exist in CSS3 spec.)
+		if (preg_match('/([\-]*[0-9\.]+)(deg|grad|rad)/i',$pos_angle,$m)) {
+			$angle = $m[1] + 0;
+			if (strtolower($m[2])=='deg') { $angle = $angle; }
+			else if (strtolower($m[2])=='grad') { $angle *= (360/400); }
+			else if (strtolower($m[2])=='rad') { $angle = rad2deg($angle); }
+			while($angle < 0) { $angle += 360; }
+			$angle = ($angle % 360);
+		}
+*/
+		if (!isset($starty)) { $starty = 0.5; }
+		if (!isset($startx)) { $startx = 0.5; }
+
+	}
+	// If neither a <point> or <angle> is specified, i.e. the entire function consists of only <stop> values, the gradient axis starts from the top of the box and runs vertically downwards, ending at the bottom of the box.
+	else {	// default values Center
+		$starty = 0.5; $startx = 0.5;
+		$endy = 0.5; $endx = 0.5;
+	}
+
+	// If valid shape/size?
+	$shape = 'ellipse';	// default
+	$size = 'farthest-corner';	// default
+	if ($shape_size) {	// default values
+		if (preg_match('/(circle|ellipse)/i',$shape_size, $m)) {
+			$shape = $m[1];
+		}
+		if (preg_match('/(closest-side|closest-corner|farthest-side|farthest-corner|contain|cover)/i',$shape_size, $m)) {
+			$size = $m[1];
+			if ($size=='contain') { $size = 'closest-side'; }
+			else if ($size=='cover') { $size = 'farthest-corner'; }
+		}
+	}
+
+	$coords = array();
+	if (!isset($startx)) { $startx = false; }
+	if (!isset($starty)) { $starty = false; }
+	if (!isset($endx)) { $endx = false; }
+	if (!isset($endy)) { $endy = false; }
+	if (!isset($radius)) { $radius = false; }
+	if (!isset($angle)) { $angle = 0; }
+	$g['coords'] = array($startx ,$starty ,$endx ,$endy, $radius, $angle, $shape, $size, $repeat );
+
+	$g['stops'] = array();
+	for($i=$startStops;$i<count($bgr);$i++) {
+		$stop = array();
+		// parse stops
+		$el = preg_split('/\s+/',trim($bgr[$i]));
+		// mPDF 5.3.74
+		$col = $this->mpdf->ConvertColor($el[0]);
+		if ($col) { $stop['col'] = $col; }
+		else { $stop['col'] = $col = $this->mpdf->ConvertColor(255); }
+		if ($col{0}==1) $g['colorspace'] = 'Gray';
+		else if ($col{0}==4 || $col{0}==6) $g['colorspace'] = 'CMYK';
+		if ($col{0}==5) { $stop['opacity'] = ord($col{4})/100; }	// transparency from rgba()
+		else if ($col{0}==6) { $stop['opacity'] = ord($col{5})/100; }	// transparency from cmyka()
+		else if ($col{0}==1 && $col{2}==1) { $stop['opacity'] = ord($col{3})/100; }	// transparency converted from rgba or cmyka()
+
+		if (isset($el[1]) && preg_match('/(\d+)[%]/',$el[1],$m)) { 
+			$stop['offset'] = $m[1]/100;
+			if ($stop['offset']>1) { unset($stop['offset']); }
+		}
+		else if (isset($el[1]) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$el[1],$m)) { 
+			$tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
+			$stop['offset'] = $el[1];
+		}
+		$g['stops'][] = $stop;
+	}
+	if (count($g['stops'] )) { return $g; }
+   }
+   return array();
+} 
+
+function parseBackgroundGradient($bg) {
+	// background-gradient: linear #00FFFF #FFFF00 0 0.5 1 0.5;  or
+	// background-gradient: radial #00FFFF #FFFF00 0.5 0.5 1 1 1.2;
+
+	$v = trim($bg);
+	$bgr = preg_split('/\s+/',$v);
+	$g = array();
+	if (count($bgr)> 6) {  
+		if (strtoupper(substr($bgr[0],0,1)) == 'L' && count($bgr)==7) {  // linear
+			$g['type'] = 2;
+			//$coords = array(0,0,1,1 );	// 0 0 1 0 or 0 1 1 1 is L 2 R; 1,1,0,1 is R2L; 1,1,1,0 is T2B; 1,0,1,1 is B2T
+			// Linear: $coords - array of the form (x1, y1, x2, y2) which defines the gradient vector (see linear_gradient_coords.jpg). 
+			//    The default value is from left to right (x1=0, y1=0, x2=1, y2=0).
+			$g['coords'] = array($bgr[3], $bgr[4], $bgr[5], $bgr[6]);
+		}
+		else if (count($bgr)==8) {	// radial
+			$g['type'] = 3;
+			// Radial: $coords - array of the form (fx, fy, cx, cy, r) where (fx, fy) is the starting point of the gradient with color1, 
+			//    (cx, cy) is the center of the circle with color2, and r is the radius of the circle (see radial_gradient_coords.jpg). 
+			//    (fx, fy) should be inside the circle, otherwise some areas will not be defined
+			$g['coords'] = array($bgr[3], $bgr[4], $bgr[5], $bgr[6], $bgr[7]);
+		}
+		$g['colorspace'] = 'RGB';
+		// mPDF 5.3.74
+		$cor = $this->mpdf->ConvertColor($bgr[1]);
+		if ($cor{0}==1) $g['colorspace'] = 'Gray';
+		else if ($cor{0}==4 || $cor{0}==6) $g['colorspace'] = 'CMYK';
+		if ($cor) { $g['col'] = $cor; }
+		else { $g['col'] = $this->mpdf->ConvertColor(255); }
+		$cor = $this->mpdf->ConvertColor($bgr[2]);
+		if ($cor) { $g['col2'] = $cor; }
+		else { $g['col2'] = $this->mpdf->ConvertColor(255); }
+		$g['extend'] = array('true','true');
+		$g['stops'] = array(array('col'=>$g['col'], 'opacity'=>1, 'offset'=>0), array('col'=>$g['col2'], 'opacity'=>1, 'offset'=>1));
+		return $g;
+	}
+	return false;
+}
+
+
+
+}
+
+?>

File diff suppressed because it is too large
+ 264 - 0
sites/all/libraries/MPDF54/classes/indic.php


+ 2596 - 0
sites/all/libraries/MPDF54/classes/svg.php

@@ -0,0 +1,2596 @@
+<?php
+//	svg class modified for mPDF version 4.4.003 by Ian Back: based on -
+//	svg2pdf fpdf class
+//	sylvain briand (syb@godisaduck.com), modified by rick trevino (rtrevino1@yahoo.com)
+//	http://www.godisaduck.com/svg2pdf_with_fpdf
+//	http://rhodopsin.blogspot.com
+//	
+//	cette class etendue est open source, toute modification devra cependant etre repertoriée~
+
+
+// NB UNITS - Works in pixels as main units - converting to PDF units when outputing to PDF string
+// and on returning size
+
+class SVG {
+
+	var $svg_gradient;	//	array - contient les infos sur les gradient fill du svg classé par id du svg
+	var $svg_shadinglist;	//	array - contient les ids des objet shading
+	var $svg_info;		//	array contenant les infos du svg voulue par l'utilisateur
+	var $svg_attribs;		//	array - holds all attributes of root <svg> tag
+	var $svg_style;		//	array contenant les style de groupes du svg
+	var $svg_string;		//	String contenant le tracage du svg en lui même.
+	var $txt_data;		//    array - holds string info to write txt to image
+	var $txt_style;		// 	array - current text style
+	var $mpdf_ref;
+	var $xbase;		// mPDF 4.4.003
+	var $ybase;		// mPDF 4.4.003
+	var $svg_error;	// mPDF 4.4.003
+	var $subPathInit;	// mPDF 4.4.003
+	var $spxstart;	// mPDF 4.4.003
+	var $spystart;	// mPDF 4.4.003
+	var $kp;		// mPDF 4.4.003  convert pixels to PDF units
+	var $pathBBox;	// mPDF 5.0.039
+
+	function SVG(&$mpdf){
+		$this->svg_gradient = array();
+		$this->svg_shadinglist = array();
+		$this->txt_data = array();
+		$this->svg_string = '';
+		$this->svg_info = array();
+		$this->svg_attribs = array();
+		$this->xbase = 0;
+		$this->ybase = 0;
+		$this->svg_error = false;
+		$this->subPathInit = false;	// mPDF 4.4.003
+		$this->dashesUsed = false;	// mPDF 5.0
+		$this->mpdf_ref =& $mpdf;
+
+		$this->kp = 72 / $mpdf->img_dpi;	// mPDF 4.4.003  constant To convert pixels to pts/PDF units
+		$this->kf = 1;				// mPDF 5.0.039	constant To convert font size if re-mapped
+		$this->pathBBox = array(); // mPDF 5.0.039
+
+		$this->svg_style = array(
+			array(
+			'fill'		=> 'black',			//	mPDF 4.4.008
+			'fill-opacity'	=> 1,				//	remplissage opaque par defaut
+			'fill-rule'		=> 'nonzero',		//	mode de remplissage par defaut
+			'stroke'		=> 'none',			//	pas de trait par defaut
+			'stroke-linecap'	=> 'butt',			//	style de langle par defaut
+			'stroke-linejoin'	=> 'miter',			//
+			'stroke-miterlimit' => 4,			//	limite de langle par defaut
+			'stroke-opacity'	=> 1,				//	trait opaque par defaut
+			'stroke-width'	=> 1,				//	mPDF 4.4.011
+			'stroke-dasharray' => 0,			//	mPDF 4.4.003
+			'stroke-dashoffset' => 0,			//	mPDF 4.4.003
+			'color' => ''					//	mPDF 4.4.005
+			)
+		);
+
+		$this->txt_style = array(
+			array(
+			'fill'		=> 'black',		//	pas de remplissage par defaut
+			'font-family' 	=> $mpdf->default_font,
+			'font-size'		=> $mpdf->default_font_size,		// 	****** this is pts
+			'font-weight'	=> 'normal',	//	normal | bold
+			'font-style'	=> 'normal',	//	italic | normal
+			'text-anchor'	=> 'start',		// alignment: start, middle, end
+/* mPDF 5.0.041 */
+			'fill-opacity'	=> 1,				//	remplissage opaque par defaut
+			'fill-rule'		=> 'nonzero',		//	mode de remplissage par defaut
+			'stroke'		=> 'none',			//	pas de trait par defaut
+			'stroke-opacity'	=> 1,				//	trait opaque par defaut
+			'stroke-width'	=> 1,				//	mPDF 4.4.011
+			'color' => ''					//	mPDF 4.4.005
+			)
+		);
+
+
+
+	}
+
+	function svgGradient($gradient_info, $attribs, $element){
+		$n = count($this->mpdf_ref->gradients)+1;
+
+		// Get bounding dimensions of element
+		$w = 100;
+		$h = 100;
+		$x_offset = 0;
+		$y_offset = 0;
+		if ($element=='rect') {
+			$w = $attribs['width'];
+			$h = $attribs['height'];
+			$x_offset = $attribs['x'];
+			$y_offset = $attribs['y'];
+		}
+		else if ($element=='ellipse') {
+			$w = $attribs['rx']*2;
+			$h = $attribs['ry']*2;
+			$x_offset = $attribs['cx']-$attribs['rx'];
+			$y_offset = $attribs['cy']-$attribs['ry'];
+		}
+		else if ($element=='circle') {
+			$w = $attribs['r']*2;
+			$h = $attribs['r']*2;
+			$x_offset = $attribs['cx']-$attribs['r'];
+			$y_offset = $attribs['cy']-$attribs['r'];
+		}
+		else if ($element=='polygon') {
+			$pts = preg_split('/[ ,]+/', trim($attribs['points']));
+			$maxr=$maxb=0;
+			$minl=$mint=999999;
+			for ($i=0;$i<count($pts); $i++) {
+				if ($i % 2 == 0) {	// x values
+					$minl = min($minl,$pts[$i]);
+					$maxr = max($maxr,$pts[$i]);
+				}
+				else {	// y values
+					$mint = min($mint,$pts[$i]);
+					$maxb = max($maxb,$pts[$i]);
+				}
+			}
+			$w = $maxr-$minl;
+			$h = $maxb-$mint;
+			$x_offset = $minl;
+			$y_offset = $mint;
+		}
+		else if ($element=='path') {
+		  // mPDF 5.0.039
+		  if (is_array($this->pathBBox) && $this->pathBBox[2]>0) {
+			$w = $this->pathBBox[2];
+			$h = $this->pathBBox[3];
+			$x_offset = $this->pathBBox[0];
+			$y_offset = $this->pathBBox[1];
+		  }
+		  else {
+			preg_match_all('/([a-z]|[A-Z])([ ,\-.\d]+)*/', $attribs['d'], $commands, PREG_SET_ORDER);
+			$maxr=$maxb=0;
+			$minl=$mint=999999;
+			foreach($commands as $c){
+				if(count($c)==3){
+					list($tmp, $cmd, $arg) = $c;
+					if ($cmd=='M' || $cmd=='L' || $cmd=='C' || $cmd=='S' || $cmd=='Q' || $cmd=='T') {
+						$pts = preg_split('/[ ,]+/', trim($arg));
+						for ($i=0;$i<count($pts); $i++) {
+							if ($i % 2 == 0) {	// x values
+								$minl = min($minl,$pts[$i]);
+								$maxr = max($maxr,$pts[$i]);
+							}
+							else {	// y values
+								$mint = min($mint,$pts[$i]);
+								$maxb = max($maxb,$pts[$i]);
+							}
+						}
+					}
+					if ($cmd=='H') { // sets new x
+						$minl = min($minl,$arg);
+						$maxr = max($maxr,$arg);
+					}
+					if ($cmd=='V') { // sets new y
+						$mint = min($mint,$arg);
+						$maxb = max($maxb,$arg);
+					}
+				}
+			}
+			$w = $maxr-$minl;
+			$h = $maxb-$mint;
+			$x_offset = $minl;
+			$y_offset = $mint;
+		  }
+		}
+		if (!$w || $w==-999999) { $w = 100; }
+		if (!$h || $h==-999999) { $h = 100; }
+		if ($x_offset==999999) { $x_offset = 0; }
+		if ($y_offset==999999) { $y_offset = 0; }
+
+		// mPDF 4.5.010
+		// TRANSFORMATIONS
+		$transformations = '';
+		if (isset($gradient_info['transform'])){
+			preg_match_all('/(matrix|translate|scale|rotate|skewX|skewY)\((.*?)\)/is',$gradient_info['transform'],$m);
+			if (count($m[0])) {
+				for($i=0; $i<count($m[0]); $i++) {
+					$c = strtolower($m[1][$i]);
+					$v = trim($m[2][$i]);
+					$vv = preg_split('/[ ,]+/',$v);
+					if ($c=='matrix' && count($vv)==6) {
+						// mPDF 5.0.039
+						// Note angle of rotation is reversed (from SVG to PDF), so vv[1] and vv[2] are negated
+						// cf svgDefineStyle()
+						$transformations .= sprintf(' %.3F %.3F %.3F %.3F %.3F %.3F cm ', $vv[0], -$vv[1], -$vv[2], $vv[3], $vv[4]*$this->kp, -$vv[5]*$this->kp);	
+					}
+					else if ($c=='translate' && count($vv)) {
+						$tm[4] = $vv[0];
+						if (count($vv)==2) { $t_y = -$vv[1]; }
+						else { $t_y = 0; }
+						$tm[5] = $t_y;
+						$transformations .= sprintf(' 1 0 0 1 %.3F %.3F cm ', $tm[4]*$this->kp, $tm[5]*$this->kp);
+					}
+					else if ($c=='scale' && count($vv)) {
+						if (count($vv)==2) { $s_y = $vv[1]; }
+						else { $s_y = $vv[0]; }
+						$tm[0] = $vv[0];
+						$tm[3] = $s_y;
+						$transformations .= sprintf(' %.3F 0 0 %.3F 0 0 cm ', $tm[0], $tm[3]);
+					}
+					else if ($c=='rotate' && count($vv)) {
+						$tm[0] = cos(deg2rad(-$vv[0]));
+						$tm[1] = sin(deg2rad(-$vv[0]));
+						$tm[2] = -$tm[1];
+						$tm[3] = $tm[0];
+						if (count($vv)==3) {
+							$transformations .= sprintf(' 1 0 0 1 %.3F %.3F cm ', $vv[1]*$this->kp, -$vv[2]*$this->kp);
+						}
+						$transformations .= sprintf(' %.3F %.3F %.3F %.3F 0 0 cm ', $tm[0], $tm[1], $tm[2], $tm[3]);
+						if (count($vv)==3) {
+							$transformations .= sprintf(' 1 0 0 1 %.3F %.3F cm ', -$vv[1]*$this->kp, $vv[2]*$this->kp);
+						}
+					}
+					else if ($c=='skewx' && count($vv)) {
+						$tm[2] = tan(deg2rad(-$vv[0]));
+						$transformations .= sprintf(' 1 0 %.3F 1 0 0 cm ', $tm[2]);
+					}
+					else if ($c=='skewy' && count($vv)) {
+						$tm[1] = tan(deg2rad(-$vv[0]));
+						$transformations .= sprintf(' 1 %.3F 0 1 0 0 cm ', $tm[1]);
+					}
+
+				}
+			}
+		}
+
+
+		$return = "";
+
+		// mPDF 5.0.039
+		if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='userspaceonuse') {
+			if ($transformations) { $return .= $transformations; }
+		}
+		// mPDF 5.0.040
+		$spread = 'P';  // pad
+		if (isset($gradient_info['spread'])) {
+			if (strtolower($gradient_info['spread'])=='reflect') { $spread = 'F'; } // reflect
+			else if (strtolower($gradient_info['spread'])=='repeat') { $spread = 'R'; } // repeat
+		}	
+
+
+		for ($i=0; $i<(count($gradient_info['color'])); $i++) {
+			if (stristr($gradient_info['color'][$i]['offset'], '%')!== false) { $gradient_info['color'][$i]['offset'] = ($gradient_info['color'][$i]['offset']+0)/100; }
+			if (stristr($gradient_info['color'][($i+1)]['offset'], '%')!== false) { $gradient_info['color'][($i+1)]['offset'] = ($gradient_info['color'][($i+1)]['offset']+0)/100; }
+			if ($gradient_info['color'][$i]['offset']<0) { $gradient_info['color'][$i]['offset'] = 0; }
+			if ($gradient_info['color'][$i]['offset']>1) { $gradient_info['color'][$i]['offset'] = 1; }
+			if ($i>0) {
+				if ($gradient_info['color'][$i]['offset']<$gradient_info['color'][($i-1)]['offset']) { 
+					$gradient_info['color'][$i]['offset']=$gradient_info['color'][($i-1)]['offset']; 
+				}
+			}
+		}
+
+		if ($gradient_info['color'][0]['offset']>0) { 
+			array_unshift($gradient_info['color'], $gradient_info['color'][0]);
+			$gradient_info['color'][0]['offset'] = 0; 
+		}
+		$ns = count($gradient_info['color']);
+		if ($gradient_info['color'][($ns-1)]['offset']<1) { 
+			$gradient_info['color'][] = $gradient_info['color'][($ns-1)];
+			$gradient_info['color'][($ns)]['offset'] = 1; 
+		}
+		$ns = count($gradient_info['color']);
+
+
+
+
+		if ($gradient_info['type'] == 'linear'){
+			// mPDF 4.4.003
+			if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='userspaceonuse') {
+				if (isset($gradient_info['info']['x1'])) { $gradient_info['info']['x1'] = ($gradient_info['info']['x1']-$x_offset) / $w; }
+				if (isset($gradient_info['info']['y1'])) { $gradient_info['info']['y1'] = ($gradient_info['info']['y1']-$y_offset) / $h; }
+				if (isset($gradient_info['info']['x2'])) { $gradient_info['info']['x2'] = ($gradient_info['info']['x2']-$x_offset) / $w; }
+				if (isset($gradient_info['info']['y2'])) { $gradient_info['info']['y2'] = ($gradient_info['info']['y2']-$y_offset) / $h; }
+			}
+			if (isset($gradient_info['info']['x1'])) { $x1 = $gradient_info['info']['x1']; }
+			else { $x1 = 0; }
+			if (isset($gradient_info['info']['y1'])) { $y1 = $gradient_info['info']['y1']; }
+			else { $y1 = 0; }
+			if (isset($gradient_info['info']['x2'])) { $x2 = $gradient_info['info']['x2']; }
+			else { $x2 = 1; }
+			if (isset($gradient_info['info']['y2'])) { $y2 = $gradient_info['info']['y2']; }
+			else { $y2 = 0; }
+
+			if (stristr($x1, '%')!== false) { $x1 = ($x1+0)/100; }
+			if (stristr($x2, '%')!== false) { $x2 = ($x2+0)/100; }
+			if (stristr($y1, '%')!== false) { $y1 = ($y1+0)/100; }
+			if (stristr($y2, '%')!== false) { $y2 = ($y2+0)/100; }
+
+			// mPDF 5.0.042
+			$bboxw = $w;
+			$bboxh = $h;
+			$usex = $x_offset;
+			$usey = $y_offset;
+			$usew = $bboxw;
+			$useh = $bboxh;
+			if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='userspaceonuse') {
+				$angle = rad2deg(atan2(($gradient_info['info']['y2']-$gradient_info['info']['y1']), ($gradient_info['info']['x2']-$gradient_info['info']['x1'])));
+				if ($angle < 0) { $angle += 360; }
+				else if ($angle > 360) { $angle -= 360; }
+				if ($angle!=0 && $angle!=360 && $angle!=90 && $angle!=180 && $angle!=270) { 
+				    if ($w >= $h) {
+					$y1 *= $h/$w ;
+					$y2 *= $h/$w ;
+					$usew = $useh = $bboxw;
+				    }
+				    else {
+					$x1 *= $w/$h ;
+					$x2 *= $w/$h ;
+					$usew = $useh = $bboxh;
+				    }
+				}
+			}
+			$a = $usew;		// width
+			$d = -$useh;	// height
+			$e = $usex;		// x- offset
+			$f = -$usey;	// -y-offset
+
+			$return .= sprintf('%.3F 0 0 %.3F %.3F %.3F cm ', $a*$this->kp, $d*$this->kp, $e*$this->kp, $f*$this->kp);
+
+			// mPDF 5.0.039
+			if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='objectboundingbox') {
+				if ($transformations) { $return .= $transformations; }
+			}
+
+			// mPDF 5.0.020
+			$trans = false;
+
+			// mPDF 5.0.040
+			if ($spread=='R' || $spread=='F') {	// Repeat  /  Reflect
+				$offs = array();
+				for($i=0;$i<$ns;$i++) {
+					$offs[$i] = $gradient_info['color'][$i]['offset'];
+				}
+				$gp = 0;
+				$inside=true;
+				while($inside) {
+				   $gp++;
+				   for($i=0;$i<$ns;$i++) {
+					if ($spread=='F' && ($gp % 2) == 1) {	// Reflect
+						$gradient_info['color'][(($ns*$gp)+$i)] = $gradient_info['color'][(($ns*($gp-1))+($ns-$i-1))];
+						$tmp = $gp+(1-$offs[($ns-$i-1)]) ;
+						$gradient_info['color'][(($ns*$gp)+$i)]['offset'] = $tmp; 
+					}
+					else {	// Reflect
+						$gradient_info['color'][(($ns*$gp)+$i)] = $gradient_info['color'][$i];
+						$tmp = $gp+$offs[$i] ;
+						$gradient_info['color'][(($ns*$gp)+$i)]['offset'] = $tmp; 
+					}
+					// IF STILL INSIDE BOX OR STILL VALID 
+					// Point on axis to test
+					$px1 = $x1 + ($x2-$x1)*$tmp;
+					$py1 = $y1 + ($y2-$y1)*$tmp;
+					// Get perpendicular axis
+					$alpha = atan2($y2-$y1, $x2-$x1);
+					$alpha += M_PI/2;	// rotate 90 degrees
+					// Get arbitrary point to define line perpendicular to axis
+					$px2 = $px1+cos($alpha);
+					$py2 = $py1+sin($alpha);
+
+					$res1 = _testIntersect($px1, $py1, $px2, $py2, 0, 0, 0, 1);	// $x=0 vert axis
+					$res2 = _testIntersect($px1, $py1, $px2, $py2, 1, 0, 1, 1);	// $x=1 vert axis
+					$res3 = _testIntersect($px1, $py1, $px2, $py2, 0, 0, 1, 0);	// $y=0 horiz axis
+					$res4 = _testIntersect($px1, $py1, $px2, $py2, 0, 1, 1, 1);	// $y=1 horiz axis
+					if (!$res1 && !$res2 && !$res3 && !$res4) { $inside = false; }
+				   }
+				}
+
+				$inside=true;
+				$gp = 0;
+				while($inside) {
+				   $gp++;
+				   $newarr = array();
+				   for($i=0;$i<$ns;$i++) {
+					if ($spread=='F') {	// Reflect
+					    $newarr[$i] = $gradient_info['color'][($ns-$i-1)];
+					    if (($gp % 2) == 1) {
+						$tmp = -$gp+(1-$offs[($ns-$i-1)]);
+							$newarr[$i]['offset'] = $tmp; 
+					   }
+					   else {
+						$tmp = -$gp+$offs[$i];
+						$newarr[$i]['offset'] = $tmp; 
+					   }
+					}
+					else {	// Reflect
+						$newarr[$i] = $gradient_info['color'][$i];
+						$tmp = -$gp+$offs[$i];
+						$newarr[$i]['offset'] = $tmp; 
+					}
+
+					// IF STILL INSIDE BOX OR STILL VALID 
+					// Point on axis to test
+					$px1 = $x1 + ($x2-$x1)*$tmp;
+					$py1 = $y1 + ($y2-$y1)*$tmp;
+					// Get perpendicular axis
+					$alpha = atan2($y2-$y1, $x2-$x1);
+					$alpha += M_PI/2;	// rotate 90 degrees
+					// Get arbitrary point to define line perpendicular to axis
+					$px2 = $px1+cos($alpha);
+					$py2 = $py1+sin($alpha);
+
+					$res1 = _testIntersect($px1, $py1, $px2, $py2, 0, 0, 0, 1);	// $x=0 vert axis
+					$res2 = _testIntersect($px1, $py1, $px2, $py2, 1, 0, 1, 1);	// $x=1 vert axis
+					$res3 = _testIntersect($px1, $py1, $px2, $py2, 0, 0, 1, 0);	// $y=0 horiz axis
+					$res4 = _testIntersect($px1, $py1, $px2, $py2, 0, 1, 1, 1);	// $y=1 horiz axis
+					if (!$res1 && !$res2 && !$res3 && !$res4) { $inside = false; }
+				   }
+				   for($i=($ns-1);$i>=0;$i--) { 
+					if (isset($newarr[$i]['offset'])) array_unshift($gradient_info['color'], $newarr[$i]); 
+				   }
+				}
+			}
+
+			// mPDF 4.4.007   Gradient STOPs
+			$stops = count($gradient_info['color']);
+			if ($stops < 2) { return ''; }
+
+			// mPDF 5.0.042
+			$range = $gradient_info['color'][count($gradient_info['color'])-1]['offset']-$gradient_info['color'][0]['offset'];
+			$min = $gradient_info['color'][0]['offset'];
+
+			for ($i=0; $i<($stops); $i++) {
+				// mPDF 5.0.051
+				if (!$gradient_info['color'][$i]['color']) { 
+					if ($gradient_info['colorspace']=='RGB') $gradient_info['color'][$i]['color'] = '0 0 0'; 
+					else if ($gradient_info['colorspace']=='Gray') $gradient_info['color'][$i]['color'] = '0'; 
+					else if ($gradient_info['colorspace']=='CMYK') $gradient_info['color'][$i]['color'] = '1 1 1 1'; 
+				}
+				$offset = ($gradient_info['color'][$i]['offset'] - $min)/$range;
+				$this->mpdf_ref->gradients[$n]['stops'][] = array(
+					'col' => $gradient_info['color'][$i]['color'],
+					'opacity' => $gradient_info['color'][$i]['opacity'],
+					'offset' => $offset);
+				if ($gradient_info['color'][$i]['opacity']<1) { $trans = true; }
+			}
+			$grx1 = $x1 + ($x2-$x1)*$gradient_info['color'][0]['offset'];
+			$gry1 = $y1 + ($y2-$y1)*$gradient_info['color'][0]['offset'];
+			$grx2 = $x1 + ($x2-$x1)*$gradient_info['color'][count($gradient_info['color'])-1]['offset'];
+			$gry2 = $y1 + ($y2-$y1)*$gradient_info['color'][count($gradient_info['color'])-1]['offset'];
+
+			$this->mpdf_ref->gradients[$n]['coords']=array($grx1, $gry1, $grx2, $gry2);
+
+			$this->mpdf_ref->gradients[$n]['colorspace'] = $gradient_info['colorspace'];	// mPDF 5.0.051
+
+			$this->mpdf_ref->gradients[$n]['type'] = 2;
+			$this->mpdf_ref->gradients[$n]['fo'] = true;
+
+			$this->mpdf_ref->gradients[$n]['extend']=array('true','true');
+			if ($trans) { 
+				$this->mpdf_ref->gradients[$n]['trans'] = true;	
+				$return .= ' /TGS'.($n).' gs ';
+			}
+			$return .= ' /Sh'.($n).' sh ';
+			$return .= " Q\n";
+		}
+		else if ($gradient_info['type'] == 'radial'){
+			// mPDF 4.4.003
+			if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='userspaceonuse') {
+				if ($w > $h) { $h = $w; }
+				else { $w = $h; }
+				if (isset($gradient_info['info']['x0'])) { $gradient_info['info']['x0'] = ($gradient_info['info']['x0']-$x_offset) / $w; }
+				if (isset($gradient_info['info']['y0'])) { $gradient_info['info']['y0'] = ($gradient_info['info']['y0']-$y_offset) / $h; }
+				if (isset($gradient_info['info']['x1'])) { $gradient_info['info']['x1'] = ($gradient_info['info']['x1']-$x_offset) / $w; }
+				if (isset($gradient_info['info']['y1'])) { $gradient_info['info']['y1'] = ($gradient_info['info']['y1']-$y_offset) / $h; }
+				if (isset($gradient_info['info']['r'])) { $gradient_info['info']['rx'] = $gradient_info['info']['r'] / $w; }
+				if (isset($gradient_info['info']['r'])) { $gradient_info['info']['ry'] = $gradient_info['info']['r'] / $h; }
+			}
+
+			if ($gradient_info['info']['x0'] || $gradient_info['info']['x0']===0) { $x0 = $gradient_info['info']['x0']; }
+			else { $x0 = 0.5; }
+			if ($gradient_info['info']['y0'] || $gradient_info['info']['y0']===0) { $y0 = $gradient_info['info']['y0']; }
+			else { $y0 = 0.5; }
+			if ($gradient_info['info']['rx'] || $gradient_info['info']['rx']===0) { $rx = $gradient_info['info']['rx']; }
+			else if ($gradient_info['info']['r'] || $gradient_info['info']['r']===0) { $rx = $gradient_info['info']['r']; }
+			else { $rx = 0.5; }
+			if ($gradient_info['info']['ry'] || $gradient_info['info']['ry']===0) { $ry = $gradient_info['info']['ry']; }
+			else if ($gradient_info['info']['r'] || $gradient_info['info']['r']===0) { $ry = $gradient_info['info']['r']; }
+			else { $ry = 0.5; }
+			if ($gradient_info['info']['x1'] || $gradient_info['info']['x1']===0) { $x1 = $gradient_info['info']['x1']; }
+			else { $x1 = $x0; }
+			if ($gradient_info['info']['y1'] || $gradient_info['info']['y1']===0) { $y1 = $gradient_info['info']['y1']; }
+			else { $y1 = $y0; }
+
+			if (stristr($x1, '%')!== false) { $x1 = ($x1+0)/100; }
+			if (stristr($x0, '%')!== false) { $x0 = ($x0+0)/100; }
+			if (stristr($y1, '%')!== false) { $y1 = ($y1+0)/100; }
+			if (stristr($y0, '%')!== false) { $y0 = ($y0+0)/100; }
+			if (stristr($rx, '%')!== false) { $rx = ($rx+0)/100; }
+			if (stristr($ry, '%')!== false) { $ry = ($ry+0)/100; }
+
+			// mPDF 5.0.043
+			$bboxw = $w;
+			$bboxh = $h;
+			$usex = $x_offset;
+			$usey = $y_offset;
+			$usew = $bboxw;
+			$useh = $bboxh;
+			if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='userspaceonuse') {
+				$angle = rad2deg(atan2(($gradient_info['info']['y0']-$gradient_info['info']['y1']), ($gradient_info['info']['x0']-$gradient_info['info']['x1'])));
+				if ($angle < 0) { $angle += 360; }
+				else if ($angle > 360) { $angle -= 360; }
+				if ($angle!=0 && $angle!=360 && $angle!=90 && $angle!=180 && $angle!=270) { 
+				    if ($w >= $h) {
+					$y1 *= $h/$w ;
+					$y0 *= $h/$w ;
+					$rx *= $h/$w ;
+					$ry *= $h/$w ;
+					$usew = $useh = $bboxw;
+				    }
+				    else {
+					$x1 *= $w/$h ;
+					$x0 *= $w/$h ;
+					$rx *= $w/$h ;
+					$ry *= $w/$h ;
+					$usew = $useh = $bboxh;
+				    }
+				}
+			}
+			$a = $usew;		// width
+			$d = -$useh;	// height
+			$e = $usex;		// x- offset
+			$f = -$usey;	// -y-offset
+
+			$r = $rx;
+
+
+			$return .= sprintf('%.3F 0 0 %.3F %.3F %.3F cm ', $a*$this->kp, $d*$this->kp, $e*$this->kp, $f*$this->kp);
+
+			// mPDF 5.0.039
+			if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='objectboundingbox') {
+				if ($transformations) { $return .= $transformations; }
+			}
+
+			// x1 and y1 (fx, fy) should be inside the circle defined by x0 y0 and r else error in mPDF
+			while (pow(($x1-$x0),2) + pow(($y1 - $y0),2) >= pow($r,2)) { $r += 0.05; }
+
+			// mPDF 5.0.040
+			if ($spread=='R' || $spread=='F') {	// Repeat  /  Reflect
+				$offs = array();
+				for($i=0;$i<$ns;$i++) {
+					$offs[$i] = $gradient_info['color'][$i]['offset'];
+				}
+				$gp = 0;
+				$inside=true;
+				while($inside) {
+				   $gp++;
+				   for($i=0;$i<$ns;$i++) {
+					if ($spread=='F' && ($gp % 2) == 1) {	// Reflect
+						$gradient_info['color'][(($ns*$gp)+$i)] = $gradient_info['color'][(($ns*($gp-1))+($ns-$i-1))];
+						$tmp = $gp+(1-$offs[($ns-$i-1)]) ;
+						$gradient_info['color'][(($ns*$gp)+$i)]['offset'] = $tmp; 
+					}
+					else {	// Reflect
+						$gradient_info['color'][(($ns*$gp)+$i)] = $gradient_info['color'][$i];
+						$tmp = $gp+$offs[$i] ;
+						$gradient_info['color'][(($ns*$gp)+$i)]['offset'] = $tmp; 
+					}
+					// IF STILL INSIDE BOX OR STILL VALID 
+					// TEST IF circle (perimeter) intersects with 
+					// or is enclosed
+					// Point on axis to test
+					$px = $x1 + ($x0-$x1)*$tmp;
+					$py = $y1 + ($y0-$y1)*$tmp;
+					$pr = $r*$tmp;
+					$res = _testIntersectCircle($px, $py, $pr);
+					if (!$res) { $inside = false; }
+				   }
+				}
+			}
+
+			// mPDF 4.4.007   Gradient STOPs
+			$stops = count($gradient_info['color']);
+			if ($stops < 2) { return ''; }
+
+			// mPDF 5.0.043
+			$range = $gradient_info['color'][count($gradient_info['color'])-1]['offset']-$gradient_info['color'][0]['offset'];
+			$min = $gradient_info['color'][0]['offset'];
+
+			for ($i=0; $i<($stops); $i++) {
+				// mPDF 5.0.051
+				if (!$gradient_info['color'][$i]['color']) { 
+					if ($gradient_info['colorspace']=='RGB') $gradient_info['color'][$i]['color'] = '0 0 0'; 
+					else if ($gradient_info['colorspace']=='Gray') $gradient_info['color'][$i]['color'] = '0'; 
+					else if ($gradient_info['colorspace']=='CMYK') $gradient_info['color'][$i]['color'] = '1 1 1 1'; 
+				}
+				$offset = ($gradient_info['color'][$i]['offset'] - $min)/$range;
+				$this->mpdf_ref->gradients[$n]['stops'][] = array(
+					'col' => $gradient_info['color'][$i]['color'],
+					'opacity' => $gradient_info['color'][$i]['opacity'],
+					'offset' => $offset);
+				if ($gradient_info['color'][$i]['opacity']<1) { $trans = true; }
+			}
+			$grx1 = $x1 + ($x0-$x1)*$gradient_info['color'][0]['offset'];
+			$gry1 = $y1 + ($y0-$y1)*$gradient_info['color'][0]['offset'];
+			$grx2 = $x1 + ($x0-$x1)*$gradient_info['color'][count($gradient_info['color'])-1]['offset'];
+			$gry2 = $y1 + ($y0-$y1)*$gradient_info['color'][count($gradient_info['color'])-1]['offset'];
+			$grir = $r*$gradient_info['color'][0]['offset'];
+			$grr = $r*$gradient_info['color'][count($gradient_info['color'])-1]['offset'];
+
+			$this->mpdf_ref->gradients[$n]['coords']=array($grx1, $gry1, $grx2, $gry2, abs($grr), abs($grir)  );
+
+			$grx1 = $x1 + ($x0-$x1)*$first_stop;
+			$gry1 = $y1 + ($y0-$y1)*$first_stop;
+			$grx2 = $x1 + ($x0-$x1)*$last_stop;
+			$gry2 = $y1 + ($y0-$y1)*$last_stop;
+			$grir = $r*$first_stop;
+			$grr = $r*$last_stop;
+			$this->mpdf_ref->gradients[$n]['colorspace'] = $gradient_info['colorspace'];	// mPDF 5.0.051
+
+			$this->mpdf_ref->gradients[$n]['type'] = 3;
+			$this->mpdf_ref->gradients[$n]['fo'] = true;
+
+			$this->mpdf_ref->gradients[$n]['extend']=array('true','true');
+			if ($trans) { 
+				$this->mpdf_ref->gradients[$n]['trans'] = true;	
+				$return .= ' /TGS'.($n).' gs ';
+			}
+			$return .= ' /Sh'.($n).' sh ';
+			$return .= " Q\n";
+
+
+		}
+
+		return $return;
+	}
+
+
+	function svgOffset ($attribs){
+		// save all <svg> tag attributes
+		$this->svg_attribs = $attribs;
+		if(isset($this->svg_attribs['viewBox'])) {
+			$vb = preg_split('/\s+/is', trim($this->svg_attribs['viewBox']));
+			if (count($vb)==4) {
+				$this->svg_info['x'] = $vb[0];
+				$this->svg_info['y'] = $vb[1];
+				$this->svg_info['w'] = $vb[2];
+				$this->svg_info['h'] = $vb[3];
+//				return;						// mPDF 5.0.005
+			}
+		}
+
+		$svg_w = $this->mpdf_ref->ConvertSize($attribs['width']);	// mm (interprets numbers as pixels)
+		$svg_h = $this->mpdf_ref->ConvertSize($attribs['height']);	// mm
+
+///*
+		// mPDF 5.0.005
+		if ($this->svg_info['w']) {	// if 'w' set by viewBox
+			if ($svg_w) {	// if width also set, use these values to determine to set size of "pixel"
+				$this->kp *= ($svg_w/0.2645) / $this->svg_info['w'];
+				$this->kf = ($svg_w/0.2645) / $this->svg_info['w'];	// mPDF 5.0.039
+			}
+			else if ($svg_h) {
+				$this->kp *= ($svg_h/0.2645) / $this->svg_info['h'];
+				$this->kf = ($svg_h/0.2645) / $this->svg_info['h'];	// mPDF 5.0.039
+			}
+			return;
+		}
+//*/
+
+		// Added to handle file without height or width specified
+		if (!$svg_w && !$svg_h) { $svg_w = $svg_h = $this->mpdf_ref->blk[$this->mpdf_ref->blklvl]['inner_width'] ; }	// DEFAULT
+		if (!$svg_w) { $svg_w = $svg_h; }
+		if (!$svg_h) { $svg_h = $svg_w; }
+
+		$this->svg_info['x'] = 0;
+		$this->svg_info['y'] = 0;
+		$this->svg_info['w'] = $svg_w/0.2645;	// mm->pixels
+		$this->svg_info['h'] = $svg_h/0.2645;	// mm->pixels
+
+	}
+
+
+	//
+	// check if points are within svg, if not, set to max
+	function svg_overflow($x,$y)
+	{
+		$x2 = $x;
+		$y2 = $y;
+		if(isset($this->svg_attribs['overflow']))
+		{
+			if($this->svg_attribs['overflow'] == 'hidden')
+			{
+				// Not sure if this is supposed to strip off units, but since I dont use any I will omlt this step
+				$svg_w = preg_replace("/([0-9\.]*)(.*)/i","$1",$this->svg_attribs['width']);
+				$svg_h = preg_replace("/([0-9\.]*)(.*)/i","$1",$this->svg_attribs['height']);
+				
+				// $xmax = floor($this->svg_attribs['width']);
+				$xmax = floor($svg_w);
+				$xmin = 0;
+				// $ymax = floor(($this->svg_attribs['height'] * -1));
+				$ymax = floor(($svg_h * -1));
+				$ymin = 0;
+
+				if($x > $xmax) $x2 = $xmax; // right edge
+				if($x < $xmin) $x2 = $xmin; // left edge
+				if($y < $ymax) $y2 = $ymax; // bottom 
+				if($y > $ymin) $y2 = $ymin; // top 
+
+			}
+		}
+
+
+		return array( 'x' => $x2, 'y' => $y2);
+	}
+
+
+
+	function svgDefineStyle($critere_style){
+
+		$tmp = count($this->svg_style)-1;
+		$current_style = $this->svg_style[$tmp];
+
+		unset($current_style['transformations']);
+
+		// TRANSFORM SCALE
+		$transformations = '';
+		if (isset($critere_style['transform'])){
+			preg_match_all('/(matrix|translate|scale|rotate|skewX|skewY)\((.*?)\)/is',$critere_style['transform'],$m);
+			if (count($m[0])) {
+				for($i=0; $i<count($m[0]); $i++) {
+					$c = strtolower($m[1][$i]);
+					$v = trim($m[2][$i]);
+					$vv = preg_split('/[ ,]+/',$v);
+					if ($c=='matrix' && count($vv)==6) {
+					// mPDF 5.0.039
+						// Note angle of rotation is reversed (from SVG to PDF), so vv[1] and vv[2] are negated
+						$transformations .= sprintf(' %.3F %.3F %.3F %.3F %.3F %.3F cm ', $vv[0], -$vv[1], -$vv[2], $vv[3], $vv[4]*$this->kp, -$vv[5]*$this->kp);
+
+/*
+// The long way of doing this??
+// need to reverse angle of rotation from SVG to PDF
+$sx=sqrt(pow($vv[0],2)+pow($vv[2],2));
+if ($vv[0] < 0) { $sx *= -1; } // change sign
+$sy=sqrt(pow($vv[1],2)+pow($vv[3],2));
+if ($vv[3] < 0) { $sy *= -1; } // change sign
+
+// rotation angle is 
+$t=atan2($vv[1],$vv[3]);
+$t=atan2(-$vv[2],$vv[0]);	// Should be the same value or skew has been applied
+
+// Reverse angle
+$t *= -1;
+
+// Rebuild matrix
+$ma = $sx * cos($t);
+$mb = $sy * sin($t);
+$mc = -$sx * sin($t);
+$md = $sy * cos($t);
+
+// $transformations .= sprintf(' %.3F %.3F %.3F %.3F %.3F %.3F cm ', $ma, $mb, $mc, $md, $vv[4]*$this->kp, -$vv[5]*$this->kp);
+*/
+
+					}
+					else if ($c=='translate' && count($vv)) {
+						$tm[4] = $vv[0];
+						if (count($vv)==2) { $t_y = -$vv[1]; }
+						else { $t_y = 0; }
+						$tm[5] = $t_y;
+						$transformations .= sprintf(' 1 0 0 1 %.3F %.3F cm ', $tm[4]*$this->kp, $tm[5]*$this->kp);
+					}
+					else if ($c=='scale' && count($vv)) {
+						if (count($vv)==2) { $s_y = $vv[1]; }
+						else { $s_y = $vv[0]; }
+						$tm[0] = $vv[0];
+						$tm[3] = $s_y;
+						$transformations .= sprintf(' %.3F 0 0 %.3F 0 0 cm ', $tm[0], $tm[3]);
+					}
+					else if ($c=='rotate' && count($vv)) {
+						$tm[0] = cos(deg2rad(-$vv[0]));
+						$tm[1] = sin(deg2rad(-$vv[0]));
+						$tm[2] = -$tm[1];
+						$tm[3] = $tm[0];
+						if (count($vv)==3) {
+							$transformations .= sprintf(' 1 0 0 1 %.3F %.3F cm ', $vv[1]*$this->kp, -$vv[2]*$this->kp);
+						}
+						$transformations .= sprintf(' %.3F %.3F %.3F %.3F 0 0 cm ', $tm[0], $tm[1], $tm[2], $tm[3]);
+						if (count($vv)==3) {
+							$transformations .= sprintf(' 1 0 0 1 %.3F %.3F cm ', -$vv[1]*$this->kp, $vv[2]*$this->kp);
+						}
+					}
+					else if ($c=='skewx' && count($vv)) {
+						$tm[2] = tan(deg2rad(-$vv[0]));
+						$transformations .= sprintf(' 1 0 %.3F 1 0 0 cm ', $tm[2]);
+					}
+					else if ($c=='skewy' && count($vv)) {
+						$tm[1] = tan(deg2rad(-$vv[0]));
+						$transformations .= sprintf(' 1 %.3F 0 1 0 0 cm ', $tm[1]);
+					}
+
+				}
+			}
+			$current_style['transformations'] = $transformations;
+		}
+
+		if (isset($critere_style['style'])){
+			if (preg_match('/fill:\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)/',$critere_style['style'], $m)) {
+				$current_style['fill'] = '#'.str_pad(dechex($m[1]), 2, "0", STR_PAD_LEFT).str_pad(dechex($m[2]), 2, "0", STR_PAD_LEFT).str_pad(dechex($m[3]), 2, "0", STR_PAD_LEFT);
+			}
+			else { $tmp = preg_replace("/(.*)fill:\s*([a-z0-9#_()]*|none)(.*)/i","$2",$critere_style['style']);	// mPDF 4.4.003
+				if ($tmp != $critere_style['style']){ $current_style['fill'] = $tmp; }
+			}
+
+			$tmp = preg_replace("/(.*)fill-opacity:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $current_style['fill-opacity'] = $tmp;}
+
+			$tmp = preg_replace("/(.*)fill-rule:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $current_style['fill-rule'] = $tmp;}
+
+			if (preg_match('/stroke:\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)/',$critere_style['style'], $m)) {
+				$current_style['stroke'] = '#'.str_pad(dechex($m[1]), 2, "0", STR_PAD_LEFT).str_pad(dechex($m[2]), 2, "0", STR_PAD_LEFT).str_pad(dechex($m[3]), 2, "0", STR_PAD_LEFT);
+			}
+			else { $tmp = preg_replace("/(.*)stroke:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
+				if ($tmp != $critere_style['style']){ $current_style['stroke'] = $tmp; }
+			}
+			
+			$tmp = preg_replace("/(.*)stroke-linecap:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $current_style['stroke-linecap'] = $tmp;}
+
+			$tmp = preg_replace("/(.*)stroke-linejoin:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $current_style['stroke-linejoin'] = $tmp;}
+			
+			$tmp = preg_replace("/(.*)stroke-miterlimit:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $current_style['stroke-miterlimit'] = $tmp;}
+			
+			$tmp = preg_replace("/(.*)stroke-opacity:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $current_style['stroke-opacity'] = $tmp; }
+			
+			$tmp = preg_replace("/(.*)stroke-width:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $current_style['stroke-width'] = $tmp;}
+
+			// mPDF 4.4.003
+			$tmp = preg_replace("/(.*)stroke-dasharray:\s*([a-z0-9., ]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $current_style['stroke-dasharray'] = $tmp;}
+
+			// mPDF 4.4.003
+			$tmp = preg_replace("/(.*)stroke-dashoffset:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $current_style['stroke-dashoffset'] = $tmp;}
+
+		}
+		if(isset($critere_style['fill'])){
+			$current_style['fill'] = $critere_style['fill'];
+		}
+
+		if(isset($critere_style['fill-opacity'])){
+			$current_style['fill-opacity'] = $critere_style['fill-opacity'];
+		}
+
+		if(isset($critere_style['fill-rule'])){
+			$current_style['fill-rule'] = $critere_style['fill-rule'];
+		}
+
+		if(isset($critere_style['stroke'])){
+			$current_style['stroke'] = $critere_style['stroke'];
+		}
+
+		if(isset($critere_style['stroke-linecap'])){
+			$current_style['stroke-linecap'] = $critere_style['stroke-linecap'];
+		}
+
+		if(isset($critere_style['stroke-linejoin'])){
+			$current_style['stroke-linejoin'] = $critere_style['stroke-linejoin'];
+		}
+
+		if(isset($critere_style['stroke-miterlimit'])){
+			$current_style['stroke-miterlimit'] = $critere_style['stroke-miterlimit'];
+		}
+
+		if(isset($critere_style['stroke-opacity'])){
+			$current_style['stroke-opacity'] = $critere_style['stroke-opacity'];
+		}
+
+		if(isset($critere_style['stroke-width'])){
+			$current_style['stroke-width'] = $critere_style['stroke-width'];
+		}
+
+		// mPDF 4.4.003
+		if(isset($critere_style['stroke-dasharray'])){
+			$current_style['stroke-dasharray'] = $critere_style['stroke-dasharray'];
+		}
+		if(isset($critere_style['stroke-dashoffset'])){
+			$current_style['stroke-dashoffset'] = $critere_style['stroke-dashoffset'];
+		}
+
+		// mPDF 4.4.005   Used as indirect setting for currentColor
+		if(isset($critere_style['color']) && $critere_style['color'] != 'inherit'){
+			$current_style['color'] = $critere_style['color'];
+		}
+
+		return $current_style;
+
+	}
+
+	//
+	//	Cette fonction ecrit le style dans le stream svg.
+	function svgStyle($critere_style, $attribs, $element){
+		$path_style = '';
+		if (substr_count($critere_style['fill'],'url')>0){
+			//
+			// couleur degradé
+			$id_gradient = preg_replace("/url\(#([\w_]*)\)/i","$1",$critere_style['fill']);
+			if ($id_gradient != $critere_style['fill']) {
+			   if (isset($this->svg_gradient[$id_gradient])) {
+				$fill_gradient = $this->svgGradient($this->svg_gradient[$id_gradient], $attribs, $element);
+				if ($fill_gradient) {	// mPDF 4.4.003
+					$path_style = "q ";
+					$w = "W";
+					$style .= 'N';
+				}
+			   }
+			}
+
+		}
+		// mPDF 4.4.005   Used as indirect setting for currentColor
+		else if (strtolower($critere_style['fill']) == 'currentcolor'){
+			$col = $this->mpdf_ref->ConvertColor($critere_style['color']);
+			if ($col) {
+				// mPDF 5.0.051
+				// mPDF 5.3.74
+				if ($col{0}==5) {	$critere_style['fill-opacity'] = ord($col{4}/100); }	// RGBa
+				if ($col{0}==6) {	$critere_style['fill-opacity'] = ord($col{5}/100); }	// CMYKa
+				$path_style .= $this->mpdf_ref->SetFColor($col, true).' ';	// mPDF 5.0.051
+				$style .= 'F';
+			}
+		}
+		else if ($critere_style['fill'] != 'none'){
+			$col = $this->mpdf_ref->ConvertColor($critere_style['fill']);
+			if ($col) {
+				// mPDF 5.0.051
+				// mPDF 5.3.74
+				if ($col{0}==5) {	$critere_style['fill-opacity'] = ord($col{4}/100); }	// RGBa
+				if ($col{0}==6) {	$critere_style['fill-opacity'] = ord($col{5}/100); }	// CMYKa
+				$path_style .= $this->mpdf_ref->SetFColor($col, true).' ';	// mPDF 5.0.051
+				$style .= 'F';
+			}
+		}
+
+		// mPDF 5.0.040
+		if (substr_count($critere_style['stroke'],'url')>0){
+/*
+			// Cannot put a gradient on a "stroke" in PDF?
+			$id_gradient = preg_replace("/url\(#([\w_]*)\)/i","$1",$critere_style['stroke']);
+			if ($id_gradient != $critere_style['stroke']) {
+			   if (isset($this->svg_gradient[$id_gradient])) {
+				$fill_gradient = $this->svgGradient($this->svg_gradient[$id_gradient], $attribs, $element);
+				if ($fill_gradient) {
+					$path_style = "q ";
+					$w = "W";
+					$style .= 'D';
+				}
+			   }
+			}
+*/
+		}
+		// mPDF 4.4.005   Used as indirect setting for currentColor
+		else if (strtolower($critere_style['stroke']) == 'currentcolor'){
+			$col = $this->mpdf_ref->ConvertColor($critere_style['color']);
+			if ($col) {
+				// mPDF 5.0.051
+				// mPDF 5.3.74
+				if ($col{0}==5) {	$critere_style['stroke-opacity'] = ord($col{4}/100); }	// RGBa
+				if ($col{0}==6) {	$critere_style['stroke-opacity'] = ord($col{5}/100); }	// CMYKa
+				$path_style .= $this->mpdf_ref->SetDColor($col, true).' ';	// mPDF 5.0.051
+				$style .= 'D';
+				$lw = $this->ConvertSVGSizePixels($critere_style['stroke-width']);
+				$path_style .= sprintf('%.3F w ',$lw*$this->kp);
+			}
+		}
+		else if ($critere_style['stroke'] != 'none'){
+			$col = $this->mpdf_ref->ConvertColor($critere_style['stroke']);
+			if ($col) {
+				// mPDF 5.0.051
+				// mPDF 5.3.74
+				if ($col{0}==5) {	$critere_style['stroke-opacity'] = ord($col{4}/100); }	// RGBa
+				if ($col{0}==6) {	$critere_style['stroke-opacity'] = ord($col{5}/100); }	// CMYKa
+				$path_style .= $this->mpdf_ref->SetDColor($col, true).' ';	// mPDF 5.0.051
+				$style .= 'D';
+				$lw = $this->ConvertSVGSizePixels($critere_style['stroke-width']);	// mPDF 4.4.003 
+				$path_style .= sprintf('%.3F w ',$lw*$this->kp);
+			}
+		}
+
+
+	if ($critere_style['stroke'] != 'none'){
+		if ($critere_style['stroke-linejoin'] == 'miter'){
+			$path_style .= ' 0 j ';
+		}
+		else if ($critere_style['stroke-linejoin'] == 'round'){
+			$path_style .= ' 1 j ';
+		}
+		else if ($critere_style['stroke-linejoin'] == 'bevel'){
+			$path_style .= ' 2 j ';
+		}
+
+		if ($critere_style['stroke-linecap'] == 'butt'){
+			$path_style .= ' 0 J ';
+		}
+		else if ($critere_style['stroke-linecap'] == 'round'){
+			$path_style .= ' 1 J ';
+		}
+		else if ($critere_style['stroke-linecap'] == 'square'){
+			$path_style .= ' 2 J ';
+		}
+
+		if (isset($critere_style['stroke-miterlimit'])){
+		   if ($critere_style['stroke-miterlimit'] == 'none'){
+		   }
+		   else if (preg_match('/^[\d.]+$/',$critere_style['stroke-miterlimit'])) {
+			$path_style .= sprintf('%.2F M ',$critere_style['stroke-miterlimit']);
+		   }
+		}
+		// mPDF 4.4.003
+		if (isset($critere_style['stroke-dasharray'])){
+			$off = 0;
+			$d = preg_split('/[ ,]/',$critere_style['stroke-dasharray']);
+			if (count($d) == 1 && $d[0]==0) {
+				$path_style .= '[] 0 d '; 
+			}
+			else {
+			  if (count($d) % 2 == 1) { $d = array_merge($d, $d); }	// 5, 3, 1 => 5,3,1,5,3,1  OR 3 => 3,3
+			  $arr = '';
+			  for($i=0; $i<count($d); $i+=2) {
+				$arr .= sprintf('%.3F %.3F ', $d[$i]*$this->kp, $d[$i+1]*$this->kp);
+			  }
+			  if (isset($critere_style['stroke-dashoffset'])){ $off = $critere_style['stroke-dashoffset'] + 0; }
+			  $path_style .= sprintf('[%s] %.3F d ', $arr, $off*$this->kp);
+			}
+		}
+	}
+
+		// mPDF 4.4.003
+		if ($critere_style['fill-rule']=='evenodd') { $fr = '*'; }
+		else { $fr = ''; }
+
+		// mPDF 4.4.003
+		if (isset($critere_style['fill-opacity'])) {
+			$opacity = 1;
+			if ($critere_style['fill-opacity'] == 0) { $opacity = 0; }
+			else if ($critere_style['fill-opacity'] > 1) { $opacity = 1; }
+			else if ($critere_style['fill-opacity'] > 0) { $opacity = $critere_style['fill-opacity']; }
+			else if ($critere_style['fill-opacity'] < 0) { $opacity = 0; }
+			$gs = $this->mpdf_ref->AddExtGState(array('ca'=>$opacity, 'BM'=>'/Normal'));
+			$this->mpdf_ref->extgstates[$gs]['fo'] = true;	// mPDF 5.0.039
+			$path_style .= sprintf(' /GS%d gs ', $gs);
+		}
+
+		// mPDF 4.4.003
+		if (isset($critere_style['stroke-opacity'])) {
+			$opacity = 1;
+			if ($critere_style['stroke-opacity'] == 0) { $opacity = 0; }
+			else if ($critere_style['stroke-opacity'] > 1) { $opacity = 1; }
+			else if ($critere_style['stroke-opacity'] > 0) { $opacity = $critere_style['stroke-opacity']; }
+			else if ($critere_style['stroke-opacity'] < 0) { $opacity = 0; }
+			$gs = $this->mpdf_ref->AddExtGState(array('CA'=>$opacity, 'BM'=>'/Normal'));
+			$this->mpdf_ref->extgstates[$gs]['fo'] = true;	// mPDF 5.0.039
+			$path_style .= sprintf(' /GS%d gs ', $gs);
+		}
+
+		switch ($style){
+			case 'F':
+				$op = 'f';
+			break;
+			case 'FD':
+				$op = 'B';
+			break;
+			case 'ND':
+				$op = 'S';
+			break;
+			case 'D':
+				$op = 'S';
+			break;
+			default:
+				$op = 'n';
+		}
+
+		// mPDF 5.0
+		$prestyle = $path_style.' ';
+		$poststyle = $w.' '. $op.$fr.' '.$fill_gradient."\n";
+		return array($prestyle,$poststyle);
+
+	}
+
+	//
+	//	fonction retracant les <path />
+	function svgPath($command, $arguments){
+		$path_cmd = '';
+		$newsubpath = false;	// mPDF 4.4.003
+		// mPDF 5.0.039
+		$minl = $this->pathBBox[0];
+		$mint = $this->pathBBox[1];
+		$maxr = $this->pathBBox[2]+$this->pathBBox[0];
+		$maxb = $this->pathBBox[3]+$this->pathBBox[1];
+		// mPDF 5.0.040
+		$start = array($this->xbase, -$this->ybase);
+
+		// mPDF 4.4.003
+		preg_match_all('/[\-^]?[\d.]+(e[\-]?[\d]+){0,1}/i', $arguments, $a, PREG_SET_ORDER);
+
+		//	if the command is a capital letter, the coords go absolute, otherwise relative
+		if(strtolower($command) == $command) $relative = true;
+		else $relative = false;
+
+
+		$ile_argumentow = count($a);
+
+		//	each command may have different needs for arguments [1 to 8]
+
+		switch(strtolower($command)){
+			case 'm': // move
+				for($i = 0; $i<$ile_argumentow; $i+=2){
+					$x = $a[$i][0]; 
+					$y = $a[$i+1][0]; 
+					if($relative){
+						$pdfx = ($this->xbase + $x);
+						$pdfy = ($this->ybase - $y);
+						$this->xbase += $x;
+						$this->ybase += -$y;
+					}
+					else{
+						$pdfx = $x;
+						$pdfy =  -$y ;
+						$this->xbase = $x;
+						$this->ybase = -$y;
+					}
+					$pdf_pt = $this->svg_overflow($pdfx,$pdfy);
+					// mPDF 5.0.039
+					$minl = min($minl,$pdf_pt['x']);
+					$maxr = max($maxr,$pdf_pt['x']);
+					$mint = min($mint,-$pdf_pt['y']);
+					$maxb = max($maxb,-$pdf_pt['y']);
+					if($i == 0) $path_cmd .= sprintf('%.3F %.3F m ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
+					else $path_cmd .= sprintf('%.3F %.3F l ',  $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
+					// mPDF 4.4.003  Save start points of subpath
+					if ($this->subPathInit) { 
+						$this->spxstart = $this->xbase;
+						$this->spystart = $this->ybase;
+						$this->subPathInit = false;
+					}
+				}
+			break;
+			case 'l': // a simple line
+				for($i = 0; $i<$ile_argumentow; $i+=2){
+					$x = ($a[$i][0]); 
+					$y = ($a[$i+1][0]); 
+					if($relative){
+						$pdfx = ($this->xbase + $x);
+						$pdfy = ($this->ybase - $y);
+						$this->xbase += $x;
+						$this->ybase += -$y;
+					}
+					else{
+						$pdfx = $x ;
+						$pdfy =  -$y ;
+						$this->xbase = $x;
+						$this->ybase = -$y;
+					}
+					$pdf_pt = $this->svg_overflow($pdfx,$pdfy);
+					// mPDF 5.0.039
+					$minl = min($minl,$pdf_pt['x']);
+					$maxr = max($maxr,$pdf_pt['x']);
+					$mint = min($mint,-$pdf_pt['y']);
+					$maxb = max($maxb,-$pdf_pt['y']);
+					$path_cmd .= sprintf('%.3F %.3F l ',  $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
+				}
+			break;
+			case 'h': // a very simple horizontal line
+				for($i = 0; $i<$ile_argumentow; $i++){
+					$x = ($a[$i][0]); 
+					if($relative){
+						$y = 0;
+						$pdfx = ($this->xbase + $x) ;
+						$pdfy = ($this->ybase - $y) ;
+						$this->xbase += $x;
+						$this->ybase += -$y;
+					}
+					else{
+						$y = -$this->ybase;
+						$pdfx = $x;
+						$pdfy =  -$y;
+						$this->xbase = $x;
+						$this->ybase = -$y;
+					}
+					$pdf_pt = $this->svg_overflow($pdfx,$pdfy);
+					// mPDF 5.0.039
+					$minl = min($minl,$pdf_pt['x']);
+					$maxr = max($maxr,$pdf_pt['x']);
+					$mint = min($mint,-$pdf_pt['y']);
+					$maxb = max($maxb,-$pdf_pt['y']);
+					$path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
+				}
+			break;
+			case 'v': // the simplest line, vertical
+				for($i = 0; $i<$ile_argumentow; $i++){
+					$y = ($a[$i][0]); 
+					if($relative){
+						$x = 0;
+						$pdfx = ($this->xbase + $x);
+						$pdfy = ($this->ybase - $y);
+						$this->xbase += $x;
+						$this->ybase += -$y;
+					}
+					else{
+						$x = $this->xbase;
+						$pdfx = $x;
+						$pdfy =  -$y;
+						$this->xbase = $x;
+						$this->ybase = -$y;
+					}
+					$pdf_pt = $this->svg_overflow($pdfx,$pdfy);
+					// mPDF 5.0.039
+					$minl = min($minl,$pdf_pt['x']);
+					$maxr = max($maxr,$pdf_pt['x']);
+					$mint = min($mint,-$pdf_pt['y']);
+					$maxb = max($maxb,-$pdf_pt['y']);
+					$path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
+				}
+			break;
+			case 's': // bezier with first vertex equal first control
+			   // mPDF 4.4.003 
+			   if (!($this->lastcommand == 'C' || $this->lastcommand == 'c' || $this->lastcommand == 'S' || $this->lastcommand == 's')) {
+ 				$this->lastcontrolpoints = array(0,0);
+			   }
+				for($i = 0; $i<$ile_argumentow; $i += 4){
+					$x1 = $this->lastcontrolpoints[0];
+					$y1 = $this->lastcontrolpoints[1];
+					$x2 = ($a[$i][0]); 
+					$y2 = ($a[$i+1][0]); 
+					$x = ($a[$i+2][0]); 
+					$y = ($a[$i+3][0]); 
+					if($relative){
+						$pdfx1 = ($this->xbase + $x1);
+						$pdfy1 = ($this->ybase - $y1);
+						$pdfx2 = ($this->xbase + $x2);
+						$pdfy2 = ($this->ybase - $y2);
+						$pdfx = ($this->xbase + $x);
+						$pdfy = ($this->ybase - $y);
+						$this->xbase += $x;
+						$this->ybase += -$y;
+					}
+					else{
+						$pdfx1 = $this->xbase + $x1;
+						$pdfy1 = $this->ybase -$y1;
+						$pdfx2 = $x2;
+						$pdfy2 = -$y2;
+						$pdfx = $x;
+						$pdfy =  -$y;
+						$this->xbase = $x;
+						$this->ybase = -$y;
+					}
+					$this->lastcontrolpoints = array(($pdfx-$pdfx2),-($pdfy-$pdfy2));	// mPDF 4.4.003 always relative
+
+					$pdf_pt = $this->svg_overflow($pdfx,$pdfy);
+
+					// mPDF 5.0.040
+					$curves = array($pdfx1,-$pdfy1,$pdfx2,-$pdfy2,$pdfx,-$pdfy);
+					$bx = calc_bezier_bbox($start, $curves);
+					$minl = min($minl,$bx[0]);
+					$maxr = max($maxr,$bx[2]);
+					$mint = min($mint,$bx[1]);
+					$maxb = max($maxb,$bx[3]);
+
+					if( ($pdf_pt['x'] != $pdfx) || ($pdf_pt['y'] != $pdfy) )
+					{
+						$path_cmd .= sprintf('%.3F %.3F l ',  $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
+					}
+					else
+					{
+						$path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $pdfx1*$this->kp, $pdfy1*$this->kp, $pdfx2*$this->kp, $pdfy2*$this->kp, $pdfx*$this->kp, $pdfy*$this->kp);
+					}
+
+			   }
+			break;
+			case 'c': // bezier with second vertex equal second control
+			for($i = 0; $i<$ile_argumentow; $i += 6){
+					$x1 = ($a[$i][0]); 
+					$y1 = ($a[$i+1][0]); 
+					$x2 = ($a[$i+2][0]); 
+					$y2 = ($a[$i+3][0]); 
+					$x = ($a[$i+4][0]); 
+					$y = ($a[$i+5][0]); 
+
+
+					if($relative){
+						$pdfx1 = ($this->xbase + $x1);
+						$pdfy1 = ($this->ybase - $y1);
+						$pdfx2 = ($this->xbase + $x2);
+						$pdfy2 = ($this->ybase - $y2);
+						$pdfx = ($this->xbase + $x);
+						$pdfy = ($this->ybase - $y);
+						$this->xbase += $x;
+						$this->ybase += -$y;
+					}
+					else{
+						$pdfx1 = $x1;
+						$pdfy1 = -$y1;
+						$pdfx2 = $x2;
+						$pdfy2 = -$y2;
+						$pdfx = $x;
+						$pdfy =  -$y;
+						$this->xbase = $x;
+						$this->ybase = -$y;
+					}
+					$this->lastcontrolpoints = array(($pdfx-$pdfx2),-($pdfy-$pdfy2));	// mPDF 4.4.003 always relative
+					// $pdf_pt2 = $this->svg_overflow($pdfx2,$pdfy2);
+					// $pdf_pt1 = $this->svg_overflow($pdfx1,$pdfy1);
+					$pdf_pt = $this->svg_overflow($pdfx,$pdfy);
+
+					// mPDF 5.0.040
+					$curves = array($pdfx1,-$pdfy1,$pdfx2,-$pdfy2,$pdfx,-$pdfy);
+					$bx = calc_bezier_bbox($start, $curves);
+					$minl = min($minl,$bx[0]);
+					$maxr = max($maxr,$bx[2]);
+					$mint = min($mint,$bx[1]);
+					$maxb = max($maxb,$bx[3]);
+
+					if( ($pdf_pt['x'] != $pdfx) || ($pdf_pt['y'] != $pdfy) )
+					{
+						$path_cmd .= sprintf('%.3F %.3F l ',  $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
+					}
+					else
+					{
+						$path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $pdfx1*$this->kp, $pdfy1*$this->kp, $pdfx2*$this->kp, $pdfy2*$this->kp, $pdfx*$this->kp, $pdfy*$this->kp);
+					}
+
+				}
+			break;
+
+			case 'q': // bezier quadratic avec point de control
+				for($i = 0; $i<$ile_argumentow; $i += 4){
+					$x1 = ($a[$i][0]); 
+					$y1 = ($a[$i+1][0]); 
+					$x = ($a[$i+2][0]); 
+					$y = ($a[$i+3][0]); 
+					if($relative){
+						$pdfx = ($this->xbase + $x);
+						$pdfy = ($this->ybase - $y);
+
+						$pdfx1 = ($this->xbase + ($x1*2/3));
+						$pdfy1 = ($this->ybase - ($y1*2/3));
+						// mPDF 4.4.003 
+    						$pdfx2 = $pdfx1 + 1/3 *($x); 
+    						$pdfy2 = $pdfy1 + 1/3 *(-$y) ;
+
+						$this->xbase += $x;
+						$this->ybase += -$y;
+					}
+					else{
+						$pdfx = $x;
+						$pdfy =  -$y;
+
+						$pdfx1 = ($this->xbase+(($x1-$this->xbase)*2/3));
+						$pdfy1 = ($this->ybase-(($y1+$this->ybase)*2/3));
+
+						$pdfx2 = ($x+(($x1-$x)*2/3));
+						$pdfy2 = (-$y-(($y1-$y)*2/3));
+
+						// mPDF 4.4.003 
+    						$pdfx2 = $pdfx1 + 1/3 *($x - $this->xbase); 
+    						$pdfy2 = $pdfy1 + 1/3 *(-$y - $this->ybase) ;
+
+						$this->xbase = $x;
+						$this->ybase = -$y;
+					}
+					$this->lastcontrolpoints = array(($pdfx-$pdfx2),-($pdfy-$pdfy2));	// mPDF 4.4.003 always relative
+
+					$pdf_pt = $this->svg_overflow($pdfx,$pdfy);
+
+					// mPDF 5.0.040
+					$curves = array($pdfx1,-$pdfy1,$pdfx2,-$pdfy2,$pdfx,-$pdfy);
+					$bx = calc_bezier_bbox($start, $curves);
+					$minl = min($minl,$bx[0]);
+					$maxr = max($maxr,$bx[2]);
+					$mint = min($mint,$bx[1]);
+					$maxb = max($maxb,$bx[3]);
+
+					if( ($pdf_pt['x'] != $pdfx) || ($pdf_pt['y'] != $pdfy) )
+					{
+						$path_cmd .= sprintf('%.3F %.3F l ',  $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
+					}
+					else
+					{
+						$path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $pdfx1*$this->kp, $pdfy1*$this->kp, $pdfx2*$this->kp, $pdfy2*$this->kp, $pdfx*$this->kp, $pdfy*$this->kp);
+					}
+				}
+			break;
+			case 't': // bezier quadratic avec point de control simetrique a lancien point de control
+			   // mPDF 4.4.003 
+			   if (!($this->lastcommand == 'Q' || $this->lastcommand == 'q' || $this->lastcommand == 'T' || $this->lastcommand == 't')) {
+ 				$this->lastcontrolpoints = array(0,0);
+			   }
+				for($i = 0; $i<$ile_argumentow; $i += 2){
+					$x = ($a[$i][0]); 
+					$y = ($a[$i+1][0]); 
+
+					$x1 = $this->lastcontrolpoints[0];
+					$y1 = $this->lastcontrolpoints[1];
+
+					if($relative){
+						$pdfx = ($this->xbase + $x);
+						$pdfy = ($this->ybase - $y);
+
+						$pdfx1 = ($this->xbase + ($x1));	// mPDF 4.4.003 
+						$pdfy1 = ($this->ybase - ($y1));	// mPDF 4.4.003 
+						// mPDF 4.4.003 
+    						$pdfx2 = $pdfx1 + 1/3 *($x); 
+    						$pdfy2 = $pdfy1 + 1/3 *(-$y) ;
+
+						$this->xbase += $x;
+						$this->ybase += -$y;
+					}
+					else{
+						$pdfx = $x;
+						$pdfy =  -$y;
+
+						$pdfx1 = ($this->xbase + ($x1));	// mPDF 4.4.003 
+						$pdfy1 = ($this->ybase - ($y1));	// mPDF 4.4.003 
+						// mPDF 4.4.003 
+    						$pdfx2 = $pdfx1 + 1/3 *($x - $this->xbase); 
+    						$pdfy2 = $pdfy1 + 1/3 *(-$y - $this->ybase) ;
+
+						$this->xbase = $x;
+						$this->ybase = -$y;
+					}
+
+					$this->lastcontrolpoints = array(($pdfx-$pdfx2),-($pdfy-$pdfy2));	// mPDF 4.4.003 always relative
+
+					// mPDF 5.0.040
+					$curves = array($pdfx1,-$pdfy1,$pdfx2,-$pdfy2,$pdfx,-$pdfy);
+					$bx = calc_bezier_bbox($start, $curves);
+					$minl = min($minl,$bx[0]);
+					$maxr = max($maxr,$bx[2]);
+					$mint = min($mint,$bx[1]);
+					$maxb = max($maxb,$bx[3]);
+
+					$path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $pdfx1*$this->kp, $pdfy1*$this->kp, $pdfx2*$this->kp, $pdfy2*$this->kp, $pdfx*$this->kp, $pdfy*$this->kp);
+				}
+
+			break;
+			case 'a':	// Elliptical arc
+				for($i = 0; $i<$ile_argumentow; $i += 7){
+					$rx = ($a[$i][0]); 
+					$ry = ($a[$i+1][0]); 
+					$angle = ($a[$i+2][0]); //x-axis-rotation 
+					$largeArcFlag = ($a[$i+3][0]); 
+					$sweepFlag = ($a[$i+4][0]); 
+					$x2 = ($a[$i+5][0]); 
+					$y2 = ($a[$i+6][0]); 
+					$x1 = $this->xbase;
+					$y1 = -$this->ybase;
+					if($relative){
+						$x2 = $this->xbase + $x2;
+						$y2 = -$this->ybase + $y2;
+						$this->xbase += ($a[$i+5][0]); 
+						$this->ybase += -($a[$i+6][0]); 
+					}
+					else{
+						$this->xbase = $x2;
+						$this->ybase = -$y2;
+					}
+					// mPDF 5.0.039 // mPDF 5.0.040
+					list($pcmd, $bounds) = $this->Arcto($x1, $y1, $x2, $y2, $rx, $ry, $angle, $largeArcFlag, $sweepFlag);
+					$minl = min($minl,$x2,min($bounds[0]));
+					$maxr = max($maxr,$x2,max($bounds[0]));
+					$mint = min($mint,$y2,min($bounds[1]));
+					$maxb = max($maxb,$y2,max($bounds[1]));
+					$path_cmd .= $pcmd;
+
+				}
+			break;
+			case'z':
+				$path_cmd .= 'h ';
+				// mPDF 4.4.003
+				$this->subPathInit = true;
+				$newsubpath = true;
+				$this->xbase = $this->spxstart;
+				$this->ybase = $this->spystart;
+			break;
+			default:
+			break;
+			}
+
+		if (!$newsubpath) { $this->subPathInit = false; }	// mPDF 4.4.003
+		$this->lastcommand = $command;
+		// mPDF 5.0.039
+		$this->pathBBox[0] = $minl;
+		$this->pathBBox[1] = $mint;
+		$this->pathBBox[2] = $maxr - $this->pathBBox[0];
+		$this->pathBBox[3] = $maxb - $this->pathBBox[1];
+		return $path_cmd;
+
+	}
+
+function Arcto($x1, $y1, $x2, $y2, $rx, $ry, $angle, $largeArcFlag, $sweepFlag) {
+
+	// mPDF 5.0.040
+	$bounds = array(0=>array($x1,$x2),1=>array($y1,$y2));
+	// 1. Treat out-of-range parameters as described in
+	// http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
+	// If the endpoints (x1, y1) and (x2, y2) are identical, then this
+	// is equivalent to omitting the elliptical arc segment entirely
+	if ($x1 == $x2 && $y1 == $y2) return array('', $bounds); // mPD 5.0.040
+
+	// If rX = 0 or rY = 0 then this arc is treated as a straight line
+	// segment (a "lineto") joining the endpoints.
+	if ($rx == 0.0 || $ry == 0.0) {
+	//   return array(Lineto(x2, y2), $bounds); // mPD 5.0.040
+	}
+
+	// If rX or rY have negative signs, these are dropped; the absolute
+	// value is used instead.
+	if ($rx<0.0) $rx = -$rx;
+	if ($ry<0.0) $ry = -$ry;
+
+	// 2. convert to center parameterization as shown in
+	// http://www.w3.org/TR/SVG/implnote.html
+	$sinPhi = sin(deg2rad($angle));
+	$cosPhi = cos(deg2rad($angle));
+
+	$x1dash =  $cosPhi * ($x1-$x2)/2.0 + $sinPhi * ($y1-$y2)/2.0;
+	$y1dash = -$sinPhi * ($x1-$x2)/2.0 + $cosPhi * ($y1-$y2)/2.0;
+
+
+	$numerator = $rx*$rx*$ry*$ry - $rx*$rx*$y1dash*$y1dash - $ry*$ry*$x1dash*$x1dash;
+
+	if ($numerator < 0.0) { 
+		//  If rX , rY and are such that there is no solution (basically,
+		//  the ellipse is not big enough to reach from (x1, y1) to (x2,
+		//  y2)) then the ellipse is scaled up uniformly until there is
+		//  exactly one solution (until the ellipse is just big enough).
+
+		// -> find factor s, such that numerator' with rx'=s*rx and
+		//    ry'=s*ry becomes 0 :
+		$s = sqrt(1.0 - $numerator/($rx*$rx*$ry*$ry));
+
+		$rx *= $s;
+		$ry *= $s;
+		$root = 0.0;
+
+	}
+	else {
+		$root = ($largeArcFlag == $sweepFlag ? -1.0 : 1.0) * sqrt( $numerator/($rx*$rx*$y1dash*$y1dash+$ry*$ry*$x1dash*$x1dash) );
+	}
+
+	$cxdash = $root*$rx*$y1dash/$ry;
+	$cydash = -$root*$ry*$x1dash/$rx;
+
+	$cx = $cosPhi * $cxdash - $sinPhi * $cydash + ($x1+$x2)/2.0;
+	$cy = $sinPhi * $cxdash + $cosPhi * $cydash + ($y1+$y2)/2.0;
+
+
+	$theta1 = $this->CalcVectorAngle(1.0, 0.0, ($x1dash-$cxdash)/$rx, ($y1dash-$cydash)/$ry);
+	$dtheta = $this->CalcVectorAngle(($x1dash-$cxdash)/$rx, ($y1dash-$cydash)/$ry, (-$x1dash-$cxdash)/$rx, (-$y1dash-$cydash)/$ry);
+	if (!$sweepFlag && $dtheta>0)
+		$dtheta -= 2.0*M_PI;
+	else if ($sweepFlag && $dtheta<0)
+		$dtheta += 2.0*M_PI;
+
+	// 3. convert into cubic bezier segments <= 90deg
+	$segments = ceil(abs($dtheta/(M_PI/2.0)));
+	$delta = $dtheta/$segments;
+	$t = 8.0/3.0 * sin($delta/4.0) * sin($delta/4.0) / sin($delta/2.0);
+	$coords = array();
+	for ($i = 0; $i < $segments; $i++) {
+		$cosTheta1 = cos($theta1);
+		$sinTheta1 = sin($theta1);
+		$theta2 = $theta1 + $delta;
+		$cosTheta2 = cos($theta2);
+		$sinTheta2 = sin($theta2);
+
+		// a) calculate endpoint of the segment:
+		$xe = $cosPhi * $rx*$cosTheta2 - $sinPhi * $ry*$sinTheta2 + $cx;
+		$ye = $sinPhi * $rx*$cosTheta2 + $cosPhi * $ry*$sinTheta2 + $cy;
+
+		// b) calculate gradients at start/end points of segment:
+		$dx1 = $t * ( - $cosPhi * $rx*$sinTheta1 - $sinPhi * $ry*$cosTheta1);
+		$dy1 = $t * ( - $sinPhi * $rx*$sinTheta1 + $cosPhi * $ry*$cosTheta1);
+
+		$dxe = $t * ( $cosPhi * $rx*$sinTheta2 + $sinPhi * $ry*$cosTheta2);
+		$dye = $t * ( $sinPhi * $rx*$sinTheta2 - $cosPhi * $ry*$cosTheta2);
+
+		// c) draw the cubic bezier:
+		$coords[$i] = array(($x1+$dx1), ($y1+$dy1), ($xe+$dxe), ($ye+$dye), $xe, $ye);
+
+		// do next segment
+		$theta1 = $theta2;
+		$x1 = $xe;
+		$y1 = $ye;
+	}
+	$path = ' ';
+	foreach($coords AS $c) {
+		$cpx1 = $c[0];
+		$cpy1 = $c[1];
+		$cpx2 = $c[2];
+		$cpy2 = $c[3];
+		$x2 = $c[4];
+		$y2 = $c[5];
+		$path .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $cpx1*$this->kp, -$cpy1*$this->kp, $cpx2*$this->kp, -$cpy2*$this->kp, $x2*$this->kp, -$y2*$this->kp)  ."\n";
+
+		// mPDF 5.0.040
+		$bounds[0][] = $c[4];
+		$bounds[1][] = $c[5];
+	}
+	return array($path, $bounds); // mPD 5.0.040
+}
+
+
+	function CalcVectorAngle($ux, $uy, $vx, $vy) {
+		$ta = atan2($uy, $ux);
+		$tb = atan2($vy, $vx);
+		if ($tb >= $ta)
+			return ($tb-$ta);
+		return (6.28318530718 - ($ta-$tb));
+	}
+
+
+	// mPDF 4.4.003
+	function ConvertSVGSizePixels($size=5,$maxsize='x'){
+	// maxsize in pixels (user units) or 'y' or 'x'
+	// e.g. $w = $this->ConvertSVGSizePixels($arguments['w'],$this->svg_info['w']*(25.4/$this->mpdf_ref->dpi));
+	// usefontsize - setfalse for e.g. margins - will ignore fontsize for % values
+	// Depends of maxsize value to make % work properly. Usually maxsize == pagewidth
+	// For text $maxsize = Fontsize
+	// Setting e.g. margin % will use maxsize (pagewidth) and em will use fontsize
+
+		if ($maxsize == 'y') { $maxsize = $this->svg_info['h']; }
+		else if ($maxsize == 'x') { $maxsize = $this->svg_info['w']; }
+		$maxsize *= (25.4/$this->mpdf_ref->dpi);	// convert pixels to mm
+		$fontsize=$this->mpdf_ref->FontSize;
+		//Return as pixels
+		$size = $this->mpdf_ref->ConvertSize($size,$maxsize,$fontsize,false) * 1/(25.4/$this->mpdf_ref->dpi);
+		return $size;
+	}
+
+	// mPDF 4.4.003
+	function ConvertSVGSizePts($size=5){
+	// usefontsize - setfalse for e.g. margins - will ignore fontsize for % values
+	// Depends of maxsize value to make % work properly. Usually maxsize == pagewidth
+	// For text $maxsize = Fontsize
+	// Setting e.g. margin % will use maxsize (pagewidth) and em will use fontsize
+		$maxsize=$this->mpdf_ref->FontSize;
+		//Return as pts
+		$size = $this->mpdf_ref->ConvertSize($size,$maxsize,false,true) * 72/25.4;
+		return $size;
+	}
+
+
+	//
+	//	fonction retracant les <rect />
+	function svgRect($arguments){
+
+		if ($arguments['h']==0 || $arguments['w']==0) { return ''; }	// mPDF 4.4.003
+
+		$x = $this->ConvertSVGSizePixels($arguments['x'],'x');	// mPDF 4.4.003 
+		$y = $this->ConvertSVGSizePixels($arguments['y'],'y');	// mPDF 4.4.003 
+		$h = $this->ConvertSVGSizePixels($arguments['h'],'y');	// mPDF 4.4.003 
+		$w = $this->ConvertSVGSizePixels($arguments['w'],'x');	// mPDF 4.4.003 
+		$rx = $this->ConvertSVGSizePixels($arguments['rx'],'x');	// mPDF 4.4.003 
+		$ry = $this->ConvertSVGSizePixels($arguments['ry'],'y');	// mPDF 4.4.003 
+
+		if ($rx > $w/2) { $rx = $w/2; }	// mPDF 4.4.003
+		if ($ry > $h/2) { $ry = $h/2; }	// mPDF 4.4.003
+
+		if ($rx>0 and $ry == 0){$ry = $rx;}
+		if ($ry>0 and $rx == 0){$rx = $ry;}
+
+		if ($rx == 0 and $ry == 0){
+			//	trace un rectangle sans angle arrondit
+			$path_cmd = sprintf('%.3F %.3F m ', ($x*$this->kp), -($y*$this->kp));
+			$path_cmd .= sprintf('%.3F %.3F l ', (($x+$w)*$this->kp), -($y*$this->kp));
+			$path_cmd .= sprintf('%.3F %.3F l ', (($x+$w)*$this->kp), -(($y+$h)*$this->kp));
+			$path_cmd .= sprintf('%.3F %.3F l ', ($x)*$this->kp, -(($y+$h)*$this->kp));
+			$path_cmd .= sprintf('%.3F %.3F l h ', ($x*$this->kp), -($y*$this->kp));
+
+			
+		}
+		else {
+			//	trace un rectangle avec les arrondit
+			//	les points de controle du bezier sont deduis grace a la constante kappa
+			$kappa = 4*(sqrt(2)-1)/3;
+
+			$kx = $kappa*$rx;
+			$ky = $kappa*$ry;
+
+			$path_cmd = sprintf('%.3F %.3F m ', ($x+$rx)*$this->kp, -$y*$this->kp);
+			$path_cmd .= sprintf('%.3F %.3F l ', ($x+($w-$rx))*$this->kp, -$y*$this->kp);
+			$path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($x+($w-$rx+$kx))*$this->kp, -$y*$this->kp, ($x+$w)*$this->kp, (-$y+(-$ry+$ky))*$this->kp, ($x+$w)*$this->kp, (-$y+(-$ry))*$this->kp );
+			$path_cmd .= sprintf('%.3F %.3F l ', ($x+$w)*$this->kp, (-$y+(-$h+$ry))*$this->kp);
+		 	$path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($x+$w)*$this->kp, (-$y+(-$h-$ky+$ry))*$this->kp, ($x+($w-$rx+$kx))*$this->kp, (-$y+(-$h))*$this->kp, ($x+($w-$rx))*$this->kp, (-$y+(-$h))*$this->kp );
+
+			$path_cmd .= sprintf('%.3F %.3F l ', ($x+$rx)*$this->kp, (-$y+(-$h))*$this->kp);
+			$path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($x+($rx-$kx))*$this->kp, (-$y+(-$h))*$this->kp, $x*$this->kp, (-$y+(-$h-$ky+$ry))*$this->kp, $x*$this->kp, (-$y+(-$h+$ry))*$this->kp );
+			$path_cmd .= sprintf('%.3F %.3F l ', $x*$this->kp, (-$y+(-$ry))*$this->kp);
+			$path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c h ', $x*$this->kp, (-$y+(-$ry+$ky))*$this->kp, ($x+($rx-$kx))*$this->kp, -$y*$this->kp, ($x+$rx)*$this->kp, -$y*$this->kp );
+
+
+		}
+		return $path_cmd;
+	}
+
+	//
+	//	fonction retracant les <ellipse /> et <circle />
+	//	 le cercle est tracé grave a 4 bezier cubic, les poitn de controles
+	//	sont deduis grace a la constante kappa * rayon
+	function svgEllipse($arguments){
+		if ($arguments['rx']==0 || $arguments['ry']==0) { return ''; }	// mPDF 4.4.003
+
+		$kappa = 4*(sqrt(2)-1)/3;
+
+		$cx = $this->ConvertSVGSizePixels($arguments['cx'],'x');	// mPDF 4.4.003 
+		$cy = $this->ConvertSVGSizePixels($arguments['cy'],'y');	// mPDF 4.4.003 
+		$rx = $this->ConvertSVGSizePixels($arguments['rx'],'x');	// mPDF 4.4.003 
+		$ry = $this->ConvertSVGSizePixels($arguments['ry'],'y');	// mPDF 4.4.003 
+
+		$x1 = $cx;
+		$y1 = -$cy+$ry;
+
+		$x2 = $cx+$rx;
+		$y2 = -$cy;
+
+		$x3 = $cx;
+		$y3 = -$cy-$ry;
+
+		$x4 = $cx-$rx;
+		$y4 = -$cy;
+
+		$path_cmd = sprintf('%.3F %.3F m ', $x1*$this->kp, $y1*$this->kp);
+		$path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($x1+($rx*$kappa))*$this->kp, $y1*$this->kp, $x2*$this->kp, ($y2+($ry*$kappa))*$this->kp, $x2*$this->kp, $y2*$this->kp);
+		$path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $x2*$this->kp, ($y2-($ry*$kappa))*$this->kp, ($x3+($rx*$kappa))*$this->kp, $y3*$this->kp, $x3*$this->kp, $y3*$this->kp);
+		$path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($x3-($rx*$kappa))*$this->kp, $y3*$this->kp, $x4*$this->kp, ($y4-($ry*$kappa))*$this->kp, $x4*$this->kp, $y4*$this->kp);
+		$path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $x4*$this->kp, ($y4+($ry*$kappa))*$this->kp, ($x1-($rx*$kappa))*$this->kp, $y1*$this->kp, $x1*$this->kp, $y1*$this->kp);
+		$path_cmd .= 'h ';
+
+		return $path_cmd;
+
+	}
+
+	//
+	//	fonction retracant les <polyline /> et les <line />
+	function svgPolyline($arguments,$ispolyline=true){
+		if ($ispolyline) {
+			$xbase = $arguments[0] ;
+			$ybase = - $arguments[1] ;
+		}
+		else {
+			if ($arguments[0]==$arguments[2] && $arguments[1]==$arguments[3]) { return ''; }	// mPDF 4.4.003  Zero length line
+			$xbase = $this->ConvertSVGSizePixels($arguments[0],'x');	// mPDF 4.4.003 
+			$ybase = - $this->ConvertSVGSizePixels($arguments[1],'y');	// mPDF 4.4.003 
+		}
+		$path_cmd = sprintf('%.3F %.3F m ', $xbase*$this->kp, $ybase*$this->kp);
+		for ($i = 2; $i<count($arguments);$i += 2) {
+			if ($ispolyline) {
+				$tmp_x = $arguments[$i] ;
+				$tmp_y = - $arguments[($i+1)] ;
+			}
+			else {
+				$tmp_x = $this->ConvertSVGSizePixels($arguments[$i],'x') ;	// mPDF 4.4.003 
+				$tmp_y = - $this->ConvertSVGSizePixels($arguments[($i+1)],'y') ;	// mPDF 4.4.003 
+			}
+			$path_cmd .= sprintf('%.3F %.3F l ', $tmp_x*$this->kp, $tmp_y*$this->kp);
+		}
+
+	//	$path_cmd .= 'h '; // ?? In error - don't close subpath here
+		return $path_cmd;
+
+	}
+
+	//
+	//	fonction retracant les <polygone />
+	function svgPolygon($arguments){
+		$xbase = $arguments[0] ;
+		$ybase = - $arguments[1] ;
+		$path_cmd = sprintf('%.3F %.3F m ', $xbase*$this->kp, $ybase*$this->kp);
+		for ($i = 2; $i<count($arguments);$i += 2) {
+			$tmp_x = $arguments[$i] ;
+			$tmp_y = - $arguments[($i+1)] ;
+
+			$path_cmd .= sprintf('%.3F %.3F l ', $tmp_x*$this->kp, $tmp_y*$this->kp);
+
+		}
+		$path_cmd .= sprintf('%.3F %.3F l ', $xbase*$this->kp, $ybase*$this->kp);
+		$path_cmd .= 'h ';
+		return $path_cmd;
+
+	}
+
+	//
+	//	write string to image
+	function svgText() {
+		// $tmp = count($this->txt_style)-1;
+		$current_style = array_pop($this->txt_style);
+		$style = '';
+		$render = -1;
+		if(isset($this->txt_data[2]))
+		{
+			// select font
+			$style .= ($current_style['font-weight'] == 'bold')?'B':'';
+			$style .= ($current_style['font-style'] == 'italic')?'I':'';
+			$size = $current_style['font-size']*$this->kf;	// mPDF 5.0.039
+
+			// mPDF 5.0
+			$current_style['font-family'] = $this->mpdf_ref->SetFont($current_style['font-family'],$style,$size,false);
+			$this->mpdf_ref->CurrentFont['fo'] = true;	// mPDF 5.0.039
+
+
+			// mPDF 5.0.041
+			$opacitystr = '';
+			$opacity = 1;
+			if (isset($current_style['fill-opacity'])) {
+				if ($current_style['fill-opacity'] == 0) { $opacity = 0; }
+				else if ($current_style['fill-opacity'] > 1) { $opacity = 1; }
+				else if ($current_style['fill-opacity'] > 0) { $opacity = $current_style['fill-opacity']; }
+				else if ($current_style['fill-opacity'] < 0) { $opacity = 0; }
+			}
+			$gs = $this->mpdf_ref->AddExtGState(array('ca'=>$opacity, 'BM'=>'/Normal'));
+			$this->mpdf_ref->extgstates[$gs]['fo'] = true;	// mPDF 5.0.039
+			$opacitystr = sprintf(' /GS%d gs ', $gs);
+
+			// mPDF 5.0.051
+			$fillstr = '';
+			if (isset($current_style['fill']) && $current_style['fill']!='none') {
+				$col = $this->mpdf_ref->ConvertColor($current_style['fill']);
+				// mPDF 5.0.051
+				$fillstr = $this->mpdf_ref->SetFColor($col, true);
+				$render = "0";	// Fill (only)
+			}
+			$strokestr = '';
+			if (isset($current_style['stroke-width']) && $current_style['stroke-width']>0 && $current_style['stroke']!='none') {
+				$scol = $this->mpdf_ref->ConvertColor($current_style['stroke']);
+				if ($scol) { 
+					$strokestr .= $this->mpdf_ref->SetDColor($scol, true).' ';	// mPDF 5.0.051
+				}
+				$linewidth = $this->ConvertSVGSizePixels($current_style['stroke-width']);
+				if ($linewidth > 0) { 
+					$strokestr .= sprintf('%.3F w 1 J 1 j ',$linewidth*$this->kp); 
+					if ($render == -1) { $render = "1"; }	// stroke only
+					else { $render = "2"; } 	// fill and stroke
+				}
+			}
+			if ($render == -1) { return ''; }	
+
+			$x = $this->ConvertSVGSizePixels($this->txt_data[0],'x');	// mPDF 4.4.003 
+			$y = $this->ConvertSVGSizePixels($this->txt_data[1],'y');	// mPDF 4.4.003
+			$txt = $this->txt_data[2];
+
+			// mPDF 4.4.003
+			$txt = preg_replace('/\f/','',$txt); 
+			$txt = preg_replace('/\r/','',$txt); 
+			$txt = preg_replace('/\n/',' ',$txt); 
+			$txt = preg_replace('/\t/',' ',$txt); 
+			$txt = preg_replace("/[ ]+/u",' ',$txt);
+
+			$txt = trim($txt);
+
+			$txt = $this->mpdf_ref->purify_utf8_text($txt);
+			if ($this->mpdf_ref->text_input_as_HTML) {
+				$txt = $this->mpdf_ref->all_entities_to_utf8($txt);
+			}
+
+			// mPDF 5.0
+			if ($this->mpdf_ref->usingCoreFont) { $txt = mb_convert_encoding($txt,$this->mpdf_ref->mb_enc,'UTF-8'); }
+			if (preg_match("/([".$this->mpdf_ref->pregRTLchars."])/u", $txt)) { $this->mpdf_ref->biDirectional = true; } // mPDF 4.4.003
+
+			$this->mpdf_ref->magic_reverse_dir($txt, true, 'ltr');	// mPDF 5.0.054
+			$this->mpdf_ref->ConvertIndic($txt);
+
+
+			if ($current_style['text-anchor']=='middle') {
+				$tw = $this->mpdf_ref->GetStringWidth($txt)*$this->mpdf_ref->k/2;	// mPDF 4.4.003
+			}
+			else if ($current_style['text-anchor']=='end') {
+				$tw = $this->mpdf_ref->GetStringWidth($txt)*$this->mpdf_ref->k;	// mPDF 4.4.003
+			}
+			else $tw = 0;
+
+			if (!$this->mpdf_ref->usingCoreFont) {
+				$this->mpdf_ref->UTF8StringToArray($txt);	// mPDF 5.0 adds chars to subset list
+				$txt= $this->mpdf_ref->UTF8ToUTF16BE($txt, false);
+			}
+			$txt='('.$this->mpdf_ref->_escape($txt).')'; 
+			$this->mpdf_ref->CurrentFont['used']= true;
+
+			$pdfx = $x - $tw/$this->kp;	// mPDF 4.4.009
+			$pdfy =  -$y  ;
+			$xbase = $x;
+			$ybase = -$y;
+
+			// mPDF 5.0.041
+			// mPDF 5.0.051
+			$path_cmd =  sprintf('q BT /F%d %s %.3F Tf %.3F %.3F Td %s Tr %s %s %s Tj ET Q ',$this->mpdf_ref->CurrentFont['i'],$opacitystr, $this->mpdf_ref->FontSizePt,$pdfx*$this->kp,$pdfy*$this->kp,$render,$fillstr,$strokestr,$txt)."\n";
+			unset($this->txt_data[0], $this->txt_data[1],$this->txt_data[2]);
+		}
+		else
+		{
+			return ' ';
+		}
+//		$path_cmd .= 'h ';	// mPDF 5.0
+		return $path_cmd;
+	}
+
+
+function svgDefineTxtStyle($critere_style)
+{
+		// get copy of current/default txt style, and modify it with supplied attributes
+		$tmp = count($this->txt_style)-1;
+		$current_style = $this->txt_style[$tmp];
+		if (isset($critere_style['style'])){
+			if (preg_match('/fill:\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)/',$critere_style['style'], $m)) {
+				$current_style['fill'] = '#'.str_pad(dechex($m[1]), 2, "0", STR_PAD_LEFT).str_pad(dechex($m[2]), 2, "0", STR_PAD_LEFT).str_pad(dechex($m[3]), 2, "0", STR_PAD_LEFT);
+			}
+			else { $tmp = preg_replace("/(.*)fill:\s*([a-z0-9#_()]*|none)(.*)/i","$2",$critere_style['style']);
+				if ($tmp != $critere_style['style']){ $current_style['fill'] = $tmp; }
+			}
+
+			$tmp = preg_replace("/(.*)fill-opacity:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $current_style['fill-opacity'] = $tmp;}
+
+			$tmp = preg_replace("/(.*)fill-rule:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $current_style['fill-rule'] = $tmp;}
+
+			if (preg_match('/stroke:\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)/',$critere_style['style'], $m)) {
+				$current_style['stroke'] = '#'.str_pad(dechex($m[1]), 2, "0", STR_PAD_LEFT).str_pad(dechex($m[2]), 2, "0", STR_PAD_LEFT).str_pad(dechex($m[3]), 2, "0", STR_PAD_LEFT);
+			}
+			else { $tmp = preg_replace("/(.*)stroke:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
+				if ($tmp != $critere_style['style']){ $current_style['stroke'] = $tmp; }
+			}
+			
+			$tmp = preg_replace("/(.*)stroke-linecap:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $current_style['stroke-linecap'] = $tmp;}
+
+			$tmp = preg_replace("/(.*)stroke-linejoin:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $current_style['stroke-linejoin'] = $tmp;}
+			
+			$tmp = preg_replace("/(.*)stroke-miterlimit:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $current_style['stroke-miterlimit'] = $tmp;}
+			
+			$tmp = preg_replace("/(.*)stroke-opacity:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $current_style['stroke-opacity'] = $tmp; }
+			
+			$tmp = preg_replace("/(.*)stroke-width:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $current_style['stroke-width'] = $tmp;}
+
+			$tmp = preg_replace("/(.*)stroke-dasharray:\s*([a-z0-9., ]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $current_style['stroke-dasharray'] = $tmp;}
+
+			$tmp = preg_replace("/(.*)stroke-dashoffset:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $current_style['stroke-dashoffset'] = $tmp;}
+
+			// mPDF 5.0.039
+			$tmp = preg_replace("/(.*)font-family:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $critere_style['font-family'] = $tmp;}
+
+			$tmp = preg_replace("/(.*)font-size:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $critere_style['font-size'] = $tmp;}
+
+			$tmp = preg_replace("/(.*)font-weight:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $critere_style['font-weight'] = $tmp;}
+
+			$tmp = preg_replace("/(.*)font-style:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
+			if ($tmp != $critere_style['style']){ $critere_style['font-style'] = $tmp;}
+
+		}
+
+		if (isset($critere_style['font'])){
+
+			// [ [ <'font-style'> || <'font-variant'> || <'font-weight'> ]?<'font-size'> [ / <'line-height'> ]? <'font-family'> ]
+
+			$tmp = preg_replace("/(.*)(italic|oblique)(.*)/i","$2",$critere_style['font']);
+			if ($tmp != $critere_style['font']){ 
+				if($tmp == 'oblique'){
+					$tmp = 'italic';
+				}
+				$current_style['font-style'] = $tmp;
+			}
+			$tmp = preg_replace("/(.*)(bold|bolder)(.*)/i","$2",$critere_style['font']);
+			if ($tmp != $critere_style['font']){ 
+				if($tmp == 'bolder'){
+					$tmp = 'bold';
+				}
+				$current_style['font-weight'] = $tmp;
+			}
+			
+			// select digits not followed by percent sign nor preceeded by forward slash
+			$tmp = preg_replace("/(.*)\b(\d+)[\b|\/](.*)/i","$2",$critere_style['font']);
+			if ($tmp != $critere_style['font']){ 
+				// mPDF 4.4.003
+				$current_style['font-size'] = $this->ConvertSVGSizePts($tmp); 
+				$this->mpdf_ref->SetFont('','',$current_style['font-size'],false);
+			}
+			
+		}
+
+		if(isset($critere_style['fill'])){
+			$current_style['fill'] = $critere_style['fill'];
+		}
+		// mPDF 4.4.003
+		if(isset($critere_style['stroke'])){
+			$current_style['stroke'] = $critere_style['stroke'];
+		}
+		if(isset($critere_style['stroke-width'])){
+			$current_style['stroke-width'] = $critere_style['stroke-width'];
+		}
+		
+		if(isset($critere_style['font-style'])){
+			if(strtolower($critere_style['font-style']) == 'oblique') 
+			{
+				$critere_style['font-style'] = 'italic';
+			}
+			$current_style['font-style'] = $critere_style['font-style'];
+		}
+		
+		if(isset($critere_style['font-weight'])){
+			if(strtolower($critere_style['font-weight']) == 'bolder')
+			{
+				$critere_style['font-weight'] = 'bold';
+			}
+			$current_style['font-weight'] = $critere_style['font-weight'];
+		}
+		
+		if(isset($critere_style['font-size'])){
+			// mPDF 4.4.003
+			$current_style['font-size'] = $this->ConvertSVGSizePts($critere_style['font-size']);
+			$this->mpdf_ref->SetFont('','',$current_style['font-size'],false);
+		}
+
+		if(isset($critere_style['font-family'])){
+			// mPDF 4.4.003
+			$v = $critere_style['font-family'];
+			$aux_fontlist = explode(",",$v);
+			$found = 0;
+			foreach($aux_fontlist AS $f) {
+				$fonttype = trim($f);
+				$fonttype = preg_replace('/["\']*(.*?)["\']*/','\\1',$fonttype);
+				$fonttype = preg_replace('/ /','',$fonttype);
+				$v = strtolower(trim($fonttype));
+				if (isset($this->mpdf_ref->fonttrans[$v]) && $this->mpdf_ref->fonttrans[$v]) { $v = $this->mpdf_ref->fonttrans[$v]; }
+				if ((!$this->mpdf_ref->usingCoreFont && in_array($v,$this->mpdf_ref->available_unifonts)) || 
+					($this->mpdf_ref->usingCoreFont && in_array($v,array('courier','times','helvetica','arial'))) || 
+					in_array($v, array('sjis','uhc','big5','gb'))) { 
+					$current_style['font-family'] = $v; 
+					$found = 1;
+					break;
+				}
+			}
+			if (!$found) {
+			   foreach($aux_fontlist AS $f) {
+				$fonttype = trim($f);
+				$fonttype = preg_replace('/["\']*(.*?)["\']*/','\\1',$fonttype);
+				$fonttype = preg_replace('/ /','',$fonttype);
+				$v = strtolower(trim($fonttype));
+				if (isset($this->mpdf_ref->fonttrans[$v]) && $this->mpdf_ref->fonttrans[$v]) { $v = $this->mpdf_ref->fonttrans[$v]; }
+				if (in_array($v,$this->mpdf_ref->sans_fonts) || in_array($v,$this->mpdf_ref->serif_fonts) || in_array($v,$this->mpdf_ref->mono_fonts) ) { 
+					$current_style['font-family'] = $v; 
+					break;
+				}
+			   }
+			}
+		}
+	
+		if(isset($critere_style['text-anchor'])){
+			$current_style['text-anchor'] = $critere_style['text-anchor'];
+		}
+	
+	// add current style to text style array (will remove it later after writing text to svg_string)
+	array_push($this->txt_style,$current_style);
+}
+
+
+
+	//
+	//	fonction ajoutant un gradient
+	function svgAddGradient($id,$array_gradient){
+
+		$this->svg_gradient[$id] = $array_gradient;
+
+	}
+	//
+	//	Ajoute une couleur dans le gradient correspondant
+
+	//
+	//	function ecrivant dans le svgstring
+	function svgWriteString($content){
+
+		$this->svg_string .= $content;
+
+	}
+
+
+
+	//	analise le svg et renvoie aux fonctions precedente our le traitement
+	function ImageSVG($data){
+		$this->svg_info = array();
+
+		// mPDF 4.4.006
+		if (preg_match('/<!ENTITY/si',$data)) {
+			// Get User-defined entities
+			preg_match_all('/<!ENTITY\s+([a-z]+)\s+\"(.*?)\">/si',$data, $ent);
+			// Replace entities
+			for ($i=0; $i<count($ent[0]); $i++) {
+				$data = preg_replace('/&'.preg_quote($ent[1][$i],'/').';/is', $ent[2][$i], $data);
+			}
+		}
+
+
+		// mPDF 4.4.003
+		if (preg_match('/xlink:href=/si',$data)) {
+			// Get links
+			preg_match_all('/(<(linearGradient|radialgradient)[^>]*)xlink:href=["\']#(.*?)["\'](.*?)\/>/si',$data, $links);
+			if (count($links[0])) { $links[5] = array(); }	// mPDF 4.5.010
+			// Delete links from data - keeping in $links
+			for ($i=0; $i<count($links[0]); $i++) {
+				$links[5][$i] = 'tmpLink'.RAND(100000,9999999);	// mPDF 4.5.010
+				$data = preg_replace('/'.preg_quote($links[0][$i],'/').'/is', '<MYLINKS'.$links[5][$i].'>' , $data);	// mPDF 4.5.010
+			}
+			// Get targets
+			preg_match_all('/<(linearGradient|radialgradient)([^>]*)id=["\'](.*?)["\'](.*?)>(.*?)<\/(linearGradient|radialgradient)>/si',$data, $m);
+			$targets = array();
+			$stops = array();
+			// keeping in $targets
+			for ($i=0; $i<count($m[0]); $i++) {
+				$stops[$m[3][$i]] = $m[5][$i];
+			}
+			// Add back links this time as targets (gradients)
+			for ($i=0; $i<count($links[0]); $i++) {
+				$def = $links[1][$i] .' '.$links[4][$i].'>'. $stops[$links[3][$i]].'</'.$links[2][$i] .'>' ;	// mPDF 4.5.010
+				$data = preg_replace('/<MYLINKS'.$links[5][$i].'>/is', $def , $data);	// mPDF 4.5.010
+			}
+		}
+		// mPDF 4.4.003	- Removes <pattern>
+		$data = preg_replace('/<pattern.*?<\/pattern>/is', '', $data);
+		// mPDF 4.4.003	- Removes <marker>
+		$data = preg_replace('/<marker.*?<\/marker>/is', '', $data);
+
+		$this->svg_info['data'] = $data;
+
+		$this->svg_string = '';
+		
+		//
+		//	chargement unique des fonctions
+		if(!function_exists("xml_svg2pdf_start")){	// mPDF 5.3.76
+
+			function xml_svg2pdf_start($parser, $name, $attribs){
+				//
+				//	definition
+				global $svg_class, $last_gradid;
+
+				// mPDF 4.4.003
+				$svg_class->xbase = 0;
+				$svg_class->ybase = 0;
+				switch (strtolower($name)){
+
+		 		// mPDF 5.0.039	- Don't output stuff inside <defs>
+				case 'defs':
+					$svg_class->inDefs = true;
+					return;
+
+				case 'svg':
+					$svg_class->svgOffset($attribs);
+					break;
+
+				case 'path':
+					$path = $attribs['d'];
+					// mPDF 4.4.003
+					preg_match_all('/([MZLHVCSQTAmzlhvcsqta])([e ,\-.\d]+)*/', $path, $commands, PREG_SET_ORDER);
+					$path_cmd = '';
+					$svg_class->subPathInit = true;	// mPDF 4.4.003
+					// mPDF 5.0.039
+					$svg_class->pathBBox = array(999999,999999,-999999,-999999);
+					foreach($commands as $c){
+						if(count($c)==3 || $c[2]==''){
+							list($tmp, $command, $arguments) = $c;
+						}
+						else{
+							list($tmp, $command) = $c;
+							$arguments = '';
+						}
+
+						$path_cmd .= $svg_class->svgPath($command, $arguments);
+					}
+					// mPDF 5.0.039
+					if ($svg_class->pathBBox[2]==-1999998) { $svg_class->pathBBox[2] = 100; }
+					if ($svg_class->pathBBox[3]==-1999998) { $svg_class->pathBBox[3] = 100; }
+					if ($svg_class->pathBBox[0]==999999) { $svg_class->pathBBox[0] = 0; }
+					if ($svg_class->pathBBox[1]==999999) { $svg_class->pathBBox[1] = 0; }
+					$critere_style = $attribs;
+					unset($critere_style['d']);
+					$path_style = $svg_class->svgDefineStyle($critere_style);
+					break;
+
+				case 'rect':
+					if (!isset($attribs['x'])) {$attribs['x'] = 0;}
+					if (!isset($attribs['y'])) {$attribs['y'] = 0;}
+					if (!isset($attribs['rx'])) {$attribs['rx'] = 0;}
+					if (!isset($attribs['ry'])) {$attribs['ry'] = 0;}
+					$arguments = array(
+						'x' => $attribs['x'],
+						'y' => $attribs['y'],
+						'w' => $attribs['width'],
+						'h' => $attribs['height'],
+						'rx' => $attribs['rx'],
+						'ry' => $attribs['ry']
+					);
+					$path_cmd =  $svg_class->svgRect($arguments);
+					$critere_style = $attribs;
+					unset($critere_style['x'],$critere_style['y'],$critere_style['rx'],$critere_style['ry'],$critere_style['height'],$critere_style['width']);
+					$path_style = $svg_class->svgDefineStyle($critere_style);
+					break;
+
+				case 'circle':
+					if (!isset($attribs['cx'])) {$attribs['cx'] = 0;}
+					if (!isset($attribs['cy'])) {$attribs['cy'] = 0;}
+					$arguments = array(
+						'cx' => $attribs['cx'],
+						'cy' => $attribs['cy'],
+						'rx' => $attribs['r'],
+						'ry' => $attribs['r']
+					);
+					$path_cmd =  $svg_class->svgEllipse($arguments);
+					$critere_style = $attribs;
+					unset($critere_style['cx'],$critere_style['cy'],$critere_style['r']);
+					$path_style = $svg_class->svgDefineStyle($critere_style);
+					break;
+
+				case 'ellipse':
+					if (!isset($attribs['cx'])) {$attribs['cx'] = 0;}
+					if (!isset($attribs['cy'])) {$attribs['cy'] = 0;}
+					$arguments = array(
+						'cx' => $attribs['cx'],
+						'cy' => $attribs['cy'],
+						'rx' => $attribs['rx'],
+						'ry' => $attribs['ry']
+					);
+					$path_cmd =  $svg_class->svgEllipse($arguments);
+					$critere_style = $attribs;
+					unset($critere_style['cx'],$critere_style['cy'],$critere_style['rx'],$critere_style['ry']);
+					$path_style = $svg_class->svgDefineStyle($critere_style);
+					break;
+
+				case 'line':
+					$arguments = array($attribs['x1'],$attribs['y1'],$attribs['x2'],$attribs['y2']);
+					$path_cmd =  $svg_class->svgPolyline($arguments,false);	//  mPDF 4.4.003
+					$critere_style = $attribs;
+					unset($critere_style['x1'],$critere_style['y1'],$critere_style['x2'],$critere_style['y2']);
+					$path_style = $svg_class->svgDefineStyle($critere_style);
+					break;
+
+				case 'polyline':
+					$path = $attribs['points'];
+					preg_match_all('/[0-9\-\.]*/',$path, $tmp, PREG_SET_ORDER);
+					$arguments = array();
+					for ($i=0;$i<count($tmp);$i++){
+						if ($tmp[$i][0] !=''){
+							array_push($arguments, $tmp[$i][0]);
+						}
+					}
+					$path_cmd =  $svg_class->svgPolyline($arguments);
+					$critere_style = $attribs;
+					unset($critere_style['points']);
+					$path_style = $svg_class->svgDefineStyle($critere_style);
+					break;
+
+				case 'polygon':
+					$path = $attribs['points'];
+					preg_match_all('/([\-]*[0-9\.]+)/',$path, $tmp);
+					$arguments = array();
+					for ($i=0;$i<count($tmp[0]);$i++){
+						if ($tmp[0][$i] !=''){
+							array_push($arguments, $tmp[0][$i]);
+						}
+					}
+					$path_cmd =  $svg_class->svgPolygon($arguments);
+					//	definition du style de la forme:
+					$critere_style = $attribs;
+					unset($critere_style['points']);
+					$path_style = $svg_class->svgDefineStyle($critere_style);
+					break;
+
+				case 'lineargradient':
+						$tmp_gradient = array(
+							'type' => 'linear',
+							'info' => array(
+								'x1' => $attribs['x1'],
+								'y1' => $attribs['y1'],
+								'x2' => $attribs['x2'],
+								'y2' => $attribs['y2']
+							),
+							'transform' => $attribs['gradientTransform'],
+							'units' => $attribs['gradientUnits'],	/* mPDF 4.4.003 */
+							'spread' => $attribs['spreadMethod'],	/* mPDF 5.0.040 */
+							'color' => array()
+						);
+
+						$last_gradid = $attribs['id'];
+						$svg_class->svgAddGradient($attribs['id'],$tmp_gradient);
+					break;
+
+				case 'radialgradient':
+						$tmp_gradient = array(
+							'type' => 'radial',
+							'info' => array(
+								'x0' => $attribs['cx'],
+								'y0' => $attribs['cy'],
+								'x1' => $attribs['fx'],
+								'y1' => $attribs['fy'],
+								'r' => $attribs['r']
+							),
+							'transform' => $attribs['gradientTransform'],
+							'units' => $attribs['gradientUnits'],	/* mPDF 4.4.003 */
+							'spread' => $attribs['spreadMethod'],	/* mPDF 5.0.040 */
+							'color' => array()
+						);
+
+						$last_gradid = $attribs['id'];
+
+						$svg_class->svgAddGradient($attribs['id'],$tmp_gradient);
+
+					break;
+
+				case 'stop':
+						if (!$last_gradid) break;
+						// mPDF 4.4.003  // mPDF 5.0.040
+						if (isset($attribs['style']) AND preg_match('/stop-color:\s*([^;]*)/i',$attribs['style'],$m)) {
+							$color = trim($m[1]);
+						} else if (isset($attribs['stop-color'])) {
+							$color = $attribs['stop-color'];
+						}
+						$col = $svg_class->mpdf_ref->ConvertColor($color);
+
+						// mPDF 5.0.051
+						// mPDF 5.3.74
+						if ($col{0}==3 || $col{0}==5) {	// RGB
+							$color_final = sprintf('%.3F %.3F %.3F',ord($col{1})/255,ord($col{2})/255,ord($col{3})/255);
+							$svg_class->svg_gradient[$last_gradid]['colorspace']='RGB';
+						}
+						else if ($col{0}==4 || $col{0}==6) {	// CMYK
+							$color_final = sprintf('%.3F %.3F %.3F %.3F',ord($col{1})/100,ord($col{2})/100,ord($col{3})/100,ord($col{4})/100);
+							$svg_class->svg_gradient[$last_gradid]['colorspace']='CMYK';
+						}
+						else if ($col{0}==1) {	// Grayscale
+							$color_final = sprintf('%.3F',ord($col{1})/255);
+							$svg_class->svg_gradient[$last_gradid]['colorspace']='Gray';
+						}
+
+
+						// mPDF 5.0.020
+						$stop_opacity = 1;
+						// mPDF 4.4.003
+						if (isset($attribs['style']) AND preg_match('/stop-opacity:\s*([0-9.]*)/i',$attribs['style'],$m)) {
+							$stop_opacity = $m[1];
+						} else if (isset($attribs['stop-opacity'])) {
+							$stop_opacity = $attribs['stop-opacity'];
+						}
+						// mPDF 5.0.051
+						// mPDF 5.3.74
+						else if ($col{0}==5) {	// RGBa
+							$stop_opacity = ord($col{4}/100);
+						}
+						else if ($col{0}==6) {	// CMYKa
+							$stop_opacity = ord($col{5}/100);
+						}
+
+						$tmp_color = array(
+							'color' => $color_final,
+							'offset' => $attribs['offset'],
+							'opacity' => $stop_opacity
+						);
+						array_push($svg_class->svg_gradient[$last_gradid]['color'],$tmp_color);
+					break;
+
+
+				case 'a':
+						if (isset($attribs['xlink:href'])) {
+							unset($attribs['xlink:href']);	// this should be a hyperlink
+								// not handled like a xlink:href in other elements
+						}		// then continue like a <g>
+				case 'g':
+						$array_style = $svg_class->svgDefineStyle($attribs);
+						if ($array_style['transformations']) {
+							$svg_class->svgWriteString(' q '.$array_style['transformations']);
+						}
+						array_push($svg_class->svg_style,$array_style);
+
+						$svg_class->svgDefineTxtStyle($attribs);	// mPDF 4.4.003
+
+					break;
+
+				case 'text':
+						// mPDF 4.4.003
+						$array_style = $svg_class->svgDefineStyle($attribs);
+						if ($array_style['transformations']) {
+							$svg_class->svgWriteString(' q '.$array_style['transformations']);
+						}
+						array_push($svg_class->svg_style,$array_style);
+
+						$svg_class->txt_data = array();
+						$svg_class->txt_data[0] = $attribs['x'];
+						$svg_class->txt_data[1] = $attribs['y'];
+						$critere_style = $attribs;
+						unset($critere_style['x'], $critere_style['y']);
+						$svg_class->svgDefineTxtStyle($critere_style);
+
+					break;
+				}
+
+				//
+				//insertion des path et du style dans le flux de donné general.
+				if (isset($path_cmd) && $path_cmd) {	// mPDF 4.4.003
+					// mPDF 5.0
+					list($prestyle,$poststyle) = $svg_class->svgStyle($path_style, $attribs, strtolower($name));
+					if ($path_style['transformations']) {	// transformation on an element
+						$svg_class->svgWriteString(" q ".$path_style['transformations']. " $prestyle $path_cmd $poststyle" . " Q\n");
+					}
+					else {
+						$svg_class->svgWriteString("$prestyle $path_cmd $poststyle\n");
+					}
+				}
+			}
+
+			function characterData($parser, $data)
+			{
+				global $svg_class;
+				if(isset($svg_class->txt_data[2])) {
+					$svg_class->txt_data[2] .= $data;
+				}
+				else {
+					$svg_class->txt_data[2] = $data;
+				}
+			}
+
+
+			function xml_svg2pdf_end($parser, $name){
+				global $svg_class;
+				switch($name){
+
+					case "g":
+					case "a":
+						$tmp = count($svg_class->svg_style)-1;
+						$current_style = $svg_class->svg_style[$tmp];
+						if ($current_style['transformations']) {
+							$svg_class->svgWriteString(" Q\n");
+						}
+						array_pop($svg_class->svg_style);
+
+						array_pop($svg_class->txt_style);	// mPDF 4.4.003
+
+						break;
+					case 'radialgradient':
+					case 'lineargradient':
+						$last_gradid = '';
+						break;
+					case "text":
+						$path_cmd = $svg_class->svgText();
+						// echo 'path >> '.$path_cmd."<br><br>";
+						// echo "style >> ".$get_style[1]."<br><br>";
+						$svg_class->svgWriteString($path_cmd);
+						// mPDF 4.4.003
+						$tmp = count($svg_class->svg_style)-1;
+						$current_style = $svg_class->svg_style[$tmp];
+						if ($current_style['transformations']) {
+							$svg_class->svgWriteString(" Q\n");
+						}
+						array_pop($svg_class->svg_style);
+
+						break;
+				}
+		 		// mPDF 5.0.039	- Don't output stuff inside <defs>
+				if ($name == 'defs') {
+					$svg_class->inDefs = false;
+				}
+
+			}
+
+		}
+
+		$svg2pdf_xml='';
+		global $svg_class;
+		$svg_class = $this;
+		// mPDF 5.0.039	- Don't output stuff inside <defs>
+		$svg_class->inDefs = false;
+ 		$svg2pdf_xml_parser = xml_parser_create("utf-8");
+		xml_parser_set_option($svg2pdf_xml_parser, XML_OPTION_CASE_FOLDING, false);
+		xml_set_element_handler($svg2pdf_xml_parser, "xml_svg2pdf_start", "xml_svg2pdf_end");
+		xml_set_character_data_handler($svg2pdf_xml_parser, "characterData");
+		xml_parse($svg2pdf_xml_parser, $data);
+		// mPDF 4.4.003
+		if ($this->svg_error) { return false; }
+		else {
+			return array('x'=>$this->svg_info['x']*$this->kp,'y'=>-$this->svg_info['y']*$this->kp,'w'=>$this->svg_info['w']*$this->kp,'h'=>-$this->svg_info['h']*$this->kp,'data'=>$svg_class->svg_string);
+		}
+
+	}
+
+}
+
+// END OF CLASS
+
+
+// mPDF 5.0.040
+function calc_bezier_bbox($start, $c) {
+	$P0 = array($start[0],$start[1]);
+	$P1 = array($c[0],$c[1]);
+	$P2 = array($c[2],$c[3]);
+	$P3 = array($c[4],$c[5]);
+	$bounds = array();
+	$bounds[0][] = $P0[0];
+	$bounds[1][] = $P0[1];
+	$bounds[0][] = $P3[0];
+	$bounds[1][] = $P3[1];
+	for ($i=0;$i<=1;$i++) {
+            $b = 6 * $P0[$i] - 12 * $P1[$i] + 6 * $P2[$i];
+            $a = -3 * $P0[$i] + 9 * $P1[$i] - 9 * $P2[$i] + 3 * $P3[$i];
+            $c = 3 * $P1[$i] - 3 * $P0[$i];
+		if ($a == 0) {
+			if ($b == 0) { continue; }
+			$t = -$c / $b;
+			if ($t>0 && $t<1) {
+				$bounds[$i][] = (pow((1-$t),3) * $P0[$i] + 3 * pow((1-$t),2) * $t * $P1[$i] + 3 * (1-$t) * pow($t,2) * $P2[$i] + pow($t,3) * $P3[$i]);
+			}
+			continue;
+		}
+		$b2ac = pow($b, 2) - 4 * $c * $a;
+		if ($b2ac < 0) { continue; }
+		$t1 = (-$b + sqrt($b2ac))/(2 * $a);
+		if ($t1>0 && $t1<1) { 
+			$bounds[$i][] = (pow((1-$t1),3) * $P0[$i] + 3 * pow((1-$t1),2) * $t1 * $P1[$i] + 3 * (1-$t1) * pow($t1,2) * $P2[$i] + pow($t1,3) * $P3[$i]);
+		}
+		$t2 = (-$b - sqrt($b2ac))/(2 * $a);
+		if ($t2>0 && $t2<1) { 
+			$bounds[$i][] = (pow((1-$t2),3) * $P0[$i] + 3 * pow((1-$t2),2) * $t2 * $P1[$i] + 3 * (1-$t2) * pow($t2,2) * $P2[$i] + pow($t2,3) * $P3[$i]);
+		}
+	}
+	$x = min($bounds[0]);
+	$x2 = max($bounds[0]);
+	$y = min($bounds[1]);
+	$y2 = max($bounds[1]);
+	return array($x, $y, $x2, $y2);
+}
+
+// mPDF 5.0.040
+function _testIntersectCircle($cx, $cy, $cr) {
+	// Tests whether a circle fully encloses a rectangle 0,0,1,1
+	// to see if any further radial gradients need adding (SVG)
+	// If centre of circle is inside 0,0,1,1 square
+	if ($cx >= 0 && $cx <= 1 && $cy >= 0 && $cy <= 1) {
+		$maxd = 1.5;
+	}
+	// distance to four corners
+	else {
+		$d1 = sqrt(pow(($cy-0),2) + pow(($cx-0),2));
+		$d2 = sqrt(pow(($cy-1),2) + pow(($cx-0),2));
+		$d3 = sqrt(pow(($cy-0),2) + pow(($cx-1),2));
+		$d4 = sqrt(pow(($cy-1),2) + pow(($cx-1),2));
+		$maxd = max($d1,$d2,$d3,$d4);
+	}
+	if ($cr < $maxd) { return true; }
+	else { return false; }
+}
+
+// mPDF 5.0.040
+function _testIntersect($x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4) {
+	// Tests whether line (x1, y1) and (x2, y2) [a gradient axis (perpendicular)]
+	// intersects with a specific line segment (x3, y3) and (x4, y4)
+	$a1 = $y2-$y1;
+	$b1 = $x1-$x2;
+	$c1 = $a1*$x1+$b1*$y1;
+	$a2 = $y4-$y3;
+	$b2 = $x3-$x4;
+	$c2 = $a2*$x3+$b2*$y3;
+	$det = $a1*$b2 - $a2*$b1;
+	if($det == 0){	//Lines are parallel
+		return false;
+	}
+	else{
+		$x = ($b2*$c1 - $b1*$c2)/$det;
+		$y = ($a1*$c2 - $a2*$c1)/$det;
+		if ($x >= $x3 && $x <= $x4 && $y >= $y3 && $y <= $y4) { return true; }
+	}
+	return false;
+}
+
+
+
+?>

File diff suppressed because it is too large
+ 42 - 0
sites/all/libraries/MPDF54/classes/tocontents.php


+ 2373 - 0
sites/all/libraries/MPDF54/classes/ttfontsuni.php

@@ -0,0 +1,2373 @@
+<?php
+
+/*******************************************************************************
+* TTFontFile class                                                             *
+*                                                                              *
+* Version:  1.05		                                                       *
+* Date:     2011-07-21                                                         *
+* Author:   Ian Back <ianb@bpm1.com>                                           *
+* License:  LGPL                                                               *
+* Copyright (c) Ian Back, 2010                                                 *
+* This class is based on The ReportLab Open Source PDF library                 *
+* written in Python - http://www.reportlab.com/software/opensource/            *
+* together with ideas from the OpenOffice source code and others.              * 
+* This header must be retained in any redistribution or                        *
+* modification of the file.                                                    *
+*                                                                              *
+*******************************************************************************/
+
+// Define the value used in the "head" table of a created TTF file
+// 0x74727565 "true" for Mac
+// 0x00010000 for Windows
+// Either seems to work for a font embedded in a PDF file
+// when read by Adobe Reader on a Windows PC(!)
+if (!defined('_TTF_MAC_HEADER')) define("_TTF_MAC_HEADER", false);
+
+// Recalculate correct metadata/profiles when making subset fonts (not SIP/SMP)
+// e.g. xMin, xMax, maxNContours
+if (!defined('_RECALC_PROFILE')) define("_RECALC_PROFILE", false);
+
+// TrueType Font Glyph operators
+define("GF_WORDS",(1 << 0));
+define("GF_SCALE",(1 << 3));
+define("GF_MORE",(1 << 5));
+define("GF_XYSCALE",(1 << 6));
+define("GF_TWOBYTWO",(1 << 7));
+
+
+
+class TTFontFile {
+
+var $panose;
+var $maxUni;
+var $sFamilyClass;
+var $sFamilySubClass;
+var $sipset;
+var $smpset;
+var $_pos;
+var $numTables;
+var $searchRange;
+var $entrySelector;
+var $rangeShift;
+var $tables;
+var $otables;
+var $filename;
+var $fh;
+var $glyphPos;
+var $charToGlyph;
+var $ascent;
+var $descent;
+var $name;
+var $familyName;
+var $styleName;
+var $fullName;
+var $uniqueFontID;
+var $unitsPerEm;
+var $bbox;
+var $capHeight;
+var $stemV;
+var $italicAngle;
+var $flags;
+var $underlinePosition;
+var $underlineThickness;
+var $charWidths;
+var $defaultWidth;
+var $maxStrLenRead;
+var $numTTCFonts;
+var $TTCFonts;
+var $maxUniChar;
+var $kerninfo;
+
+	function TTFontFile() {
+		$this->maxStrLenRead = 200000;	// Maximum size of glyf table to read in as string (otherwise reads each glyph from file)
+	}
+
+
+	function getMetrics($file, $TTCfontID=0, $debug=false, $BMPonly=false, $kerninfo=false) {
+		$this->filename = $file;
+		$this->fh = fopen($file,'rb') or die('Can\'t open file ' . $file);
+		$this->_pos = 0;
+		$this->charWidths = '';
+		$this->glyphPos = array();
+		$this->charToGlyph = array();
+		$this->tables = array();
+		$this->otables = array();
+		$this->kerninfo = array();
+		$this->ascent = 0;
+		$this->descent = 0;
+		$this->numTTCFonts = 0;
+		$this->TTCFonts = array();
+		$this->version = $version = $this->read_ulong();
+		$this->panose = array();
+		if ($version==0x4F54544F) 
+			die("Postscript outlines are not supported");
+		if ($version==0x74746366 && !$TTCfontID) 
+			die("ERROR - You must define the TTCfontID for a TrueType Collection in config_fonts.php (". $file.")");
+		if (!in_array($version, array(0x00010000,0x74727565)) && !$TTCfontID)
+			die("Not a TrueType font: version=".$version);
+		if ($TTCfontID > 0) {
+			$this->version = $version = $this->read_ulong();	// TTC Header version now
+			if (!in_array($version, array(0x00010000,0x00020000)))
+				die("ERROR - Error parsing TrueType Collection: version=".$version." - " . $file);
+			$this->numTTCFonts = $this->read_ulong();
+			for ($i=1; $i<=$this->numTTCFonts; $i++) {
+	      	      $this->TTCFonts[$i]['offset'] = $this->read_ulong();
+			}
+			$this->seek($this->TTCFonts[$TTCfontID]['offset']);
+			$this->version = $version = $this->read_ulong();	// TTFont version again now
+		}
+		$this->readTableDirectory($debug);
+		$this->extractInfo($debug, $BMPonly, $kerninfo); 
+		fclose($this->fh);
+	}
+
+
+	function readTableDirectory($debug=false) {
+	    $this->numTables = $this->read_ushort();
+            $this->searchRange = $this->read_ushort();
+            $this->entrySelector = $this->read_ushort();
+            $this->rangeShift = $this->read_ushort();
+            $this->tables = array();	
+            for ($i=0;$i<$this->numTables;$i++) {
+                $record = array();
+                $record['tag'] = $this->read_tag();
+                $record['checksum'] = array($this->read_ushort(),$this->read_ushort());
+                $record['offset'] = $this->read_ulong();
+                $record['length'] = $this->read_ulong();
+                $this->tables[$record['tag']] = $record;
+		}
+		if ($debug) $this->checksumTables();
+	}
+
+	function checksumTables() {
+		// Check the checksums for all tables
+		foreach($this->tables AS $t) {
+		  if ($t['length'] > 0 && $t['length'] < $this->maxStrLenRead) {	// 1.02
+            	$table = $this->get_chunk($t['offset'], $t['length']);
+            	$checksum = $this->calcChecksum($table);
+            	if ($t['tag'] == 'head') {
+				$up = unpack('n*', substr($table,8,4));
+				$adjustment[0] = $up[1];
+				$adjustment[1] = $up[2];
+            		$checksum = $this->sub32($checksum, $adjustment);
+			}
+            	$xchecksum = $t['checksum'];
+            	if ($xchecksum != $checksum) 
+            	    die(sprintf('TTF file "%s": invalid checksum %s table: %s (expected %s)', $this->filename,dechex($checksum[0]).dechex($checksum[1]),$t['tag'],dechex($xchecksum[0]).dechex($xchecksum[1])));
+		  }
+		}
+	}
+
+	function sub32($x, $y) {
+		$xlo = $x[1];
+		$xhi = $x[0];
+		$ylo = $y[1];
+		$yhi = $y[0];
+		if ($ylo > $xlo) { $xlo += 1 << 16; $yhi += 1; }
+		$reslo = $xlo-$ylo;
+		if ($yhi > $xhi) { $xhi += 1 << 16;  }
+		$reshi = $xhi-$yhi;
+		$reshi = $reshi & 0xFFFF;
+		return array($reshi, $reslo);
+	}
+
+	function calcChecksum($data)  {
+		if (strlen($data) % 4) { $data .= str_repeat("\0",(4-(strlen($data) % 4))); }
+		$len = strlen($data);
+		$hi=0x0000;
+		$lo=0x0000;
+		for($i=0;$i<$len;$i+=4) {
+			$hi += (ord($data[$i])<<8) + ord($data[$i+1]);
+			$lo += (ord($data[$i+2])<<8) + ord($data[$i+3]);
+			$hi += ($lo >> 16) & 0xFFFF;	// mPDF 5.3.07
+			$lo = $lo & 0xFFFF;
+		}
+		return array($hi, $lo);
+	}
+
+	function get_table_pos($tag) {
+		$offset = $this->tables[$tag]['offset'];
+		$length = $this->tables[$tag]['length'];
+		return array($offset, $length);
+	}
+
+	function seek($pos) {
+		$this->_pos = $pos;
+		fseek($this->fh,$this->_pos);
+	}
+
+	function skip($delta) {
+		$this->_pos = $this->_pos + $delta;
+	//	fseek($this->fh,$this->_pos);
+		fseek($this->fh,$delta,SEEK_CUR);	// mPDF 5.3.19
+	}
+
+	function seek_table($tag, $offset_in_table = 0) {
+		$tpos = $this->get_table_pos($tag);
+		$this->_pos = $tpos[0] + $offset_in_table;
+		fseek($this->fh, $this->_pos);
+		return $this->_pos;
+	}
+
+	function read_tag() {
+		$this->_pos += 4;
+		return fread($this->fh,4);
+	}
+
+	function read_short() {
+		$this->_pos += 2;
+		$s = fread($this->fh,2);
+		$a = (ord($s[0])<<8) + ord($s[1]);
+		if ($a & (1 << 15) ) { 
+			$a = ($a - (1 << 16)); 
+		}
+		return $a;
+	}
+
+	function unpack_short($s) {
+		$a = (ord($s[0])<<8) + ord($s[1]);
+		if ($a & (1 << 15) ) { 
+			$a = ($a - (1 << 16)); 
+		}
+		return $a;
+	}
+
+	function read_ushort() {
+		$this->_pos += 2;
+		$s = fread($this->fh,2);
+		return (ord($s[0])<<8) + ord($s[1]);
+	}
+
+	function read_ulong() {
+		$this->_pos += 4;
+		$s = fread($this->fh,4);
+		// if large uInt32 as an integer, PHP converts it to -ve
+		return (ord($s[0])*16777216) + (ord($s[1])<<16) + (ord($s[2])<<8) + ord($s[3]); // 	16777216  = 1<<24
+	}
+
+	function get_ushort($pos) {
+		fseek($this->fh,$pos);
+		$s = fread($this->fh,2);
+		return (ord($s[0])<<8) + ord($s[1]);
+	}
+
+	function get_ulong($pos) {
+		fseek($this->fh,$pos);
+		$s = fread($this->fh,4);
+		// iF large uInt32 as an integer, PHP converts it to -ve
+		return (ord($s[0])*16777216) + (ord($s[1])<<16) + (ord($s[2])<<8) + ord($s[3]); // 	16777216  = 1<<24
+	}
+
+	function pack_short($val) {
+		if ($val<0) { 
+			$val = abs($val);
+			$val = ~$val;
+			$val += 1;
+		}
+		return pack("n",$val); 
+	}
+
+	function splice($stream, $offset, $value) {
+		return substr($stream,0,$offset) . $value . substr($stream,$offset+strlen($value));
+	}
+
+	function _set_ushort($stream, $offset, $value) {
+		$up = pack("n", $value);
+		return $this->splice($stream, $offset, $up);
+	}
+
+	// mPDF 5.0
+	function _set_short($stream, $offset, $val) {
+		if ($val<0) { 
+			$val = abs($val);
+			$val = ~$val;
+			$val += 1;
+		}
+		$up = pack("n",$val); 
+		return $this->splice($stream, $offset, $up);
+	}
+
+	function get_chunk($pos, $length) {
+		fseek($this->fh,$pos);
+		if ($length <1) { return ''; }
+		return (fread($this->fh,$length));
+	}
+
+	function get_table($tag) {
+		list($pos, $length) = $this->get_table_pos($tag);
+		if ($length == 0) { return ''; }
+		fseek($this->fh,$pos);
+		return (fread($this->fh,$length));
+	}
+
+	function add($tag, $data) {
+		if ($tag == 'head') {
+			$data = $this->splice($data, 8, "\0\0\0\0");
+		}
+		$this->otables[$tag] = $data;
+	}
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+	function getCTG($file, $TTCfontID=0, $debug=false) {
+		$this->filename = $file;
+		$this->fh = fopen($file,'rb') or die('Can\'t open file ' . $file);
+		$this->_pos = 0;
+		$this->charWidths = '';
+		$this->glyphPos = array();
+		$this->charToGlyph = array();
+		$this->tables = array();
+		$this->numTTCFonts = 0;
+		$this->TTCFonts = array();
+		$this->skip(4);
+		if ($TTCfontID > 0) {
+			$this->version = $version = $this->read_ulong();	// TTC Header version now
+			if (!in_array($version, array(0x00010000,0x00020000)))
+				die("ERROR - Error parsing TrueType Collection: version=".$version." - " . $file);
+			$this->numTTCFonts = $this->read_ulong();
+			for ($i=1; $i<=$this->numTTCFonts; $i++) {
+	      	      $this->TTCFonts[$i]['offset'] = $this->read_ulong();
+			}
+			$this->seek($this->TTCFonts[$TTCfontID]['offset']);
+			$this->version = $version = $this->read_ulong();	// TTFont version again now
+		}
+		$this->readTableDirectory($debug);
+
+
+		// cmap - Character to glyph index mapping table
+		$cmap_offset = $this->seek_table("cmap");
+		$this->skip(2);
+		$cmapTableCount = $this->read_ushort();
+		$unicode_cmap_offset = 0;
+		for ($i=0;$i<$cmapTableCount;$i++) {
+			$platformID = $this->read_ushort();
+			$encodingID = $this->read_ushort();
+			$offset = $this->read_ulong();
+			$save_pos = $this->_pos;
+			if ($platformID == 3 && $encodingID == 1) { // Microsoft, Unicode
+				$format = $this->get_ushort($cmap_offset + $offset);
+				if ($format == 4) {
+					$unicode_cmap_offset = $cmap_offset + $offset;
+					break;
+				}
+			}
+			else if ($platformID == 0) { // Unicode -- assume all encodings are compatible
+				$format = $this->get_ushort($cmap_offset + $offset);
+				if ($format == 4) {
+					$unicode_cmap_offset = $cmap_offset + $offset;
+					break;
+				}
+			}
+			$this->seek($save_pos );
+		}
+
+		$glyphToChar = array();
+		$charToGlyph = array();
+		$this->getCMAP4($unicode_cmap_offset, $glyphToChar, $charToGlyph );
+
+		fclose($this->fh);
+		return ($charToGlyph);
+	}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+	function getTTCFonts($file) {
+		$this->filename = $file;
+		$this->fh = fopen($file,'rb');
+		if (!$this->fh) { return ('ERROR - Can\'t open file ' . $file); }
+		$this->numTTCFonts = 0;
+		$this->TTCFonts = array();
+		$this->version = $version = $this->read_ulong();
+		if ($version==0x74746366) {
+			$this->version = $version = $this->read_ulong();	// TTC Header version now
+			if (!in_array($version, array(0x00010000,0x00020000)))
+				return("ERROR - Error parsing TrueType Collection: version=".$version." - " . $file);
+		}
+		else {
+			return("ERROR - Not a TrueType Collection: version=".$version." - " . $file);
+		}
+		$this->numTTCFonts = $this->read_ulong();
+		for ($i=1; $i<=$this->numTTCFonts; $i++) {
+	            $this->TTCFonts[$i]['offset'] = $this->read_ulong();
+		}
+	}
+
+
+	// Used to get font information from files in directory for mPDF config
+	function extractCoreInfo($file, $TTCfontID=0) {
+		$this->filename = $file;
+		$this->fh = fopen($file,'rb');
+		if (!$this->fh) { return ('ERROR - Can\'t open file ' . $file); }
+		$this->_pos = 0;
+		$this->charWidths = '';
+		$this->glyphPos = array();
+		$this->charToGlyph = array();
+		$this->tables = array();
+		$this->otables = array();
+		$this->ascent = 0;
+		$this->descent = 0;
+		$this->numTTCFonts = 0;
+		$this->TTCFonts = array();
+		$this->version = $version = $this->read_ulong();
+		$this->panose = array();	// mPDF 5.0
+		if ($version==0x4F54544F) 
+			return("ERROR - NOT ADDED as Postscript outlines are not supported - " . $file);
+		if ($version==0x74746366) {
+			if ($TTCfontID > 0) {
+				$this->version = $version = $this->read_ulong();	// TTC Header version now
+				if (!in_array($version, array(0x00010000,0x00020000)))
+					return("ERROR - NOT ADDED as Error parsing TrueType Collection: version=".$version." - " . $file);
+			}
+			else return("ERROR - Error parsing TrueType Collection - " . $file);
+			$this->numTTCFonts = $this->read_ulong();
+			for ($i=1; $i<=$this->numTTCFonts; $i++) {
+	      	      $this->TTCFonts[$i]['offset'] = $this->read_ulong();
+			}
+			$this->seek($this->TTCFonts[$TTCfontID]['offset']);
+			$this->version = $version = $this->read_ulong();	// TTFont version again now
+			$this->readTableDirectory(false);
+		}
+		else {
+			if (!in_array($version, array(0x00010000,0x74727565)))
+				return("ERROR - NOT ADDED as Not a TrueType font: version=".$version." - " . $file);
+			$this->readTableDirectory(false);
+		}
+
+/* Included for testing...
+		$cmap_offset = $this->seek_table("cmap");
+		$this->skip(2);
+		$cmapTableCount = $this->read_ushort();
+		$unicode_cmap_offset = 0;
+		for ($i=0;$i<$cmapTableCount;$i++) {
+			$x[$i]['platformId'] = $this->read_ushort();
+			$x[$i]['encodingId'] = $this->read_ushort();
+			$x[$i]['offset'] = $this->read_ulong();
+			$save_pos = $this->_pos;
+			$x[$i]['format'] = $this->get_ushort($cmap_offset + $x[$i]['offset'] );
+			$this->seek($save_pos );
+		}
+		print_r($x); exit;
+*/
+		///////////////////////////////////
+		// name - Naming table
+		///////////////////////////////////
+			$name_offset = $this->seek_table("name");
+			$format = $this->read_ushort();
+			if ($format != 0 && $format != 1)	// mPDF 5.3.73
+				return("ERROR - NOT ADDED as Unknown name table format ".$format." - " . $file);
+			$numRecords = $this->read_ushort();
+			$string_data_offset = $name_offset + $this->read_ushort();
+			$names = array(1=>'',2=>'',3=>'',4=>'',6=>'');
+			$K = array_keys($names);
+			$nameCount = count($names);
+			for ($i=0;$i<$numRecords; $i++) {
+				$platformId = $this->read_ushort();
+				$encodingId = $this->read_ushort();
+				$languageId = $this->read_ushort();
+				$nameId = $this->read_ushort();
+				$length = $this->read_ushort();
+				$offset = $this->read_ushort();
+				if (!in_array($nameId,$K)) continue;
+				$N = '';
+				if ($platformId == 3 && $encodingId == 1 && $languageId == 0x409) { // Microsoft, Unicode, US English, PS Name
+					$opos = $this->_pos;
+					$this->seek($string_data_offset + $offset);
+					if ($length % 2 != 0)
+						$length += 1;
+					$length /= 2;
+					$N = '';
+					while ($length > 0) {
+						$char = $this->read_ushort();
+						$N .= (chr($char));
+						$length -= 1;
+					}
+					$this->_pos = $opos;
+					$this->seek($opos);
+				}
+				else if ($platformId == 1 && $encodingId == 0 && $languageId == 0) { // Macintosh, Roman, English, PS Name
+					$opos = $this->_pos;
+					$N = $this->get_chunk($string_data_offset + $offset, $length);
+					$this->_pos = $opos;
+					$this->seek($opos);
+				}
+				if ($N && $names[$nameId]=='') {
+					$names[$nameId] = $N;
+					$nameCount -= 1;
+					if ($nameCount==0) break;
+				}
+			}
+			if ($names[6])
+				$psName = preg_replace('/ /','-',$names[6]);
+			else if ($names[4])
+				$psName = preg_replace('/ /','-',$names[4]);
+			else if ($names[1])
+				$psName = preg_replace('/ /','-',$names[1]);
+			else
+				$psName = '';
+			if (!$names[1] && !$psName)
+				return("ERROR - NOT ADDED as Could not find valid font name - " . $file);
+			$this->name = $psName;
+			if ($names[1]) { $this->familyName = $names[1]; } else { $this->familyName = $psName; }
+			if ($names[2]) { $this->styleName = $names[2]; } else { $this->styleName = 'Regular'; }
+
+		///////////////////////////////////
+		// head - Font header table
+		///////////////////////////////////
+		$this->seek_table("head");
+		$ver_maj = $this->read_ushort();
+		$ver_min = $this->read_ushort();
+		if ($ver_maj != 1)
+			return('ERROR - NOT ADDED as Unknown head table version '. $ver_maj .'.'. $ver_min." - " . $file);
+		$this->fontRevision = $this->read_ushort() . $this->read_ushort();
+		$this->skip(4);
+		$magic = $this->read_ulong();
+		if ($magic != 0x5F0F3CF5) 
+			return('ERROR - NOT ADDED as Invalid head table magic ' .$magic." - " . $file);
+		$this->skip(2);
+		$this->unitsPerEm = $unitsPerEm = $this->read_ushort();
+		$scale = 1000 / $unitsPerEm;
+		$this->skip(24);
+		$macStyle = $this->read_short();
+		$this->skip(4);
+		$indexLocFormat = $this->read_short();
+
+		///////////////////////////////////
+		// OS/2 - OS/2 and Windows metrics table
+		///////////////////////////////////
+		$sFamily = '';
+		$panose = '';
+		$fsSelection = '';
+		if (isset($this->tables["OS/2"])) {
+			$this->seek_table("OS/2");
+			$this->skip(30);
+			$sF = $this->read_short();
+			$sFamily = ($sF >> 8);
+			$this->_pos += 10;  //PANOSE = 10 byte length
+			$panose = fread($this->fh,10);
+			$this->panose = array();
+			for ($p=0;$p<strlen($panose);$p++) { $this->panose[] = ord($panose[$p]); }
+			$this->skip(20); 
+			$fsSelection = $this->read_short();
+		}
+
+		///////////////////////////////////
+		// post - PostScript table
+		///////////////////////////////////
+		$this->seek_table("post");
+		$this->skip(4); 
+		$this->italicAngle = $this->read_short() + $this->read_ushort() / 65536.0;
+		$this->skip(4);
+		$isFixedPitch = $this->read_ulong();
+
+
+
+		///////////////////////////////////
+		// cmap - Character to glyph index mapping table
+		///////////////////////////////////
+		$cmap_offset = $this->seek_table("cmap");
+		$this->skip(2);
+		$cmapTableCount = $this->read_ushort();
+		$unicode_cmap_offset = 0;
+		for ($i=0;$i<$cmapTableCount;$i++) {
+			$platformID = $this->read_ushort();
+			$encodingID = $this->read_ushort();
+			$offset = $this->read_ulong();
+			$save_pos = $this->_pos;
+			if (($platformID == 3 && $encodingID == 1) || $platformID == 0) { // Microsoft, Unicode
+				$format = $this->get_ushort($cmap_offset + $offset);
+				if ($format == 4) {
+					if (!$unicode_cmap_offset) $unicode_cmap_offset = $cmap_offset + $offset;
+				}
+			}
+			else if ((($platformID == 3 && $encodingID == 10) || $platformID == 0)) { // Microsoft, Unicode Format 12 table HKCS
+				$format = $this->get_ushort($cmap_offset + $offset);
+				if ($format == 12) {
+					$unicode_cmap_offset = $cmap_offset + $offset;
+					break;
+				}
+			}
+			$this->seek($save_pos );
+		}
+
+		if (!$unicode_cmap_offset)
+			return('ERROR - Font ('.$this->filename .') NOT ADDED as it is not Unicode encoded, and cannot be used by mPDF');
+
+		$rtl = false;
+		$indic = false;
+		$cjk = false;
+		$sip = false;
+		$smp = false;
+
+		// Format 12 CMAP does characters above Unicode BMP i.e. some HKCS characters U+20000 and above
+		if ($format == 12) {
+			$this->seek($unicode_cmap_offset + 4);
+			$length = $this->read_ulong();
+			$limit = $unicode_cmap_offset + $length;
+			$this->skip(4);
+			$nGroups = $this->read_ulong();
+			for($i=0; $i<$nGroups ; $i++) { 
+				$startCharCode = $this->read_ulong(); 
+				$endCharCode = $this->read_ulong(); 
+				$startGlyphCode = $this->read_ulong(); 
+				if (($endCharCode > 0x20000 && $endCharCode < 0x2A6DF) || ($endCharCode > 0x2F800 && $endCharCode < 0x2FA1F)) {
+					$sip = true; 
+				}
+				else if ($endCharCode > 0x10000 && $endCharCode < 0x1FFFF) {
+					$smp = true; 
+				}
+				else if (($endCharCode > 0x0590 && $endCharCode < 0x077F) || ($endCharCode > 0xFE70 && $endCharCode < 0xFEFF) || ($endCharCode > 0xFB50 && $endCharCode < 0xFDFF)) {
+					$rtl = true; 
+				}
+				else if ($endCharCode > 0x0900 && $endCharCode < 0x0DFF) {
+					$indic = true; 
+				}
+				else if (($endCharCode > 0x2E80 && $endCharCode < 0x4DC0) || ($endCharCode > 0x4E00 && $endCharCode < 0xA4CF) || ($endCharCode > 0xAC00 && $endCharCode < 0xD7AF) || ($endCharCode > 0xF900 && $endCharCode < 0xFAFF) || ($endCharCode > 0xFE30 && $endCharCode < 0xFE4F)) {
+					$cjk = true; 
+				}
+			}
+		}
+
+		else {	// Format 4 CMap
+			$this->seek($unicode_cmap_offset + 2);
+			$length = $this->read_ushort();
+			$limit = $unicode_cmap_offset + $length;
+			$this->skip(2);
+
+			$segCount = $this->read_ushort() / 2;
+			$this->skip(6);
+			$endCount = array();
+			for($i=0; $i<$segCount; $i++) { $endCount[] = $this->read_ushort(); }
+			$this->skip(2);
+			$startCount = array();
+			for($i=0; $i<$segCount; $i++) { $startCount[] = $this->read_ushort(); }
+			$idDelta = array();
+			for($i=0; $i<$segCount; $i++) { $idDelta[] = $this->read_short(); }		// ???? was unsigned short
+			$idRangeOffset_start = $this->_pos;
+			$idRangeOffset = array();
+			for($i=0; $i<$segCount; $i++) { $idRangeOffset[] = $this->read_ushort(); }
+
+			for ($n=0;$n<$segCount;$n++) {
+				if (($endCount[$n] > 0x0590 && $endCount[$n] < 0x077F) || ($endCount[$n] > 0xFE70 && $endCount[$n] < 0xFEFF) || ($endCount[$n] > 0xFB50 && $endCount[$n] < 0xFDFF)) {
+					$rtl = true; 
+				}
+				else if ($endCount[$n] > 0x0900 && $endCount[$n] < 0x0DFF) {
+					$indic = true; 
+				}
+				else if (($endCount[$n] > 0x2E80 && $endCount[$n] < 0x4DC0) || ($endCount[$n] > 0x4E00 && $endCount[$n] < 0xA4CF) || ($endCount[$n] > 0xAC00 && $endCount[$n] < 0xD7AF) || ($endCount[$n] > 0xF900 && $endCount[$n] < 0xFAFF) || ($endCount[$n] > 0xFE30 && $endCount[$n] < 0xFE4F)) {
+					$cjk = true; 
+				}
+			}
+		}
+
+
+
+		$bold = false; 
+		$italic = false; 
+		$ftype = '';
+		if ($macStyle & (1 << 0)) { $bold = true; }	// bit 0 bold
+		else if ($fsSelection & (1 << 5)) { $bold = true; }	// 5 	BOLD 	Characters are emboldened
+
+		if ($macStyle & (1 << 1)) { $italic = true; }	// bit 1 italic
+		else if ($fsSelection & (1 << 0)) { $italic = true; }	// 0 	ITALIC 	Font contains Italic characters, otherwise they are upright
+		else if ($this->italicAngle <> 0) { $italic = true; }
+
+		if ($isFixedPitch ) { $ftype = 'mono'; }
+		else if ($sFamily >0 && $sFamily <8) { $ftype = 'serif'; }
+		else if ($sFamily ==8) { $ftype = 'sans'; }
+		else if ($sFamily ==10) { $ftype = 'cursive'; }
+		// Use PANOSE
+		if ($panose) { 
+			$bFamilyType=ord($panose[0]); 
+			if ($bFamilyType==2) {
+				$bSerifStyle=ord($panose[1]); 
+				if (!$ftype) { 
+					if ($bSerifStyle>1 && $bSerifStyle<11) { $ftype = 'serif'; }
+					else if ($bSerifStyle>10) { $ftype = 'sans'; }
+				}
+				$bProportion=ord($panose[3]);
+				if ($bProportion==9 || $bProportion==1) { $ftype = 'mono'; }	// ==1 i.e. No Fit needed for OCR-a and -b
+			}
+			else if ($bFamilyType==3) {
+				$ftype = 'cursive'; 
+			}
+		}
+
+		fclose($this->fh);
+		return array($this->familyName, $bold, $italic, $ftype, $TTCfontID, $rtl, $indic, $cjk, $sip, $smp);
+	}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+	function extractInfo($debug=false, $BMPonly=false, $kerninfo=false) {
+		///////////////////////////////////
+		// name - Naming table
+		///////////////////////////////////
+			$this->panose = array();
+			$this->sFamilyClass = 0;
+			$this->sFamilySubClass = 0;
+
+/* Test purposes - displays table of names 
+			$name_offset = $this->seek_table("name");
+			$format = $this->read_ushort();
+			if ($format != 0 && $format != 1)	// mPDF 5.3.73
+				die("Unknown name table format ".$format);
+			$numRecords = $this->read_ushort();
+			$string_data_offset = $name_offset + $this->read_ushort();
+			for ($i=0;$i<$numRecords; $i++) {
+				$x[$i]['platformId'] = $this->read_ushort();
+				$x[$i]['encodingId'] = $this->read_ushort();
+				$x[$i]['languageId'] = $this->read_ushort();
+				$x[$i]['nameId'] = $this->read_ushort();
+				$x[$i]['length'] = $this->read_ushort();
+				$x[$i]['offset'] = $this->read_ushort();
+
+				$N = '';
+				if ($x[$i]['platformId'] == 1 && $x[$i]['encodingId'] == 0 && $x[$i]['languageId'] == 0) { // Roman
+					$opos = $this->_pos;
+					$N = $this->get_chunk($string_data_offset + $x[$i]['offset'] , $x[$i]['length'] );
+					$this->_pos = $opos;
+					$this->seek($opos);
+				}
+				else { 	// Unicode
+					$opos = $this->_pos;
+					$this->seek($string_data_offset + $x[$i]['offset'] );
+					$length = $x[$i]['length'] ;
+					if ($length % 2 != 0)
+						$length -= 1;
+				//		die("PostScript name is UTF-16BE string of odd length");
+					$length /= 2;
+					$N = '';
+					while ($length > 0) {
+						$char = $this->read_ushort();
+						$N .= (chr($char));
+						$length -= 1;
+					}
+					$this->_pos = $opos;
+					$this->seek($opos);
+				}
+				$x[$i]['names'][$nameId] = $N;
+			}
+			print_r($x); exit;
+*/
+
+			$name_offset = $this->seek_table("name");
+			$format = $this->read_ushort();
+			if ($format != 0 && $format != 1)		// mPDF 5.3.73
+				die("Unknown name table format ".$format);
+			$numRecords = $this->read_ushort();
+			$string_data_offset = $name_offset + $this->read_ushort();
+			$names = array(1=>'',2=>'',3=>'',4=>'',6=>'');
+			$K = array_keys($names);
+			$nameCount = count($names);
+			for ($i=0;$i<$numRecords; $i++) {
+				$platformId = $this->read_ushort();
+				$encodingId = $this->read_ushort();
+				$languageId = $this->read_ushort();
+				$nameId = $this->read_ushort();
+				$length = $this->read_ushort();
+				$offset = $this->read_ushort();
+				if (!in_array($nameId,$K)) continue;
+				$N = '';
+				if ($platformId == 3 && $encodingId == 1 && $languageId == 0x409) { // Microsoft, Unicode, US English, PS Name
+					$opos = $this->_pos;
+					$this->seek($string_data_offset + $offset);
+					if ($length % 2 != 0)
+						die("PostScript name is UTF-16BE string of odd length");
+					$length /= 2;
+					$N = '';
+					while ($length > 0) {
+						$char = $this->read_ushort();
+						$N .= (chr($char));
+						$length -= 1;
+					}
+					$this->_pos = $opos;
+					$this->seek($opos);
+				}
+				else if ($platformId == 1 && $encodingId == 0 && $languageId == 0) { // Macintosh, Roman, English, PS Name
+					$opos = $this->_pos;
+					$N = $this->get_chunk($string_data_offset + $offset, $length);
+					$this->_pos = $opos;
+					$this->seek($opos);
+				}
+				if ($N && $names[$nameId]=='') {
+					$names[$nameId] = $N;
+					$nameCount -= 1;
+					if ($nameCount==0) break;
+				}
+			}
+			if ($names[6])
+	//			$psName = preg_replace('/ /','-',$names[6]);	// mPDF 5.2.03
+				$psName = $names[6];
+			else if ($names[4])
+				$psName = preg_replace('/ /','-',$names[4]);
+			else if ($names[1])
+				$psName = preg_replace('/ /','-',$names[1]);
+			else
+				$psName = '';
+			if (!$psName)
+				die("Could not find PostScript font name: ".$this->filename);
+			if ($debug) {
+			   for ($i=0;$i<count($psName);$i++) {	// mPDF 5.3.07
+				$c = $psName[$i];
+				$oc = ord($c);
+				if ($oc>126 || strpos(' [](){}<>/%',$c)!==false)
+					die("psName=".$psName." contains invalid character ".$c." ie U+".ord(c));
+			   }
+			}
+			$this->name = $psName;
+			if ($names[1]) { $this->familyName = $names[1]; } else { $this->familyName = $psName; }
+			if ($names[2]) { $this->styleName = $names[2]; } else { $this->styleName = 'Regular'; }
+			if ($names[4]) { $this->fullName = $names[4]; } else { $this->fullName = $psName; }
+			if ($names[3]) { $this->uniqueFontID = $names[3]; } else { $this->uniqueFontID = $psName; }
+
+			if ($names[6]) { $this->fullName = $names[6]; }	// mPDF 5.2.03
+
+		///////////////////////////////////
+		// head - Font header table
+		///////////////////////////////////
+		$this->seek_table("head");
+		if ($debug) { 
+			$ver_maj = $this->read_ushort();
+			$ver_min = $this->read_ushort();
+			if ($ver_maj != 1)
+				die('Unknown head table version '. $ver_maj .'.'. $ver_min);
+			$this->fontRevision = $this->read_ushort() . $this->read_ushort();
+
+			$this->skip(4);
+			$magic = $this->read_ulong();
+			if ($magic != 0x5F0F3CF5) 
+				die('Invalid head table magic ' .$magic);
+			$this->skip(2);
+		}
+		else {
+			$this->skip(18); 
+		}
+		$this->unitsPerEm = $unitsPerEm = $this->read_ushort();
+		$scale = 1000 / $unitsPerEm;
+		$this->skip(16);
+		$xMin = $this->read_short();
+		$yMin = $this->read_short();
+		$xMax = $this->read_short();
+		$yMax = $this->read_short();
+		$this->bbox = array(($xMin*$scale), ($yMin*$scale), ($xMax*$scale), ($yMax*$scale));
+		$this->skip(3*2);
+		$indexToLocFormat = $this->read_ushort();
+		$glyphDataFormat = $this->read_ushort();
+		if ($glyphDataFormat != 0)
+			die('Unknown glyph data format '.$glyphDataFormat);
+
+		///////////////////////////////////
+		// hhea metrics table
+		///////////////////////////////////
+		// ttf2t1 seems to use this value rather than the one in OS/2 - so put in for compatibility
+		if (isset($this->tables["hhea"])) {
+			$this->seek_table("hhea");
+			$this->skip(4);
+			$hheaAscender = $this->read_short();
+			$hheaDescender = $this->read_short();
+			$this->ascent = ($hheaAscender *$scale);
+			$this->descent = ($hheaDescender *$scale);
+		}
+
+		///////////////////////////////////
+		// OS/2 - OS/2 and Windows metrics table
+		///////////////////////////////////
+		if (isset($this->tables["OS/2"])) {
+			$this->seek_table("OS/2");
+			$version = $this->read_ushort();
+			$this->skip(2);
+			$usWeightClass = $this->read_ushort();
+			$this->skip(2);
+			$fsType = $this->read_ushort();
+			if ($fsType == 0x0002 || ($fsType & 0x0300) != 0) {
+				global $overrideTTFFontRestriction;
+				if (!$overrideTTFFontRestriction) die('ERROR - Font file '.$this->filename.' cannot be embedded due to copyright restrictions.');
+				$this->restrictedUse = true;
+			}
+			$this->skip(20);
+			$sF = $this->read_short();
+			$this->sFamilyClass = ($sF >> 8);
+			$this->sFamilySubClass = ($sF & 0xFF);
+			$this->_pos += 10;  //PANOSE = 10 byte length
+			$panose = fread($this->fh,10);
+			$this->panose = array();
+			for ($p=0;$p<strlen($panose);$p++) { $this->panose[] = ord($panose[$p]); }
+			$this->skip(26);
+			$sTypoAscender = $this->read_short();
+			$sTypoDescender = $this->read_short();
+			if (!$this->ascent) $this->ascent = ($sTypoAscender*$scale);
+			if (!$this->descent) $this->descent = ($sTypoDescender*$scale);
+			if ($version > 1) {
+				$this->skip(16);
+				$sCapHeight = $this->read_short();
+				$this->capHeight = ($sCapHeight*$scale);
+			}
+			else {
+				$this->capHeight = $this->ascent;
+			}
+		}
+		else {
+			$usWeightClass = 500;
+			if (!$this->ascent) $this->ascent = ($yMax*$scale);
+			if (!$this->descent) $this->descent = ($yMin*$scale);
+			$this->capHeight = $this->ascent;
+		}
+		$this->stemV = 50 + intval(pow(($usWeightClass / 65.0),2));
+
+		///////////////////////////////////
+		// post - PostScript table
+		///////////////////////////////////
+		$this->seek_table("post");
+		if ($debug) { 
+			$ver_maj = $this->read_ushort();
+			$ver_min = $this->read_ushort();
+			if ($ver_maj <1 || $ver_maj >4) 
+				die('Unknown post table version '.$ver_maj);
+		}
+		else {
+			$this->skip(4); 
+		}
+		$this->italicAngle = $this->read_short() + $this->read_ushort() / 65536.0;
+		$this->underlinePosition = $this->read_short() * $scale;
+		$this->underlineThickness = $this->read_short() * $scale;
+		$isFixedPitch = $this->read_ulong();
+
+		$this->flags = 4;
+
+		if ($this->italicAngle!= 0) 
+			$this->flags = $this->flags | 64;
+		if ($usWeightClass >= 600)
+			$this->flags = $this->flags | 262144;
+		if ($isFixedPitch)
+			$this->flags = $this->flags | 1;
+
+		///////////////////////////////////
+		// hhea - Horizontal header table
+		///////////////////////////////////
+		$this->seek_table("hhea");
+		if ($debug) { 
+			$ver_maj = $this->read_ushort();
+			$ver_min = $this->read_ushort();
+			if ($ver_maj != 1)
+				die('Unknown hhea table version '.$ver_maj);
+			$this->skip(28);
+		}
+		else {
+			$this->skip(32); 
+		}
+		$metricDataFormat = $this->read_ushort();
+		if ($metricDataFormat != 0)
+			die('Unknown horizontal metric data format '.$metricDataFormat);
+		$numberOfHMetrics = $this->read_ushort();
+		if ($numberOfHMetrics == 0) 
+			die('Number of horizontal metrics is 0');
+
+		///////////////////////////////////
+		// maxp - Maximum profile table
+		///////////////////////////////////
+		$this->seek_table("maxp");
+		if ($debug) { 
+			$ver_maj = $this->read_ushort();
+			$ver_min = $this->read_ushort();
+			if ($ver_maj != 1)
+				die('Unknown maxp table version '.$ver_maj);
+		}
+		else {
+			$this->skip(4); 
+		}
+		$numGlyphs = $this->read_ushort();
+
+
+		///////////////////////////////////
+		// cmap - Character to glyph index mapping table
+		///////////////////////////////////
+/* Test purposes - displays list of cmaps
+		$cmap_offset = $this->seek_table("cmap");
+		$this->skip(2);
+		$cmapTableCount = $this->read_ushort();
+		$unicode_cmap_offset = 0;
+		for ($i=0;$i<$cmapTableCount;$i++) {
+			$x[$i]['platformId'] = $this->read_ushort();
+			$x[$i]['encodingId'] = $this->read_ushort();
+			$x[$i]['offset'] = $this->read_ulong();
+			$save_pos = $this->_pos;
+			$x[$i]['format'] = $this->get_ushort($cmap_offset + $x[$i]['offset'] );
+			$this->seek($save_pos );
+		}
+		print_r($x); exit;
+*/
+
+		$cmap_offset = $this->seek_table("cmap");
+		$this->skip(2);
+		$cmapTableCount = $this->read_ushort();
+		$unicode_cmap_offset = 0;
+		for ($i=0;$i<$cmapTableCount;$i++) {
+			$platformID = $this->read_ushort();
+			$encodingID = $this->read_ushort();
+			$offset = $this->read_ulong();
+			$save_pos = $this->_pos;
+			if (($platformID == 3 && $encodingID == 1) || $platformID == 0) { // Microsoft, Unicode
+				$format = $this->get_ushort($cmap_offset + $offset);
+				if ($format == 4) {
+					if (!$unicode_cmap_offset) $unicode_cmap_offset = $cmap_offset + $offset;
+					if ($BMPonly) break;	// mPDF 5.0
+				}
+			}
+			// Microsoft, Unicode Format 12 table HKCS
+			else if ((($platformID == 3 && $encodingID == 10) || $platformID == 0) && !$BMPonly) {
+				$format = $this->get_ushort($cmap_offset + $offset);
+				if ($format == 12) {
+					$unicode_cmap_offset = $cmap_offset + $offset;
+					break;
+				}
+			}
+			$this->seek($save_pos );
+		}
+		if (!$unicode_cmap_offset)
+			die('Font ('.$this->filename .') does not have cmap for Unicode (platform 3, encoding 1, format 4, or platform 0, any encoding, format 4)');
+
+
+		$sipset = false;
+		$smpset = false;
+		// Format 12 CMAP does characters above Unicode BMP i.e. some HKCS characters U+20000 and above
+		if ($format == 12 && !$BMPonly) {
+			$this->maxUniChar = 0;	// mPDF 5.0
+			$this->seek($unicode_cmap_offset + 4);
+			$length = $this->read_ulong();
+			$limit = $unicode_cmap_offset + $length;
+			$this->skip(4);
+
+			$nGroups = $this->read_ulong();
+
+			$glyphToChar = array();
+			$charToGlyph = array();
+			for($i=0; $i<$nGroups ; $i++) { 
+				$startCharCode = $this->read_ulong(); 
+				$endCharCode = $this->read_ulong(); 
+				$startGlyphCode = $this->read_ulong(); 
+				if (($endCharCode > 0x20000 && $endCharCode < 0x2A6DF) || ($endCharCode > 0x2F800 && $endCharCode < 0x2FA1F)) {
+					$sipset = true; 
+				}
+				else if ($endCharCode > 0x10000 && $endCharCode < 0x1FFFF) {
+					$smpset = true; 
+				}
+				$offset = 0;
+				for ($unichar=$startCharCode;$unichar<=$endCharCode;$unichar++) {
+					$glyph = $startGlyphCode + $offset ;
+					$offset++;
+					$charToGlyph[$unichar] = $glyph;
+					if ($unichar < 196608) { $this->maxUniChar = max($unichar,$this->maxUniChar); }
+					$glyphToChar[$glyph][] = $unichar;
+				}
+			}
+		}
+		else {
+
+			$glyphToChar = array();
+			$charToGlyph = array();
+			$this->getCMAP4($unicode_cmap_offset, $glyphToChar, $charToGlyph );
+
+		}
+		$this->sipset = $sipset ;
+		$this->smpset = $smpset ;
+
+		///////////////////////////////////
+		// hmtx - Horizontal metrics table
+		///////////////////////////////////
+		$this->getHMTX($numberOfHMetrics, $numGlyphs, $glyphToChar, $scale);
+
+		///////////////////////////////////
+		// kern - Kerning pair table  mPDF 5.1
+		///////////////////////////////////
+		if ($kerninfo) {
+			// Recognises old form of Kerning table - as required by Windows - Format 0 only
+			$kern_offset = $this->seek_table("kern");
+			$version = $this->read_ushort();
+			$nTables = $this->read_ushort();
+			// subtable header
+			$sversion = $this->read_ushort();
+			$slength = $this->read_ushort();
+			$scoverage = $this->read_ushort();
+			$format = $scoverage >> 8;
+ 			if ($kern_offset && $version==0 && $format==0) {
+				// Format 0
+				$nPairs = $this->read_ushort();
+				$this->skip(6);
+				for ($i=0; $i<$nPairs; $i++) {
+					$left = $this->read_ushort();
+					$right = $this->read_ushort();
+					$val = $this->read_short();
+					if (count($glyphToChar[$left])==1 && count($glyphToChar[$right])==1) {
+					  if ($left != 32 && $right != 32) {
+						$this->kerninfo[$glyphToChar[$left][0]][$glyphToChar[$right][0]] = intval($val*$scale);
+					  }
+					}
+				}
+			}
+		}
+	}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+
+	function makeSubset($file, &$subset, $TTCfontID=0, $debug=false) {
+		$this->filename = $file;
+		$this->fh = fopen($file ,'rb') or die('Can\'t open file ' . $file);
+		$this->_pos = 0;
+		$this->charWidths = '';
+		$this->glyphPos = array();
+		$this->charToGlyph = array();
+		$this->tables = array();
+		$this->otables = array();
+		$this->ascent = 0;
+		$this->descent = 0;
+		$this->numTTCFonts = 0;
+		$this->TTCFonts = array();
+		$this->skip(4);
+		$this->maxUni = 0;
+		if ($TTCfontID > 0) {
+			$this->version = $version = $this->read_ulong();	// TTC Header version now
+			if (!in_array($version, array(0x00010000,0x00020000)))
+				die("ERROR - Error parsing TrueType Collection: version=".$version." - " . $file);
+			$this->numTTCFonts = $this->read_ulong();
+			for ($i=1; $i<=$this->numTTCFonts; $i++) {
+	      	      $this->TTCFonts[$i]['offset'] = $this->read_ulong();
+			}
+			$this->seek($this->TTCFonts[$TTCfontID]['offset']);
+			$this->version = $version = $this->read_ulong();	// TTFont version again now
+		}
+		$this->readTableDirectory($debug);
+
+
+		///////////////////////////////////
+		// head - Font header table
+		///////////////////////////////////
+		$this->seek_table("head");
+		$this->skip(50); 
+		$indexToLocFormat = $this->read_ushort();
+		$glyphDataFormat = $this->read_ushort();
+
+		///////////////////////////////////
+		// hhea - Horizontal header table
+		///////////////////////////////////
+		$this->seek_table("hhea");
+		$this->skip(32); 
+		$metricDataFormat = $this->read_ushort();
+		$orignHmetrics = $numberOfHMetrics = $this->read_ushort();
+
+		///////////////////////////////////
+		// maxp - Maximum profile table
+		///////////////////////////////////
+		$this->seek_table("maxp");
+		$this->skip(4);
+		$numGlyphs = $this->read_ushort();
+
+
+		///////////////////////////////////
+		// cmap - Character to glyph index mapping table
+		///////////////////////////////////
+		$cmap_offset = $this->seek_table("cmap");
+		$this->skip(2);
+		$cmapTableCount = $this->read_ushort();
+		$unicode_cmap_offset = 0;
+		for ($i=0;$i<$cmapTableCount;$i++) {
+			$platformID = $this->read_ushort();
+			$encodingID = $this->read_ushort();
+			$offset = $this->read_ulong();
+			$save_pos = $this->_pos;
+			if (($platformID == 3 && $encodingID == 1) || $platformID == 0) { // Microsoft, Unicode
+				$format = $this->get_ushort($cmap_offset + $offset);
+				if ($format == 4) {
+					$unicode_cmap_offset = $cmap_offset + $offset;
+					break;
+				}
+			}
+			$this->seek($save_pos );
+		}
+
+		if (!$unicode_cmap_offset)
+			die('Font ('.$this->filename .') does not have Unicode cmap (platform 3, encoding 1, format 4, or platform 0 [any encoding] format 4)');
+
+
+		$glyphToChar = array();
+		$charToGlyph = array();
+		$this->getCMAP4($unicode_cmap_offset, $glyphToChar, $charToGlyph );
+
+		$this->charToGlyph = $charToGlyph;
+
+		///////////////////////////////////
+		// hmtx - Horizontal metrics table
+		///////////////////////////////////
+		$scale = 1;	// not used
+		$this->getHMTX($numberOfHMetrics, $numGlyphs, $glyphToChar, $scale);
+
+		///////////////////////////////////
+		// loca - Index to location
+		///////////////////////////////////
+		$this->getLOCA($indexToLocFormat, $numGlyphs);
+
+		$subsetglyphs = array(0=>0, 1=>1, 2=>2); 	// mPDF 5.3.31
+		$subsetCharToGlyph = array();
+		foreach($subset AS $code) {
+			if (isset($this->charToGlyph[$code])) {
+				$subsetglyphs[$this->charToGlyph[$code]] = $code;	// Old Glyph ID => Unicode
+				$subsetCharToGlyph[$code] = $this->charToGlyph[$code];	// Unicode to old GlyphID
+
+			}
+			$this->maxUni = max($this->maxUni, $code);
+		}
+
+		list($start,$dummy) = $this->get_table_pos('glyf');
+
+		$glyphSet = array();
+		ksort($subsetglyphs);
+		$n = 0;
+		// mPDF 5.0
+		$fsLastCharIndex = 0;	// maximum Unicode index (character code) in this font, according to the cmap subtable for platform ID 3 and platform- specific encoding ID 0 or 1.
+		foreach($subsetglyphs AS $originalGlyphIdx => $uni) {
+			$fsLastCharIndex = max($fsLastCharIndex , $uni); 	// mPDF 5.0
+			$glyphSet[$originalGlyphIdx] = $n;	// old glyphID to new glyphID
+			$n++;
+		}
+
+		ksort($subsetCharToGlyph);
+		foreach($subsetCharToGlyph AS $uni => $originalGlyphIdx) {
+			$codeToGlyph[$uni] = $glyphSet[$originalGlyphIdx] ;
+		}
+		$this->codeToGlyph = $codeToGlyph;
+
+		ksort($subsetglyphs);
+		foreach($subsetglyphs AS $originalGlyphIdx => $uni) {
+			$this->getGlyphs($originalGlyphIdx, $start, $glyphSet, $subsetglyphs);
+		}
+
+		$numGlyphs = $numberOfHMetrics = count($subsetglyphs );
+
+		///////////////////////////////////
+		// name - table copied from the original
+		///////////////////////////////////
+		$this->add('name', $this->get_table('name'));
+
+		///////////////////////////////////
+		//tables copied from the original
+		///////////////////////////////////
+		// mPDF 5.0.067  // 5.1.020
+		$tags = array ('cvt ', 'fpgm', 'prep', 'gasp');
+		foreach($tags AS $tag) {
+			if (isset($this->tables[$tag])) { $this->add($tag, $this->get_table($tag)); }
+		}
+
+		///////////////////////////////////
+		// post - PostScript
+		///////////////////////////////////
+		if (isset($this->tables['post'])) {
+			$opost = $this->get_table('post');
+			$post = "\x00\x03\x00\x00" . substr($opost,4,12) . "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
+			$this->add('post', $post);
+		}
+
+		///////////////////////////////////
+		// Sort CID2GID map into segments of contiguous codes
+		///////////////////////////////////
+		ksort($codeToGlyph);
+		unset($codeToGlyph[0]);
+		//unset($codeToGlyph[65535]);
+		$rangeid = 0;
+		$range = array();
+		$prevcid = -2;
+		$prevglidx = -1;
+		// for each character
+		foreach ($codeToGlyph as $cid => $glidx) {
+			if ($cid == ($prevcid + 1) && $glidx == ($prevglidx + 1)) {
+				$range[$rangeid][] = $glidx;
+			} else {
+				// new range
+				$rangeid = $cid;
+				$range[$rangeid] = array();
+				$range[$rangeid][] = $glidx;
+			}
+			$prevcid = $cid;
+			$prevglidx = $glidx;
+		}
+
+
+
+		///////////////////////////////////
+		// CMap table
+		///////////////////////////////////
+		// cmap - Character to glyph mapping 
+		$segCount = count($range) + 1;	// + 1 Last segment has missing character 0xFFFF
+		$searchRange = 1;
+		$entrySelector = 0;
+		while ($searchRange * 2 <= $segCount ) {
+			$searchRange = $searchRange * 2;
+			$entrySelector = $entrySelector + 1;
+		}
+		$searchRange = $searchRange * 2;
+		$rangeShift = $segCount * 2 - $searchRange;
+		$length = 16 + (8*$segCount ) + ($numGlyphs+1);
+		// mPDF 5.3.30
+		$cmap = array(0, 3,		// Index : version, number of encoding subtables
+			0, 0,				// Encoding Subtable : platform (UNI=0), encoding 0
+			0, 28,			// Encoding Subtable : offset (hi,lo)
+			0, 3,				// Encoding Subtable : platform (UNI=0), encoding 3
+			0, 28,			// Encoding Subtable : offset (hi,lo)
+			3, 1,				// Encoding Subtable : platform (MS=3), encoding 1
+			0, 28,			// Encoding Subtable : offset (hi,lo)
+			4, $length, 0, 		// Format 4 Mapping subtable: format, length, language
+			$segCount*2,
+			$searchRange,
+			$entrySelector,
+			$rangeShift);
+
+		// endCode(s)
+		foreach($range AS $start=>$subrange) {
+			$endCode = $start + (count($subrange)-1);
+			$cmap[] = $endCode;	// endCode(s)
+		}
+		$cmap[] =	0xFFFF;	// endCode of last Segment
+		$cmap[] =	0;	// reservedPad
+
+		// startCode(s)
+		foreach($range AS $start=>$subrange) {
+			$cmap[] = $start;	// startCode(s)
+		}
+		$cmap[] =	0xFFFF;	// startCode of last Segment
+		// idDelta(s) 
+		foreach($range AS $start=>$subrange) {
+			$idDelta = -($start-$subrange[0]);
+			$n += count($subrange);
+			$cmap[] = $idDelta;	// idDelta(s)
+		}
+		$cmap[] =	1;	// idDelta of last Segment
+		// idRangeOffset(s) 
+		foreach($range AS $subrange) {
+			$cmap[] = 0;	// idRangeOffset[segCount]  	Offset in bytes to glyph indexArray, or 0
+
+		}
+		$cmap[] =	0;	// idRangeOffset of last Segment
+		foreach($range AS $subrange) {
+			foreach($subrange AS $glidx) {
+				$cmap[] = $glidx;
+			}
+		}
+		$cmap[] = 0;	// Mapping for last character
+		$cmapstr = '';
+		foreach($cmap AS $cm) { $cmapstr .= pack("n",$cm); }
+		$this->add('cmap', $cmapstr);
+
+
+		///////////////////////////////////
+		// glyf - Glyph data
+		///////////////////////////////////
+		list($glyfOffset,$glyfLength) = $this->get_table_pos('glyf');
+		if ($glyfLength < $this->maxStrLenRead) {
+			$glyphData = $this->get_table('glyf');
+		}
+
+		$offsets = array();
+		$glyf = '';
+		$pos = 0;
+		$hmtxstr = '';
+		$xMinT = 0;
+		$yMinT = 0;
+		$xMaxT = 0;
+		$yMaxT = 0;
+		$advanceWidthMax = 0;
+		$minLeftSideBearing = 0;
+		$minRightSideBearing = 0;
+		$xMaxExtent = 0;
+		$maxPoints = 0;			// points in non-compound glyph
+		$maxContours = 0;			// contours in non-compound glyph
+		$maxComponentPoints = 0;	// points in compound glyph
+		$maxComponentContours = 0;	// contours in compound glyph
+		$maxComponentElements = 0;	// number of glyphs referenced at top level
+		$maxComponentDepth = 0;		// levels of recursion, set to 0 if font has only simple glyphs
+		$this->glyphdata = array();
+
+		foreach($subsetglyphs AS $originalGlyphIdx => $uni) {
+			// hmtx - Horizontal Metrics
+			$hm = $this->getHMetric($orignHmetrics, $originalGlyphIdx);
+			$hmtxstr .= $hm;
+
+			$offsets[] = $pos;
+			$glyphPos = $this->glyphPos[$originalGlyphIdx];
+			$glyphLen = $this->glyphPos[$originalGlyphIdx + 1] - $glyphPos;
+			if ($glyfLength < $this->maxStrLenRead) {
+				$data = substr($glyphData,$glyphPos,$glyphLen);
+			}
+			else {
+				if ($glyphLen > 0) $data = $this->get_chunk($glyfOffset+$glyphPos,$glyphLen);
+				else $data = '';
+			}
+
+			// mPDF 5.0
+			if ($glyphLen > 0) {
+			  if (_RECALC_PROFILE) {
+				$xMin = $this->unpack_short(substr($data,2,2));
+				$yMin = $this->unpack_short(substr($data,4,2));
+				$xMax = $this->unpack_short(substr($data,6,2));
+				$yMax = $this->unpack_short(substr($data,8,2));
+				$xMinT = min($xMinT,$xMin);
+				$yMinT = min($yMinT,$yMin);
+				$xMaxT = max($xMaxT,$xMax);
+				$yMaxT = max($yMaxT,$yMax);
+				$aw = $this->unpack_short(substr($hm,0,2)); 
+				$lsb = $this->unpack_short(substr($hm,2,2));
+				$advanceWidthMax = max($advanceWidthMax,$aw);
+				$minLeftSideBearing = min($minLeftSideBearing,$lsb);
+				$minRightSideBearing = min($minRightSideBearing,($aw - $lsb - ($xMax - $xMin)));
+				$xMaxExtent = max($xMaxExtent,($lsb + ($xMax - $xMin)));
+			   }
+				$up = unpack("n", substr($data,0,2));
+			}
+			if ($glyphLen > 2 && ($up[1] & (1 << 15)) ) {	// If number of contours <= -1 i.e. composiste glyph
+				$pos_in_glyph = 10;
+				$flags = GF_MORE;
+				$nComponentElements = 0;
+				while ($flags & GF_MORE) {
+					$nComponentElements += 1;	// number of glyphs referenced at top level
+					$up = unpack("n", substr($data,$pos_in_glyph,2));
+					$flags = $up[1];
+					$up = unpack("n", substr($data,$pos_in_glyph+2,2));
+					$glyphIdx = $up[1];
+					$this->glyphdata[$originalGlyphIdx]['compGlyphs'][] = $glyphIdx;
+					$data = $this->_set_ushort($data, $pos_in_glyph + 2, $glyphSet[$glyphIdx]);
+					$pos_in_glyph += 4;
+					if ($flags & GF_WORDS) { $pos_in_glyph += 4; }
+					else { $pos_in_glyph += 2; }
+					if ($flags & GF_SCALE) { $pos_in_glyph += 2; }
+					else if ($flags & GF_XYSCALE) { $pos_in_glyph += 4; }
+					else if ($flags & GF_TWOBYTWO) { $pos_in_glyph += 8; }
+				}
+				$maxComponentElements = max($maxComponentElements, $nComponentElements);
+			}
+			// mPDF 5.0 - Simple Glyph
+			else if (_RECALC_PROFILE && $glyphLen > 2 && $up[1] < (1 << 15) && $up[1] > 0) { 	// Number of contours > 0 simple glyph
+				$nContours = $up[1];
+				$this->glyphdata[$originalGlyphIdx]['nContours'] = $nContours;
+				$maxContours = max($maxContours, $nContours);
+
+				// Count number of points in simple glyph
+				$pos_in_glyph = 10 + ($nContours  * 2) - 2;	// Last endContourPoint
+				$up = unpack("n", substr($data,$pos_in_glyph,2));
+				$points = $up[1]+1;
+				$this->glyphdata[$originalGlyphIdx]['nPoints'] = $points;
+				$maxPoints = max($maxPoints, $points);
+			}
+
+			$glyf .= $data;
+			$pos += $glyphLen;
+			if ($pos % 4 != 0) {
+				$padding = 4 - ($pos % 4);
+				$glyf .= str_repeat("\0",$padding);
+				$pos += $padding;
+			}
+		}
+
+		if (_RECALC_PROFILE) {
+		   foreach($this->glyphdata AS $originalGlyphIdx => $val) {
+			$maxdepth = $depth = -1;
+			$points = 0;
+			$contours = 0;
+			$this->getGlyphData($originalGlyphIdx, $maxdepth, $depth, $points, $contours) ;
+			$maxComponentDepth = max($maxComponentDepth , $maxdepth);
+			$maxComponentPoints = max($maxComponentPoints , $points);
+			$maxComponentContours = max($maxComponentContours , $contours);
+		   }
+		}
+
+
+		$offsets[] = $pos;
+		$this->add('glyf', $glyf);
+
+		///////////////////////////////////
+		// hmtx - Horizontal Metrics
+		///////////////////////////////////
+		$this->add('hmtx', $hmtxstr);
+
+
+		///////////////////////////////////
+		// loca - Index to location
+		///////////////////////////////////
+		$locastr = '';
+		if ((($pos + 1) >> 1) > 0xFFFF) {
+			$indexToLocFormat = 1;        // long format
+			foreach($offsets AS $offset) { $locastr .= pack("N",$offset); }
+		}
+		else {
+			$indexToLocFormat = 0;        // short format
+			foreach($offsets AS $offset) { $locastr .= pack("n",($offset/2)); }
+		}
+		$this->add('loca', $locastr);
+
+		///////////////////////////////////
+		// head - Font header
+		///////////////////////////////////
+		$head = $this->get_table('head');
+		$head = $this->_set_ushort($head, 50, $indexToLocFormat);
+		if (_RECALC_PROFILE) {
+			$head = $this->_set_short($head, 36, $xMinT);	// for all glyph bounding boxes
+			$head = $this->_set_short($head, 38, $yMinT);	// for all glyph bounding boxes
+			$head = $this->_set_short($head, 40, $xMaxT);	// for all glyph bounding boxes
+			$head = $this->_set_short($head, 42, $yMaxT);	// for all glyph bounding boxes
+			// mPDF 5.3.33
+			$head[17] = chr($head[17] & ~(1 << 4)); 	// Unset Bit 4 (as hdmx/LTSH tables not included)
+		}
+		$this->add('head', $head);
+
+
+		///////////////////////////////////
+		// hhea - Horizontal Header
+		///////////////////////////////////
+		$hhea = $this->get_table('hhea');
+		$hhea = $this->_set_ushort($hhea, 34, $numberOfHMetrics);
+		if (_RECALC_PROFILE) {
+			$hhea = $this->_set_ushort($hhea, 10, $advanceWidthMax);	
+			$hhea = $this->_set_short($hhea, 12, $minLeftSideBearing);	
+			$hhea = $this->_set_short($hhea, 14, $minRightSideBearing);	
+			$hhea = $this->_set_short($hhea, 16, $xMaxExtent);	
+		}
+		$this->add('hhea', $hhea);
+
+		///////////////////////////////////
+		// maxp - Maximum Profile
+		///////////////////////////////////
+		$maxp = $this->get_table('maxp');
+		$maxp = $this->_set_ushort($maxp, 4, $numGlyphs);
+		if (_RECALC_PROFILE) {
+			$maxp = $this->_set_ushort($maxp, 6, $maxPoints);	// points in non-compound glyph
+			$maxp = $this->_set_ushort($maxp, 8, $maxContours);	// contours in non-compound glyph
+			$maxp = $this->_set_ushort($maxp, 10, $maxComponentPoints);	// points in compound glyph
+			$maxp = $this->_set_ushort($maxp, 12, $maxComponentContours);	// contours in compound glyph
+			$maxp = $this->_set_ushort($maxp, 28, $maxComponentElements);	// number of glyphs referenced at top level
+			$maxp = $this->_set_ushort($maxp, 30, $maxComponentDepth);	// levels of recursion, set to 0 if font has only simple glyphs
+		}
+		$this->add('maxp', $maxp);
+
+
+		///////////////////////////////////
+		// OS/2 - OS/2
+		///////////////////////////////////
+		if (isset($this->tables['OS/2'])) { 
+			// mPDF 5.2.03
+			$os2_offset = $this->seek_table("OS/2");
+			// mPDF 5.0
+			if (_RECALC_PROFILE) {
+				$fsSelection = $this->get_ushort($os2_offset+62);
+				$fsSelection = ($fsSelection & ~(1 << 6)); 	// 2-byte bit field containing information concerning the nature of the font patterns
+					// bit#0 = Italic; bit#5=Bold
+					// Match name table's font subfamily string
+					// Clear bit#6 used for 'Regular' and optional
+			}
+
+			// NB Currently this method never subsets characters above BMP
+			// Could set nonBMP bit according to $this->maxUni 
+			$nonBMP = $this->get_ushort($os2_offset+46);
+			$nonBMP = ($nonBMP & ~(1 << 9)); 	// Unset Bit 57 (indicates non-BMP) - for interactive forms
+
+			$os2 = $this->get_table('OS/2');
+			if (_RECALC_PROFILE) {
+				$os2 = $this->_set_ushort($os2, 62, $fsSelection);	
+				// mPDF 5.2.03
+				$os2 = $this->_set_ushort($os2, 66, $fsLastCharIndex);
+				$os2 = $this->_set_ushort($os2, 42, 0x0000);	// ulCharRange (ulUnicodeRange) bits 24-31 | 16-23
+				$os2 = $this->_set_ushort($os2, 44, 0x0000);	// ulCharRange (Unicode ranges) bits  8-15 |  0-7
+				$os2 = $this->_set_ushort($os2, 46, $nonBMP);	// ulCharRange (Unicode ranges) bits 56-63 | 48-55
+				$os2 = $this->_set_ushort($os2, 48, 0x0000);	// ulCharRange (Unicode ranges) bits 40-47 | 32-39
+				$os2 = $this->_set_ushort($os2, 50, 0x0000);	// ulCharRange (Unicode ranges) bits  88-95 | 80-87
+				$os2 = $this->_set_ushort($os2, 52, 0x0000);	// ulCharRange (Unicode ranges) bits  72-79 | 64-71
+				$os2 = $this->_set_ushort($os2, 54, 0x0000);	// ulCharRange (Unicode ranges) bits  120-127 | 112-119
+				$os2 = $this->_set_ushort($os2, 56, 0x0000);	// ulCharRange (Unicode ranges) bits  104-111 | 96-103
+			}
+			$os2 = $this->_set_ushort($os2, 46, $nonBMP);	// Unset Bit 57 (indicates non-BMP) - for interactive forms
+
+			$this->add('OS/2', $os2 );
+		}
+
+		fclose($this->fh);
+		// Put the TTF file together
+		$stm = '';
+		$this->endTTFile($stm);
+		//file_put_contents('testfont.ttf', $stm); exit;
+		return $stm ;
+	}
+
+//================================================================================
+
+	// Also does SMP
+	function makeSubsetSIP($file, &$subset, $TTCfontID=0, $debug=false) {
+		$this->fh = fopen($file ,'rb') or die('Can\'t open file ' . $file);
+		$this->filename = $file;
+		$this->_pos = 0;
+		$this->charWidths = '';
+		$this->glyphPos = array();
+		$this->charToGlyph = array();
+		$this->tables = array();
+		$this->otables = array();
+		$this->ascent = 0;
+		$this->descent = 0;
+		$this->numTTCFonts = 0;
+		$this->TTCFonts = array();
+		$this->skip(4);
+		if ($TTCfontID > 0) {
+			$this->version = $version = $this->read_ulong();	// TTC Header version now
+			if (!in_array($version, array(0x00010000,0x00020000)))
+				die("ERROR - Error parsing TrueType Collection: version=".$version." - " . $file);
+			$this->numTTCFonts = $this->read_ulong();
+			for ($i=1; $i<=$this->numTTCFonts; $i++) {
+	      	      $this->TTCFonts[$i]['offset'] = $this->read_ulong();
+			}
+			$this->seek($this->TTCFonts[$TTCfontID]['offset']);
+			$this->version = $version = $this->read_ulong();	// TTFont version again now
+		}
+		$this->readTableDirectory($debug);
+
+
+
+		///////////////////////////////////
+		// head - Font header table
+		///////////////////////////////////
+		$this->seek_table("head");
+		$this->skip(50); 
+		$indexToLocFormat = $this->read_ushort();
+		$glyphDataFormat = $this->read_ushort();
+
+		///////////////////////////////////
+		// hhea - Horizontal header table
+		///////////////////////////////////
+		$this->seek_table("hhea");
+		$this->skip(32); 
+		$metricDataFormat = $this->read_ushort();
+		$orignHmetrics = $numberOfHMetrics = $this->read_ushort();
+
+		///////////////////////////////////
+		// maxp - Maximum profile table
+		///////////////////////////////////
+		$this->seek_table("maxp");
+		$this->skip(4);
+		$numGlyphs = $this->read_ushort();
+
+
+		///////////////////////////////////
+		// cmap - Character to glyph index mapping table
+		///////////////////////////////////
+
+		$cmap_offset = $this->seek_table("cmap");
+		$this->skip(2);
+		$cmapTableCount = $this->read_ushort();
+		$unicode_cmap_offset = 0;
+		for ($i=0;$i<$cmapTableCount;$i++) {
+			$platformID = $this->read_ushort();
+			$encodingID = $this->read_ushort();
+			$offset = $this->read_ulong();
+			$save_pos = $this->_pos;
+			// mPDF 5.3.30
+			if (($platformID == 3 && $encodingID == 10) || $platformID == 0) { // Microsoft, Unicode Format 12 table HKCS
+				$format = $this->get_ushort($cmap_offset + $offset);
+				if ($format == 12) {
+					$unicode_cmap_offset = $cmap_offset + $offset;
+					break;
+				}
+			}
+			$this->seek($save_pos );
+		}
+
+		if (!$unicode_cmap_offset)
+			die('Font does not have cmap for Unicode (platform 3, encoding 1, format 4, or platform 0, any encoding, format 4)');
+		// Format 12 CMAP does characters above Unicode BMP i.e. some HKCS characters U+20000 and above
+		if ($format == 12) {
+			$this->maxUniChar = 0;
+			$this->seek($unicode_cmap_offset + 4);
+			$length = $this->read_ulong();
+			$limit = $unicode_cmap_offset + $length;
+			$this->skip(4);
+
+			$nGroups = $this->read_ulong();
+
+			$glyphToChar = array();
+			$charToGlyph = array();
+			for($i=0; $i<$nGroups ; $i++) { 
+				$startCharCode = $this->read_ulong(); 
+				$endCharCode = $this->read_ulong(); 
+				$startGlyphCode = $this->read_ulong(); 
+				$offset = 0;
+				for ($unichar=$startCharCode;$unichar<=$endCharCode;$unichar++) {
+					$glyph = $startGlyphCode + $offset ;
+					$offset++;
+					$charToGlyph[$unichar] = $glyph;
+					if ($unichar < 196608) { $this->maxUniChar = max($unichar,$this->maxUniChar); }
+					$glyphToChar[$glyph][] = $unichar;
+				}
+			}
+		}
+		else 
+			die('Font does not have cmap for Unicode (format 12)');
+
+
+		///////////////////////////////////
+		// hmtx - Horizontal metrics table
+		///////////////////////////////////
+		$scale = 1; // not used here
+		$this->getHMTX($numberOfHMetrics, $numGlyphs, $glyphToChar, $scale);
+
+		///////////////////////////////////
+		// loca - Index to location
+		///////////////////////////////////
+		$this->getLOCA($indexToLocFormat, $numGlyphs);
+
+		///////////////////////////////////////////////////////////////////
+
+		$glyphMap = array(0=>0); 
+		$glyphSet = array(0=>0);
+		$codeToGlyph = array();
+		// mPDF 5.0.067  Set a substitute if ASCII characters do not have glyphs
+		if (isset($charToGlyph[0x3F])) { $subs = $charToGlyph[0x3F]; }	// Question mark
+		else { $subs = $charToGlyph[32]; }
+		foreach($subset AS $code) {
+			if (isset($charToGlyph[$code]))
+				$originalGlyphIdx = $charToGlyph[$code];
+			else if ($code<128) {	// mPDF 5.0.067
+				$originalGlyphIdx = $subs;
+			}
+			else { $originalGlyphIdx = 0; }
+			if (!isset($glyphSet[$originalGlyphIdx])) {
+				$glyphSet[$originalGlyphIdx] = count($glyphMap);
+				$glyphMap[] = $originalGlyphIdx;
+			}
+			$codeToGlyph[$code] = $glyphSet[$originalGlyphIdx];
+		}
+
+		list($start,$dummy) = $this->get_table_pos('glyf');
+
+		$n = 0;
+		while ($n < count($glyphMap)) {
+			$originalGlyphIdx = $glyphMap[$n];
+			$glyphPos = $this->glyphPos[$originalGlyphIdx];
+			$glyphLen = $this->glyphPos[$originalGlyphIdx + 1] - $glyphPos;
+			$n += 1;
+			if (!$glyphLen) continue;
+			$this->seek($start + $glyphPos);
+			$numberOfContours = $this->read_short();
+			if ($numberOfContours < 0) {
+				$this->skip(8);
+				$flags = GF_MORE;
+				while ($flags & GF_MORE) {
+					$flags = $this->read_ushort();
+					$glyphIdx = $this->read_ushort();
+					if (!isset($glyphSet[$glyphIdx])) {
+						$glyphSet[$glyphIdx] = count($glyphMap);
+						$glyphMap[] = $glyphIdx;
+					}
+					if ($flags & GF_WORDS)
+						$this->skip(4);
+					else
+						$this->skip(2);
+					if ($flags & GF_SCALE)
+						$this->skip(2);
+					else if ($flags & GF_XYSCALE)
+						$this->skip(4);
+					else if ($flags & GF_TWOBYTWO)
+						$this->skip(8);
+				}
+			}
+		}
+
+		$numGlyphs = $n = count($glyphMap);
+		$numberOfHMetrics = $n;
+
+		///////////////////////////////////
+		// name
+		///////////////////////////////////
+		// Needs to have a name entry in 3,0 (e.g. symbol) - original font will be 3,1 (i.e. Unicode)
+		$name = $this->get_table('name'); 
+		$name_offset = $this->seek_table("name");
+		$format = $this->read_ushort();
+		$numRecords = $this->read_ushort();
+		$string_data_offset = $name_offset + $this->read_ushort();
+		for ($i=0;$i<$numRecords; $i++) {
+			$platformId = $this->read_ushort();
+			$encodingId = $this->read_ushort();
+			if ($platformId == 3 && $encodingId == 1) {
+				$pos = 6 + ($i * 12) + 2;
+				$name = $this->_set_ushort($name, $pos, 0x00);	// Change encoding to 3,0 rather than 3,1
+			}
+			$this->skip(8);
+		}
+		$this->add('name', $name);
+
+		///////////////////////////////////
+		// OS/2
+		///////////////////////////////////
+		if (isset($this->tables['OS/2'])) { 
+			$os2 = $this->get_table('OS/2');
+			$os2 = $this->_set_ushort($os2, 42, 0x00);	// ulCharRange (Unicode ranges)
+			$os2 = $this->_set_ushort($os2, 44, 0x00);	// ulCharRange (Unicode ranges)
+			$os2 = $this->_set_ushort($os2, 46, 0x00);	// ulCharRange (Unicode ranges)
+			$os2 = $this->_set_ushort($os2, 48, 0x00);	// ulCharRange (Unicode ranges)
+
+			$os2 = $this->_set_ushort($os2, 50, 0x00);	// ulCharRange (Unicode ranges)
+			$os2 = $this->_set_ushort($os2, 52, 0x00);	// ulCharRange (Unicode ranges)
+			$os2 = $this->_set_ushort($os2, 54, 0x00);	// ulCharRange (Unicode ranges)
+			$os2 = $this->_set_ushort($os2, 56, 0x00);	// ulCharRange (Unicode ranges)
+			// Set Symbol character only in ulCodePageRange
+			$os2 = $this->_set_ushort($os2, 78, 0x8000);	// ulCodePageRange = Bit #31 Symbol ****  78 = Bit 16-31
+			$os2 = $this->_set_ushort($os2, 80, 0x0000);	// ulCodePageRange = Bit #31 Symbol ****  80 = Bit 0-15
+			$os2 = $this->_set_ushort($os2, 82, 0x0000);	// ulCodePageRange = Bit #32- Symbol **** 82 = Bits 48-63
+			$os2 = $this->_set_ushort($os2, 84, 0x0000);	// ulCodePageRange = Bit #32- Symbol **** 84 = Bits 32-47
+	
+			$os2 = $this->_set_ushort($os2, 64, 0x01);		// FirstCharIndex
+			$os2 = $this->_set_ushort($os2, 66, count($subset));		// LastCharIndex
+			// Set PANOSE first bit to 5 for Symbol 	mPDF 5.0.017
+			$os2 = $this->splice($os2, 32, chr(5).chr(0).chr(1).chr(0).chr(1).chr(0).chr(0).chr(0).chr(0).chr(0));
+			$this->add('OS/2', $os2 );
+		}
+
+
+		///////////////////////////////////
+		//tables copied from the original
+		///////////////////////////////////
+		// mPDF 5.1.020	// mPDF 5.1.022
+		$tags = array ('cvt ', 'fpgm', 'prep', 'gasp');	
+		foreach($tags AS $tag) { 	// 1.02
+			if (isset($this->tables[$tag])) { $this->add($tag, $this->get_table($tag)); } 
+		}
+
+		///////////////////////////////////
+		// post - PostScript
+		///////////////////////////////////
+		if (isset($this->tables['post'])) { 
+			$opost = $this->get_table('post');
+			$post = "\x00\x03\x00\x00" . substr($opost,4,12) . "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
+		}
+		$this->add('post', $post);
+
+		///////////////////////////////////
+		// hhea - Horizontal Header
+		///////////////////////////////////
+		$hhea = $this->get_table('hhea');
+		$hhea = $this->_set_ushort($hhea, 34, $numberOfHMetrics);
+		$this->add('hhea', $hhea);
+
+		///////////////////////////////////
+		// maxp - Maximum Profile
+		///////////////////////////////////
+		$maxp = $this->get_table('maxp');
+		$maxp = $this->_set_ushort($maxp, 4, $numGlyphs);
+		$this->add('maxp', $maxp);
+
+
+		///////////////////////////////////
+		// CMap table Formats [1,0,]6 and [3,0,]4
+		///////////////////////////////////
+		///////////////////////////////////
+		// Sort CID2GID map into segments of contiguous codes
+		///////////////////////////////////
+		$rangeid = 0;
+		$range = array();
+		$prevcid = -2;
+		$prevglidx = -1;
+		// for each character
+		foreach ($subset as $cid => $code) {
+			$glidx = $codeToGlyph[$code]; 
+			if ($cid == ($prevcid + 1) && $glidx == ($prevglidx + 1)) {
+				$range[$rangeid][] = $glidx;
+			} else {
+				// new range
+				$rangeid = $cid;
+				$range[$rangeid] = array();
+				$range[$rangeid][] = $glidx;
+			}
+			$prevcid = $cid;
+			$prevglidx = $glidx;
+		}
+		// cmap - Character to glyph mapping 
+		$segCount = count($range) + 1;	// + 1 Last segment has missing character 0xFFFF
+		$searchRange = 1;
+		$entrySelector = 0;
+		while ($searchRange * 2 <= $segCount ) {
+			$searchRange = $searchRange * 2;
+			$entrySelector = $entrySelector + 1;
+		}
+		$searchRange = $searchRange * 2;
+		$rangeShift = $segCount * 2 - $searchRange;
+		$length = 16 + (8*$segCount ) + ($numGlyphs+1);
+		$cmap = array(
+			4, $length, 0, 		// Format 4 Mapping subtable: format, length, language
+			$segCount*2,
+			$searchRange,
+			$entrySelector,
+			$rangeShift);
+
+		// endCode(s)
+		foreach($range AS $start=>$subrange) {
+			$endCode = $start + (count($subrange)-1);
+			$cmap[] = $endCode;	// endCode(s)
+		}
+		$cmap[] =	0xFFFF;	// endCode of last Segment
+		$cmap[] =	0;	// reservedPad
+
+		// startCode(s)
+		foreach($range AS $start=>$subrange) {
+			$cmap[] = $start;	// startCode(s)
+		}
+		$cmap[] =	0xFFFF;	// startCode of last Segment
+		// idDelta(s) 
+		foreach($range AS $start=>$subrange) {
+			$idDelta = -($start-$subrange[0]);
+			$n += count($subrange);
+			$cmap[] = $idDelta;	// idDelta(s)
+		}
+		$cmap[] =	1;	// idDelta of last Segment
+		// idRangeOffset(s) 
+		foreach($range AS $subrange) {
+			$cmap[] = 0;	// idRangeOffset[segCount]  	Offset in bytes to glyph indexArray, or 0
+
+		}
+		$cmap[] =	0;	// idRangeOffset of last Segment
+		foreach($range AS $subrange) {
+			foreach($subrange AS $glidx) {
+				$cmap[] = $glidx;
+			}
+		}
+		$cmap[] = 0;	// Mapping for last character
+		$cmapstr4 = '';
+		foreach($cmap AS $cm) { $cmapstr4 .= pack("n",$cm); }
+
+		///////////////////////////////////
+		// cmap - Character to glyph mapping
+		///////////////////////////////////
+		$entryCount = count($subset);
+		$length = 10 + $entryCount * 2;
+
+		$off = 20 + $length;
+		$hoff = $off >> 16;
+		$loff = $off & 0xFFFF;
+
+		$cmap = array(0, 2,	// Index : version, number of subtables
+			1, 0,			// Subtable : platform, encoding
+			0, 20,		// offset (hi,lo)
+			3, 0,			// Subtable : platform, encoding
+			$hoff, $loff,	// offset (hi,lo)
+			6, $length, 	// Format 6 Mapping table: format, length
+			0, 1,			// language, First char code
+			$entryCount
+		);
+		$cmapstr = '';
+		foreach($subset AS $code) { $cmap[] = $codeToGlyph[$code]; }
+		foreach($cmap AS $cm) { $cmapstr .= pack("n",$cm); }
+		$cmapstr .= $cmapstr4;
+		$this->add('cmap', $cmapstr);
+
+		///////////////////////////////////
+		// hmtx - Horizontal Metrics
+		///////////////////////////////////
+		$hmtxstr = '';
+		for($n=0;$n<$numGlyphs;$n++) {
+			$originalGlyphIdx = $glyphMap[$n];
+			$hm = $this->getHMetric($orignHmetrics, $originalGlyphIdx);
+			$hmtxstr .= $hm;
+		}
+		$this->add('hmtx', $hmtxstr);
+
+		///////////////////////////////////
+		// glyf - Glyph data
+		///////////////////////////////////
+		list($glyfOffset,$glyfLength) = $this->get_table_pos('glyf');
+		if ($glyfLength < $this->maxStrLenRead) {
+			$glyphData = $this->get_table('glyf');
+		}
+
+		$offsets = array();
+		$glyf = '';
+		$pos = 0;
+		for ($n=0;$n<$numGlyphs;$n++) {
+			$offsets[] = $pos;
+			$originalGlyphIdx = $glyphMap[$n];
+			$glyphPos = $this->glyphPos[$originalGlyphIdx];
+			$glyphLen = $this->glyphPos[$originalGlyphIdx + 1] - $glyphPos;
+			if ($glyfLength < $this->maxStrLenRead) {
+				$data = substr($glyphData,$glyphPos,$glyphLen);
+			}
+			else {
+				if ($glyphLen > 0) $data = $this->get_chunk($glyfOffset+$glyphPos,$glyphLen);
+				else $data = '';
+			}
+			if ($glyphLen > 0) $up = unpack("n", substr($data,0,2));
+			if ($glyphLen > 2 && ($up[1] & (1 << 15)) ) {
+				$pos_in_glyph = 10;
+				$flags = GF_MORE;
+				while ($flags & GF_MORE) {
+					$up = unpack("n", substr($data,$pos_in_glyph,2));
+					$flags = $up[1];
+					$up = unpack("n", substr($data,$pos_in_glyph+2,2));
+					$glyphIdx = $up[1];
+					$data = $this->_set_ushort($data, $pos_in_glyph + 2, $glyphSet[$glyphIdx]);
+					$pos_in_glyph += 4;
+					if ($flags & GF_WORDS) { $pos_in_glyph += 4; }
+					else { $pos_in_glyph += 2; }
+					if ($flags & GF_SCALE) { $pos_in_glyph += 2; }
+					else if ($flags & GF_XYSCALE) { $pos_in_glyph += 4; }
+					else if ($flags & GF_TWOBYTWO) { $pos_in_glyph += 8; }
+				}
+			}
+			$glyf .= $data;
+			$pos += $glyphLen;
+			if ($pos % 4 != 0) {
+				$padding = 4 - ($pos % 4);
+				$glyf .= str_repeat("\0",$padding);
+				$pos += $padding;
+			}
+		}
+		$offsets[] = $pos;
+		$this->add('glyf', $glyf);
+
+		///////////////////////////////////
+		// loca - Index to location
+		///////////////////////////////////
+		$locastr = '';
+		if ((($pos + 1) >> 1) > 0xFFFF) {
+			$indexToLocFormat = 1;        // long format
+			foreach($offsets AS $offset) { $locastr .= pack("N",$offset); }
+		}
+		else {
+			$indexToLocFormat = 0;        // short format
+			foreach($offsets AS $offset) { $locastr .= pack("n",($offset/2)); }
+		}
+		$this->add('loca', $locastr);
+
+		///////////////////////////////////
+		// head - Font header
+		///////////////////////////////////
+		$head = $this->get_table('head');
+		$head = $this->_set_ushort($head, 50, $indexToLocFormat);
+		$this->add('head', $head);
+
+		fclose($this->fh);
+
+		// Put the TTF file together
+		$stm = '';
+		$this->endTTFile($stm);
+		//file_put_contents('testfont.ttf', $stm); exit;
+		return $stm ;
+	}
+
+	//////////////////////////////////////////////////////////////////////////////////
+	// Recursively get composite glyph data
+	function getGlyphData($originalGlyphIdx, &$maxdepth, &$depth, &$points, &$contours) {
+		$depth++;
+		$maxdepth = max($maxdepth, $depth);
+		if (count($this->glyphdata[$originalGlyphIdx]['compGlyphs'])) {
+			foreach($this->glyphdata[$originalGlyphIdx]['compGlyphs'] AS $glyphIdx) {
+				$this->getGlyphData($glyphIdx, $maxdepth, $depth, $points, $contours);
+			}
+		}
+		else if (($this->glyphdata[$originalGlyphIdx]['nContours'] > 0) && $depth > 0) {	// simple
+			$contours += $this->glyphdata[$originalGlyphIdx]['nContours'];
+			$points += $this->glyphdata[$originalGlyphIdx]['nPoints'];
+		}
+		$depth--;
+	}
+
+
+	//////////////////////////////////////////////////////////////////////////////////
+	// Recursively get composite glyphs
+	function getGlyphs($originalGlyphIdx, &$start, &$glyphSet, &$subsetglyphs) {
+		$glyphPos = $this->glyphPos[$originalGlyphIdx];
+		$glyphLen = $this->glyphPos[$originalGlyphIdx + 1] - $glyphPos;
+		if (!$glyphLen) { 
+			return;
+		}
+		$this->seek($start + $glyphPos);
+		$numberOfContours = $this->read_short();
+		if ($numberOfContours < 0) {
+			$this->skip(8);
+			$flags = GF_MORE;
+			while ($flags & GF_MORE) {
+				$flags = $this->read_ushort();
+				$glyphIdx = $this->read_ushort();
+				if (!isset($glyphSet[$glyphIdx])) {
+					$glyphSet[$glyphIdx] = count($subsetglyphs);	// old glyphID to new glyphID
+					$subsetglyphs[$glyphIdx] = true;
+				}
+				$savepos = ftell($this->fh);
+				$this->getGlyphs($glyphIdx, $start, $glyphSet, $subsetglyphs);
+				$this->seek($savepos);
+				if ($flags & GF_WORDS)
+					$this->skip(4);
+				else
+					$this->skip(2);
+				if ($flags & GF_SCALE)
+					$this->skip(2);
+				else if ($flags & GF_XYSCALE)
+					$this->skip(4);
+				else if ($flags & GF_TWOBYTWO)
+					$this->skip(8);
+			}
+		}
+	}
+
+	//////////////////////////////////////////////////////////////////////////////////
+
+	function getHMTX($numberOfHMetrics, $numGlyphs, &$glyphToChar, $scale) {
+		$start = $this->seek_table("hmtx");
+		$aw = 0;
+		$this->charWidths = str_pad('', 256*256*2, "\x00");
+		if ($this->maxUniChar > 65536) { $this->charWidths .= str_pad('', 256*256*2, "\x00"); }	// Plane 1 SMP
+		if ($this->maxUniChar > 131072) { $this->charWidths .= str_pad('', 256*256*2, "\x00"); }	// Plane 2 SMP
+		$nCharWidths = 0;
+		if (($numberOfHMetrics*4) < $this->maxStrLenRead) {
+			$data = $this->get_chunk($start,($numberOfHMetrics*4));
+			$arr = unpack("n*", $data);
+		}
+		else { $this->seek($start); }
+		for( $glyph=0; $glyph<$numberOfHMetrics; $glyph++) {
+			if (($numberOfHMetrics*4) < $this->maxStrLenRead) {
+				$aw = $arr[($glyph*2)+1];
+			}
+			else {
+				$aw = $this->read_ushort();
+				$lsb = $this->read_ushort();
+			}
+			if (isset($glyphToChar[$glyph]) || $glyph == 0) {
+
+				if ($aw >= (1 << 15) ) { $aw = 0; }	// 1.03 Some (arabic) fonts have -ve values for width
+					// although should be unsigned value - comes out as e.g. 65108 (intended -50)
+				if ($glyph == 0) {
+					$this->defaultWidth = $scale*$aw;
+					continue;
+				}
+				foreach($glyphToChar[$glyph] AS $char) {
+					//$this->charWidths[$char] = intval(round($scale*$aw));
+					if ($char != 0 && $char != 65535) {
+ 						$w = intval(round($scale*$aw));
+						if ($w == 0) { $w = 65535; }
+						if ($char < 196608) {
+							$this->charWidths[$char*2] = chr($w >> 8);
+							$this->charWidths[$char*2 + 1] = chr($w & 0xFF);
+							$nCharWidths++;
+						}
+					}
+				}
+			}
+		}
+		$data = $this->get_chunk(($start+$numberOfHMetrics*4),($numGlyphs*2));
+		$arr = unpack("n*", $data);
+		$diff = $numGlyphs-$numberOfHMetrics;
+		$w = intval(round($scale*$aw));	// mPDF 5.3.32
+		if ($w == 0) { $w = 65535; }	// mPDF 5.3.32
+		for( $pos=0; $pos<$diff; $pos++) {
+			$glyph = $pos + $numberOfHMetrics;
+			if (isset($glyphToChar[$glyph])) {
+				foreach($glyphToChar[$glyph] AS $char) {
+					if ($char != 0 && $char != 65535) {
+						if ($char < 196608) { 
+							$this->charWidths[$char*2] = chr($w >> 8);
+							$this->charWidths[$char*2 + 1] = chr($w & 0xFF);
+							$nCharWidths++;
+						}
+					}
+				}
+			}
+		}
+		// NB 65535 is a set width of 0
+		// First bytes define number of chars in font
+		$this->charWidths[0] = chr($nCharWidths >> 8);
+		$this->charWidths[1] = chr($nCharWidths & 0xFF);
+	}
+
+	function getHMetric($numberOfHMetrics, $gid) {
+		$start = $this->seek_table("hmtx");
+		if ($gid < $numberOfHMetrics) {
+			$this->seek($start+($gid*4));
+			$hm = fread($this->fh,4);
+		}
+		else {
+			$this->seek($start+(($numberOfHMetrics-1)*4));
+			$hm = fread($this->fh,2);
+			$this->seek($start+($numberOfHMetrics*2)+($gid*2));
+			$hm .= fread($this->fh,2);
+		}
+		return $hm;
+	}
+
+	function getLOCA($indexToLocFormat, $numGlyphs) {
+		$start = $this->seek_table('loca');
+		$this->glyphPos = array();
+		if ($indexToLocFormat == 0) {
+			$data = $this->get_chunk($start,($numGlyphs*2)+2);
+			$arr = unpack("n*", $data);
+			for ($n=0; $n<=$numGlyphs; $n++) {
+				$this->glyphPos[] = ($arr[$n+1] * 2);
+			}
+		}
+		else if ($indexToLocFormat == 1) {
+			$data = $this->get_chunk($start,($numGlyphs*4)+4);
+			$arr = unpack("N*", $data);
+			for ($n=0; $n<=$numGlyphs; $n++) {
+				$this->glyphPos[] = ($arr[$n+1]);
+			}
+		}
+		else 
+			die('Unknown location table format '.$indexToLocFormat);
+	}
+
+
+	// CMAP Format 4
+	function getCMAP4($unicode_cmap_offset, &$glyphToChar, &$charToGlyph ) {
+		$this->maxUniChar = 0;	
+		$this->seek($unicode_cmap_offset + 2);
+		$length = $this->read_ushort();
+		$limit = $unicode_cmap_offset + $length;
+		$this->skip(2);
+
+		$segCount = $this->read_ushort() / 2;
+		$this->skip(6);
+		$endCount = array();
+		for($i=0; $i<$segCount; $i++) { $endCount[] = $this->read_ushort(); }
+		$this->skip(2);
+		$startCount = array();
+		for($i=0; $i<$segCount; $i++) { $startCount[] = $this->read_ushort(); }
+		$idDelta = array();
+		for($i=0; $i<$segCount; $i++) { $idDelta[] = $this->read_short(); }		// ???? was unsigned short
+		$idRangeOffset_start = $this->_pos;
+		$idRangeOffset = array();
+		for($i=0; $i<$segCount; $i++) { $idRangeOffset[] = $this->read_ushort(); }
+
+		for ($n=0;$n<$segCount;$n++) {
+			$endpoint = ($endCount[$n] + 1);
+			for ($unichar=$startCount[$n];$unichar<$endpoint;$unichar++) {
+				if ($idRangeOffset[$n] == 0)
+					$glyph = ($unichar + $idDelta[$n]) & 0xFFFF;
+				else {
+					$offset = ($unichar - $startCount[$n]) * 2 + $idRangeOffset[$n];
+					$offset = $idRangeOffset_start + 2 * $n + $offset;
+					if ($offset >= $limit)
+						$glyph = 0;
+					else {
+						$glyph = $this->get_ushort($offset);
+						if ($glyph != 0)
+						   $glyph = ($glyph + $idDelta[$n]) & 0xFFFF;
+					}
+				}
+				$charToGlyph[$unichar] = $glyph;
+				if ($unichar < 196608) { $this->maxUniChar = max($unichar,$this->maxUniChar); }
+				$glyphToChar[$glyph][] = $unichar;
+			}
+		}
+	}
+
+
+		// Put the TTF file together
+	function endTTFile(&$stm) {
+		$stm = '';
+		$numTables = count($this->otables);
+		$searchRange = 1;
+		$entrySelector = 0;
+		while ($searchRange * 2 <= $numTables) {
+			$searchRange = $searchRange * 2;
+			$entrySelector = $entrySelector + 1;
+		}
+		$searchRange = $searchRange * 16;
+		$rangeShift = $numTables * 16 - $searchRange;
+
+		// Header
+		if (_TTF_MAC_HEADER) {
+			$stm .= (pack("Nnnnn", 0x74727565, $numTables, $searchRange, $entrySelector, $rangeShift));	// Mac
+		}
+		else {
+			$stm .= (pack("Nnnnn", 0x00010000 , $numTables, $searchRange, $entrySelector, $rangeShift));	// Windows
+		}
+
+		// Table directory
+		$tables = $this->otables;
+		ksort ($tables); 
+		$offset = 12 + $numTables * 16;
+		foreach ($tables AS $tag=>$data) {
+			if ($tag == 'head') { $head_start = $offset; }
+			$stm .= $tag;
+			$checksum = $this->calcChecksum($data);
+			$stm .= pack("nn", $checksum[0],$checksum[1]);
+			$stm .= pack("NN", $offset, strlen($data));
+			$paddedLength = (strlen($data)+3)&~3;
+			$offset = $offset + $paddedLength;
+		}
+
+		// Table data
+		foreach ($tables AS $tag=>$data) {
+			$data .= "\0\0\0";
+			$stm .= substr($data,0,(strlen($data)&~3));
+		}
+
+		$checksum = $this->calcChecksum($stm);
+		$checksum = $this->sub32(array(0xB1B0,0xAFBA), $checksum);
+		$chk = pack("nn", $checksum[0],$checksum[1]);
+		$stm = $this->splice($stm,($head_start + 8),$chk);
+		return $stm ;
+	}
+
+
+	function repackageTTF($file, $TTCfontID=0, $debug=false) {
+		$this->filename = $file;
+		$this->fh = fopen($file ,'rb') or die('Can\'t open file ' . $file);
+		$this->_pos = 0;
+		$this->charWidths = '';
+		$this->glyphPos = array();
+		$this->charToGlyph = array();
+		$this->tables = array();
+		$this->otables = array();
+		$this->ascent = 0;
+		$this->descent = 0;
+		$this->numTTCFonts = 0;
+		$this->TTCFonts = array();
+		$this->skip(4);
+		$this->maxUni = 0;
+		if ($TTCfontID > 0) {
+			$this->version = $version = $this->read_ulong();	// TTC Header version now
+			if (!in_array($version, array(0x00010000,0x00020000)))
+				die("ERROR - Error parsing TrueType Collection: version=".$version." - " . $file);
+			$this->numTTCFonts = $this->read_ulong();
+			for ($i=1; $i<=$this->numTTCFonts; $i++) {
+	      	      $this->TTCFonts[$i]['offset'] = $this->read_ulong();
+			}
+			$this->seek($this->TTCFonts[$TTCfontID]['offset']);
+			$this->version = $version = $this->read_ulong();	// TTFont version again now
+		}
+		$this->readTableDirectory($debug);
+		$tags = array ('OS/2', 'cmap', 'glyf', 'head', 'hhea', 'hmtx', 'loca', 'maxp', 'name', 'post', 'cvt ', 'fpgm', 'gasp', 'prep');
+/*
+Tables which require glyphIndex
+hdmx
+kern
+LTSH
+
+Tables which do NOT require glyphIndex
+VDMX
+
+GDEF
+GPOS
+GSUB
+JSTF
+
+DSIG
+PCLT - not recommended
+*/
+
+		foreach($tags AS $tag) {
+			if (isset($this->tables[$tag])) { $this->add($tag, $this->get_table($tag)); }
+		}
+		fclose($this->fh);
+		$stm = '';
+		$this->endTTFile($stm);
+		return $stm ;
+	}
+
+
+}
+
+
+?>

+ 236 - 0
sites/all/libraries/MPDF54/classes/wmf.php

@@ -0,0 +1,236 @@
+<?php
+
+class wmf {
+
+var $mpdf = null;
+var $gdiObjectArray;
+
+function wmf(&$mpdf) {
+	$this->mpdf = $mpdf;
+}
+
+
+function _getWMFimage($data) {
+	$k = _MPDFK;
+
+		$this->gdiObjectArray = array();
+		$a=unpack('stest',"\1\0");
+		if ($a['test']!=1)
+		return array(0, 'Error parsing WMF image - Big-endian architecture not supported'); 
+		// check for Aldus placeable metafile header
+		$key = unpack('Lmagic', substr($data, 0, 4));
+		$p = 18;  // WMF header 
+		if ($key['magic'] == (int)0x9AC6CDD7) { $p +=22; } // Aldus header
+		// define some state variables
+		$wo=null; // window origin
+		$we=null; // window extent
+		$polyFillMode = 0;
+		$nullPen = false;
+		$nullBrush = false;
+		$endRecord = false;
+		$wmfdata = '';
+		while ($p < strlen($data) && !$endRecord) {
+			$recordInfo = unpack('Lsize/Sfunc', substr($data, $p, 6));	$p += 6;
+			// size of record given in WORDs (= 2 bytes)
+			$size = $recordInfo['size'];
+			// func is number of GDI function
+			$func = $recordInfo['func'];
+			if ($size > 3) {
+				$parms = substr($data, $p, 2*($size-3));	$p += 2*($size-3);
+			}
+			switch ($func) {
+				case 0x020b:  // SetWindowOrg
+					// do not allow window origin to be changed
+					// after drawing has begun
+					if (!$wmfdata)
+						$wo = array_reverse(unpack('s2', $parms));
+					break;
+				case 0x020c:  // SetWindowExt
+					// do not allow window extent to be changed
+					// after drawing has begun
+					if (!$wmfdata)
+						$we = array_reverse(unpack('s2', $parms));
+					break;
+				case 0x02fc:  // CreateBrushIndirect
+					$brush = unpack('sstyle/Cr/Cg/Cb/Ca/Shatch', $parms);
+					$brush['type'] = 'B';
+					$this->_AddGDIObject($brush);
+					break;
+				case 0x02fa:  // CreatePenIndirect
+					$pen = unpack('Sstyle/swidth/sdummy/Cr/Cg/Cb/Ca', $parms);
+					// convert width from twips to user unit
+					$pen['width'] /= (20 * $k);
+					$pen['type'] = 'P';
+					$this->_AddGDIObject($pen);
+					break;
+
+				// MUST create other GDI objects even if we don't handle them
+				case 0x06fe: // CreateBitmap
+				case 0x02fd: // CreateBitmapIndirect
+				case 0x00f8: // CreateBrush
+				case 0x02fb: // CreateFontIndirect
+				case 0x00f7: // CreatePalette
+				case 0x01f9: // CreatePatternBrush
+				case 0x06ff: // CreateRegion
+				case 0x0142: // DibCreatePatternBrush
+					$dummyObject = array('type'=>'D');
+					$this->_AddGDIObject($dummyObject);
+					break;
+				case 0x0106:  // SetPolyFillMode
+					$polyFillMode = unpack('smode', $parms);
+					$polyFillMode = $polyFillMode['mode'];
+					break;
+				case 0x01f0:  // DeleteObject
+					$idx = unpack('Sidx', $parms);
+					$idx = $idx['idx'];
+					$this->_DeleteGDIObject($idx);
+					break;
+				case 0x012d:  // SelectObject
+					$idx = unpack('Sidx', $parms);
+					$idx = $idx['idx'];
+					$obj = $this->_GetGDIObject($idx);
+					switch ($obj['type']) {
+						case 'B':
+							$nullBrush = false;
+							if ($obj['style'] == 1) { $nullBrush = true; }
+							else {
+								$wmfdata .= $this->mpdf->SetFColor($this->mpdf->ConvertColor('rgb('.$obj['r'].','.$obj['g'].','.$obj['b'].')'), true)."\n";	
+							}
+							break;
+						case 'P':
+							$nullPen = false;
+							$dashArray = array(); 
+							// dash parameters are custom
+							switch ($obj['style']) {
+								case 0: // PS_SOLID
+									break;
+								case 1: // PS_DASH
+									$dashArray = array(3,1);
+									break;
+								case 2: // PS_DOT
+									$dashArray = array(0.5,0.5);
+									break;
+								case 3: // PS_DASHDOT
+									$dashArray = array(2,1,0.5,1);
+									break;
+								case 4: // PS_DASHDOTDOT
+									$dashArray = array(2,1,0.5,1,0.5,1);
+									break;
+								case 5: // PS_NULL
+									$nullPen = true;
+									break;
+							}
+							if (!$nullPen) {
+								$wmfdata .= $this->mpdf->SetDColor($this->mpdf->ConvertColor('rgb('.$obj['r'].','.$obj['g'].','.$obj['b'].')'), true)."\n";
+								$wmfdata .= sprintf("%.3F w\n",$obj['width']*$k);
+							}
+							if (!empty($dashArray)) {
+								$s = '[';
+								for ($i=0; $i<count($dashArray);$i++) {
+									$s .= $dashArray[$i] * $k;
+									if ($i != count($dashArray)-1) { $s .= ' '; }
+								}
+								$s .= '] 0 d';
+								$wmfdata .= $s."\n";
+							}
+							break;
+					}
+					break;
+				case 0x0325: // Polyline
+				case 0x0324: // Polygon
+					$coords = unpack('s'.($size-3), $parms);
+					$numpoints = $coords[1];
+					for ($i = $numpoints; $i > 0; $i--) {
+						$px = $coords[2*$i];
+						$py = $coords[2*$i+1];
+
+						if ($i < $numpoints) { $wmfdata .= $this->_LineTo($px, $py); }
+					   else { $wmfdata .= $this->_MoveTo($px, $py); }
+					}
+					if ($func == 0x0325) { $op = 's'; }
+					else if ($func == 0x0324) {
+						if ($nullPen) {
+							if ($nullBrush) { $op = 'n'; } // no op
+							else { $op = 'f'; } // fill
+						}
+						else {
+							if ($nullBrush) { $op = 's'; } // stroke
+							else { $op = 'b'; } // stroke and fill
+						}
+						if ($polyFillMode==1 && ($op=='b' || $op=='f')) { $op .= '*'; } // use even-odd fill rule
+					}
+					$wmfdata .= $op."\n";
+					break;
+				case 0x0538: // PolyPolygon
+					$coords = unpack('s'.($size-3), $parms);
+					$numpolygons = $coords[1];
+					$adjustment = $numpolygons;
+					for ($j = 1; $j <= $numpolygons; $j++) {
+						$numpoints = $coords[$j + 1];
+						for ($i = $numpoints; $i > 0; $i--) {
+							$px = $coords[2*$i   + $adjustment];
+							$py = $coords[2*$i+1 + $adjustment];
+							if ($i == $numpoints) { $wmfdata .= $this->_MoveTo($px, $py); }
+							else { $wmfdata .= $this->_LineTo($px, $py); }
+						}
+						$adjustment += $numpoints * 2;
+					}
+
+					if ($nullPen) {
+						if ($nullBrush) { $op = 'n'; } // no op
+						else { $op = 'f'; } // fill
+					}
+					else {
+						if ($nullBrush) { $op = 's'; } // stroke
+						else { $op = 'b'; } // stroke and fill
+					}
+					if ($polyFillMode==1 && ($op=='b' || $op=='f')) { $op .= '*'; } // use even-odd fill rule
+					$wmfdata .= $op."\n";
+					break;
+				case 0x0000:
+					$endRecord = true;
+					break;
+			}
+		}
+
+
+	return array(1,$wmfdata,$wo,$we);
+}
+
+
+function _MoveTo($x, $y) {
+	return "$x $y m\n";
+}
+
+// a line must have been started using _MoveTo() first
+function _LineTo($x, $y) {
+	return "$x $y l\n";
+}
+
+function _AddGDIObject($obj) {
+	// find next available slot
+	$idx = 0;
+	if (!empty($this->gdiObjectArray)) {
+		$empty = false;
+		$i = 0;
+		while (!$empty) {
+			$empty = !isset($this->gdiObjectArray[$i]);
+			$i++;
+		}
+		$idx = $i-1;
+	}
+	$this->gdiObjectArray[$idx] = $obj;
+}
+
+function _GetGDIObject($idx) {
+	return $this->gdiObjectArray[$idx];
+}
+
+function _DeleteGDIObject($idx) {
+	unset($this->gdiObjectArray[$idx]);
+}
+
+
+}
+
+?>

+ 172 - 0
sites/all/libraries/MPDF54/compress.php

@@ -0,0 +1,172 @@
+<?php
+
+$excl = array( 'HTML-CSS', 'DIRECTW', 'TABLES', 'LISTS', 'IMAGES-CORE', 
+'IMAGES-BMP', 'IMAGES-WMF', 'TABLES-ADVANCED-BORDERS', 'HTMLHEADERS-FOOTERS', 'COLUMNS', 'TOC', 'INDEX', 'BOOKMARKS', 'BARCODES', 'FORMS', 'WATERMARK', 'CJK-FONTS', 'RTL', 'INDIC', 'ANNOTATIONS', 'BACKGROUNDS', 'CSS-FLOAT', 'CSS-IMAGE-FLOAT', 'CSS-POSITION', 'CSS-PAGE', 'BORDER-RADIUS', 'HYPHENATION', 'ENCRYPTION', 'IMPORTS', 'PROGRESS-BAR');
+
+
+	// *DIRECTW* = Write, WriteText, WriteCell, Text, Shaded_box, AutosizeText
+	// IMAGES-CORE = [PNG, GIF, and JPG] NB background-images and watermark images
+
+	// Excluding 'HTML-CSS' will also exclude: 'TABLES', 'LISTS', 'TABLES-ADVANCED-BORDERS', 'HTMLHEADERS-FOOTERS', 'FORMS', 'BACKGROUNDS', 'CSS-FLOAT', 'CSS-IMAGE-FLOAT', 'CSS-POSITION', 'CSS-PAGE', 'BORDER-RADIUS'
+
+// Text is marked in mpdf_source.php with e.g. :
+/*-- TABLES-ADVANCED-BORDERS --*/
+/*-- END TABLES-ADVANCED-BORDERS --*/
+	// *TABLES-ADVANCED-BORDERS*
+
+
+if (!isset($_POST['generate']) || $_POST['generate']!='generate') {
+
+
+if (!file_exists('mpdf_source.php')) {
+	die("ERROR - Could not find mpdf_source.php file in current directory. Please rename mpdf.php as mpdf_source.php"); 
+}
+
+
+
+
+echo '<html>
+<head>
+<script language=javascript>
+checked=false;
+function checkedAll (frm1) {
+	var aa= document.getElementById("frm1");
+	 if (checked == false)
+          {
+           checked = true
+          }
+        else
+          {
+          checked = false
+          }
+	for (var i =0; i < aa.elements.length; i++) 
+	{
+	 aa.elements[i].checked = checked;
+	}
+      }
+</script>
+</head>
+<body>
+<p><span style="color:red; font-weight: bold;">WARNING</span>: This utility will OVERWRITE mpdf.php file in the current directory.</p>
+<p>Select the functions you wish to INCLUDE in your mpdf.php program. When you click generate, a new mpdf.php file will be written to the current directory.</p>
+<div><b>Notes</b>
+<ul>
+<li>HTML-CSS is required for many of the other functions to work including: Tables, Lists, Backgrounds, Forms, Border-radius and all other CSS</li>
+<li>DIRECTW includes the functions to Write directly to the PDF file e.g. Write, WriteText, WriteCell, Text, Shaded_box, AutosizeText</li>
+<li>You must include either HTML-CSS or DIRECTW</li>
+<li>JPG, PNG and JPG images are supported with IMAGES-CORE</li>
+<li>For WMF Images, you must include both IMAGES-CORE and IMAGES-WMF</li>
+<li>IMAGES-CORE are required for BACKGROUNDS (IMAGES) or WATERMARKS to work</li>
+</ul>
+</div>
+<input type="checkbox" name="checkall" onclick="checkedAll(frm1);"> <i>Select/Unselect All</i><br /><br />
+
+<form id="frm1" action="compress.php" method="POST">
+';
+foreach($excl AS $k=>$ex) {
+	echo '<input type="checkbox" value="1" name="inc['.$ex.']"';
+	if ($k==0 || ($k > 1 && $k < 5)) {
+		echo ' checked="checked"';
+	}
+	echo ' /> '.$ex.'<br />';
+}
+
+echo '<br />
+<input type="submit" name="generate" value="generate" />
+</form>
+</body>
+</html>';
+exit;
+}
+
+$inc = $_POST['inc'];
+if (is_array($inc) && count($inc)>0 ) { 
+	foreach($inc AS $i=>$v) {
+		$key = array_search($i, $excl);
+		unset($excl[$key]);
+	}
+}
+
+if (!defined('PHP_VERSION_ID')) {
+    $version = explode('.', PHP_VERSION);
+    define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));
+}
+if (PHP_VERSION_ID < 50300) { $mqr = @get_magic_quotes_runtime(); }
+	else { $mqr=0; }
+if ($mqr) { set_magic_quotes_runtime(0); }
+
+$l = file('mpdf_source.php');
+if (!count($l)) { die("ERROR - Could not find mpdf_source.php file in current directory"); }
+$exclflags = array();
+$x = '';
+
+	// Excluding 'HTML-CSS' will also exclude: 'TABLES', 'LISTS', 'TABLES-ADVANCED-BORDERS', 'HTMLHEADERS-FOOTERS', 'FORMS', 'BACKGROUNDS', 'CSS-FLOAT', 'CSS-IMAGE-FLOAT', 'CSS-POSITION', 'CSS-PAGE', 'BORDER-RADIUS'
+if ($excl[0]=='HTML-CSS') {
+	$excl[] = 'TABLES';
+	$excl[] = 'LISTS';
+	$excl[] = 'TABLES-ADVANCED-BORDERS';
+	$excl[] = 'HTMLHEADERS-FOOTERS';
+	$excl[] = 'FORMS';
+	$excl[] = 'BACKGROUNDS';
+	$excl[] = 'CSS-FLOAT';
+	$excl[] = 'CSS-IMAGE-FLOAT';
+	$excl[] = 'CSS-POSITION';
+	$excl[] = 'CSS-PAGE';
+	$excl[] = 'BORDER-RADIUS';
+}
+$excl = array_unique($excl);
+
+foreach($l AS $k=>$ln) {
+	$exclude = false;
+	// *XXXXX*
+	preg_match_all("/\/\/ \*([A-Za-z\-]+)\*/", $ln, $m);
+	foreach($m[1] AS $mm) {
+		if (in_array($mm, $excl)) {
+			$exclude = true;
+		}
+	}
+	/*-- XXXXX --*/
+	preg_match_all("/\/\*-- ([A-Za-z\-]+) --\*\//", $ln, $m);
+	foreach($m[1] AS $mm) {
+		if (in_array($mm, $excl)) {
+			$exclflags[$mm] = true;
+		}
+		$exclude = true;
+	}
+	$exclflags = array_unique($exclflags);
+	/*-- END XXXX --*/
+	preg_match_all("/\/\*-- END ([A-Za-z\-]+) --\*\//", $ln, $m);
+	foreach($m[1] AS $mm) {
+		if (in_array($mm, $excl)) {
+			unset($exclflags[$mm]);
+		}
+		$exclude = true;
+	}
+	if (count($exclflags)==0 && !$exclude) { 
+		$x .= $ln; 
+	}
+}
+// mPDF 5.0
+if (function_exists('file_put_contents')) {
+	$check = file_put_contents('mpdf.php', $x);
+}
+else {
+	$f=fopen('mpdf.php', 'w');
+	$check = fwrite($f, $x);
+	fclose($f);
+}
+if (!$check) { die("ERROR - Could not write to mpdf.php file. Are permissions correctly set?"); }
+echo '<p><b>mPDF file generated successfully!</b></p>';
+echo '<div>mPDF file size '.number_format((strlen($x)/1024)).' kB</div>';
+
+unset($l);
+unset($x);
+
+include('mpdf.php');
+$mpdf = new mPDF();
+
+echo '<div>Memory usage on loading mPDF class '.number_format((memory_get_usage(true)/(1024*1024)),2).' MB</div>';
+
+exit;
+
+?>

File diff suppressed because it is too large
+ 499 - 0
sites/all/libraries/MPDF54/config.php


+ 153 - 0
sites/all/libraries/MPDF54/config_cp.php

@@ -0,0 +1,153 @@
+<?php
+
+
+function GetLangOpts($llcc, $adobeCJK) {
+	if (strlen($llcc) == 5) {
+		$lang = substr(strtolower($llcc),0,2);
+		$country = substr(strtoupper($llcc),3,2);
+	}
+	else { $lang = strtolower($llcc); $country = ''; }
+	$unifonts = "";
+	$coreSuitable = false;
+
+	switch($lang){
+	  CASE "en":
+	  CASE "ca":
+	  CASE "cy":
+	  CASE "da":
+	  CASE "de":
+	  CASE "es":
+	  CASE "eu":
+	  CASE "fr":
+	  CASE "ga":
+	  CASE "fi": 
+	  CASE "is":
+	  CASE "it":
+	  CASE "nl":
+	  CASE "no":
+	  CASE "pt":
+	  CASE "sv":
+		// Edit this value to define how mPDF behaves when using new mPDF('-x')
+		// If set to TRUE, mPDF will use Adobe core fonts only when it recognises the languages above
+		$coreSuitable = true;  break;
+
+
+
+	  // RTL Languages
+	  CASE "he":
+	  CASE "yi":
+		$unifonts = "dejavusans,dejavusansB,dejavusansI,dejavusansBI";  break;
+
+	  // Arabic
+	  CASE "ar":  
+		$unifonts = "xbriyaz,xbriyazB,xbriyazI,xbriyazBI,xbzar,xbzarB,xbzarI,xbzarBI";  break;
+	  CASE "fa":  
+		$unifonts = "xbriyaz,xbriyazB,xbriyazI,xbriyazBI,xbzar,xbzarB,xbzarI,xbzarBI";  break;
+	  CASE "ps": 
+		$unifonts = "xbriyaz,xbriyazB,xbriyazI,xbriyazBI,xbzar,xbzarB,xbzarI,xbzarBI"; break;
+	  CASE "ur":  
+		$unifonts = "xbriyaz,xbriyazB,xbriyazI,xbriyazBI,xbzar,xbzarB,xbzarI,xbzarBI"; break;
+
+	  // Sindhi (can be Arabic or Devanagari)
+	  CASE "sd":
+		if ($country == "IN") { $unifonts = "ind_hi_1_001"; }
+	//	else if ($country == "PK") { $unifonts = ""; }
+	//	else { $unifonts = ""; }
+		break;
+
+
+	  // INDIC 
+	  // Assamese
+	  CASE "as":  $unifonts = "ind_bn_1_001"; break;
+	  // Bengali
+	  CASE "bn":  $unifonts = "ind_bn_1_001"; break;
+	  // Gujarati
+	  CASE "gu":  $unifonts = "ind_gu_1_001"; break;
+	  // Hindi (Devanagari)
+	  CASE "hi":  $unifonts = "ind_hi_1_001"; break;
+	  // Kannada
+	  CASE "kn":  $unifonts = "ind_kn_1_001"; break;
+	  // Kashmiri
+	  CASE "ks":  $unifonts = "ind_hi_1_001"; break;
+	  // Malayalam
+	  CASE "ml":  $unifonts = "ind_ml_1_001"; break;
+	  // Nepali (Devanagari)
+	  CASE "ne":  $unifonts = "ind_hi_1_001"; break;
+	  // Oriya
+	  CASE "or":  $unifonts = "ind_or_1_001"; break;
+	  // Punjabi (Gurmukhi)
+	  CASE "pa":  $unifonts = "ind_pa_1_001"; break;
+	  // Tamil
+	  CASE "ta":  $unifonts = "ind_ta_1_001"; break;
+	  // Telegu
+	  CASE "te":  $unifonts = "ind_te_1_001"; break;
+
+	  // THAI
+	  CASE "th":  $unifonts = "garuda,garudaB,garudaI,garudaBI,norasi,norasiB,norasiI,norasiBI";  break;
+
+	  // VIETNAMESE
+	  CASE "vi":  
+		$unifonts = "dejavusanscondensed,dejavusanscondensedB,dejavusanscondensedI,dejavusanscondensedBI,dejavusans,dejavusansB,dejavusansI,dejavusansBI"; break;
+
+	  // CJK Langauges
+	  CASE "ja":  
+		if ($adobeCJK) {
+			$unifonts = "sjis,sjisB,sjisI,sjisBI";
+		}
+/* Uncomment these lines if CJK fonts available */
+//		else {
+//			$unifonts = "sun-exta,sun-extb,hannoma,hannomb";
+//		}
+		break;
+
+	  CASE "ko":  
+		if ($adobeCJK) {
+			$unifonts = "uhc,uhcB,uhcI,uhcBI";
+		}
+/* Uncomment these lines if CJK fonts available */
+//		else {
+//			$unifonts = "unbatang_0613"; 
+//		}
+		break;
+
+	  CASE "zh":
+		if ($country == "HK" || $country == "TW") { 
+			if ($adobeCJK) {
+				$unifonts = "big5,big5B,big5I,big5BI"; 
+			}
+/* Uncomment these lines if CJK fonts available */
+//			else {
+//				$unifonts = "sun-exta,sun-extb,hannoma,hannomb";
+//			}
+		}
+		else if ($country == "CN") { 
+			if ($adobeCJK) {
+				$unifonts = "gb,gbB,gbI,gbBI";  
+			}
+/* Uncomment these lines if CJK fonts available */
+//			else {
+//				$unifonts = "sun-exta,sun-extb,hannoma,hannomb";
+//			}
+		}
+	  	else { 
+			if ($adobeCJK) {
+				$unifonts = "gb,gbB,gbI,gbBI"; 
+			}
+/* Uncomment these lines if CJK fonts available */
+//			else {
+//				$unifonts = "sun-exta,sun-extb,hannoma,hannomb";
+//			}
+		}
+		break;
+
+	}
+
+
+	$unifonts_arr = array();
+	if ($unifonts) {
+		$unifonts_arr = preg_split('/\s*,\s*/',$unifonts);
+	}
+	return array($coreSuitable ,$unifonts_arr);
+}
+
+?>

+ 302 - 0
sites/all/libraries/MPDF54/config_fonts.php

@@ -0,0 +1,302 @@
+<?php
+
+
+// Optionally define a folder which contains TTF fonts
+// mPDF will look here before looking in the usual _MPDF_TTFONTPATH
+// Useful if you already have a folder for your fonts
+// e.g. on Windows: define("_MPDF_SYSTEM_TTFONTS", 'C:/Windows/Fonts/');
+// Leave undefined if not required
+
+// define("_MPDF_SYSTEM_TTFONTS", '');
+
+
+// Optionally set font(s) (names as defined below in $this->fontdata) to use for missing characters
+// when using useSubstitutions. Use a font with wide coverage - dejavusanscondensed is a good start
+// only works using subsets (otherwise would add very large file)
+// doesn't do Indic or arabic
+// More than 1 font can be specified but each will add to the processing time of the script
+
+$this->backupSubsFont = array('dejavusanscondensed');
+
+
+// Optionally set a font (name as defined below in $this->fontdata) to use for CJK characters
+// in Plane 2 Unicode (> U+20000) when using useSubstitutions. 
+// Use a font like hannomb or sun-extb if available
+// only works using subsets (otherwise would add very large file)
+// Leave undefined or blank if not not required
+
+// $this->backupSIPFont = 'sun-extb';
+
+
+/*
+This array defines translations from font-family in CSS or HTML
+to the internal font-family name used in mPDF. 
+Can include as many as want, regardless of which fonts are installed.
+By default mPDF will take a CSS/HTML font-family and remove spaces
+and change to lowercase e.g. "Arial Unicode MS" will be recognised as
+"arialunicodems"
+You only need to define additional translations.
+You can also use it to define specific substitutions e.g.
+'frutiger55roman' => 'arial'
+Generic substitutions (i.e. to a sans-serif or serif font) are set 
+by including the font-family in $this->sans_fonts below
+To aid backwards compatability some are included:
+*/
+$this->fonttrans = array(
+	'helvetica' => 'arial',
+	'times' => 'timesnewroman',
+	'courier' => 'couriernew',
+	'trebuchet' => 'trebuchetms',
+	'comic' => 'comicsansms',
+	'franklin' => 'franklingothicbook',
+	'albertus' => 'albertusmedium',
+	'arialuni' => 'arialunicodems',
+	'zn_hannom_a' => 'hannoma',
+	'ocr-b' => 'ocrb',
+	'ocr-b10bt' => 'ocrb',
+
+
+);
+
+/*
+This array lists the file names of the TrueType .ttf or .otf font files
+for each variant of the (internal mPDF) font-family name.
+['R'] = Regular (Normal), others are Bold, Italic, and Bold-Italic
+Each entry must contain an ['R'] entry, but others are optional.
+Only the font (files) entered here will be available to use in mPDF.
+Put preferred default first in order.
+This will be used if a named font cannot be found in any of 
+$this->sans_fonts, $this->serif_fonts or $this->mono_fonts
+
+['indic'] = true; for special mPDF fonts containing Indic characters
+['sip-ext'] = 'hannomb'; name a related font file containing SIP characters
+
+If a .ttc TrueType collection file is referenced, the number of the font
+within the collection is required. Fonts in the collection are numbered 
+starting at 1, as they appear in the .ttc file e.g.
+	"cambria" => array(
+		'R' => "cambria.ttc",
+		'B' => "cambriab.ttf",
+		'I' => "cambriai.ttf",
+		'BI' => "cambriaz.ttf",
+		'TTCfontID' => array(
+			'R' => 1,	
+			),
+		),
+	"cambriamath" => array(
+		'R' => "cambria.ttc",
+		'TTCfontID' => array(
+			'R' => 2,	
+			),
+		),
+*/
+
+$this->fontdata = array(
+	"dejavusanscondensed" => array(
+		'R' => "DejaVuSansCondensed.ttf",
+		'B' => "DejaVuSansCondensed-Bold.ttf",
+		'I' => "DejaVuSansCondensed-Oblique.ttf",
+		'BI' => "DejaVuSansCondensed-BoldOblique.ttf",
+		),
+	"dejavusans" => array(
+		'R' => "DejaVuSans.ttf",
+		'B' => "DejaVuSans-Bold.ttf",
+		'I' => "DejaVuSans-Oblique.ttf",
+		'BI' => "DejaVuSans-BoldOblique.ttf",
+		),
+	"dejavuserif" => array(
+		'R' => "DejaVuSerif.ttf",
+		'B' => "DejaVuSerif-Bold.ttf",
+		'I' => "DejaVuSerif-Italic.ttf",
+		'BI' => "DejaVuSerif-BoldItalic.ttf",
+		),
+	"dejavuserifcondensed" => array(
+		'R' => "DejaVuSerifCondensed.ttf",
+		'B' => "DejaVuSerifCondensed-Bold.ttf",
+		'I' => "DejaVuSerifCondensed-Italic.ttf",
+		'BI' => "DejaVuSerifCondensed-BoldItalic.ttf",
+		),
+	"dejavusansmono" => array(
+		'R' => "DejaVuSansMono.ttf",
+		'B' => "DejaVuSansMono-Bold.ttf",
+		'I' => "DejaVuSansMono-Oblique.ttf",
+		'BI' => "DejaVuSansMono-BoldOblique.ttf",
+		),
+
+
+/* OCR-B font for Barcodes */
+	"ocrb" => array(
+		'R' => "ocrb10.ttf",
+		),
+
+/* Thai fonts */
+	"garuda" => array(
+		'R' => "Garuda.ttf",
+		'B' => "Garuda-Bold.ttf",
+		'I' => "Garuda-Oblique.ttf",
+		'BI' => "Garuda-BoldOblique.ttf",
+		),
+	"norasi" => array(
+		'R' => "Norasi.ttf",
+		'B' => "Norasi-Bold.ttf",
+		'I' => "Norasi-Oblique.ttf",
+		'BI' => "Norasi-BoldOblique.ttf",
+		),
+
+
+/* Indic fonts */
+	"ind_bn_1_001" => array(
+		'R' => "ind_bn_1_001.ttf",
+		'indic' => true,
+		),
+	"ind_hi_1_001" => array(
+		'R' => "ind_hi_1_001.ttf",
+		'indic' => true,
+		),
+	"ind_ml_1_001" => array(
+		'R' => "ind_ml_1_001.ttf",
+		'indic' => true,
+		),
+	"ind_kn_1_001" => array(
+		'R' => "ind_kn_1_001.ttf",
+		'indic' => true,
+		),
+	"ind_gu_1_001" => array(
+		'R' => "ind_gu_1_001.ttf",
+		'indic' => true,
+		),
+	"ind_or_1_001" => array(
+		'R' => "ind_or_1_001.ttf",
+		'indic' => true,
+		),
+	"ind_ta_1_001" => array(
+		'R' => "ind_ta_1_001.ttf",
+		'indic' => true,
+		),
+	"ind_te_1_001" => array(
+		'R' => "ind_te_1_001.ttf",
+		'indic' => true,
+		),
+	"ind_pa_1_001" => array(
+		'R' => "ind_pa_1_001.ttf",
+		'indic' => true,
+		),
+
+
+/* XW Zar Arabic fonts */
+	"xbriyaz" => array(
+		'R' => "XB Riyaz.ttf",
+		'B' => "XB RiyazBd.ttf",
+		'I' => "XB RiyazIt.ttf",
+		'BI' => "XB RiyazBdIt.ttf",
+		),
+	"xbzar" => array(
+		'R' => "XB Zar.ttf",
+		'B' => "XB Zar Bd.ttf",
+		'I' => "XB Zar It.ttf",
+		'BI' => "XB Zar BdIt.ttf",
+		),
+
+
+
+
+/* Examples of some CJK fonts */
+/*
+	"unbatang_0613" => array(
+		'R' => "UnBatang_0613.ttf",
+		),
+	"sun-exta" => array(
+		'R' => "Sun-ExtA.ttf",
+		'sip-ext' => 'sun-extb',
+		),
+	"sun-extb" => array(
+		'R' => "Sun-ExtB.ttf",
+		),
+	"hannoma" => array(
+		'R' => "HAN NOM A.ttf",
+		'sip-ext' => 'hannomb',	
+		),
+	"hannomb" => array(
+		'R' => "HAN NOM B.ttf",
+		),
+
+
+	'mingliu' => array (
+		'R' => 'mingliu.ttc',
+		'TTCfontID' => array (
+			'R' => 1,
+		),
+		'sip-ext' => 'mingliu-extb',
+	),
+	'pmingliu' => array (
+		'R' => 'mingliu.ttc',
+		'TTCfontID' => array (
+			'R' => 2,
+		),
+		'sip-ext' => 'pmingliu-extb',
+	),
+	'mingliu_hkscs' => array (
+		'R' => 'mingliu.ttc',
+		'TTCfontID' => array (
+			'R' => 3,
+		),
+		'sip-ext' => 'mingliu_hkscs-extb',
+	),
+	'mingliu-extb' => array (
+		'R' => 'mingliub.ttc',
+		'TTCfontID' => array (
+			'R' => 1,
+		),
+	),
+	'pmingliu-extb' => array (
+		'R' => 'mingliub.ttc',
+		'TTCfontID' => array (
+			'R' => 2,
+		),
+	),
+	'mingliu_hkscs-extb' => array (
+		'R' => 'mingliub.ttc',
+		'TTCfontID' => array (
+			'R' => 3,
+		),
+	),
+*/
+
+);
+
+
+// Add fonts to this array if they contain characters in the SIP or SMP Unicode planes
+// but you do not require them. This allows a more efficient form of subsetting to be used.
+$this->BMPonly = array(
+	"dejavusanscondensed",
+	"dejavusans",
+	"dejavuserifcondensed",
+	"dejavuserif",
+	"dejavusansmono",
+	);
+
+// These next 3 arrays do two things:
+// 1. If a font referred to in HTML/CSS is not available to mPDF, these arrays will determine whether
+//    a serif/sans-serif or monospace font is substituted
+// 2. The first font in each array will be the font which is substituted in circumstances as above
+//     (Otherwise the order is irrelevant)
+// Use the mPDF font-family names i.e. lowercase and no spaces (after any translations in $fonttrans)
+// Always include "sans-serif", "serif" and "monospace" etc.
+$this->sans_fonts = array('dejavusanscondensed','dejavusans','freesans','liberationsans','sans','sans-serif','cursive','fantasy', 
+				'arial','helvetica','verdana','geneva','lucida','arialnarrow','arialblack','arialunicodems',
+				'franklin','franklingothicbook','tahoma','garuda','calibri','trebuchet','lucidagrande','microsoftsansserif',
+				'trebuchetms','lucidasansunicode','franklingothicmedium','albertusmedium','xbriyaz','albasuper','quillscript'
+
+);
+
+$this->serif_fonts = array('dejavuserifcondensed','dejavuserif','freeserif','liberationserif','serif',
+				'timesnewroman','times','centuryschoolbookl','palatinolinotype','centurygothic',
+				'bookmanoldstyle','bookantiqua','cyberbit','cambria',
+				'norasi','charis','palatino','constantia','georgia','albertus','xbzar','algerian','garamond',
+);
+
+$this->mono_fonts = array('dejavusansmono','freemono','liberationmono','courier', 'mono','monospace','ocrb','ocr-b','lucidaconsole',
+				'couriernew','monotypecorsiva'
+);
+
+?>

BIN
sites/all/libraries/MPDF54/examples/alpha.gif


BIN
sites/all/libraries/MPDF54/examples/alpha.png


BIN
sites/all/libraries/MPDF54/examples/alpha3.png


BIN
sites/all/libraries/MPDF54/examples/bayeux1.jpg


BIN
sites/all/libraries/MPDF54/examples/bg.jpg


BIN
sites/all/libraries/MPDF54/examples/bgbarcode.png


BIN
sites/all/libraries/MPDF54/examples/bgrock.jpg


BIN
sites/all/libraries/MPDF54/examples/borders2FF.jpg


BIN
sites/all/libraries/MPDF54/examples/borders2IE.jpg


BIN
sites/all/libraries/MPDF54/examples/borders3FF.jpg


BIN
sites/all/libraries/MPDF54/examples/borders3IE.jpg


BIN
sites/all/libraries/MPDF54/examples/borders4FF.jpg


BIN
sites/all/libraries/MPDF54/examples/borders4IE.jpg


BIN
sites/all/libraries/MPDF54/examples/bordersFF.jpg


BIN
sites/all/libraries/MPDF54/examples/bordersIE.jpg


BIN
sites/all/libraries/MPDF54/examples/bordersMPDF2.jpg


BIN
sites/all/libraries/MPDF54/examples/clematis.jpg


File diff suppressed because it is too large
+ 11 - 0
sites/all/libraries/MPDF54/examples/example01_basic.php


File diff suppressed because it is too large
+ 11 - 0
sites/all/libraries/MPDF54/examples/example02_CSS_styles.php


File diff suppressed because it is too large
+ 71 - 0
sites/all/libraries/MPDF54/examples/example03_backgrounds_and_borders.php


+ 207 - 0
sites/all/libraries/MPDF54/examples/example04_images.php

@@ -0,0 +1,207 @@
+<?php
+
+
+
+$html = '
+<style>
+table { border-collapse: collapse; margin-top: 0; text-align: center; }
+td { padding: 0.5em; }
+h1 { margin-bottom: 0; }
+</style>
+<h1>mPDF Images</h1>
+
+<table>
+<tr>
+<td>GIF</td>
+<td>JPG</td>
+<td>JPG (CMYK)</td>
+<td>PNG</td>
+<td>BMP</td>
+<td>WMF</td>
+<td>SVG</td>
+</tr>
+<tr>
+<td><img style="vertical-align: top" src="tiger.gif" width="80" /></td>
+<td><img style="vertical-align: top" src="tiger.jpg" width="80" /></td>
+<td><img style="vertical-align: top" src="tigercmyk.jpg" width="80" /></td>
+<td><img style="vertical-align: top" src="tiger.png" width="80" /></td>
+<td><img style="vertical-align: top" src="tiger.bmp" width="80" /></td>
+<td><img style="vertical-align: top" src="tiger2.wmf" width="80" /></td>
+<td><img style="vertical-align: top" src="tiger.svg" width="80" /></td>
+</tr>
+</tr>
+<tr>
+<td colspan="7" style="text-align: left" ><h4>Opacity 50%</h4></td>
+</tr>
+<tr>
+<tr>
+<td><img style="vertical-align: top; opacity: 0.5" src="tiger.gif" width="80" /></td>
+<td><img style="vertical-align: top; opacity: 0.5" src="tiger.jpg" width="80" /></td>
+<td><img style="vertical-align: top; opacity: 0.5" src="tigercmyk.jpg" width="80" /></td>
+<td><img style="vertical-align: top; opacity: 0.5" src="tiger.png" width="80" /></td>
+<td><img style="vertical-align: top; opacity: 0.5" src="tiger.bmp" width="80" /></td>
+<td><img style="vertical-align: top; opacity: 0.5" src="tiger2.wmf" width="80" /></td>
+<td><img style="vertical-align: top; opacity: 0.5" src="tiger.svg" width="80" /></td>
+</tr>
+</table>
+
+<h4>Alpha channel</h4>
+<table>
+<tr>
+<td>PNG</td>
+<td><img style="vertical-align: top" src="alpha.png" width="85" /></td>
+<td style="background-color:#FFCCFF; "><img style="vertical-align: top" src="alpha.png" width="85" /></td>
+<td style="background-color:#FFFFCC;"><img style="vertical-align: top" src="alpha.png" width="85" /></td>
+<td style="background-color:#CCFFFF;"><img style="vertical-align: top" src="alpha.png" width="85" /></td>
+<td style="background-color:#CCFFFF; background: transparent url(\'bg.jpg\') repeat scroll right top;"><img style="vertical-align: top" src="alpha.png" width="85" /></td>
+</tr>
+</table>
+<h4>Transparency</h4>
+<table><tr>
+<td>PNG</td>
+<td style="background-color:#FFCCFF; "><img style="vertical-align: top" src="tiger24trns.png" width="85" /></td>
+<td style="background-color:#FFFFCC;"><img style="vertical-align: top" src="tiger24trns.png" width="85" /></td>
+<td style="background-color:#CCFFFF;"><img style="vertical-align: top" src="tiger24trns.png" width="85" /></td>
+<td style="background-color:#CCFFFF; background: transparent url(\'bg.jpg\') repeat scroll right top;"><img style="vertical-align: top" src="tiger24trns.png" width="85" /></td>
+</tr><tr>
+<td>GIF</td>
+<td style="background-color:#FFCCFF;"><img style="vertical-align: top" src="tiger8trns.gif" width="85" /></td>
+<td style="background-color:#FFFFCC;"><img style="vertical-align: top" src="tiger8trns.gif" width="85" /></td>
+<td style="background-color:#CCFFFF;"><img style="vertical-align: top" src="tiger8trns.gif" width="85" /></td>
+<td style="background-color:#CCFFFF; background: transparent url(\'bg.jpg\') repeat scroll right top;"><img style="vertical-align: top" src="tiger8trns.gif" width="85" /></td>
+</tr><tr>
+<td>WMF</td>
+<td style="background-color:#FFCCFF;"><img style="vertical-align: top" src="tiger2.wmf" width="85" /></td>
+<td style="background-color:#FFFFCC;"><img style="vertical-align: top" src="tiger2.wmf" width="85" /></td>
+<td style="background-color:#CCFFFF;"><img style="vertical-align: top" src="tiger2.wmf" width="85" /></td>
+<td style="background-color:#CCFFFF; background: transparent url(\'bg.jpg\') repeat scroll right top;"><img style="vertical-align: top" src="tiger2.wmf" width="85" /></td>
+</tr><tr>
+<td>SVG</td>
+<td style="background-color:#FFCCFF;"><img style="vertical-align: top" src="tiger.svg" width="85" /></td>
+<td style="background-color:#FFFFCC;"><img style="vertical-align: top" src="tiger.svg" width="85" /></td>
+<td style="background-color:#CCFFFF;"><img style="vertical-align: top" src="tiger.svg" width="85" /></td>
+<td style="background-color:#CCFFFF; background: transparent url(\'bg.jpg\') repeat scroll right top;"><img style="vertical-align: top" src="tiger.svg" width="85" /></td>
+</tr></table>
+
+
+Images returned from tiger.php
+<div>
+GIF <img style="vertical-align: top" src="tiger.php?t=gif" width="85" />
+JPG <img style="vertical-align: top" src="tiger.php?t=jpg" width="85" />
+PNG <img style="vertical-align: top" src="tiger.php?t=png" width="85" />
+WMF <img style="vertical-align: top" src="tiger.php?t=wmf" width="85" />
+SVG <img style="vertical-align: top" src="tiger.php?t=svg" width="85" />
+</div>
+
+<pagebreak />
+
+
+<h3>Image Alignment</h3>
+<div>From mPDF version 4.2 onwards, in-line images can be individually aligned (vertically). Most of the values for "vertical-align" are supported: top, bottom, middle, baseline, text-top, and text-bottom. The default value for vertical alignment has been changed to baseline, and the default padding to 0, consistent with most browsers.
+</div>
+<br />
+
+<div style="background-color:#CCFFFF;">
+These images <img src="img1.png" style="vertical-align: top;" />
+are <img src="img2.png" style="vertical-align: top;" />
+<b>top</b> <img src="img3.png" style="vertical-align: top;" />
+aligned <img src="img4.png" style="vertical-align: middle;" />
+</div>
+<br />
+
+<div style="background-color:#CCFFFF;">
+These images <img src="img1.png" style="vertical-align: text-top;" />
+are <img src="img2.png" style="vertical-align: text-top;" />
+<b>text-top</b> <img src="img3.png" style="vertical-align: text-top;" />
+aligned <img src="img4.png" style="vertical-align: middle;" />
+</div>
+<br />
+
+<div style="background-color:#CCFFFF;">
+These images <img src="img1.png" style="vertical-align: bottom;" />
+are <img src="img2.png" style="vertical-align: bottom;" />
+<b>bottom</b> <img src="img3.png" style="vertical-align: bottom;" />
+aligned <img src="img4.png" style="vertical-align: middle;" />
+</div>
+<br />
+
+<div style="background-color:#CCFFFF;">
+These images <img src="img1.png" style="vertical-align: text-bottom;" />
+are <img src="img2.png" style="vertical-align: text-bottom;" />
+<b>text-bottom</b> <img src="img3.png" style="vertical-align: text-bottom;" />
+aligned <img src="img4.png" style="vertical-align: middle;" />
+</div>
+<br />
+
+<div style="background-color:#CCFFFF;">
+These images <img src="img1.png" style="vertical-align: baseline;" />
+are <img src="img2.png" style="vertical-align: baseline;" />
+<b>baseline</b> <img src="img3.png" style="vertical-align: baseline;" />
+aligned <img src="img4.png" style="vertical-align: middle;" />
+</div>
+<br />
+
+<div style="background-color:#CCFFFF;">
+These images <img src="img1.png" style="vertical-align: middle;" />
+are <img src="img2.png" style="vertical-align: middle;" />
+<b>middle</b> <img src="img3.png" style="vertical-align: middle;" />
+aligned <img src="img5.png" style="vertical-align: bottom;" />
+</div>
+<br />
+
+<h4>Mixed alignment</h4>
+<div style="background-color:#CCFFFF;">
+baseline: <img src="sunset.jpg" width="50" style="vertical-align: baseline;" />
+text-bottom: <img src="sunset.jpg" width="30" style="vertical-align: text-bottom;" />
+middle: <img src="sunset.jpg" width="30" style="vertical-align: middle;" />
+bottom: <img src="sunset.jpg" width="80" style="vertical-align: bottom;" />
+text-top: <img src="sunset.jpg" width="50" style="vertical-align: text-top;" />
+top: <img src="sunset.jpg" width="100" style="vertical-align: top;" />
+</div>
+
+<h3>Image Border and padding</h3>
+From mPDF v4.2, Image padding is supported as well as border and margin.
+<img src="sunset.jpg" width="100" style="border:3px solid #44FF44; padding: 1em;" />
+
+<h3>Rotated Images</h3>
+<img src="tiger.png" width="100" /> 
+<img src="tiger.png" rotate="90" width="100" /> 
+<img src="tiger.png" rotate="180" width="100" /> 
+<img src="tiger.png" rotate="-90" width="100" /> 
+<br />
+<img src="tiger.jpg" width="100" /> 
+<img src="tiger.jpg" rotate="90" width="100" /> 
+<img src="tiger.jpg" rotate="180" width="100" /> 
+<img src="tiger.jpg" rotate="-90" width="100" /> 
+<br />
+<img src="tiger2.wmf" width="80" /> &nbsp; &nbsp; &nbsp;
+<img src="tiger2.wmf" rotate="90" width="80" /> &nbsp; &nbsp; &nbsp;
+<img src="tiger2.wmf" rotate="180" width="80" /> &nbsp; &nbsp; &nbsp;
+<img src="tiger2.wmf" rotate="-90" width="80" />
+<br />
+<img src="tiger.svg" width="100" />&nbsp;
+<img src="tiger.svg" rotate="90" width="85" />&nbsp;
+<img src="tiger.svg" rotate="180" width="100" />&nbsp;
+<img src="tiger.svg" rotate="-90" width="85" /> 
+<br />
+
+';
+//==============================================================
+//==============================================================
+//==============================================================
+include("../mpdf.php");
+
+$mpdf=new mPDF('c'); 
+
+$mpdf->WriteHTML($html);
+
+$mpdf->Output();
+exit;
+//==============================================================
+//==============================================================
+//==============================================================
+//==============================================================
+//==============================================================
+
+
+?>

File diff suppressed because it is too large
+ 412 - 0
sites/all/libraries/MPDF54/examples/example05_tables.php


File diff suppressed because it is too large
+ 93 - 0
sites/all/libraries/MPDF54/examples/example06_tables_nested.php


+ 500 - 0
sites/all/libraries/MPDF54/examples/example07_tables_borders.php

@@ -0,0 +1,500 @@
+<?php
+
+
+
+$html = '
+<html><head>
+<style>
+table {
+	font-family: sans-serif;
+	border: 7mm solid aqua;
+	border-collapse: collapse;
+}
+table.table2 {
+	border: 2mm solid aqua;
+	border-collapse: collapse;
+}
+table.layout {
+	border: 0mm solid black;
+	border-collapse: collapse;
+}
+td.layout {
+	text-align: center;
+	border: 0mm solid black;
+}
+td {
+	padding: 3mm;
+	border: 2mm solid blue;
+	vertical-align: middle;
+}
+td.redcell {
+	border: 3mm solid red;
+}
+td.redcell2 {
+	border: 2mm solid red;
+}
+</style>
+</head>
+<body>
+
+<h1>mPDF</h1>
+<h2>Tables - Borders</h2>
+<h4>mPDF</h4>
+
+Border conflict resolution in tables with border-collapse set to "collapse". mPDF follows the rules set by CSS as well as possible, but as you can see, there is some difference in interpretation of the rules:
+
+<table class="layout">
+
+<tr>
+    <td class="layout">mPDF</td>
+    <td class="layout">Internet Explorer<br />IE 7</td>
+    <td class="layout">Firefox<br />v 3.0.3</td>
+</tr>
+
+<tr>
+	<td class="layout">
+
+
+<table>
+<tr>
+    <td style="border:5mm solid green">1</td>
+    <td>1</td>
+    <td>1</td>
+</tr>
+<tr>
+    <td rowspan="2" class="redcell" style="border:5mm solid teal">1</td>
+    <td style="border:3mm solid pink">1</td>
+    <td style="border:5mm solid purple">1</td>
+</tr>
+<tr>
+    <td style="border:2mm solid gray">1</td>
+    <td>1</td>
+</tr>
+<tr>
+    <td class="redcell">1</td>
+    <td>1</td>
+    <td>1</td>
+</tr>
+</table>
+
+
+
+	</td>
+
+    <td class="layout" rowspan="3"><img src="bordersIE.jpg" /></td>
+    <td class="layout" rowspan="3"><img src="bordersFF.jpg" /></td>
+
+
+</tr>
+
+<tr>
+	<td class="layout" style="text-align: left">
+
+<table style="border: 2.5mm solid aqua">
+<tr>
+    <td class="redcell">1</td>
+    <td>1</td>
+    <td>1</td>
+</tr>
+<tr>
+    <td rowspan="2" class="redcell" style="border:5mm solid green">1</td>
+    <td>1</td>
+    <td>1</td>
+</tr>
+<tr>
+    <td>1</td>
+    <td>1</td>
+</tr>
+<tr>
+    <td class="redcell">1</td>
+    <td>1</td>
+    <td>1</td>
+</tr>
+</table>
+
+
+	</td>
+</tr>
+
+<tr>
+	<td class="layout">
+
+<table>
+<tr>
+    <td class="redcell">1</td>
+    <td>1</td>
+    <td>1</td>
+</tr>
+<tr>
+    <td rowspan="2" >1</td>
+    <td>1</td>
+    <td>1</td>
+</tr>
+<tr>
+    <td style="border:5mm solid yellow">1</td>
+    <td>1</td>
+</tr>
+<tr>
+    <td class="redcell">1</td>
+    <td>1</td>
+    <td>1</td>
+</tr>
+</table>
+
+
+	</td>
+</tr>
+</table>
+
+
+<pagebreak />
+
+
+<table class="layout">
+
+<tr>
+    <td class="layout">mPDF</td>
+    <td class="layout">mPDF &lt; v3</td>
+    <td class="layout">Internet Explorer<br />IE 7</td>
+    <td class="layout">Firefox<br />v 3.0.3</td>
+</tr>
+
+<tr>
+	<td class="layout">
+
+
+<table class="table2">
+<tr>
+    <td style="border:2mm solid green">1</td>
+    <td>1</td>
+    <td>1</td>
+</tr>
+<tr>
+    <td rowspan="2" class="redcell2" style="border:2mm solid teal">1</td>
+    <td style="border:2mm solid pink">1</td>
+    <td style="border:2mm solid purple">1</td>
+</tr>
+<tr>
+    <td style="border:2mm solid gray">1</td>
+    <td>1</td>
+</tr>
+<tr>
+    <td class="redcell2">1</td>
+    <td>1</td>
+    <td>1</td>
+</tr>
+</table>
+
+
+
+	</td>
+
+    <td class="layout" rowspan="3"><img src="bordersMPDF2.jpg" /></td>
+    <td class="layout" rowspan="3"><img src="borders2IE.jpg" /></td>
+    <td class="layout" rowspan="3"><img src="borders2FF.jpg" /></td>
+
+
+</tr>
+
+<tr>
+	<td class="layout" style="text-align: left">
+
+<table style="border: 2mm solid aqua" class="table2">
+<tr>
+    <td class="redcell2">1</td>
+    <td>1</td>
+    <td>1</td>
+</tr>
+<tr>
+    <td rowspan="2" class="redcell2" style="border:2mm solid green">1</td>
+    <td>1</td>
+    <td>1</td>
+</tr>
+<tr>
+    <td>1</td>
+    <td>1</td>
+</tr>
+<tr>
+    <td class="redcell2">1</td>
+    <td>1</td>
+    <td>1</td>
+</tr>
+</table>
+
+
+	</td>
+</tr>
+
+<tr>
+	<td class="layout">
+
+<table class="table2">
+<tr>
+    <td class="redcell2">1</td>
+    <td>1</td>
+    <td>1</td>
+</tr>
+<tr>
+    <td rowspan="2" >1</td>
+    <td>1</td>
+    <td>1</td>
+</tr>
+<tr>
+    <td style="border:2mm solid yellow">1</td>
+    <td>1</td>
+</tr>
+<tr>
+    <td class="redcell2">1</td>
+    <td>1</td>
+    <td>1</td>
+</tr>
+</table>
+
+
+	</td>
+</tr>
+</table>
+
+
+<pagebreak />
+<h4>mPDF</h4>
+
+<table style="border: 10px solid orange">
+<tr>
+<td style="border: 10px solid orange">Data</td>
+<td style="border: 10px double red">double red</td>
+<td style="border: 10px dashed yellow">dashed yellow</td>
+<td style="border: 10px dotted green">dotted green</td>
+<td style="border: 10px solid orange">Data</td>
+</tr>
+<tr>
+<td style="border: 10px solid orange">Data</td>
+<td style="border: 10px hidden orange">hidden </td>
+<td style="border: 10px solid orange">Data</td>
+<td style="border: 10px none orange">none</td>
+<td style="border: 10px solid orange">Data</td>
+</tr>
+<tr>
+<td style="border: 10px solid orange">Data</td>
+<td style="border: 10px ridge blue">ridge blue</td>
+<td style="border: 10px none orange">none </td>
+<td style="border: 10px none orange">none </td>
+<td style="border: 10px solid orange">Data</td>
+</tr>
+<tr>
+<td style="border: 10px solid orange">Data</td>
+<td style="border: 10px none orange">none </td>
+<td style="border: 10px groove pink">groove pink</td>
+<td style="border: 10px none orange">none </td>
+<td style="border: 10px solid orange">Data</td>
+</tr>
+<tr>
+<td style="border: 10px none orange">none </td>
+<td style="border: 10px inset gray">inset gray</td>
+<td style="border: 10px none orange">none </td>
+<td style="border: 10px outset purple">outset purple</td>
+<td style="border: 10px none orange">none </td>
+</tr>
+</table>
+
+<h4>Firefox</h4>
+<img src="borders3FF.jpg" />
+
+<br />
+
+
+<h4>IE 7</h4>
+<img src="borders3IE.jpg" />
+
+<pagebreak />
+
+<div>mPDF</div>
+
+<table style="border: 10px solid orange; border-collapse: separate;">
+<tr>
+<td style="border: 10px solid orange">Data</td>
+<td style="border: 10px double red">double red</td>
+<td style="border: 10px dashed yellow">dashed yellow</td>
+<td style="border: 10px dotted green">dotted green</td>
+<td style="border: 10px solid orange">Data</td>
+</tr>
+<tr>
+<td style="border: 10px solid orange">Data</td>
+<td style="border: 10px hidden orange">hidden </td>
+<td style="border: 10px solid orange">Data</td>
+<td style="border: 10px none orange">none</td>
+<td style="border: 10px solid orange">Data</td>
+</tr>
+<tr>
+<td style="border: 10px solid orange">Data</td>
+<td style="border: 10px ridge blue">ridge blue</td>
+<td style="border: 10px none orange">none </td>
+<td style="border: 10px none orange">none </td>
+<td style="border: 10px solid orange">Data</td>
+</tr>
+<tr>
+<td style="border: 10px solid orange">Data</td>
+<td style="border: 10px none orange">none </td>
+<td style="border: 10px groove pink">groove pink</td>
+<td style="border: 10px none orange">none </td>
+<td style="border: 10px solid orange">Data</td>
+</tr>
+<tr>
+<td style="border: 10px none orange">none </td>
+<td style="border: 10px inset gray">inset gray</td>
+<td style="border: 10px none orange">none </td>
+<td style="border: 10px outset purple">outset purple</td>
+<td style="border: 10px none orange">none </td>
+</tr>
+</table>
+
+<div>Firefox</div>
+<img style="margin:0;" src="borders4FF.jpg" />
+
+
+
+<div>IE 7</div>
+<img style="margin:0;" src="borders4IE.jpg" />
+
+<pagebreak />
+
+
+<table style="border: 5px inset teal">
+<tr>
+<td style="border: 5px solid orange">solid orange</td>
+
+<td style="border: 0px none black">none</td>
+
+<td style="border: 5px double red">double red</td>
+
+<td style="border: 0px none black">none</td>
+
+<td style="border: 5px inset gray">inset gray</td>
+
+<td style="border: 0px none black">none</td>
+
+<td style="border: 5px outset purple">outset purple</td>
+
+<td style="border: 0px none black">none</td>
+
+<td style="border: 5px groove pink">groove pink</td>
+
+<td style="border: 0px none black">none</td>
+
+<td style="border: 5px ridge blue">ridge blue</td>
+</tr>
+</table>
+
+
+<table style="border: 5px inset gray; border-collapse: separate;">
+<tr>
+<td style="border: 5px solid orange">solid orange</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px double red">double red</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px inset gray">inset gray</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px outset purple">outset purple</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px groove pink">groove pink</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px ridge blue">ridge blue</td>
+</tr>
+</table>
+
+
+<table style="border: 5px outset purple; border-collapse: separate;">
+<tr>
+<td style="border: 5px solid orange">solid orange</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px double red">double red</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px inset gray">inset gray</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px outset purple">outset purple</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px groove pink">groove pink</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px ridge blue">ridge blue</td>
+</tr>
+</table>
+
+
+<table style="border: 5px groove pink; border-collapse: separate;">
+<tr>
+<td style="border: 5px solid orange">solid orange</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px double red">double red</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px inset gray">inset gray</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px outset purple">outset purple</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px groove pink">groove pink</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px ridge blue">ridge blue</td>
+</tr>
+</table>
+
+
+<table style="border: 5px ridge blue; border-collapse: separate;">
+<tr>
+<td style="border: 5px solid orange">solid orange</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px double red">double red</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px inset gray">inset gray</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px outset purple">outset purple</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px groove pink">groove pink</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px ridge blue">ridge blue</td>
+</tr>
+</table>
+
+
+<table style="border: 5px double red; border-collapse: separate;">
+<tr>
+<td style="border: 5px solid orange">solid orange</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px double red">double red</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px inset gray">inset gray</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px outset purple">outset purple</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px groove pink">groove pink</td>
+<td style="border: 0px none black">none</td>
+<td style="border: 5px ridge blue">ridge blue</td>
+</tr>
+</table>
+
+</body>
+</html>
+';
+
+//==============================================================
+//==============================================================
+//==============================================================
+include("../mpdf.php");
+
+$mpdf=new mPDF('en-GB-x','A4','','',10,10,10,10,6,3); 
+
+$mpdf->SetDisplayMode('fullpage');
+
+$mpdf->list_indent_first_level = 0;	// 1 or 0 - whether to indent the first level of a list
+
+// LOAD a stylesheet
+$stylesheet = file_get_contents('mpdfstyletables.css');
+$mpdf->WriteHTML($stylesheet,1);	// The parameter 1 tells that this is css/style only and no body/html/text
+
+$mpdf->WriteHTML($html);
+
+$mpdf->Output();
+exit;
+//==============================================================
+//==============================================================
+//==============================================================
+
+?>

+ 137 - 0
sites/all/libraries/MPDF54/examples/example08_lists.php

@@ -0,0 +1,137 @@
+<?php
+
+$html = '
+<style>
+ol, ul { text-align: justify; 
+}
+
+.lista { list-style-type: upper-roman; }
+.listb{ list-style-type: decimal; font-family: sans-serif; color: blue; font-weight: bold; font-style: italic; font-size: 19pt; }
+.listc{ list-style-type: upper-alpha; text-indent: 25mm; }
+.listd{ list-style-type: lower-alpha; color: teal; line-height: 2; }
+.liste{ list-style-type: disc; }
+</style>
+
+
+<h1>mPDF</h1>
+<h2>Lists</h2>
+
+<div style="background-color:#ddccff; padding:0pt; border: 1px solid #555555;">
+<ol class="lista">
+<li>Text here lorem ipsum ibisque totum.</li>
+<li><span style="color:green; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">Text here lorem ipsum ibisque totum.</span></li>
+<li style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum. Text here lorem ipsum ibisque totum. Text here lorem ipsum ibisque totum. Text here lorem ipsum ibisque totum. Text here lorem ipsum ibisque totum. Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.
+<ol class="listb">
+<li>Text here lorem ipsum ibisque totum.</li>
+<li><span style="color:green; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">Text here lorem ipsum ibisque totum.</span></li>
+<li style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem <span style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">ipsum</span> ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+<li style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">Text here lorem ipsum ibisque totum.
+<ol class="listc">
+<li>Big text indent 25mm: Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem <span style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">ipsum</span> ibisque totum.
+</li>
+<li>Text here lorem ipsum ibisque totum.
+<ol class="listd">
+<li>Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem <span style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">ipsum</span> ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+<li style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.
+<ol class="liste">
+<li>Text here lorem ipsum ibisque totum.</li>
+<li style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem <span style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">ipsum</span> ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+</ol>
+</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem <span style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">ipsum</span> ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+</ol>
+</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+</ol>
+</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem <span style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">ipsum</span> ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+</ol>
+</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum. 
+<ol class="listc">
+<li>Big text indent 25mm: Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem <span style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">ipsum</span> ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.
+<ol class="listd">
+<li>Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem <span style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">ipsum</span> ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+<li style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">Text here lorem ipsum ibisque totum.
+<ol class="liste">
+<li>Text here lorem ipsum ibisque totum.</li>
+<li style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem <span style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">ipsum</span> ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+</ol>
+</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem <span style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">ipsum</span> ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.
+<ol>
+<li>No class specified. Text here lorem ipsum ibisque totum.</li>
+<li style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem <span style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">ipsum</span> ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+</ol>
+</li>
+</ol>
+</li>
+</ol>
+</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem <span style="color:red; font-size:9pt; font-family:courier; font-weight: normal; font-style: normal;">ipsum</span> ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+<li>Text here lorem ipsum ibisque totum.</li>
+</ol>
+</div>
+';
+//==============================================================
+//==============================================================
+//==============================================================
+include("../mpdf.php");
+
+$mpdf=new mPDF('-s'); 
+
+$mpdf->SetDisplayMode('fullpage');
+
+$mpdf->WriteHTML($html);
+
+$mpdf->list_align_style = 'L';	// Determines alignment of numbers in numbered lists
+$mpdf->list_number_suffix = ')';
+
+$mpdf->WriteHTML($html);
+
+$mpdf->Output();
+
+exit;
+//==============================================================
+//==============================================================
+//==============================================================
+
+
+?>

File diff suppressed because it is too large
+ 13 - 0
sites/all/libraries/MPDF54/examples/example09_forms.php


File diff suppressed because it is too large
+ 75 - 0
sites/all/libraries/MPDF54/examples/example10_floating_and_fixed_position_elements.php


File diff suppressed because it is too large
+ 8 - 0
sites/all/libraries/MPDF54/examples/example11_overflow_auto.php


File diff suppressed because it is too large
+ 40 - 0
sites/all/libraries/MPDF54/examples/example12_paging_html.php


File diff suppressed because it is too large
+ 26 - 0
sites/all/libraries/MPDF54/examples/example13_paging_css.php


File diff suppressed because it is too large
+ 5 - 0
sites/all/libraries/MPDF54/examples/example14_page_numbers_ToC_Index_Bookmarks.php


File diff suppressed because it is too large
+ 48 - 0
sites/all/libraries/MPDF54/examples/example15_headers_method_1.php


File diff suppressed because it is too large
+ 37 - 0
sites/all/libraries/MPDF54/examples/example16_headers_method_2.php


File diff suppressed because it is too large
+ 26 - 0
sites/all/libraries/MPDF54/examples/example17_headers_method_3.php


File diff suppressed because it is too large
+ 51 - 0
sites/all/libraries/MPDF54/examples/example18_headers_method_4.php


+ 59 - 0
sites/all/libraries/MPDF54/examples/example19_page_sizes.php

@@ -0,0 +1,59 @@
+<?php
+
+
+
+$hhtml = '
+<htmlpageheader name="myHTMLHeaderOdd" style="display:none">
+<div style="background-color:#BBEEFF" align="center"><b>&nbsp;{PAGENO}&nbsp;</b></div>
+</htmlpageheader>
+<htmlpagefooter name="myHTMLFooterOdd" style="display:none">
+<div style="background-color:#CFFFFC" align="center"><b>&nbsp;{PAGENO}&nbsp;</b></div>
+</htmlpagefooter>
+<sethtmlpageheader name="myHTMLHeaderOdd" page="O" value="on" show-this-page="1" />
+<sethtmlpagefooter name="myHTMLFooterOdd" page="O" value="on" show-this-page="1" />
+';
+
+//==============================================================
+$html = '
+<h1>mPDF Page Sizes</h1>
+<h3>Changing page (sheet) sizes within the document</h3>
+';
+//==============================================================
+//==============================================================
+include("../mpdf.php");
+
+$mpdf=new mPDF('c','A4'); 
+
+$mpdf->WriteHTML($hhtml);
+
+$mpdf->WriteHTML($html);
+$mpdf->WriteHTML('<p>This should print on an A4 (portrait) sheet</p>');
+
+$mpdf->WriteHTML('<tocpagebreak sheet-size="A4-L" toc-sheet-size="A5" toc-preHTML="This ToC should print on an A5 sheet" />');
+$mpdf->WriteHTML($html);
+$mpdf->WriteHTML('<tocentry content="A4 landscape" /><p>This page appears just after the ToC and should print on an A4 (landscape) sheet</p>');
+
+$mpdf->WriteHTML('<pagebreak sheet-size="A5-L" />');
+$mpdf->WriteHTML($html);
+$mpdf->WriteHTML('<tocentry content="A5 landscape" /><p>This should print on an A5 (landscape) sheet</p>');
+
+$mpdf->WriteHTML('<pagebreak sheet-size="Letter" />');
+$mpdf->WriteHTML($html);
+$mpdf->WriteHTML('<tocentry content="Letter portrait" /><p>This should print on an Letter sheet</p>');
+
+$mpdf->WriteHTML('<pagebreak sheet-size="150mm 150mm" />');
+$mpdf->WriteHTML($html);
+$mpdf->WriteHTML('<tocentry content="150mm square" /><p>This should print on a sheet 150mm x 150mm</p>');
+
+$mpdf->WriteHTML('<pagebreak sheet-size="11.69in 8.27in" />');
+$mpdf->WriteHTML($html);
+$mpdf->WriteHTML('<tocentry content="A4 landscape (ins)" /><p>This should print on a sheet 11.69in x 8.27in = A4 landscape</p>');
+
+
+$mpdf->Output();
+exit;
+//==============================================================
+//==============================================================
+
+
+?>

File diff suppressed because it is too large
+ 41 - 0
sites/all/libraries/MPDF54/examples/example20_justify.php


File diff suppressed because it is too large
+ 8 - 0
sites/all/libraries/MPDF54/examples/example21_hyphenation.php


File diff suppressed because it is too large
+ 15 - 0
sites/all/libraries/MPDF54/examples/example22_columns.php


File diff suppressed because it is too large
+ 7 - 0
sites/all/libraries/MPDF54/examples/example23_orientation.php


File diff suppressed because it is too large
+ 7 - 0
sites/all/libraries/MPDF54/examples/example24_orientation_2.php


File diff suppressed because it is too large
+ 13 - 0
sites/all/libraries/MPDF54/examples/example26_RTL.php


File diff suppressed because it is too large
+ 20 - 0
sites/all/libraries/MPDF54/examples/example27_CJK_using_Adobe_fonts.php


File diff suppressed because it is too large
+ 20 - 0
sites/all/libraries/MPDF54/examples/example28_CJK_using_embedded_fonts.php


File diff suppressed because it is too large
+ 113 - 0
sites/all/libraries/MPDF54/examples/example29_multilingual_autofont.php


File diff suppressed because it is too large
+ 11 - 0
sites/all/libraries/MPDF54/examples/example30_arabic.php


File diff suppressed because it is too large
+ 14 - 0
sites/all/libraries/MPDF54/examples/example32_indic.php


File diff suppressed because it is too large
+ 5 - 0
sites/all/libraries/MPDF54/examples/example35_watermarks.php


File diff suppressed because it is too large
+ 9 - 0
sites/all/libraries/MPDF54/examples/example36_annotations_and_Attached_files.php


+ 437 - 0
sites/all/libraries/MPDF54/examples/example37_barcodes.php

@@ -0,0 +1,437 @@
+<?php
+
+
+$html = '
+<html>
+<head>
+<style>
+body {font-family: sans-serif;
+	font-size: 9pt;
+	background: transparent url(\'bgbarcode.png\') repeat-y scroll left top;
+}
+h5, p {	margin: 0pt;
+}
+table.items {
+	font-size: 9pt; 
+	border-collapse: collapse;
+	border: 3px solid #880000; 
+}
+td { vertical-align: top; 
+}
+table thead td { background-color: #EEEEEE;
+	text-align: center;
+}
+table tfoot td { background-color: #AAFFEE;
+	text-align: center;
+}
+.barcode {
+	padding: 1.5mm;
+	margin: 0;
+	vertical-align: top;
+	color: #000000;
+}
+.barcodecell {
+	text-align: center;
+	vertical-align: middle;
+	padding: 0;
+}
+</style>
+</head>
+<body>
+
+<!--mpdf
+<htmlpagefooter name="myfooter">
+<div style="border-top: 1px solid #000000; font-size: 9pt; text-align: center; padding-top: 3mm; ">
+Page {PAGENO} of {nb}
+</div>
+</htmlpagefooter>
+
+<sethtmlpagefooter name="myfooter" value="on" />
+mpdf-->
+
+<h1>mPDF</h1>
+<h2>Barcodes</h2>
+<p>NB <b>Quiet zones</b> - The barcode object includes space to the right/left or top/bottom only when the specification states a \'quiet zone\' or \'light margin\'. All the examples below also have CSS property set on the barcode object i.e. padding: 1.5mm; </p>
+
+<h3>EAN-13 Barcodes (EAN-2 and EAN-5)</h3>
+<p>NB EAN-13, UPC-A, UPC-E, and EAN-8 may all include an additional bar code(EAN-2 and EAN-5) to the right of the main bar code (see below).</p>
+<p>A nominal height and width for these barcodes is defined by the specification. \'size\' will scale both the height and width. Values between 0.8 and 2 are allowed (i.e. 80% to 200% of the nominal size). \'height\' can also be varied as a factor of 1; this is applied after the scaling factor used for \'size\'.</p>
+<table class="items" width="100%" cellpadding="8" border="1">
+<thead>
+<tr>
+<td width="10%">CODE</td>
+<td>DESCRIPTION</td>
+<td>BARCODE</td>
+</tr>
+</thead>
+<tbody>
+<!-- ITEMS HERE -->
+<tr>
+<td align="center">EAN13</td>
+<td>Standard EAN-13 barcode. Accepts 12 or 13 characters (creating checksum digit if required). [0-9] numeric only.</td>
+<td class="barcodecell"><barcode code="978-0-9542246-0" text="1" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">ISBN</td>
+<td>Standard EAN-13 barcode with \'ISBN\' number shown above [shown at height="0.66"]</td>
+<td class="barcodecell"><barcode code="978-0-9542246-0" type="ISBN" class="barcode" height="0.66" text="1" /></td>
+</tr>
+<tr>
+<td align="center">ISSN</td>
+<td>Standard EAN-13 barcode with \'ISSN\' number shown above [shown at size="0.8"]</td>
+<td class="barcodecell"><barcode code="978-0-9542246-0-8" type="ISSN" size="0.8" class="barcode" text="1" /></td>
+</tr>
+</tbody>
+</table>
+
+<h3>EAN-8, UPC-A and UPC-E Barcodes</h3>
+<p>UPC-A, UPC-E, EAN-13, and EAN-8 may all include an additional bar code(EAN-2 and EAN-5) to the right of the main bar code (see below).</p>
+<p>A nominal height and width for these barcodes is defined by the specification. \'size\' will scale both the height and width. Values between 0.8 and 2 are allowed (i.e. 80% to 200% of the nominal size). \'height\' can also be varied as a factor of 1; this is applied after the scaling factor used for \'size\'.</p>
+<table class="items" width="100%" cellpadding="8" border="1">
+<thead>
+<tr>
+<td width="10%">CODE</td>
+<td>DESCRIPTION</td>
+<td>BARCODE</td>
+</tr>
+</thead>
+<tbody>
+<!-- ITEMS HERE -->
+<tr>
+<td align="center">UPCA</td>
+<td>UPC-A barcode. This is a subset of the EAN-13. (098277211236) Accepts 11 or 12 characters (creating checksum digit if required). [0-9] numeric only</td>
+<td class="barcodecell"><barcode code="09827721123" type="UPCA" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">UPCE</td>
+<td>UPC-E barcode. Requires the UPC-A code to be entered as above (e.g. 042100005264 to give 425261). NB mPDF will die with an error message if the code is not valid, as only some UPC-A codes can be converted into valid UPC-E codes. UPC-E doesn\'t have a check digit encoded explicity, rather the check digit is encoded in the parity of the other six characters. The check digit that is encoded is the check digit from the original UPC-A barcode.</td>
+<td class="barcodecell"><barcode code="04210000526" type="UPCE" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">EAN8</td>
+<td>EAN-8. Accepts 7 or 8 characters (creating checksum digit if required). [0-9] numeric only</td>
+<td class="barcodecell"><barcode code="2468123" type="EAN8" class="barcode" /></td>
+</tr>
+</tbody>
+</table>
+
+<h3>EAN-2 and EAN-5 supplements, and combined forms</h3>
+<p>UPC-A, UPC-E, EAN-13, and EAN-8 may all include an additional bar code(EAN-2 and EAN-5) to the right of the main bar code.</p>
+<table class="items" width="100%" cellpadding="8" border="1">
+<thead>
+<tr>
+<td width="10%">CODE</td>
+<td>DESCRIPTION</td>
+<td>BARCODE</td>
+</tr>
+</thead>
+<tbody>
+<!-- ITEMS HERE -->
+<tr>
+<td align="center">EAN2</td>
+<td colspan="2">EAN-2 supplement barcode. mPDF does not generate EAN-5 barcode on its own; see supplements below. Used to denote an issue of a periodical. EAN-2 supplement accepts 2 digits [0-9] only, EAN-5 five.</td>
+</tr>
+<tr>
+<td align="center">EAN5</td>
+<td colspan="2">EAN-5 supplement barcode. mPDF does not generate EAN-5 barcode on its own; see supplements below. Usually used in conjunction with EAN-13 for the price of books. 90000 is the code for no price. </td>
+</tr>
+<tr>
+<td align="center">EAN13P2</td>
+<td>Standard EAN-13 barcode with 2-digit UPC supplement (07)</td>
+<td class="barcodecell"><barcode code="978-0-9542246-0 07" type="EAN13P2" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">ISBNP2</td>
+<td>Standard EAN-13 barcode with \'ISBN\' number shown above, and 2-digit EAN-2 supplement</td>
+<td class="barcodecell"><barcode code="978-0-9542246-0-8 07" type="ISBNP2" class="barcode" text="1" /></td>
+</tr>
+<tr>
+<td align="center">ISSNP2</td>
+<td>Standard EAN-13 barcode with \'ISSN\' number shown above, and 2-digit EAN-2 supplement</td>
+<td class="barcodecell"><barcode code="978-0-9542246-0-8 07" type="ISSNP2" class="barcode" text="1" /></td>
+</tr>
+<tr>
+<td align="center">UPCAP2</td>
+<td>UPC-A barcode with 2-digit EAN-2 supplement. This is a subset of the EAN-13. </td>
+<td class="barcodecell"><barcode code="00633895260 24" type="UPCAP2" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">UPCEP2</td>
+<td>UPC-E barcode with 2-digit EAN-2 supplement. </td>
+<td class="barcodecell"><barcode code="042100005264 07" type="UPCEP2" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">EAN8P2</td>
+<td>EAN-8 barcode with 2-digit EAN-2 supplement</td>
+<td class="barcodecell"><barcode code="5512345 07" type="EAN8P2" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">EAN13P5</td>
+<td>Standard EAN-13 barcode with 5-digit UPC supplement (90000)</td>
+<td class="barcodecell"><barcode code="978-0-9542246-0 90000" type="EAN13P5" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">ISBNP5</td>
+<td>Standard EAN-13 barcode with \'ISBN\' number shown above, and 5-digit EAN-5 supplement</td>
+<td class="barcodecell"><barcode code="978-0-9542246-0-8 90000" type="ISBNP5" class="barcode" text="1" /></td>
+</tr>
+<tr>
+<td align="center">ISSNP5</td>
+<td>Standard EAN-13 barcode with \'ISSN\' number shown above, and 5-digit EAN-5 supplement</td>
+<td class="barcodecell"><barcode code="978-0-9542246-0-8 90000" type="ISSNP5" class="barcode" text="1" /></td>
+</tr>
+<tr>
+<td align="center">UPCAP5</td>
+<td>UPC-A barcode with 5-digit EAN-5 supplement. This is a subset of the EAN-13</td>
+<td class="barcodecell"><barcode code="07567816412 90000" type="UPCAP5" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">UPCEP5</td>
+<td>UPC-E barcode with 5-digit EAN-5 supplement. (042100005264 90000)</td>
+<td class="barcodecell"><barcode code="042100005264 90000" type="UPCEP5" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">EAN8P5</td>
+<td>EAN-8 barcode with 5-digit EAN-5 supplement (55123457 90000)</td>
+<td class="barcodecell"><barcode code="55123457 90000" type="EAN8P5" class="barcode" /></td>
+</tr>
+</tbody>
+</table>
+
+<h3>Postcode Barcodes</h3>
+<p>These all have sizes fixed by their specification. Although they can be altered using \'size\' it is not recommended. \'height\' is ignored.</p>
+<table class="items" width="100%" cellpadding="8" border="1">
+<thead>
+<tr>
+<td width="10%">CODE</td>
+<td>DESCRIPTION</td>
+<td>BARCODE</td>
+</tr>
+</thead>
+<tbody>
+<!-- ITEMS HERE -->
+<tr>
+<td align="center">IMB</td>
+<td>Intelligent Mail Barcode - also known as: USPS OneCode 4-State Customer Barcode, OneCode 4CB, USPS 4CB, 4-CB, 4-State Customer Barcode, USPS OneCode Solution Barcode. (01234567094987654321-01234567891) Accepts: Up to 31 digits (required 20-digit Tracking Code, and up to 11-digit Routing Code; this may be 0, 5, 9, or 11 digits). If the Routing code is included, it should be spearated by a hyphen - like this example.</td>
+<td class="barcodecell"><barcode code="01234567094987654321-01234567891" type="IMB" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">RM4SCC</td>
+<td>Royal Mail 4-state Customer barcode (SN34RD1A). Accepts: max. 9 characters. Valid characters: [A-Z,0-9] Checksum digit: automatic.</td>
+<td class="barcodecell"><barcode code="SN34RD1A" type="RM4SCC" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">KIX</td>
+<td>Dutch KIX version of Royal Mail 4-state Customer barcode (SN34RD1A). Valid characters: [A-Z,0-9]. Checksum digit: automatic.</td>
+<td class="barcodecell"><barcode code="SN34RD1A" type="KIX" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">POSTNET</td>
+<td>POSTNET barcode. Accepts 5, 9 or 11 digits. Valid characters: [0-9]. Checksum digit: automatic.</td>
+<td class="barcodecell"><barcode code="123456789" type="POSTNET" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">PLANET</td>
+<td>PLANET barcode. Accepts 11 or 13 digits. Valid characters: [0-9]. Checksum digit: automatic.</td>
+<td class="barcodecell"><barcode code="00123456789" type="PLANET" class="barcode" /></td>
+</tr>
+</tbody>
+</table>
+
+
+<h3>Variable width Barcodes</h3>
+<p>These barcodes are all of variable length depending on the code entered. There is no recommended maximum size for any of these specs, but all recommend a minimum X-dimension (width of narrowest bar) as 7.5mil (=0.19mm). The default used here is twice the minimum i.e. X-dim = 0.38mm.</p>
+<p>The specifications give a minimum height of 15% of the barcode length (which can be variable). The bar height in mPDF is set to a default value of 10mm. </p>
+<p>\'size\' will scale the barcode in both dimensions. mPDF will accept any number, but bear in mind that size="0.5" will set the bar width to the minimum. The \'height\' attribute further allows scaling - this factor is applied to already scaled barcode. Thus size="2" height="0.5" will give a barcode twice the default width (X-dim=0.76mm) and at the default height set in mPDF i.e. 10mm.</p>
+<table class="items" width="100%" cellpadding="8" border="1">
+<thead>
+<tr>
+<td width="10%">CODE</td>
+<td>DESCRIPTION</td>
+<td>BARCODE</td>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="center">C128A</td>
+<td>CODE 128 A. Valid characters: [A-Z uppercase and control chars ASCII 0-31]. Checksum digit: automatic.</td>
+<td class="barcodecell"><barcode code="CODE 128 A" type="C128A" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">C128B</td>
+<td>CODE 128 B. Valid characters: [Upper / Lower Case + All ASCII Printable Characters]. Checksum digit: automatic.</td>
+<td class="barcodecell"><barcode code="ABC123abc@456" type="C128B" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">C128C</td>
+<td>CODE 128 C. Valid characters: [0-9]. Must be an even number of digits. Checksum digit: automatic.</td>
+<td class="barcodecell"><barcode code="0123456789" type="C128C" class="barcode" /></td>
+</tr>
+
+<tr>
+<td align="center">EAN128C [A/B/C]</td>
+<td>EAN128 (A, B, and C). Specified variant of Code 128, utilising an FNC1 start code. Also known as UCC/EAN-128 or GS1-128. Valid characters: [cf. Code 128]. Checksum digit: automatic.</td>
+<td class="barcodecell"><barcode code="0112345678912343" type="EAN128C" class="barcode" /></td>
+</tr>
+
+<tr>
+<td align="center">C39</td>
+<td>CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9. Valid characters: [0-9 A-Z \'-\' . Space $/+%]</td>
+<td class="barcodecell"><barcode code="TEC-IT" type="C39" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">C39+</td>
+<td>CODE 39 + CHECKSUM. Checksum digit: automatic.</td>
+<td class="barcodecell"><barcode code="39OR93" type="C39+" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">C39E</td>
+<td>CODE 39 EXTENDED. Valid characters: [ASCII-characters between 0..127]</td>
+<td class="barcodecell"><barcode code="CODE 39 E" type="C39E" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">C39E+</td>
+<td>CODE 39 EXTENDED + CHECKSUM. Checksum digit: automatic.</td>
+<td class="barcodecell"><barcode code="CODE 39 E+" type="C39E+" class="barcode" /></td>
+</tr>
+
+<tr>
+<td align="center">S25</td>
+<td>Standard 2 of 5. Valid characters: [0-9]</td>
+<td class="barcodecell"><barcode code="54321068" type="S25" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">S25+</td>
+<td>Standard 2 of 5 + CHECKSUM. Valid characters: [0-9]. Checksum digit: automatic.</td>
+<td class="barcodecell"><barcode code="54321068" type="S25+" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">I25</td>
+<td>Interleaved 2 of 5. Valid characters: [0-9]</td>
+<td class="barcodecell"><barcode code="54321068" type="I25" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">I25+</td>
+<td>Interleaved 2 of 5 + CHECKSUM. Valid characters: [0-9]. Checksum digit: automatic.</td>
+<td class="barcodecell"><barcode code="54321068" type="I25+" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">I25B</td>
+<td>Interleaved 2 of 5 with bearer bars. Valid characters: [0-9]</td>
+<td class="barcodecell"><barcode code="1234567" type="I25B" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">I25B+</td>
+<td>Interleaved 2 of 5 + CHECKSUM with bearer bars. Valid characters: [0-9]. Checksum digit: automatic.</td>
+<td class="barcodecell"><barcode code="1234567" type="I25B+" class="barcode" /></td>
+</tr>
+
+<tr>
+<td align="center">C93</td>
+<td>CODE 93 - USS-93 (extended). Valid characters: [ASCII-characters between 0..127]. Checksum digits: automatic.</td>
+<td class="barcodecell"><barcode code="39OR93" type="C93" class="barcode" /></td>
+</tr>
+
+<tr>
+<td align="center">MSI</td>
+<td>MSI. Modified Plessey. Valid characters: [0-9]</td>
+<td class="barcodecell"><barcode code="01234567897" type="MSI" class="barcode" /></td>
+</tr>
+<tr>
+<td align="center">MSI+</td>
+<td>MSI + CHECKSUM (module 11). Checksum digit: automatic.</td>
+<td class="barcodecell"><barcode code="0123456789" type="MSI+" class="barcode" /></td>
+</tr>
+
+<tr>
+<td align="center">CODABAR</td>
+<td>CODABAR. Valid characters: [0-9 \'-\' $:/.+ ABCD] ABCD are used as stop and start characters e.g. A34698735B</td>
+<td class="barcodecell"><barcode code="A34698735B" type="CODABAR" class="barcode" /></td>
+</tr>
+
+<tr>
+<td align="center">CODE11</td>
+<td>CODE 11. Valid characters: [0-9 and \'-\']. Checksum digits: 1 (or 2 if length of code is > 10 characters) - automatic.</td>
+<td class="barcodecell"><barcode code="123-456-789" type="CODE11" class="barcode" /></td>
+</tr>
+
+
+</tbody>
+</table>
+
+<!-- QR-CODE 
+<h3>2D Code (QR-code)</h3>
+<p>A nominal height and width for these barcodes is set as 25mm. \'size\' will scale both the height and width.</p>
+<table class="items" width="100%" cellpadding="8" border="1">
+<thead>
+<tr>
+<td width="10%">CODE</td>
+<td>DESCRIPTION</td>
+<td>BARCODE</td>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="center">QR-code</td>
+<td>QR-code. Accepts numeric, alphanumeric or binary input, with specified error level: L, M, Q, H.</td>
+<td class="barcodecell"><barcode code="Your message here" type="QR" class="barcode" size="0.8" error="M" /></td>
+</tr>
+</tbody>
+</table>
+-->
+
+
+<br />
+
+<div>
+<h5>Useful links</h5>
+<p><a href="http://www.adams1.com">http://www.adams1.com</a></p>
+<p><a href="http://www.tec-it.com/Download/PDF/Barcode_Reference_EN.pdf">http://www.tec-it.com/Download/PDF/Barcode_Reference_EN.pdf</a></p>
+<p><a href="http://www.tec-it.com/en/support/knowbase/symbologies/barcode-overview/linear/Default.aspx">http://www.tec-it.com/en/support/knowbase/symbologies/barcode-overview/linear/Default.aspx</a></p>
+<p><a href="http://www.gs1uk.org/downloads/bar_code/Bar%20coding%20getting%20it%20right.pdf">http://www.gs1uk.org/downloads/bar_code/Bar%20coding%20getting%20it%20right.pdf</a></p>
+<p><a href="http://web.archive.org/web/19990501035133/http://www.uc-council.org/d36-d.htm">http://web.archive.org/web/19990501035133/http://www.uc-council.org/d36-d.htm (EAN2 and EAN5)</a></p>
+<p><a href="http://www.barcodeisland.com/ean13.phtml">http://www.barcodeisland.com/ean13.phtml (UPC-A)</a></p>
+<p><a href="http://www.idautomation.com/fonts/postnet/#Specifications">http://www.idautomation.com/fonts/postnet/#Specifications</a></p>
+<p><a href="http://www.outputlinks.com/sites/AFP/ibm_bcocafaq.pdf">http://www.outputlinks.com/sites/AFP/ibm_bcocafaq.pdf</a></p>
+<p><a href="https://ribbs.usps.gov/intelligentmail_mailpieces/documents/tech_guides/USPSIMB_Tech_Resource_Guide.pdf">https://ribbs.usps.gov/intelligentmail_mailpieces/documents/tech_guides/USPSIMB_Tech_Resource_Guide.pdf (Intelligent Mail)</a></p>
+<p><a href="http://www.mailsorttechnical.com/downloads_mailsort_user_guide.cfm">http://www.mailsorttechnical.com/downloads_mailsort_user_guide.cfm</a></p>
+
+<p><a href="http://www.mailsorttechnical.com/docs/mug_jun_2009/MUG_10_2008_Mailsort_700.pdf">http://www.mailsorttechnical.com/docs/mug_jun_2009/MUG_10_2008_Mailsort_700.pdf</a>  page 20</p>
+ 
+
+</div>
+
+<pagebreak />
+<div>
+<h3>Human-readable text</h3>
+Human-readable text is only produced as part of the barcode object in EAN-13, ISBN, ISSN, EAN-8, UPC-A and UPC-E. Here is an example to add text to a barcode:
+</div>
+
+<div style="border:1px solid #555555; background-color: #DDDDDD; padding: 1em; font-size:8pt; font-family: lucidaconsole, mono;">
+
+&lt;div style="position:fixed; right: 50mm; top: 60mm; border: 0.2mm solid #000000; text-align: center; padding: 0.5mm; padding-top: 2mm;"&gt;<br />
+&lt;barcode code="00034698735346987355" type="EAN128C" /&gt;&lt;br /&gt;<br />
+&lt;div style="font-family: ocrb;"&gt;(00) 0346987 35346987 355&lt;/div&gt;<br />
+&lt;/div&gt;
+
+</div>
+
+<div style="position:fixed; right: 50mm; top: 60mm; border: 0.2mm solid #000000; text-align: center; padding: 0.5mm; padding-top: 2mm;">
+<barcode code="00034698735346987355" type="EAN128C" /><br />
+<div style="font-family: ocrb;">(00) 0346987 35346987 355</div>
+</div>
+
+</body>
+</html>
+';
+//==============================================================
+//==============================================================
+include("../mpdf.php");
+
+$mpdf=new mPDF('','','','',20,15,25,25,10,10); 
+$mpdf->WriteHTML($html);
+$mpdf->Output(); 
+
+exit;
+
+?>

+ 32 - 0
sites/all/libraries/MPDF54/examples/example38_dot_tab.php

@@ -0,0 +1,32 @@
+<?php
+
+
+$html = '<h3>Menu</h3>
+
+<div style="border: 0.2mm solid #000088; padding: 1em;">
+<p style="text-align: left;">Nulla felis erat, imperdiet eu, ullamcorper non, nonummy quis, elit. Suspendisse potenti. Ut a eros at ligula vehicula pretium. Maecenas feugiat pede vel risus. Nulla et lectus <dottab /> &pound;37.00</p>
+
+<p style="text-align: left;">Fusce eleifend neque sit amet erat. Integer consectetuer nulla non orci. Morbi feugiat <dottab /> &pound;3700.00</p>
+
+<p style="text-align: left; color: #880000;">Cras odio. Donec mattis, nisi id euismod auctor, neque metus pellentesque risus, at eleifend lacus sapien et risus <dottab /> &pound;27.00</p>
+
+<p style="text-align: left;">Phasellus metus. Phasellus feugiat, lectus ac aliquam molestie, leo lacus tincidunt turpis, vel aliquam quam odio et sapien. Mauris ante pede, auctor ac, suscipit quis, malesuada sed, nulla. Integer sit amet odio sit amet lectus luctus euismod <dottab /> &pound;7.00</p>
+
+<p style="text-align: left;">Donec et nulla. Sed quis orci <dottab /> &pound;1137.00</p>
+</div>
+';
+
+
+include("../mpdf.php");
+
+$mpdf=new mPDF(); 
+
+$mpdf->WriteHTML($html);
+
+$mpdf->Output(); 
+
+exit;
+
+
+
+?>

+ 32 - 0
sites/all/libraries/MPDF54/examples/example39_PDFA_compliance.php

@@ -0,0 +1,32 @@
+<?php
+
+
+
+$html = '
+<h1>mPDF</h1>
+<h2>PDFA Compliance</h2>
+<p>PDF/A1-b is a file format for the long-term archiving of electronic documents. This is an example of a PDF/A1-b compliant files.</p>
+';
+//==============================================================
+//==============================================================
+//==============================================================
+include("../mpdf.php");
+
+$mpdf=new mPDF(); 
+
+$mpdf->PDFA = true;
+$mpdf->PDFAauto = true;
+
+$mpdf->WriteHTML($html);
+
+$mpdf->Output();
+
+exit;
+//==============================================================
+//==============================================================
+//==============================================================
+//==============================================================
+//==============================================================
+
+
+?>

+ 20 - 0
sites/all/libraries/MPDF54/examples/example40_MPDFI_thumbnails.php

@@ -0,0 +1,20 @@
+<?php
+
+include("../mpdf.php");
+
+$mpdf=new mPDF(); 
+$mpdf->SetImportUse();	
+
+$mpdf->Thumbnail('sample_orientation2.pdf', 4, 5);	// number per row	// spacing in mm
+
+$mpdf->WriteHTML('<pagebreak /><div>Now with rotated pages</div>');
+
+$mpdf->Thumbnail('sample_orientation3.pdf', 4);	// number per row	// spacing in mm
+
+
+$mpdf->Output();
+
+exit;
+
+
+?>

+ 36 - 0
sites/all/libraries/MPDF54/examples/example41_MPDFI_template.php

@@ -0,0 +1,36 @@
+<?php
+
+include("../mpdf.php");
+
+$mpdf=new mPDF('','','','',15,15,57,16,9,9); 
+$mpdf->SetImportUse();	
+
+$mpdf->SetDisplayMode('fullpage');
+
+$mpdf->SetCompression(false);
+
+// Add First page
+$pagecount = $mpdf->SetSourceFile('sample_basic.pdf');
+
+$crop_x = 50;
+$crop_y = 50;
+$crop_w = 100;
+$crop_h = 100;
+
+$tplIdx = $mpdf->ImportPage(2, $crop_x, $crop_y, $crop_w, $crop_h);
+
+$x = 50;
+$y = 50;
+$w = 100;
+$h = 100;
+
+$mpdf->UseTemplate($tplIdx, $x, $y, $w, $h);
+
+$mpdf->Rect($x, $y, $w, $h);
+
+$mpdf->Output('newpdf.pdf', 'I');
+
+exit;
+
+
+?>

+ 35 - 0
sites/all/libraries/MPDF54/examples/example42_MPDFI_templatedoc.php

@@ -0,0 +1,35 @@
+<?php
+
+include("../mpdf.php");
+
+$mpdf=new mPDF('','','','',15,15,47,16,9,9); 
+$mpdf->SetImportUse();	
+
+$mpdf->SetDocTemplate('sample_logoheader2.pdf',1);	// 1|0 to continue after end of document or not - used on matching page numbers
+
+//===================================================
+$mpdf->AddPage();
+$mpdf->WriteHTML('Hallo World');
+$mpdf->AddPage();
+$mpdf->WriteHTML('Hallo World');
+$mpdf->AddPage();
+$mpdf->WriteHTML('Hallo World');
+//===================================================
+
+$mpdf->RestartDocTemplate();
+
+//===================================================
+$mpdf->AddPage();
+$mpdf->WriteHTML('Hallo World');
+$mpdf->AddPage();
+$mpdf->WriteHTML('Hallo World');
+$mpdf->AddPage();
+$mpdf->WriteHTML('Hallo World');
+//===================================================
+
+
+$mpdf->Output();
+
+exit;
+
+?>

File diff suppressed because it is too large
+ 14 - 0
sites/all/libraries/MPDF54/examples/example43_MPDFI_booklet.php


File diff suppressed because it is too large
+ 30 - 0
sites/all/libraries/MPDF54/examples/example44_MPDFI_yearbook.php


File diff suppressed because it is too large
+ 236 - 0
sites/all/libraries/MPDF54/examples/example46_progress_bars_simple.php


File diff suppressed because it is too large
+ 236 - 0
sites/all/libraries/MPDF54/examples/example47_progress_bars_simple_custom.php


File diff suppressed because it is too large
+ 236 - 0
sites/all/libraries/MPDF54/examples/example48_progress_bars_advanced.php


+ 41 - 0
sites/all/libraries/MPDF54/examples/example49_changelog.php

@@ -0,0 +1,41 @@
+<?php
+ini_set("memory_limit","384M");
+
+// This is because changelog.txt contains over 100000 characters, and preg_* functions in mPDF won't work.
+ini_set("pcre.backtrack_limit","200000");
+
+include("../mpdf.php");
+
+$mpdf=new mPDF(); 
+
+$mpdf->tabSpaces = 6;
+
+$mpdf->allow_charset_conversion=true;
+$mpdf->charset_in='windows-1252';
+
+
+//==============================================================
+
+$html = '
+<h1>mPDF</h1>
+<h2>ChangeLog</h2>
+<div style="border:1px solid #555555; background-color: #DDDDDD; padding: 1em; font-size:8pt; font-family: lucidaconsole, mono;">
+';
+$lines = file('../CHANGELOG.txt');
+
+$html .= '<pre>';
+foreach($lines AS $line) {
+	$html .= htmlspecialchars($line);
+}
+$html .= '</pre>';
+$html .= '</div>';
+
+//==============================================================
+
+$mpdf->WriteHTML($html);
+
+$mpdf->Output();
+exit;
+
+
+?>

File diff suppressed because it is too large
+ 86 - 0
sites/all/libraries/MPDF54/examples/example50_new_mPDF_3_features.php


Some files were not shown because too many files changed in this diff