WooCommerce PDF Invoices - Version 1.0.0

Version Description

Download this release

Release Info

Developer baaaaas
Plugin Icon 128x128 WooCommerce PDF Invoices
Version 1.0.0
Comparing to
See all releases

Version 1.0.0

assets/css/admin-styles.css ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ .delete{
2
+ position: absolute; top: 16px; right: 0px; background: #f7f7f7; border: 1px solid #d5d5d5; padding: 1px;
3
+ }
assets/css/styles.css ADDED
File without changes
includes/class-admin.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class BEWPI_Admin {
4
+
5
+ function __construct() {
6
+ add_action( 'admin_init', array($this, 'register_settings' ));
7
+ add_action( 'admin_menu', array($this, 'add_menu_item'));
8
+
9
+ require BEWPI_PLUGIN_DIR . 'includes/class-invoice.php';
10
+ add_filter( 'woocommerce_email_attachments', array('BEWPI_Invoice', 'generate_invoice'),10,3 );
11
+ }
12
+
13
+ function register_settings() {
14
+ register_setting( 'be_woocommerce_pdf_invoices', 'be_woocommerce_pdf_invoices', array($this, 'validate_settings'));
15
+ }
16
+
17
+ function add_menu_item() {
18
+ add_submenu_page( 'woocommerce', 'Invoices by Bas Elbers', 'Invoices', 'manage_options', 'bewpi', array($this, 'show_settings_page') );
19
+ }
20
+
21
+ function validate_settings($settings)
22
+ {
23
+ $old_settings = get_option('be_woocommerce_pdf_invoices');
24
+
25
+ if(isset($_FILES['logo']))
26
+ {
27
+ if ($_FILES['logo']['size'] <= 30000)
28
+ {
29
+ if ( preg_match('/(jpg|jpeg|png)$/', $_FILES['logo']['type']) )
30
+ {
31
+ $override = array('test_form' => false);
32
+ $file = wp_handle_upload( $_FILES['logo'], $override );
33
+ $settings['file_upload'] = $file['url'];
34
+ }
35
+ }
36
+ }
37
+ return $settings;
38
+ }
39
+
40
+ public function show_settings_page() {
41
+ $options = bewpi_get_options();
42
+ include BEWPI_PLUGIN_DIR . 'includes/views/settings-page.php';
43
+ }
44
+ }
includes/class-invoice.php ADDED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class BEWPI_Invoice {
4
+
5
+ function generate_invoice($val, $id, $order){
6
+ if($id == 'customer_invoice')
7
+ {
8
+ include(BEWPI_PLUGIN_DIR . '/mpdf/mpdf.php');
9
+
10
+ $options = get_option('be_woocommerce_pdf_invoices');
11
+
12
+ $items = $order->get_items();
13
+
14
+ $today = date('d');
15
+
16
+ $month = date('m');
17
+
18
+ $year = date('Y');
19
+
20
+ //$current_date = date('d-m-Y');
21
+
22
+ $order_number = str_replace("#", "", $order->get_order_number());
23
+
24
+ $invoice_number = $year . $order_number;
25
+
26
+ $purchase_note = $order->customer_note;
27
+
28
+ $billing_address = $order->get_formatted_billing_address();
29
+
30
+ $shipping_address = $order->get_formatted_shipping_address();
31
+
32
+ $order_total = $order->get_total();
33
+
34
+ $total_tax = $order->get_total_tax();
35
+
36
+ $order_subtotal = $order_total - $total_tax;
37
+
38
+ $mpdf = new mPDF('win-1252','A4','','',20,15,48,25,10,10);
39
+ $mpdf->useOnlyCoreFonts = true; // false is default
40
+ $mpdf->SetProtection(array('print'));
41
+ $mpdf->SetDisplayMode('fullpage');
42
+
43
+ // Get all items and output in table rows and datacells.
44
+ $all_items;
45
+ foreach ( $items as $item ) {
46
+ $item_subtotal = $order->get_item_subtotal($item);
47
+ $item_total = $item['qty'] * $item_subtotal;
48
+ $formatted_item_subtotal = woocommerce_price($item_subtotal);
49
+ $formatted_item_total = woocommerce_price($item_total);
50
+
51
+ $all_items .= "<tr><td align='center'>" . $item['product_id'] . "</td>" .
52
+ "<td align='center'>" . $item['qty'] . "</td>" .
53
+ "<td>" . $item['name'] . "</td>" .
54
+ "<td align='right'>" . $formatted_item_subtotal . "</td>" .
55
+ "<td align='right'>" . $formatted_item_total . "</td>" .
56
+ "</tr>";
57
+ }
58
+
59
+ // The HTML PDF invoice
60
+ ob_start();
61
+ ?>
62
+ <html>
63
+ <head>
64
+ <style>
65
+ body {
66
+ font-family: 'calibri';
67
+ font-size: 10pt;
68
+ }
69
+ p {
70
+ margin: 0pt;
71
+ }
72
+ td {
73
+ vertical-align: top;
74
+ }
75
+ .items td {
76
+ border-left: 0.1mm solid #000000;
77
+ border-right: 0.1mm solid #000000;
78
+ }
79
+ table thead td { background-color: #EEEEEE;
80
+ text-align: center;
81
+ border: 0.1mm solid #000000;
82
+ }
83
+ .items td.blanktotal {
84
+ background-color: #FFFFFF;
85
+ border: 0mm none #000000;
86
+ border-top: 0.1mm solid #000000;
87
+ border-right: 0.1mm solid #000000;
88
+ }
89
+ .items td.totals {
90
+ text-align: right;
91
+ border: 0.1mm solid #000000;
92
+ }
93
+ </style>
94
+ </head>
95
+ <body>
96
+ <htmlpageheader name="myheader">
97
+ <table width="100%">
98
+ <tr>
99
+ <td width="50%">
100
+ <?php if($options['file_upload'] != ''){ ?>
101
+ <img src="<?php echo $options['file_upload']; ?>"/><br /><br />
102
+ <?php }
103
+ else
104
+ { ?>
105
+ <span style="font-size: 16pt; font-weight: bold;"><?php echo $options['company_name']; ?></span><br />
106
+ <?php echo $options['company_slogan']; ?><br /><br />
107
+ <?php }
108
+ echo $options['address']; ?><br />
109
+ <?php echo $options['zip_code'] . " " . $options['city']; ?><br />
110
+ <?php echo $options['country']; ?><br />
111
+ </td>
112
+ <td width="50%" style="text-align: right;">
113
+ <span style="font-size:22pt;">
114
+ <?php echo __( 'INVOICE', 'woocommerce-pdf-invoices' ); ?><br />
115
+ </span>
116
+ </td>
117
+ </tr>
118
+ <tr>
119
+ <td>
120
+ <?php echo __( 'Tel: ', 'woocommerce-pdf-invoices' ) . $options['telephone']; ?><br />
121
+ <?php echo __( 'Email: ', 'woocommerce-pdf-invoices' ) . $options['email']; ?>
122
+ </td>
123
+ </tr>
124
+ <tr>
125
+ <td width="50%">
126
+ <?php echo $options['extra_company_info']; ?><br />
127
+ </td>
128
+ <td width="50%" style="font-size: 9pt; text-align:right;">
129
+ <?php echo sprintf( __( 'INVOICE NUMBER: ', 'woocommerce-pdf-invoices' )); echo $invoice_number; ?><br />
130
+ <?php echo sprintf( __( 'DATE: %02d-%02d-%04d', 'woocommerce-pdf-invoices' ), $today, $month, $year); ?>
131
+ </td>
132
+ </tr>
133
+ </table>
134
+ <br/>
135
+ <br/>
136
+ <table width="100%">
137
+ <tr>
138
+ <td style="50%">
139
+ <span style="font-weight: bold;"><?php echo __( 'TO:', 'woocommerce-pdf-invoices' ); ?></span><br />
140
+ <?php echo $billing_address; ?>
141
+ </td>
142
+ <td style="50%">
143
+ <span style="font-weight: bold;"><?php echo __( 'SHIP TO:', 'woocommerce-pdf-invoices' ); ?></span><br />
144
+ <?php echo $shipping_address; ?>
145
+ </td>
146
+ </tr>
147
+ </table>
148
+ <br/>
149
+ <table>
150
+ <tr>
151
+ <td>
152
+ <span style="font-weight: bold;"><?php echo __( 'Notes:', 'woocommerce-pdf-invoices' ); ?></span><br />
153
+ <?php echo $purchase_note; ?>
154
+ </td>
155
+ </tr>
156
+ </table>
157
+ <br/>
158
+ <br/>
159
+ <table class="items" width="100%" style="font-size: 9pt; border-collapse: collapse;" cellpadding="8">
160
+ <thead>
161
+ <tr style="font-weight: bold">
162
+ <td width="15%"><?php echo __( 'SKU', 'woocommerce-pdf-invoices' ); ?></td>
163
+ <td width="10%"><?php echo __( 'QUANTITY', 'woocommerce-pdf-invoices' ); ?></td>
164
+ <td width="45%"><?php echo __( 'DESCRIPTION', 'woocommerce-pdf-invoices' ); ?></td>
165
+ <td width="15%"><?php echo __( 'UNIT PRICE', 'woocommerce-pdf-invoices' ); ?></td>
166
+ <td width="15%"><?php echo __( 'TOTAL', 'woocommerce-pdf-invoices' ); ?></td>
167
+ </tr>
168
+ </thead>
169
+ <tbody>
170
+ <!-- ITEMS HERE -->
171
+ <?php echo $all_items; ?>
172
+ <!-- END ITEMS HERE -->
173
+ <tr>
174
+ <td class="blanktotal" colspan="3" rowspan="6"></td>
175
+ <td class="totals"><?php echo __( 'SUBTOTAL', 'woocommerce-pdf-invoices' ); ?></td>
176
+ <td class="totals"><?php echo woocommerce_price($order_subtotal); ?></td>
177
+ </tr>
178
+ <tr>
179
+ <td class="totals"><?php echo __( 'SALES TAX', 'woocommerce-pdf-invoices' ); ?></td>
180
+ <td class="totals"><?php echo woocommerce_price($total_tax); ?></td>
181
+ </tr>
182
+ <tr>
183
+ <td class="totals"><?php echo __( 'SHIPPING & HANDLING', 'woocommerce-pdf-invoices' ); ?></td>
184
+ <td class="totals"><?php echo woocommerce_price($order->get_shipping()); ?></td>
185
+ </tr>
186
+ <tr>
187
+ <td class="totals"><?php echo __( 'TOTAL DUE', 'woocommerce-pdf-invoices' ); ?></td>
188
+ <td class="totals"><?php echo woocommerce_price($order->get_total()); ?></td>
189
+ </tr>
190
+ </tbody>
191
+ </table>
192
+ <br />
193
+ <br />
194
+ <table style="text-align: left; font-style: italic;">
195
+ <tr>
196
+ <td>
197
+ <?php echo $options['extra_info']; ?>
198
+ </td>
199
+ </tr>
200
+ </table>
201
+ </htmlpageheader>
202
+ <htmlpagefooter name="myfooter">
203
+ <div style="font-size: 9pt; text-align: center; padding-top: 3mm; ">
204
+ <?php echo sprintf( __( 'Page %s of %s', 'woocommerce-pdf-invoices' ), "{PAGENO}", "{nb}"); ?>
205
+ </div>
206
+ </htmlpagefooter>
207
+
208
+ <sethtmlpageheader name="myheader" value="on" show-this-page="1" />
209
+ <sethtmlpagefooter name="myfooter" value="on" />
210
+ </body>
211
+ </html>
212
+
213
+ <?php
214
+ $output = ob_get_contents();
215
+ ob_end_clean();
216
+
217
+ // Yeah baby, do the trick!
218
+ $mpdf->WriteHTML($output);
219
+
220
+ // Get upload folder and create filename.
221
+ $uploads_dir = WP_CONTENT_DIR . '/uploads';
222
+ $filename = '/' . $invoice_number . '.pdf';
223
+ $full_path = $uploads_dir.$filename;
224
+
225
+ // Upload invoice
226
+ $mpdf->Output($full_path, 'F');
227
+
228
+ return $full_path;
229
+ }
230
+ else
231
+ {
232
+ return "";
233
+ }
234
+ }
235
+ }
includes/plugin.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ function bewpi_get_options(){
4
+ static $options;
5
+
6
+ if(!$options){
7
+ $defaults = array(
8
+ 'company_name' => get_option('woocommerce_email_from_name'),
9
+ 'company_slogan' => '',
10
+ 'file_upload' => '',
11
+ 'address' => '',
12
+ 'zip_code' => '',
13
+ 'city' => '',
14
+ 'country' => '',
15
+ 'telephone' => '',
16
+ 'email' => '',
17
+ 'extra_company_info' => '',
18
+ 'extra_info' => '',
19
+ );
20
+
21
+ // Get options from database.
22
+ $db_option = get_option('be_woocommerce_pdf_invoices', array());
23
+
24
+ if(!$db_option) {
25
+ update_option('be_woocommerce_pdf_invoices', $defaults);
26
+ }
27
+
28
+ $options = wp_parse_args($db_option, $defaults);
29
+ }
30
+
31
+ return $options;
32
+ }
33
+
34
+ ?>
includes/views/settings-page.php ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script type="text/javascript">
2
+ function removeImage(){
3
+ var elem = document.getElementById('custom-logo-wrap');
4
+ elem.parentNode.removeChild(elem);
5
+ document.getElementById('hiddenField').value = '';
6
+ }
7
+ </script>
8
+ <div class="wrap">
9
+ <h2>Woocommerc PDF Invoices</h2>
10
+ <h3>Woocommerce PDF Invoices Settings</h3>
11
+ <p>Please fill in the settings below. Woocommerce PDF Invoices generates a PDF invoice based upon the customer order and attaches it to the confirmation email.
12
+ You can leave the custom logo blank, the plugin will use your company name.</p>
13
+
14
+ <form method="post" action="options.php" enctype="multipart/form-data">
15
+ <?php
16
+ settings_fields( 'be_woocommerce_pdf_invoices' );
17
+ do_settings_sections( 'be_woocommerce_pdf_invoices' );
18
+ $plugin_url = plugins_url();
19
+ ?>
20
+ <table class="form-table">
21
+ <tr valign="top">
22
+ <th scope="row"><strong>Company name:</strong></th>
23
+ <td>
24
+ <input required type="text" size="40" name="be_woocommerce_pdf_invoices[company_name]" value="<?php echo $options['company_name']; ?>" />
25
+ </td>
26
+ </tr>
27
+
28
+ <tr valign="top">
29
+ <th scope="row"><strong>Company slogan:</strong></th>
30
+ <td>
31
+ <input type="text" size="40" name="be_woocommerce_pdf_invoices[company_slogan]" value="<?php echo $options['company_slogan']; ?>" />
32
+ </td>
33
+ </tr>
34
+
35
+ <tr valign="top">
36
+ <th scope="row"><strong>Custom logo:</strong></th>
37
+ <td>
38
+ <input type="file" name="logo" accept="image/*" /><br />
39
+ <?php if($options['file_upload'] != ''){ ?>
40
+ <style>
41
+ #delete{
42
+ position: absolute; top: 16px; right: 0px; background: #f7f7f7; border: 1px solid #d5d5d5; padding: 1px; display: none;
43
+ }
44
+ #custom-logo-wrap:hover #delete{
45
+ display: block;
46
+ }
47
+ </style>
48
+ <div id="custom-logo-wrap" style="position: relative; display: inline-block; padding-top: 16px;">
49
+ <img id="custom-logo" src="<?php echo esc_attr($options['file_upload']); ?>" /><br/ >
50
+ <a href="#" title="Remove custom logo" onclick="removeImage();">
51
+ <img id="delete" src="<?php echo $plugin_url.'/woocommerce/assets/images/icons/delete_10.png'?>" />
52
+ </a>
53
+ </div>
54
+ <?php } ?>
55
+ <input type="hidden" id="hiddenField" name="be_woocommerce_pdf_invoices[file_upload]" value="<?php echo esc_attr($options['file_upload']); ?>" />
56
+ </td>
57
+ </tr>
58
+
59
+ <tr valign="top">
60
+ <th scope="row"><strong>Company address:</strong></th>
61
+ <td>
62
+ <input required type="text" size="40" name="be_woocommerce_pdf_invoices[address]" value="<?php echo esc_attr($options['address']); ?>" /><br />
63
+ </td>
64
+ </tr>
65
+
66
+ <tr valign="top">
67
+ <th scope="row"><strong>Company ZIP code:</strong></th>
68
+ <td>
69
+ <input required type="text" size="40" name="be_woocommerce_pdf_invoices[zip_code]" value="<?php echo esc_attr($options['zip_code']); ?>" />
70
+ </td>
71
+ </tr>
72
+
73
+ <tr valign="top">
74
+ <th scope="row"><strong>Company city:</strong></th>
75
+ <td>
76
+ <input required type="text" size="40" name="be_woocommerce_pdf_invoices[city]" value="<?php echo esc_attr($options['city']); ?>" />
77
+ </td>
78
+ </tr>
79
+
80
+ <tr valign="top">
81
+ <th scope="row"><strong>Company country:</strong></th>
82
+ <td>
83
+ <input required type="text" size="40" name="be_woocommerce_pdf_invoices[country]" value="<?php echo esc_attr($options['country']); ?>" />
84
+ </td>
85
+ </tr>
86
+
87
+ <tr valign="top">
88
+ <th scope="row"><strong>Company telephone number:</strong></th>
89
+ <td>
90
+ <input type="text" size="40" name="be_woocommerce_pdf_invoices[telephone]" value="<?php echo esc_attr($options['telephone']); ?>" />
91
+ </td>
92
+ </tr>
93
+
94
+ <tr valign="top">
95
+ <th scope="row"><strong>Company email:</strong></th>
96
+ <td>
97
+ <input required type="text" size="40" name="be_woocommerce_pdf_invoices[email]" value="<?php echo esc_attr($options['email']); ?>" />
98
+ </td>
99
+ </tr>
100
+
101
+ <tr valign="top">
102
+ <th scope="row"><strong>Company information:</strong></th>
103
+ <td>
104
+ <textarea name="be_woocommerce_pdf_invoices[extra_company_info]" rows=6 cols=120 ><?php echo esc_textarea($options['extra_company_info']); ?></textarea><br/>
105
+ <span style="font-style:italic; font-weight:bold;">Note: </span><span style="font-style:italic; color:grey;">Use <?php echo htmlspecialchars("<b />"); ?> to get a line break.</span>
106
+ </td>
107
+ </tr>
108
+
109
+ <tr valign="top">
110
+ <th scope="row"><strong>Payment information:</strong></th>
111
+ <td>
112
+ <textarea name="be_woocommerce_pdf_invoices[extra_info]" rows=6 cols=120 ><?php echo esc_textarea($options['extra_info']);?></textarea><br/>
113
+ <span style="font-style:italic; font-weight:bold;">Note: </span><span style="font-style:italic; color:grey;">Use <?php echo htmlspecialchars("<b />"); ?> to get a line break.</span>
114
+ </td>
115
+ </tr>
116
+ </table>
117
+ <?php submit_button(); ?>
118
+ </form>
119
+ </div>
index.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Plugin Name: Woocommerce PDF Invoices
5
+ * Description: Generate PDF invoice and automatically attach to Woocommerce confirmation email.
6
+ * Version: 1.0.0
7
+ * Author: Bas Elbers
8
+ * License: GPL2
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) exit;
12
+
13
+ define("BEWPI_VERSION", "1.0.0");
14
+ define("BEWPI_PLUGIN_DIR", plugin_dir_path(__FILE__));
15
+ define("BEWPI_PLUGIN_URL", plugins_url( '/' , __FILE__ ));
16
+
17
+ require_once BEWPI_PLUGIN_DIR . 'includes/plugin.php';
18
+ require BEWPI_PLUGIN_DIR . 'includes/class-admin.php';
19
+ new BEWPI_Admin();
20
+
21
+ ?>
license.txt ADDED
@@ -0,0 +1,621 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+ Preamble
9
+
10
+ The GNU General Public License is a free, copyleft license for
11
+ software and other kinds of works.
12
+
13
+ The licenses for most software and other practical works are designed
14
+ to take away your freedom to share and change the works. By contrast,
15
+ the GNU General Public License is intended to guarantee your freedom to
16
+ share and change all versions of a program--to make sure it remains free
17
+ software for all its users. We, the Free Software Foundation, use the
18
+ GNU General Public License for most of our software; it applies also to
19
+ any other work released this way by its authors. You can apply it to
20
+ your programs, too.
21
+
22
+ When we speak of free software, we are referring to freedom, not
23
+ price. Our General Public Licenses are designed to make sure that you
24
+ have the freedom to distribute copies of free software (and charge for
25
+ them if you wish), that you receive source code or can get it if you
26
+ want it, that you can change the software or use pieces of it in new
27
+ free programs, and that you know you can do these things.
28
+
29
+ To protect your rights, we need to prevent others from denying you
30
+ these rights or asking you to surrender the rights. Therefore, you have
31
+ certain responsibilities if you distribute copies of the software, or if
32
+ you modify it: responsibilities to respect the freedom of others.
33
+
34
+ For example, if you distribute copies of such a program, whether
35
+ gratis or for a fee, you must pass on to the recipients the same
36
+ freedoms that you received. You must make sure that they, too, receive
37
+ or can get the source code. And you must show them these terms so they
38
+ know their rights.
39
+
40
+ Developers that use the GNU GPL protect your rights with two steps:
41
+ (1) assert copyright on the software, and (2) offer you this License
42
+ giving you legal permission to copy, distribute and/or modify it.
43
+
44
+ For the developers' and authors' protection, the GPL clearly explains
45
+ that there is no warranty for this free software. For both users' and
46
+ authors' sake, the GPL requires that modified versions be marked as
47
+ changed, so that their problems will not be attributed erroneously to
48
+ authors of previous versions.
49
+
50
+ Some devices are designed to deny users access to install or run
51
+ modified versions of the software inside them, although the manufacturer
52
+ can do so. This is fundamentally incompatible with the aim of
53
+ protecting users' freedom to change the software. The systematic
54
+ pattern of such abuse occurs in the area of products for individuals to
55
+ use, which is precisely where it is most unacceptable. Therefore, we
56
+ have designed this version of the GPL to prohibit the practice for those
57
+ products. If such problems arise substantially in other domains, we
58
+ stand ready to extend this provision to those domains in future versions
59
+ of the GPL, as needed to protect the freedom of users.
60
+
61
+ Finally, every program is threatened constantly by software patents.
62
+ States should not allow patents to restrict development and use of
63
+ software on general-purpose computers, but in those that do, we wish to
64
+ avoid the special danger that patents applied to a free program could
65
+ make it effectively proprietary. To prevent this, the GPL assures that
66
+ patents cannot be used to render the program non-free.
67
+
68
+ The precise terms and conditions for copying, distribution and
69
+ modification follow.
70
+
71
+ TERMS AND CONDITIONS
72
+
73
+ 0. Definitions.
74
+
75
+ "This License" refers to version 3 of the GNU General Public License.
76
+
77
+ "Copyright" also means copyright-like laws that apply to other kinds of
78
+ works, such as semiconductor masks.
79
+
80
+ "The Program" refers to any copyrightable work licensed under this
81
+ License. Each licensee is addressed as "you". "Licensees" and
82
+ "recipients" may be individuals or organizations.
83
+
84
+ To "modify" a work means to copy from or adapt all or part of the work
85
+ in a fashion requiring copyright permission, other than the making of an
86
+ exact copy. The resulting work is called a "modified version" of the
87
+ earlier work or a work "based on" the earlier work.
88
+
89
+ A "covered work" means either the unmodified Program or a work based
90
+ on the Program.
91
+
92
+ To "propagate" a work means to do anything with it that, without
93
+ permission, would make you directly or secondarily liable for
94
+ infringement under applicable copyright law, except executing it on a
95
+ computer or modifying a private copy. Propagation includes copying,
96
+ distribution (with or without modification), making available to the
97
+ public, and in some countries other activities as well.
98
+
99
+ To "convey" a work means any kind of propagation that enables other
100
+ parties to make or receive copies. Mere interaction with a user through
101
+ a computer network, with no transfer of a copy, is not conveying.
102
+
103
+ An interactive user interface displays "Appropriate Legal Notices"
104
+ to the extent that it includes a convenient and prominently visible
105
+ feature that (1) displays an appropriate copyright notice, and (2)
106
+ tells the user that there is no warranty for the work (except to the
107
+ extent that warranties are provided), that licensees may convey the
108
+ work under this License, and how to view a copy of this License. If
109
+ the interface presents a list of user commands or options, such as a
110
+ menu, a prominent item in the list meets this criterion.
111
+
112
+ 1. Source Code.
113
+
114
+ The "source code" for a work means the preferred form of the work
115
+ for making modifications to it. "Object code" means any non-source
116
+ form of a work.
117
+
118
+ A "Standard Interface" means an interface that either is an official
119
+ standard defined by a recognized standards body, or, in the case of
120
+ interfaces specified for a particular programming language, one that
121
+ is widely used among developers working in that language.
122
+
123
+ The "System Libraries" of an executable work include anything, other
124
+ than the work as a whole, that (a) is included in the normal form of
125
+ packaging a Major Component, but which is not part of that Major
126
+ Component, and (b) serves only to enable use of the work with that
127
+ Major Component, or to implement a Standard Interface for which an
128
+ implementation is available to the public in source code form. A
129
+ "Major Component", in this context, means a major essential component
130
+ (kernel, window system, and so on) of the specific operating system
131
+ (if any) on which the executable work runs, or a compiler used to
132
+ produce the work, or an object code interpreter used to run it.
133
+
134
+ The "Corresponding Source" for a work in object code form means all
135
+ the source code needed to generate, install, and (for an executable
136
+ work) run the object code and to modify the work, including scripts to
137
+ control those activities. However, it does not include the work's
138
+ System Libraries, or general-purpose tools or generally available free
139
+ programs which are used unmodified in performing those activities but
140
+ which are not part of the work. For example, Corresponding Source
141
+ includes interface definition files associated with source files for
142
+ the work, and the source code for shared libraries and dynamically
143
+ linked subprograms that the work is specifically designed to require,
144
+ such as by intimate data communication or control flow between those
145
+ subprograms and other parts of the work.
146
+
147
+ The Corresponding Source need not include anything that users
148
+ can regenerate automatically from other parts of the Corresponding
149
+ Source.
150
+
151
+ The Corresponding Source for a work in source code form is that
152
+ same work.
153
+
154
+ 2. Basic Permissions.
155
+
156
+ All rights granted under this License are granted for the term of
157
+ copyright on the Program, and are irrevocable provided the stated
158
+ conditions are met. This License explicitly affirms your unlimited
159
+ permission to run the unmodified Program. The output from running a
160
+ covered work is covered by this License only if the output, given its
161
+ content, constitutes a covered work. This License acknowledges your
162
+ rights of fair use or other equivalent, as provided by copyright law.
163
+
164
+ You may make, run and propagate covered works that you do not
165
+ convey, without conditions so long as your license otherwise remains
166
+ in force. You may convey covered works to others for the sole purpose
167
+ of having them make modifications exclusively for you, or provide you
168
+ with facilities for running those works, provided that you comply with
169
+ the terms of this License in conveying all material for which you do
170
+ not control copyright. Those thus making or running the covered works
171
+ for you must do so exclusively on your behalf, under your direction
172
+ and control, on terms that prohibit them from making any copies of
173
+ your copyrighted material outside their relationship with you.
174
+
175
+ Conveying under any other circumstances is permitted solely under
176
+ the conditions stated below. Sublicensing is not allowed; section 10
177
+ makes it unnecessary.
178
+
179
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180
+
181
+ No covered work shall be deemed part of an effective technological
182
+ measure under any applicable law fulfilling obligations under article
183
+ 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184
+ similar laws prohibiting or restricting circumvention of such
185
+ measures.
186
+
187
+ When you convey a covered work, you waive any legal power to forbid
188
+ circumvention of technological measures to the extent such circumvention
189
+ is effected by exercising rights under this License with respect to
190
+ the covered work, and you disclaim any intention to limit operation or
191
+ modification of the work as a means of enforcing, against the work's
192
+ users, your or third parties' legal rights to forbid circumvention of
193
+ technological measures.
194
+
195
+ 4. Conveying Verbatim Copies.
196
+
197
+ You may convey verbatim copies of the Program's source code as you
198
+ receive it, in any medium, provided that you conspicuously and
199
+ appropriately publish on each copy an appropriate copyright notice;
200
+ keep intact all notices stating that this License and any
201
+ non-permissive terms added in accord with section 7 apply to the code;
202
+ keep intact all notices of the absence of any warranty; and give all
203
+ recipients a copy of this License along with the Program.
204
+
205
+ You may charge any price or no price for each copy that you convey,
206
+ and you may offer support or warranty protection for a fee.
207
+
208
+ 5. Conveying Modified Source Versions.
209
+
210
+ You may convey a work based on the Program, or the modifications to
211
+ produce it from the Program, in the form of source code under the
212
+ terms of section 4, provided that you also meet all of these conditions:
213
+
214
+ a) The work must carry prominent notices stating that you modified
215
+ it, and giving a relevant date.
216
+
217
+ b) The work must carry prominent notices stating that it is
218
+ released under this License and any conditions added under section
219
+ 7. This requirement modifies the requirement in section 4 to
220
+ "keep intact all notices".
221
+
222
+ c) You must license the entire work, as a whole, under this
223
+ License to anyone who comes into possession of a copy. This
224
+ License will therefore apply, along with any applicable section 7
225
+ additional terms, to the whole of the work, and all its parts,
226
+ regardless of how they are packaged. This License gives no
227
+ permission to license the work in any other way, but it does not
228
+ invalidate such permission if you have separately received it.
229
+
230
+ d) If the work has interactive user interfaces, each must display
231
+ Appropriate Legal Notices; however, if the Program has interactive
232
+ interfaces that do not display Appropriate Legal Notices, your
233
+ work need not make them do so.
234
+
235
+ A compilation of a covered work with other separate and independent
236
+ works, which are not by their nature extensions of the covered work,
237
+ and which are not combined with it such as to form a larger program,
238
+ in or on a volume of a storage or distribution medium, is called an
239
+ "aggregate" if the compilation and its resulting copyright are not
240
+ used to limit the access or legal rights of the compilation's users
241
+ beyond what the individual works permit. Inclusion of a covered work
242
+ in an aggregate does not cause this License to apply to the other
243
+ parts of the aggregate.
244
+
245
+ 6. Conveying Non-Source Forms.
246
+
247
+ You may convey a covered work in object code form under the terms
248
+ of sections 4 and 5, provided that you also convey the
249
+ machine-readable Corresponding Source under the terms of this License,
250
+ in one of these ways:
251
+
252
+ a) Convey the object code in, or embodied in, a physical product
253
+ (including a physical distribution medium), accompanied by the
254
+ Corresponding Source fixed on a durable physical medium
255
+ customarily used for software interchange.
256
+
257
+ b) Convey the object code in, or embodied in, a physical product
258
+ (including a physical distribution medium), accompanied by a
259
+ written offer, valid for at least three years and valid for as
260
+ long as you offer spare parts or customer support for that product
261
+ model, to give anyone who possesses the object code either (1) a
262
+ copy of the Corresponding Source for all the software in the
263
+ product that is covered by this License, on a durable physical
264
+ medium customarily used for software interchange, for a price no
265
+ more than your reasonable cost of physically performing this
266
+ conveying of source, or (2) access to copy the
267
+ Corresponding Source from a network server at no charge.
268
+
269
+ c) Convey individual copies of the object code with a copy of the
270
+ written offer to provide the Corresponding Source. This
271
+ alternative is allowed only occasionally and noncommercially, and
272
+ only if you received the object code with such an offer, in accord
273
+ with subsection 6b.
274
+
275
+ d) Convey the object code by offering access from a designated
276
+ place (gratis or for a charge), and offer equivalent access to the
277
+ Corresponding Source in the same way through the same place at no
278
+ further charge. You need not require recipients to copy the
279
+ Corresponding Source along with the object code. If the place to
280
+ copy the object code is a network server, the Corresponding Source
281
+ may be on a different server (operated by you or a third party)
282
+ that supports equivalent copying facilities, provided you maintain
283
+ clear directions next to the object code saying where to find the
284
+ Corresponding Source. Regardless of what server hosts the
285
+ Corresponding Source, you remain obligated to ensure that it is
286
+ available for as long as needed to satisfy these requirements.
287
+
288
+ e) Convey the object code using peer-to-peer transmission, provided
289
+ you inform other peers where the object code and Corresponding
290
+ Source of the work are being offered to the general public at no
291
+ charge under subsection 6d.
292
+
293
+ A separable portion of the object code, whose source code is excluded
294
+ from the Corresponding Source as a System Library, need not be
295
+ included in conveying the object code work.
296
+
297
+ A "User Product" is either (1) a "consumer product", which means any
298
+ tangible personal property which is normally used for personal, family,
299
+ or household purposes, or (2) anything designed or sold for incorporation
300
+ into a dwelling. In determining whether a product is a consumer product,
301
+ doubtful cases shall be resolved in favor of coverage. For a particular
302
+ product received by a particular user, "normally used" refers to a
303
+ typical or common use of that class of product, regardless of the status
304
+ of the particular user or of the way in which the particular user
305
+ actually uses, or expects or is expected to use, the product. A product
306
+ is a consumer product regardless of whether the product has substantial
307
+ commercial, industrial or non-consumer uses, unless such uses represent
308
+ the only significant mode of use of the product.
309
+
310
+ "Installation Information" for a User Product means any methods,
311
+ procedures, authorization keys, or other information required to install
312
+ and execute modified versions of a covered work in that User Product from
313
+ a modified version of its Corresponding Source. The information must
314
+ suffice to ensure that the continued functioning of the modified object
315
+ code is in no case prevented or interfered with solely because
316
+ modification has been made.
317
+
318
+ If you convey an object code work under this section in, or with, or
319
+ specifically for use in, a User Product, and the conveying occurs as
320
+ part of a transaction in which the right of possession and use of the
321
+ User Product is transferred to the recipient in perpetuity or for a
322
+ fixed term (regardless of how the transaction is characterized), the
323
+ Corresponding Source conveyed under this section must be accompanied
324
+ by the Installation Information. But this requirement does not apply
325
+ if neither you nor any third party retains the ability to install
326
+ modified object code on the User Product (for example, the work has
327
+ been installed in ROM).
328
+
329
+ The requirement to provide Installation Information does not include a
330
+ requirement to continue to provide support service, warranty, or updates
331
+ for a work that has been modified or installed by the recipient, or for
332
+ the User Product in which it has been modified or installed. Access to a
333
+ network may be denied when the modification itself materially and
334
+ adversely affects the operation of the network or violates the rules and
335
+ protocols for communication across the network.
336
+
337
+ Corresponding Source conveyed, and Installation Information provided,
338
+ in accord with this section must be in a format that is publicly
339
+ documented (and with an implementation available to the public in
340
+ source code form), and must require no special password or key for
341
+ unpacking, reading or copying.
342
+
343
+ 7. Additional Terms.
344
+
345
+ "Additional permissions" are terms that supplement the terms of this
346
+ License by making exceptions from one or more of its conditions.
347
+ Additional permissions that are applicable to the entire Program shall
348
+ be treated as though they were included in this License, to the extent
349
+ that they are valid under applicable law. If additional permissions
350
+ apply only to part of the Program, that part may be used separately
351
+ under those permissions, but the entire Program remains governed by
352
+ this License without regard to the additional permissions.
353
+
354
+ When you convey a copy of a covered work, you may at your option
355
+ remove any additional permissions from that copy, or from any part of
356
+ it. (Additional permissions may be written to require their own
357
+ removal in certain cases when you modify the work.) You may place
358
+ additional permissions on material, added by you to a covered work,
359
+ for which you have or can give appropriate copyright permission.
360
+
361
+ Notwithstanding any other provision of this License, for material you
362
+ add to a covered work, you may (if authorized by the copyright holders of
363
+ that material) supplement the terms of this License with terms:
364
+
365
+ a) Disclaiming warranty or limiting liability differently from the
366
+ terms of sections 15 and 16 of this License; or
367
+
368
+ b) Requiring preservation of specified reasonable legal notices or
369
+ author attributions in that material or in the Appropriate Legal
370
+ Notices displayed by works containing it; or
371
+
372
+ c) Prohibiting misrepresentation of the origin of that material, or
373
+ requiring that modified versions of such material be marked in
374
+ reasonable ways as different from the original version; or
375
+
376
+ d) Limiting the use for publicity purposes of names of licensors or
377
+ authors of the material; or
378
+
379
+ e) Declining to grant rights under trademark law for use of some
380
+ trade names, trademarks, or service marks; or
381
+
382
+ f) Requiring indemnification of licensors and authors of that
383
+ material by anyone who conveys the material (or modified versions of
384
+ it) with contractual assumptions of liability to the recipient, for
385
+ any liability that these contractual assumptions directly impose on
386
+ those licensors and authors.
387
+
388
+ All other non-permissive additional terms are considered "further
389
+ restrictions" within the meaning of section 10. If the Program as you
390
+ received it, or any part of it, contains a notice stating that it is
391
+ governed by this License along with a term that is a further
392
+ restriction, you may remove that term. If a license document contains
393
+ a further restriction but permits relicensing or conveying under this
394
+ License, you may add to a covered work material governed by the terms
395
+ of that license document, provided that the further restriction does
396
+ not survive such relicensing or conveying.
397
+
398
+ If you add terms to a covered work in accord with this section, you
399
+ must place, in the relevant source files, a statement of the
400
+ additional terms that apply to those files, or a notice indicating
401
+ where to find the applicable terms.
402
+
403
+ Additional terms, permissive or non-permissive, may be stated in the
404
+ form of a separately written license, or stated as exceptions;
405
+ the above requirements apply either way.
406
+
407
+ 8. Termination.
408
+
409
+ You may not propagate or modify a covered work except as expressly
410
+ provided under this License. Any attempt otherwise to propagate or
411
+ modify it is void, and will automatically terminate your rights under
412
+ this License (including any patent licenses granted under the third
413
+ paragraph of section 11).
414
+
415
+ However, if you cease all violation of this License, then your
416
+ license from a particular copyright holder is reinstated (a)
417
+ provisionally, unless and until the copyright holder explicitly and
418
+ finally terminates your license, and (b) permanently, if the copyright
419
+ holder fails to notify you of the violation by some reasonable means
420
+ prior to 60 days after the cessation.
421
+
422
+ Moreover, your license from a particular copyright holder is
423
+ reinstated permanently if the copyright holder notifies you of the
424
+ violation by some reasonable means, this is the first time you have
425
+ received notice of violation of this License (for any work) from that
426
+ copyright holder, and you cure the violation prior to 30 days after
427
+ your receipt of the notice.
428
+
429
+ Termination of your rights under this section does not terminate the
430
+ licenses of parties who have received copies or rights from you under
431
+ this License. If your rights have been terminated and not permanently
432
+ reinstated, you do not qualify to receive new licenses for the same
433
+ material under section 10.
434
+
435
+ 9. Acceptance Not Required for Having Copies.
436
+
437
+ You are not required to accept this License in order to receive or
438
+ run a copy of the Program. Ancillary propagation of a covered work
439
+ occurring solely as a consequence of using peer-to-peer transmission
440
+ to receive a copy likewise does not require acceptance. However,
441
+ nothing other than this License grants you permission to propagate or
442
+ modify any covered work. These actions infringe copyright if you do
443
+ not accept this License. Therefore, by modifying or propagating a
444
+ covered work, you indicate your acceptance of this License to do so.
445
+
446
+ 10. Automatic Licensing of Downstream Recipients.
447
+
448
+ Each time you convey a covered work, the recipient automatically
449
+ receives a license from the original licensors, to run, modify and
450
+ propagate that work, subject to this License. You are not responsible
451
+ for enforcing compliance by third parties with this License.
452
+
453
+ An "entity transaction" is a transaction transferring control of an
454
+ organization, or substantially all assets of one, or subdividing an
455
+ organization, or merging organizations. If propagation of a covered
456
+ work results from an entity transaction, each party to that
457
+ transaction who receives a copy of the work also receives whatever
458
+ licenses to the work the party's predecessor in interest had or could
459
+ give under the previous paragraph, plus a right to possession of the
460
+ Corresponding Source of the work from the predecessor in interest, if
461
+ the predecessor has it or can get it with reasonable efforts.
462
+
463
+ You may not impose any further restrictions on the exercise of the
464
+ rights granted or affirmed under this License. For example, you may
465
+ not impose a license fee, royalty, or other charge for exercise of
466
+ rights granted under this License, and you may not initiate litigation
467
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
468
+ any patent claim is infringed by making, using, selling, offering for
469
+ sale, or importing the Program or any portion of it.
470
+
471
+ 11. Patents.
472
+
473
+ A "contributor" is a copyright holder who authorizes use under this
474
+ License of the Program or a work on which the Program is based. The
475
+ work thus licensed is called the contributor's "contributor version".
476
+
477
+ A contributor's "essential patent claims" are all patent claims
478
+ owned or controlled by the contributor, whether already acquired or
479
+ hereafter acquired, that would be infringed by some manner, permitted
480
+ by this License, of making, using, or selling its contributor version,
481
+ but do not include claims that would be infringed only as a
482
+ consequence of further modification of the contributor version. For
483
+ purposes of this definition, "control" includes the right to grant
484
+ patent sublicenses in a manner consistent with the requirements of
485
+ this License.
486
+
487
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
488
+ patent license under the contributor's essential patent claims, to
489
+ make, use, sell, offer for sale, import and otherwise run, modify and
490
+ propagate the contents of its contributor version.
491
+
492
+ In the following three paragraphs, a "patent license" is any express
493
+ agreement or commitment, however denominated, not to enforce a patent
494
+ (such as an express permission to practice a patent or covenant not to
495
+ sue for patent infringement). To "grant" such a patent license to a
496
+ party means to make such an agreement or commitment not to enforce a
497
+ patent against the party.
498
+
499
+ If you convey a covered work, knowingly relying on a patent license,
500
+ and the Corresponding Source of the work is not available for anyone
501
+ to copy, free of charge and under the terms of this License, through a
502
+ publicly available network server or other readily accessible means,
503
+ then you must either (1) cause the Corresponding Source to be so
504
+ available, or (2) arrange to deprive yourself of the benefit of the
505
+ patent license for this particular work, or (3) arrange, in a manner
506
+ consistent with the requirements of this License, to extend the patent
507
+ license to downstream recipients. "Knowingly relying" means you have
508
+ actual knowledge that, but for the patent license, your conveying the
509
+ covered work in a country, or your recipient's use of the covered work
510
+ in a country, would infringe one or more identifiable patents in that
511
+ country that you have reason to believe are valid.
512
+
513
+ If, pursuant to or in connection with a single transaction or
514
+ arrangement, you convey, or propagate by procuring conveyance of, a
515
+ covered work, and grant a patent license to some of the parties
516
+ receiving the covered work authorizing them to use, propagate, modify
517
+ or convey a specific copy of the covered work, then the patent license
518
+ you grant is automatically extended to all recipients of the covered
519
+ work and works based on it.
520
+
521
+ A patent license is "discriminatory" if it does not include within
522
+ the scope of its coverage, prohibits the exercise of, or is
523
+ conditioned on the non-exercise of one or more of the rights that are
524
+ specifically granted under this License. You may not convey a covered
525
+ work if you are a party to an arrangement with a third party that is
526
+ in the business of distributing software, under which you make payment
527
+ to the third party based on the extent of your activity of conveying
528
+ the work, and under which the third party grants, to any of the
529
+ parties who would receive the covered work from you, a discriminatory
530
+ patent license (a) in connection with copies of the covered work
531
+ conveyed by you (or copies made from those copies), or (b) primarily
532
+ for and in connection with specific products or compilations that
533
+ contain the covered work, unless you entered into that arrangement,
534
+ or that patent license was granted, prior to 28 March 2007.
535
+
536
+ Nothing in this License shall be construed as excluding or limiting
537
+ any implied license or other defenses to infringement that may
538
+ otherwise be available to you under applicable patent law.
539
+
540
+ 12. No Surrender of Others' Freedom.
541
+
542
+ If conditions are imposed on you (whether by court order, agreement or
543
+ otherwise) that contradict the conditions of this License, they do not
544
+ excuse you from the conditions of this License. If you cannot convey a
545
+ covered work so as to satisfy simultaneously your obligations under this
546
+ License and any other pertinent obligations, then as a consequence you may
547
+ not convey it at all. For example, if you agree to terms that obligate you
548
+ to collect a royalty for further conveying from those to whom you convey
549
+ the Program, the only way you could satisfy both those terms and this
550
+ License would be to refrain entirely from conveying the Program.
551
+
552
+ 13. Use with the GNU Affero General Public License.
553
+
554
+ Notwithstanding any other provision of this License, you have
555
+ permission to link or combine any covered work with a work licensed
556
+ under version 3 of the GNU Affero General Public License into a single
557
+ combined work, and to convey the resulting work. The terms of this
558
+ License will continue to apply to the part which is the covered work,
559
+ but the special requirements of the GNU Affero General Public License,
560
+ section 13, concerning interaction through a network will apply to the
561
+ combination as such.
562
+
563
+ 14. Revised Versions of this License.
564
+
565
+ The Free Software Foundation may publish revised and/or new versions of
566
+ the GNU General Public License from time to time. Such new versions will
567
+ be similar in spirit to the present version, but may differ in detail to
568
+ address new problems or concerns.
569
+
570
+ Each version is given a distinguishing version number. If the
571
+ Program specifies that a certain numbered version of the GNU General
572
+ Public License "or any later version" applies to it, you have the
573
+ option of following the terms and conditions either of that numbered
574
+ version or of any later version published by the Free Software
575
+ Foundation. If the Program does not specify a version number of the
576
+ GNU General Public License, you may choose any version ever published
577
+ by the Free Software Foundation.
578
+
579
+ If the Program specifies that a proxy can decide which future
580
+ versions of the GNU General Public License can be used, that proxy's
581
+ public statement of acceptance of a version permanently authorizes you
582
+ to choose that version for the Program.
583
+
584
+ Later license versions may give you additional or different
585
+ permissions. However, no additional obligations are imposed on any
586
+ author or copyright holder as a result of your choosing to follow a
587
+ later version.
588
+
589
+ 15. Disclaimer of Warranty.
590
+
591
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594
+ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597
+ IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598
+ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599
+
600
+ 16. Limitation of Liability.
601
+
602
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604
+ THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605
+ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606
+ USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607
+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609
+ EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610
+ SUCH DAMAGES.
611
+
612
+ 17. Interpretation of Sections 15 and 16.
613
+
614
+ If the disclaimer of warranty and limitation of liability provided
615
+ above cannot be given local legal effect according to their terms,
616
+ reviewing courts shall apply local law that most closely approximates
617
+ an absolute waiver of all civil liability in connection with the
618
+ Program, unless a warranty or assumption of liability accompanies a
619
+ copy of the Program in return for a fee.
620
+
621
+ END OF TERMS AND CONDITIONS
mpdf/classes/cssmgr.php ADDED
@@ -0,0 +1,1566 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class cssmgr {
4
+
5
+ var $mpdf = null;
6
+
7
+ var $tablecascadeCSS;
8
+ var $listcascadeCSS;
9
+ var $cascadeCSS;
10
+ var $CSS;
11
+ var $tbCSSlvl;
12
+ var $listCSSlvl;
13
+
14
+
15
+ function cssmgr(&$mpdf) {
16
+ $this->mpdf = $mpdf;
17
+ $this->tablecascadeCSS = array();
18
+ $this->listcascadeCSS = array();
19
+ $this->CSS=array();
20
+ $this->cascadeCSS = array();
21
+ $this->tbCSSlvl = 0;
22
+ $this->listCSSlvl = 0;
23
+ }
24
+
25
+
26
+ function ReadDefaultCSS($CSSstr) {
27
+ $CSS = array();
28
+ $CSSstr = preg_replace('|/\*.*?\*/|s',' ',$CSSstr);
29
+ $CSSstr = preg_replace('/[\s\n\r\t\f]/s',' ',$CSSstr);
30
+ $CSSstr = preg_replace('/(<\!\-\-|\-\->)/s',' ',$CSSstr);
31
+ if ($CSSstr ) {
32
+ preg_match_all('/(.*?)\{(.*?)\}/',$CSSstr,$styles);
33
+ for($i=0; $i < count($styles[1]) ; $i++) {
34
+ $stylestr= trim($styles[2][$i]);
35
+ $stylearr = explode(';',$stylestr);
36
+ foreach($stylearr AS $sta) {
37
+ if (trim($sta)) {
38
+ // Changed to allow style="background: url('http://www.bpm1.com/bg.jpg')"
39
+ list($property,$value) = explode(':',$sta,2);
40
+ $property = trim($property);
41
+ $value = preg_replace('/\s*!important/i','',$value);
42
+ $value = trim($value);
43
+ if ($property && ($value || $value==='0')) {
44
+ $classproperties[strtoupper($property)] = $value;
45
+ }
46
+ }
47
+ }
48
+ $classproperties = $this->fixCSS($classproperties);
49
+ $tagstr = strtoupper(trim($styles[1][$i]));
50
+ $tagarr = explode(',',$tagstr);
51
+ foreach($tagarr AS $tg) {
52
+ $tags = preg_split('/\s+/',trim($tg));
53
+ $level = count($tags);
54
+ if ($level == 1) { // e.g. p or .class or #id or p.class or p#id
55
+ $t = trim($tags[0]);
56
+ if ($t) {
57
+ $tag = '';
58
+ if (preg_match('/^('.$this->mpdf->allowedCSStags.')$/',$t)) { $tag= $t; }
59
+ if ($this->CSS[$tag] && $tag) { $CSS[$tag] = $this->array_merge_recursive_unique($CSS[$tag], $classproperties); }
60
+ else if ($tag) { $CSS[$tag] = $classproperties; }
61
+ }
62
+ }
63
+ }
64
+ $properties = array();
65
+ $values = array();
66
+ $classproperties = array();
67
+ }
68
+
69
+ } // end of if
70
+ return $CSS;
71
+ }
72
+
73
+
74
+
75
+ function ReadCSS($html) {
76
+ preg_match_all('/<style[^>]*media=["\']([^"\'>]*)["\'].*?<\/style>/is',$html,$m);
77
+ for($i=0; $i<count($m[0]); $i++) {
78
+ if ($this->mpdf->CSSselectMedia && !preg_match('/('.trim($this->mpdf->CSSselectMedia).'|all)/i',$m[1][$i])) {
79
+ $html = preg_replace('/'.preg_quote($m[0][$i],'/').'/','',$html);
80
+ }
81
+ }
82
+ preg_match_all('/<link[^>]*media=["\']([^"\'>]*)["\'].*?>/is',$html,$m);
83
+ for($i=0; $i<count($m[0]); $i++) {
84
+ if ($this->mpdf->CSSselectMedia && !preg_match('/('.trim($this->mpdf->CSSselectMedia).'|all)/i',$m[1][$i])) {
85
+ $html = preg_replace('/'.preg_quote($m[0][$i],'/').'/','',$html);
86
+ }
87
+ }
88
+
89
+ // mPDF 5.5.02
90
+ // Remove Comment tags <!-- ... --> inside CSS as <style> in HTML document
91
+ // Remove Comment tags /* ... */ inside CSS as <style> in HTML document
92
+ // But first, we replace upper and mixed case closing style tag with lower
93
+ // case so we can use str_replace later.
94
+ preg_replace('/<\/style>/i', '</style>', $html);
95
+ preg_match_all('/<style.*?>(.*?)<\/style>/si',$html,$m);
96
+ if (count($m[1])) {
97
+ for($i=0;$i<count($m[1]);$i++) {
98
+ // Remove comment tags
99
+ $sub = preg_replace('/(<\!\-\-|\-\->)/s',' ',$m[1][$i]);
100
+ $sub = '>'.preg_replace('|/\*.*?\*/|s',' ',$sub).'</style>';
101
+ $html = str_replace('>'.$m[1][$i].'</style>', $sub, $html);
102
+ }
103
+ }
104
+
105
+
106
+ $html = preg_replace('/<!--mpdf/i','',$html);
107
+ $html = preg_replace('/mpdf-->/i','',$html);
108
+ $html = preg_replace('/<\!\-\-.*?\-\->/s',' ',$html);
109
+
110
+ $match = 0; // no match for instance
111
+ $regexp = ''; // This helps debugging: showing what is the REAL string being processed
112
+ $CSSext = array();
113
+
114
+ //CSS inside external files
115
+ $regexp = '/<link[^>]*rel=["\']stylesheet["\'][^>]*href=["\']([^>"\']*)["\'].*?>/si';
116
+ $x = preg_match_all($regexp,$html,$cxt);
117
+ if ($x) {
118
+ $match += $x;
119
+ $CSSext = $cxt[1];
120
+ }
121
+
122
+ $regexp = '/<link[^>]*href=["\']([^>"\']*)["\'][^>]*?rel=["\']stylesheet["\'].*?>/si';
123
+ $x = preg_match_all($regexp,$html,$cxt);
124
+ if ($x) {
125
+ $match += $x;
126
+ $CSSext = array_merge($CSSext,$cxt[1]);
127
+ }
128
+
129
+ // look for @import stylesheets
130
+ //$regexp = '/@import url\([\'\"]{0,1}([^\)]*?\.css)[\'\"]{0,1}\)/si';
131
+ $regexp = '/@import url\([\'\"]{0,1}([^\)]*?\.css(\?\S+)?)[\'\"]{0,1}\)/si';
132
+ $x = preg_match_all($regexp,$html,$cxt);
133
+ if ($x) {
134
+ $match += $x;
135
+ $CSSext = array_merge($CSSext,$cxt[1]);
136
+ }
137
+
138
+ // look for @import without the url()
139
+ //$regexp = '/@import [\'\"]{0,1}([^;]*?\.css)[\'\"]{0,1}/si';
140
+ $regexp = '/@import [\'\"]{0,1}([^;]*?\.css(\?\S+)?)[\'\"]{0,1}/si';
141
+ $x = preg_match_all($regexp,$html,$cxt);
142
+ if ($x) {
143
+ $match += $x;
144
+ $CSSext = array_merge($CSSext,$cxt[1]);
145
+ }
146
+
147
+ $ind = 0;
148
+ $CSSstr = '';
149
+
150
+ if (!is_array($this->cascadeCSS)) $this->cascadeCSS = array();
151
+
152
+ while($match){
153
+ $path = $CSSext[$ind];
154
+ $this->mpdf->GetFullPath($path);
155
+ $CSSextblock = $this->mpdf->_get_file($path);
156
+ if ($CSSextblock) {
157
+ // look for embedded @import stylesheets in other stylesheets
158
+ // and fix url paths (including background-images) relative to stylesheet
159
+ //$regexpem = '/@import url\([\'\"]{0,1}(.*?\.css)[\'\"]{0,1}\)/si';
160
+ $regexpem = '/@import url\([\'\"]{0,1}(.*?\.css(\?\S+)?)[\'\"]{0,1}\)/si';
161
+ $xem = preg_match_all($regexpem,$CSSextblock,$cxtem);
162
+ $cssBasePath = preg_replace('/\/[^\/]*$/','',$path) . '/';
163
+ if ($xem) {
164
+ foreach($cxtem[1] AS $cxtembedded) {
165
+ // path is relative to original stlyesheet!!
166
+ $this->mpdf->GetFullPath($cxtembedded, $cssBasePath );
167
+ $match++;
168
+ $CSSext[] = $cxtembedded;
169
+ }
170
+ }
171
+ $regexpem = '/(background[^;]*url\s*\(\s*[\'\"]{0,1})([^\)\'\"]*)([\'\"]{0,1}\s*\))/si';
172
+ $xem = preg_match_all($regexpem,$CSSextblock,$cxtem);
173
+ if ($xem) {
174
+ for ($i=0;$i<count($cxtem[0]);$i++) {
175
+ // path is relative to original stlyesheet!!
176
+ $embedded = $cxtem[2][$i];
177
+ if (!preg_match('/^data:image/i', $embedded)) { // mPDF 5.5.13
178
+ $this->mpdf->GetFullPath($embedded, $cssBasePath );
179
+ $CSSextblock = preg_replace('/'.preg_quote($cxtem[0][$i],'/').'/', ($cxtem[1][$i].$embedded.$cxtem[3][$i]), $CSSextblock);
180
+ }
181
+ }
182
+ }
183
+ $CSSstr .= ' '.$CSSextblock;
184
+ }
185
+ $match--;
186
+ $ind++;
187
+ } //end of match
188
+
189
+ $match = 0; // reset value, if needed
190
+ // CSS as <style> in HTML document
191
+ $regexp = '/<style.*?>(.*?)<\/style>/si';
192
+ $match = preg_match_all($regexp,$html,$CSSblock);
193
+ if ($match) {
194
+ $tmpCSSstr = implode(' ',$CSSblock[1]);
195
+ $regexpem = '/(background[^;]*url\s*\(\s*[\'\"]{0,1})([^\)\'\"]*)([\'\"]{0,1}\s*\))/si';
196
+ $xem = preg_match_all($regexpem,$tmpCSSstr ,$cxtem);
197
+ if ($xem) {
198
+ for ($i=0;$i<count($cxtem[0]);$i++) {
199
+ $embedded = $cxtem[2][$i];
200
+ if (!preg_match('/^data:image/i', $embedded)) { // mPDF 5.5.13
201
+ $this->mpdf->GetFullPath($embedded);
202
+ $tmpCSSstr = preg_replace('/'.preg_quote($cxtem[0][$i],'/').'/', ($cxtem[1][$i].$embedded.$cxtem[3][$i]), $tmpCSSstr );
203
+ }
204
+ }
205
+ }
206
+ $CSSstr .= ' '.$tmpCSSstr;
207
+ }
208
+ // Remove comments
209
+ $CSSstr = preg_replace('|/\*.*?\*/|s',' ',$CSSstr);
210
+ $CSSstr = preg_replace('/[\s\n\r\t\f]/s',' ',$CSSstr);
211
+
212
+ if (preg_match('/@media/',$CSSstr)) {
213
+ preg_match_all('/@media(.*?)\{(([^\{\}]*\{[^\{\}]*\})+)\s*\}/is',$CSSstr,$m);
214
+ for($i=0; $i<count($m[0]); $i++) {
215
+ if ($this->mpdf->CSSselectMedia && !preg_match('/('.trim($this->mpdf->CSSselectMedia).'|all)/i',$m[1][$i])) {
216
+ $CSSstr = preg_replace('/'.preg_quote($m[0][$i],'/').'/','',$CSSstr);
217
+ }
218
+ else {
219
+ $CSSstr = preg_replace('/'.preg_quote($m[0][$i],'/').'/',' '.$m[2][$i].' ',$CSSstr);
220
+ }
221
+ }
222
+ }
223
+
224
+ // mPDF 5.5.13
225
+ // Replace any background: url(data:image... with temporary image file reference
226
+ preg_match_all("/(url\(data:image\/(jpeg|gif|png);base64,(.*)\))/si", $CSSstr, $idata);
227
+ if (count($idata[0])) {
228
+ for($i=0;$i<count($idata[0]);$i++) {
229
+ $file = _MPDF_TEMP_PATH.'_tempCSSidata'.RAND(1,10000).'_'.$i.'.'.$idata[2][$i];
230
+ //Save to local file
231
+ file_put_contents($file, base64_decode($idata[3][$i]));
232
+ // $this->mpdf->GetFullPath($file); // ? is this needed - NO mPDF 5.6.03
233
+ $CSSstr = str_replace($idata[0][$i], 'url("'.$file.'")', $CSSstr); // mPDF 5.5.17
234
+ }
235
+ }
236
+
237
+ $CSSstr = preg_replace('/(<\!\-\-|\-\->)/s',' ',$CSSstr);
238
+ if ($CSSstr ) {
239
+ preg_match_all('/(.*?)\{(.*?)\}/',$CSSstr,$styles);
240
+ for($i=0; $i < count($styles[1]) ; $i++) {
241
+ // SET array e.g. $classproperties['COLOR'] = '#ffffff';
242
+ $stylestr= trim($styles[2][$i]);
243
+ $stylearr = explode(';',$stylestr);
244
+ foreach($stylearr AS $sta) {
245
+ if (trim($sta)) {
246
+ // Changed to allow style="background: url('http://www.bpm1.com/bg.jpg')"
247
+ list($property,$value) = explode(':',$sta,2);
248
+ $property = trim($property);
249
+ $value = preg_replace('/\s*!important/i','',$value);
250
+ $value = trim($value);
251
+ if ($property && ($value || $value==='0')) {
252
+ // Ignores -webkit-gradient so doesn't override -moz-
253
+ if ((strtoupper($property)=='BACKGROUND-IMAGE' || strtoupper($property)=='BACKGROUND') && preg_match('/-webkit-gradient/i',$value)) {
254
+ continue;
255
+ }
256
+ $classproperties[strtoupper($property)] = $value;
257
+ }
258
+ }
259
+ }
260
+ $classproperties = $this->fixCSS($classproperties);
261
+ $tagstr = strtoupper(trim($styles[1][$i]));
262
+ $tagarr = explode(',',$tagstr);
263
+ $pageselectors = false; // used to turn on $this->mpdf->mirrorMargins
264
+ foreach($tagarr AS $tg) {
265
+ $tags = preg_split('/\s+/',trim($tg));
266
+ $level = count($tags);
267
+ $t = '';
268
+ $t2 = '';
269
+ $t3 = '';
270
+ if (trim($tags[0])=='@PAGE') {
271
+ if (isset($tags[0])) { $t = trim($tags[0]); }
272
+ if (isset($tags[1])) { $t2 = trim($tags[1]); }
273
+ if (isset($tags[2])) { $t3 = trim($tags[2]); }
274
+ $tag = '';
275
+ if ($level==1) { $tag = $t; }
276
+ else if ($level==2 && preg_match('/^[:](.*)$/',$t2,$m)) {
277
+ $tag = $t.'>>PSEUDO>>'.$m[1];
278
+ if ($m[1]=='LEFT' || $m[1]=='RIGHT') { $pageselectors = true; } // used to turn on $this->mpdf->mirrorMargins
279
+ }
280
+ else if ($level==2) { $tag = $t.'>>NAMED>>'.$t2; }
281
+ else if ($level==3 && preg_match('/^[:](.*)$/',$t3,$m)) {
282
+ $tag = $t.'>>NAMED>>'.$t2.'>>PSEUDO>>'.$m[1];
283
+ if ($m[1]=='LEFT' || $m[1]=='RIGHT') { $pageselectors = true; } // used to turn on $this->mpdf->mirrorMargins
284
+ }
285
+ if (isset($this->CSS[$tag]) && $tag) { $this->CSS[$tag] = $this->array_merge_recursive_unique($this->CSS[$tag], $classproperties); }
286
+ else if ($tag) { $this->CSS[$tag] = $classproperties; }
287
+ }
288
+
289
+ else if ($level == 1) { // e.g. p or .class or #id or p.class or p#id
290
+ if (isset($tags[0])) { $t = trim($tags[0]); }
291
+ if ($t) {
292
+ $tag = '';
293
+ if (preg_match('/^[.](.*)$/',$t,$m)) { $tag = 'CLASS>>'.$m[1]; }
294
+ else if (preg_match('/^[#](.*)$/',$t,$m)) { $tag = 'ID>>'.$m[1]; }
295
+ else if (preg_match('/^('.$this->mpdf->allowedCSStags.')[.](.*)$/',$t,$m)) { $tag = $m[1].'>>CLASS>>'.$m[2]; }
296
+ else if (preg_match('/^('.$this->mpdf->allowedCSStags.')\s*:NTH-CHILD\((.*)\)$/',$t,$m)) { $tag = $m[1].'>>SELECTORNTHCHILD>>'.$m[2]; }
297
+ else if (preg_match('/^('.$this->mpdf->allowedCSStags.')[#](.*)$/',$t,$m)) { $tag = $m[1].'>>ID>>'.$m[2]; }
298
+ else if (preg_match('/^('.$this->mpdf->allowedCSStags.')$/',$t)) { $tag= $t; }
299
+ if (isset($this->CSS[$tag]) && $tag) { $this->CSS[$tag] = $this->array_merge_recursive_unique($this->CSS[$tag], $classproperties); }
300
+ else if ($tag) { $this->CSS[$tag] = $classproperties; }
301
+ }
302
+ }
303
+ else {
304
+ $tmp = array();
305
+ for($n=0;$n<$level;$n++) {
306
+ if (isset($tags[$n])) { $t = trim($tags[$n]); }
307
+ else { $t = ''; }
308
+ if ($t) {
309
+ $tag = '';
310
+ if (preg_match('/^[.](.*)$/',$t,$m)) { $tag = 'CLASS>>'.$m[1]; }
311
+ else if (preg_match('/^[#](.*)$/',$t,$m)) { $tag = 'ID>>'.$m[1]; }
312
+ else if (preg_match('/^('.$this->mpdf->allowedCSStags.')[.](.*)$/',$t,$m)) { $tag = $m[1].'>>CLASS>>'.$m[2]; }
313
+ else if (preg_match('/^('.$this->mpdf->allowedCSStags.')\s*:NTH-CHILD\((.*)\)$/',$t,$m)) { $tag = $m[1].'>>SELECTORNTHCHILD>>'.$m[2]; }
314
+ else if (preg_match('/^('.$this->mpdf->allowedCSStags.')[#](.*)$/',$t,$m)) { $tag = $m[1].'>>ID>>'.$m[2]; }
315
+ else if (preg_match('/^('.$this->mpdf->allowedCSStags.')$/',$t)) { $tag= $t; }
316
+
317
+ if ($tag) $tmp[] = $tag;
318
+ else { break; }
319
+ }
320
+ }
321
+
322
+ if ($tag) {
323
+ $x = &$this->cascadeCSS;
324
+ foreach($tmp AS $tp) { $x = &$x[$tp]; }
325
+ $x = $this->array_merge_recursive_unique($x, $classproperties);
326
+ $x['depth'] = $level;
327
+ }
328
+ }
329
+ }
330
+ if ($pageselectors) { $this->mpdf->mirrorMargins = true; }
331
+ $properties = array();
332
+ $values = array();
333
+ $classproperties = array();
334
+ }
335
+ } // end of if
336
+ //Remove CSS (tags and content), if any
337
+ $regexp = '/<style.*?>(.*?)<\/style>/si'; // it can be <style> or <style type="txt/css">
338
+ $html = preg_replace($regexp,'',$html);
339
+ //print_r($this->CSS); exit;
340
+ //print_r($this->cascadeCSS); exit;
341
+ return $html;
342
+ }
343
+
344
+
345
+
346
+ function readInlineCSS($html) {
347
+ //Fix incomplete CSS code
348
+ $size = strlen($html)-1;
349
+ if (substr($html,$size,1) != ';') $html .= ';';
350
+ //Make CSS[Name-of-the-class] = array(key => value)
351
+ $regexp = '|\\s*?(\\S+?):(.+?);|i';
352
+ preg_match_all( $regexp, $html, $styleinfo);
353
+ $properties = $styleinfo[1];
354
+ $values = $styleinfo[2];
355
+ //Array-properties and Array-values must have the SAME SIZE!
356
+ $classproperties = array();
357
+ for($i = 0; $i < count($properties) ; $i++) {
358
+ // Ignores -webkit-gradient so doesn't override -moz-
359
+ if ((strtoupper($properties[$i])=='BACKGROUND-IMAGE' || strtoupper($properties[$i])=='BACKGROUND') && preg_match('/-webkit-gradient/i',$values[$i])) {
360
+ continue;
361
+ }
362
+ $classproperties[strtoupper($properties[$i])] = trim($values[$i]);
363
+ }
364
+ return $this->fixCSS($classproperties);
365
+ }
366
+
367
+
368
+
369
+ function _fix_borderStr($bd) {
370
+ preg_match_all("/\((.*?)\)/", $bd, $m);
371
+ if (count($m[1])) {
372
+ for($i=0;$i<count($m[1]);$i++) {
373
+ $sub = preg_replace("/ /", "", $m[1][$i]);
374
+ $bd = preg_replace('/'.preg_quote($m[1][$i], '/').'/si', $sub, $bd);
375
+ }
376
+ }
377
+
378
+ $prop = preg_split('/\s+/',trim($bd));
379
+ $w = 'medium';
380
+ $c = '#000000';
381
+ $s = 'none';
382
+
383
+ if ( count($prop) == 1 ) {
384
+ // solid
385
+ if (in_array($prop[0],$this->mpdf->borderstyles) || $prop[0] == 'none' || $prop[0] == 'hidden' ) { $s = $prop[0]; }
386
+ // #000000
387
+ else if (is_array($this->mpdf->ConvertColor($prop[0]))) { $c = $prop[0]; }
388
+ // 1px
389
+ else { $w = $prop[0]; }
390
+ }
391
+ else if (count($prop) == 2 ) {
392
+ // 1px solid
393
+ if (in_array($prop[1],$this->mpdf->borderstyles) || $prop[1] == 'none' || $prop[1] == 'hidden' ) { $w = $prop[0]; $s = $prop[1]; }
394
+ // solid #000000
395
+ else if (in_array($prop[0],$this->mpdf->borderstyles) || $prop[0] == 'none' || $prop[0] == 'hidden' ) { $s = $prop[0]; $c = $prop[1]; }
396
+ // 1px #000000
397
+ else { $w = $prop[0]; $c = $prop[1]; }
398
+ }
399
+ else if ( count($prop) == 3 ) {
400
+ // Change #000000 1px solid to 1px solid #000000 (proper)
401
+ if (substr($prop[0],0,1) == '#') { $c = $prop[0]; $w = $prop[1]; $s = $prop[2]; }
402
+ // Change solid #000000 1px to 1px solid #000000 (proper)
403
+ else if (substr($prop[0],1,1) == '#') { $s = $prop[0]; $c = $prop[1]; $w = $prop[2]; }
404
+ // Change solid 1px #000000 to 1px solid #000000 (proper)
405
+ else if (in_array($prop[0],$this->mpdf->borderstyles) || $prop[0] == 'none' || $prop[0] == 'hidden' ) {
406
+ $s = $prop[0]; $w = $prop[1]; $c = $prop[2];
407
+ }
408
+ else { $w = $prop[0]; $s = $prop[1]; $c = $prop[2]; }
409
+ }
410
+ else { return ''; }
411
+ $s = strtolower($s);
412
+ return $w.' '.$s.' '.$c;
413
+ }
414
+
415
+
416
+
417
+ function fixCSS($prop) {
418
+ if (!is_array($prop) || (count($prop)==0)) return array();
419
+ $newprop = array();
420
+ foreach($prop AS $k => $v) {
421
+ if ($k != 'BACKGROUND-IMAGE' && $k != 'BACKGROUND' && $k != 'ODD-HEADER-NAME' && $k != 'EVEN-HEADER-NAME' && $k != 'ODD-FOOTER-NAME' && $k != 'EVEN-FOOTER-NAME' && $k != 'HEADER' && $k != 'FOOTER') {
422
+ $v = strtolower($v);
423
+ }
424
+
425
+ if ($k == 'FONT') {
426
+ $s = trim($v);
427
+ preg_match_all('/\"(.*?)\"/',$s,$ff);
428
+ if (count($ff[1])) {
429
+ foreach($ff[1] AS $ffp) {
430
+ $w = preg_split('/\s+/',$ffp);
431
+ $s = preg_replace('/\"'.$ffp.'\"/',$w[0],$s);
432
+ }
433
+ }
434
+ preg_match_all('/\'(.*?)\'/',$s,$ff);
435
+ if (count($ff[1])) {
436
+ foreach($ff[1] AS $ffp) {
437
+ $w = preg_split('/\s+/',$ffp);
438
+ $s = preg_replace('/\''.$ffp.'\'/',$w[0],$s);
439
+ }
440
+ }
441
+ $s = preg_replace('/\s*,\s*/',',',$s);
442
+ $bits = preg_split('/\s+/',$s);
443
+ if (count($bits)>1) {
444
+ $k = 'FONT-FAMILY'; $v = $bits[(count($bits)-1)];
445
+ $fs = $bits[(count($bits)-2)];
446
+ if (preg_match('/(.*?)\/(.*)/',$fs, $fsp)) {
447
+ $newprop['FONT-SIZE'] = $fsp[1];
448
+ $newprop['LINE-HEIGHT'] = $fsp[2];
449
+ }
450
+ else { $newprop['FONT-SIZE'] = $fs; }
451
+ if (preg_match('/(italic|oblique)/i',$s)) { $newprop['FONT-STYLE'] = 'italic'; }
452
+ else { $newprop['FONT-STYLE'] = 'normal'; }
453
+ if (preg_match('/bold/i',$s)) { $newprop['FONT-WEIGHT'] = 'bold'; }
454
+ else { $newprop['FONT-WEIGHT'] = 'normal'; }
455
+ if (preg_match('/small-caps/i',$s)) { $newprop['TEXT-TRANSFORM'] = 'uppercase'; }
456
+ }
457
+ }
458
+ if ($k == 'FONT-FAMILY') {
459
+ $aux_fontlist = explode(",",$v);
460
+ $found = 0;
461
+ foreach($aux_fontlist AS $f) {
462
+ $fonttype = trim($f);
463
+ $fonttype = preg_replace('/["\']*(.*?)["\']*/','\\1',$fonttype);
464
+ $fonttype = preg_replace('/ /','',$fonttype);
465
+ $v = strtolower(trim($fonttype));
466
+ if (isset($this->mpdf->fonttrans[$v]) && $this->mpdf->fonttrans[$v]) { $v = $this->mpdf->fonttrans[$v]; }
467
+ if ((!$this->mpdf->onlyCoreFonts && in_array($v,$this->mpdf->available_unifonts)) ||
468
+ in_array($v,array('ccourier','ctimes','chelvetica')) ||
469
+ ($this->mpdf->onlyCoreFonts && in_array($v,array('courier','times','helvetica','arial'))) ||
470
+ in_array($v, array('sjis','uhc','big5','gb'))) {
471
+ $newprop[$k] = $v;
472
+ $found = 1;
473
+ break;
474
+ }
475
+ }
476
+ if (!$found) {
477
+ foreach($aux_fontlist AS $f) {
478
+ $fonttype = trim($f);
479
+ $fonttype = preg_replace('/["\']*(.*?)["\']*/','\\1',$fonttype);
480
+ $fonttype = preg_replace('/ /','',$fonttype);
481
+ $v = strtolower(trim($fonttype));
482
+ if (isset($this->mpdf->fonttrans[$v]) && $this->mpdf->fonttrans[$v]) { $v = $this->mpdf->fonttrans[$v]; }
483
+ if (in_array($v,$this->mpdf->sans_fonts) || in_array($v,$this->mpdf->serif_fonts) || in_array($v,$this->mpdf->mono_fonts) ) {
484
+ $newprop[$k] = $v;
485
+ break;
486
+ }
487
+ }
488
+ }
489
+ }
490
+ else if ($k == 'MARGIN') {
491
+ $tmp = $this->expand24($v);
492
+ $newprop['MARGIN-TOP'] = $tmp['T'];
493
+ $newprop['MARGIN-RIGHT'] = $tmp['R'];
494
+ $newprop['MARGIN-BOTTOM'] = $tmp['B'];
495
+ $newprop['MARGIN-LEFT'] = $tmp['L'];
496
+ }
497
+ /*-- BORDER-RADIUS --*/
498
+ else if ($k == 'BORDER-RADIUS' || $k == 'BORDER-TOP-LEFT-RADIUS' || $k == 'BORDER-TOP-RIGHT-RADIUS' || $k == 'BORDER-BOTTOM-LEFT-RADIUS' || $k == 'BORDER-BOTTOM-RIGHT-RADIUS') {
499
+ $tmp = $this->border_radius_expand($v,$k);
500
+ if (isset($tmp['TL-H'])) $newprop['BORDER-TOP-LEFT-RADIUS-H'] = $tmp['TL-H'];
501
+ if (isset($tmp['TL-V'])) $newprop['BORDER-TOP-LEFT-RADIUS-V'] = $tmp['TL-V'];
502
+ if (isset($tmp['TR-H'])) $newprop['BORDER-TOP-RIGHT-RADIUS-H'] = $tmp['TR-H'];
503
+ if (isset($tmp['TR-V'])) $newprop['BORDER-TOP-RIGHT-RADIUS-V'] = $tmp['TR-V'];
504
+ if (isset($tmp['BL-H'])) $newprop['BORDER-BOTTOM-LEFT-RADIUS-H'] = $tmp['BL-H'];
505
+ if (isset($tmp['BL-V'])) $newprop['BORDER-BOTTOM-LEFT-RADIUS-V'] = $tmp['BL-V'];
506
+ if (isset($tmp['BR-H'])) $newprop['BORDER-BOTTOM-RIGHT-RADIUS-H'] = $tmp['BR-H'];
507
+ if (isset($tmp['BR-V'])) $newprop['BORDER-BOTTOM-RIGHT-RADIUS-V'] = $tmp['BR-V'];
508
+ }
509
+ /*-- END BORDER-RADIUS --*/
510
+ else if ($k == 'PADDING') {
511
+ $tmp = $this->expand24($v);
512
+ $newprop['PADDING-TOP'] = $tmp['T'];
513
+ $newprop['PADDING-RIGHT'] = $tmp['R'];
514
+ $newprop['PADDING-BOTTOM'] = $tmp['B'];
515
+ $newprop['PADDING-LEFT'] = $tmp['L'];
516
+ }
517
+ else if ($k == 'BORDER') {
518
+ if ($v == '1') { $v = '1px solid #000000'; }
519
+ else { $v = $this->_fix_borderStr($v); }
520
+ $newprop['BORDER-TOP'] = $v;
521
+ $newprop['BORDER-RIGHT'] = $v;
522
+ $newprop['BORDER-BOTTOM'] = $v;
523
+ $newprop['BORDER-LEFT'] = $v;
524
+ }
525
+ else if ($k == 'BORDER-TOP') {
526
+ $newprop['BORDER-TOP'] = $this->_fix_borderStr($v);
527
+ }
528
+ else if ($k == 'BORDER-RIGHT') {
529
+ $newprop['BORDER-RIGHT'] = $this->_fix_borderStr($v);
530
+ }
531
+ else if ($k == 'BORDER-BOTTOM') {
532
+ $newprop['BORDER-BOTTOM'] = $this->_fix_borderStr($v);
533
+ }
534
+ else if ($k == 'BORDER-LEFT') {
535
+ $newprop['BORDER-LEFT'] = $this->_fix_borderStr($v);
536
+ }
537
+ else if ($k == 'BORDER-STYLE') {
538
+ $e = $this->expand24($v);
539
+ $newprop['BORDER-TOP-STYLE'] = $e['T'];
540
+ $newprop['BORDER-RIGHT-STYLE'] = $e['R'];
541
+ $newprop['BORDER-BOTTOM-STYLE'] = $e['B'];
542
+ $newprop['BORDER-LEFT-STYLE'] = $e['L'];
543
+ }
544
+ else if ($k == 'BORDER-WIDTH') {
545
+ $e = $this->expand24($v);
546
+ $newprop['BORDER-TOP-WIDTH'] = $e['T'];
547
+ $newprop['BORDER-RIGHT-WIDTH'] = $e['R'];
548
+ $newprop['BORDER-BOTTOM-WIDTH'] = $e['B'];
549
+ $newprop['BORDER-LEFT-WIDTH'] = $e['L'];
550
+ }
551
+ else if ($k == 'BORDER-COLOR') {
552
+ $e = $this->expand24($v);
553
+ $newprop['BORDER-TOP-COLOR'] = $e['T'];
554
+ $newprop['BORDER-RIGHT-COLOR'] = $e['R'];
555
+ $newprop['BORDER-BOTTOM-COLOR'] = $e['B'];
556
+ $newprop['BORDER-LEFT-COLOR'] = $e['L'];
557
+ }
558
+
559
+ else if ($k == 'BORDER-SPACING') {
560
+ $prop = preg_split('/\s+/',trim($v));
561
+ if (count($prop) == 1 ) {
562
+ $newprop['BORDER-SPACING-H'] = $prop[0];
563
+ $newprop['BORDER-SPACING-V'] = $prop[0];
564
+ }
565
+ else if (count($prop) == 2 ) {
566
+ $newprop['BORDER-SPACING-H'] = $prop[0];
567
+ $newprop['BORDER-SPACING-V'] = $prop[1];
568
+ }
569
+ }
570
+ else if ($k == 'TEXT-OUTLINE') { // mPDF 5.6.07
571
+ $prop = preg_split('/\s+/',trim($v));
572
+ if (trim(strtolower($v)) == 'none' ) {
573
+ $newprop['TEXT-OUTLINE'] = 'none';
574
+ }
575
+ else if (count($prop) == 2 ) {
576
+ $newprop['TEXT-OUTLINE-WIDTH'] = $prop[0];
577
+ $newprop['TEXT-OUTLINE-COLOR'] = $prop[1];
578
+ }
579
+ else if (count($prop) == 3 ) {
580
+ $newprop['TEXT-OUTLINE-WIDTH'] = $prop[0];
581
+ $newprop['TEXT-OUTLINE-COLOR'] = $prop[2];
582
+ }
583
+ }
584
+ else if ($k == 'SIZE') {
585
+ $prop = preg_split('/\s+/',trim($v));
586
+ if (preg_match('/(auto|portrait|landscape)/',$prop[0])) {
587
+ $newprop['SIZE'] = strtoupper($prop[0]);
588
+ }
589
+ else if (count($prop) == 1 ) {
590
+ $newprop['SIZE']['W'] = $this->mpdf->ConvertSize($prop[0]);
591
+ $newprop['SIZE']['H'] = $this->mpdf->ConvertSize($prop[0]);
592
+ }
593
+ else if (count($prop) == 2 ) {
594
+ $newprop['SIZE']['W'] = $this->mpdf->ConvertSize($prop[0]);
595
+ $newprop['SIZE']['H'] = $this->mpdf->ConvertSize($prop[1]);
596
+ }
597
+ }
598
+ else if ($k == 'SHEET-SIZE') {
599
+ $prop = preg_split('/\s+/',trim($v));
600
+ if (count($prop) == 2 ) {
601
+ $newprop['SHEET-SIZE'] = array($this->mpdf->ConvertSize($prop[0]), $this->mpdf->ConvertSize($prop[1]));
602
+ }
603
+ else {
604
+ if(preg_match('/([0-9a-zA-Z]*)-L/i',$v,$m)) { // e.g. A4-L = A$ landscape
605
+ $ft = $this->mpdf->_getPageFormat($m[1]);
606
+ $format = array($ft[1],$ft[0]);
607
+ }
608
+ else { $format = $this->mpdf->_getPageFormat($v); }
609
+ if ($format) { $newprop['SHEET-SIZE'] = array($format[0]/_MPDFK, $format[1]/_MPDFK); }
610
+ }
611
+ }
612
+ else if ($k == 'BACKGROUND') {
613
+ $bg = $this->parseCSSbackground($v);
614
+ if ($bg['c']) { $newprop['BACKGROUND-COLOR'] = $bg['c']; }
615
+ else { $newprop['BACKGROUND-COLOR'] = 'transparent'; }
616
+ /*-- BACKGROUNDS --*/
617
+ if ($bg['i']) {
618
+ $newprop['BACKGROUND-IMAGE'] = $bg['i'];
619
+ if ($bg['r']) { $newprop['BACKGROUND-REPEAT'] = $bg['r']; }
620
+ if ($bg['p']) { $newprop['BACKGROUND-POSITION'] = $bg['p']; }
621
+ }
622
+ else { $newprop['BACKGROUND-IMAGE'] = ''; }
623
+ /*-- END BACKGROUNDS --*/
624
+ }
625
+ /*-- BACKGROUNDS --*/
626
+ else if ($k == 'BACKGROUND-IMAGE') {
627
+ if (preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient\(.*\)/i',$v,$m)) {
628
+ $newprop['BACKGROUND-IMAGE'] = $m[0];
629
+ continue;
630
+ }
631
+ if (preg_match('/url\([\'\"]{0,1}(.*?)[\'\"]{0,1}\)/i',$v,$m)) {
632
+ $newprop['BACKGROUND-IMAGE'] = $m[1];
633
+ }
634
+
635
+ else if (strtolower($v)=='none') { $newprop['BACKGROUND-IMAGE'] = ''; }
636
+
637
+ }
638
+ else if ($k == 'BACKGROUND-REPEAT') {
639
+ if (preg_match('/(repeat-x|repeat-y|no-repeat|repeat)/i',$v,$m)) {
640
+ $newprop['BACKGROUND-REPEAT'] = strtolower($m[1]);
641
+ }
642
+ }
643
+ else if ($k == 'BACKGROUND-POSITION') {
644
+ $s = $v;
645
+ $bits = preg_split('/\s+/',trim($s));
646
+ // These should be Position x1 or x2
647
+ if (count($bits)==1) {
648
+ if (preg_match('/bottom/',$bits[0])) { $bg['p'] = '50% 100%'; }
649
+ else if (preg_match('/top/',$bits[0])) { $bg['p'] = '50% 0%'; }
650
+ else { $bg['p'] = $bits[0] . ' 50%'; }
651
+ }
652
+ else if (count($bits)==2) {
653
+ // Can be either right center or center right
654
+ if (preg_match('/(top|bottom)/',$bits[0]) || preg_match('/(left|right)/',$bits[1])) {
655
+ $bg['p'] = $bits[1] . ' '.$bits[0];
656
+ }
657
+ else {
658
+ $bg['p'] = $bits[0] . ' '.$bits[1];
659
+ }
660
+ }
661
+ if ($bg['p']) {
662
+ $bg['p'] = preg_replace('/(left|top)/','0%',$bg['p']);
663
+ $bg['p'] = preg_replace('/(right|bottom)/','100%',$bg['p']);
664
+ $bg['p'] = preg_replace('/(center)/','50%',$bg['p']);
665
+ if (!preg_match('/[\-]{0,1}\d+(in|cm|mm|pt|pc|em|ex|px|%)* [\-]{0,1}\d+(in|cm|mm|pt|pc|em|ex|px|%)*/',$bg['p'])) {
666
+ $bg['p'] = false;
667
+ }
668
+ }
669
+ if ($bg['p']) { $newprop['BACKGROUND-POSITION'] = $bg['p']; }
670
+ }
671
+ /*-- END BACKGROUNDS --*/
672
+ else if ($k == 'IMAGE-ORIENTATION') {
673
+ if (preg_match('/([\-]*[0-9\.]+)(deg|grad|rad)/i',$v,$m)) {
674
+ $angle = $m[1] + 0;
675
+ if (strtolower($m[2])=='deg') { $angle = $angle; }
676
+ else if (strtolower($m[2])=='grad') { $angle *= (360/400); }
677
+ else if (strtolower($m[2])=='rad') { $angle = rad2deg($angle); }
678
+ while($angle < 0) { $angle += 360; }
679
+ $angle = ($angle % 360);
680
+ $angle /= 90;
681
+ $angle = round($angle) * 90;
682
+ $newprop['IMAGE-ORIENTATION'] = $angle;
683
+ }
684
+ }
685
+ // mPDF 5.6.13
686
+ else if ($k == 'TEXT-ALIGN') {
687
+ if (preg_match('/["\'](.){1}["\']/i',$v,$m)) {
688
+ $d = array_search($m[1],$this->mpdf->decimal_align);
689
+ if ($d !== false) { $newprop['TEXT-ALIGN'] = $d; }
690
+ if (preg_match('/(center|left|right)/i',$v,$m)) { $newprop['TEXT-ALIGN'] .= strtoupper(substr($m[1],0,1)); }
691
+ else { $newprop['TEXT-ALIGN'] .= 'R'; } // default = R
692
+ }
693
+ else if (preg_match('/["\'](\\\[a-fA-F0-9]{1,6})["\']/i',$v,$m)) {
694
+ $utf8 = codeHex2utf(substr($m[1],1,6));
695
+ $d = array_search($utf8,$this->mpdf->decimal_align);
696
+ if ($d !== false) { $newprop['TEXT-ALIGN'] = $d; }
697
+ if (preg_match('/(center|left|right)/i',$v,$m)) { $newprop['TEXT-ALIGN'] .= strtoupper(substr($m[1],0,1)); }
698
+ else { $newprop['TEXT-ALIGN'] .= 'R'; } // default = R
699
+ }
700
+ else { $newprop[$k] = $v; }
701
+ }
702
+
703
+ else {
704
+ $newprop[$k] = $v;
705
+ }
706
+ }
707
+
708
+ return $newprop;
709
+ }
710
+
711
+ function setCSSboxshadow($v) {
712
+ $sh = array();
713
+ $c = preg_match_all('/(rgba|rgb|device-cmyka|cmyka|device-cmyk|cmyk|hsla|hsl)\(.*?\)/',$v,$x); // mPDF 5.6.05
714
+ for($i=0; $i<$c; $i++) {
715
+ $col = preg_replace('/,/','*',$x[0][$i]);
716
+ $v = preg_replace('/'.preg_quote($x[0][$i],'/').'/',$col,$v);
717
+ }
718
+ $ss = explode(',',$v);
719
+ foreach ($ss AS $s) {
720
+ $new = array('inset'=>false, 'blur'=>0, 'spread'=>0);
721
+ if (preg_match('/inset/i',$s)) { $new['inset'] = true; $s = preg_replace('/\s*inset\s*/','',$s); }
722
+ $p = explode(' ',trim($s));
723
+ if (isset($p[0])) { $new['x'] = $this->mpdf->ConvertSize(trim($p[0]),$this->mpdf->blk[$this->mpdf->blklvl-1]['inner_width'],$this->mpdf->FontSize,false); }
724
+ if (isset($p[1])) { $new['y'] = $this->mpdf->ConvertSize(trim($p[1]),$this->mpdf->blk[$this->mpdf->blklvl-1]['inner_width'],$this->mpdf->FontSize,false); }
725
+ if (isset($p[2])) {
726
+ if (preg_match('/^\s*[\.\-0-9]/',$p[2])) {
727
+ $new['blur'] = $this->mpdf->ConvertSize(trim($p[2]),$this->mpdf->blk[$this->mpdf->blklvl-1]['inner_width'],$this->mpdf->FontSize,false);
728
+ }
729
+ else { $new['col'] = $this->mpdf->ConvertColor(preg_replace('/\*/',',',$p[2])); }
730
+ if (isset($p[3])) {
731
+ if (preg_match('/^\s*[\.\-0-9]/',$p[3])) {
732
+ $new['spread'] = $this->mpdf->ConvertSize(trim($p[3]),$this->mpdf->blk[$this->mpdf->blklvl-1]['inner_width'],$this->mpdf->FontSize,false);
733
+ }
734
+ else { $new['col'] = $this->mpdf->ConvertColor(preg_replace('/\*/',',',$p[3])); }
735
+ if (isset($p[4])) {
736
+ $new['col'] = $this->mpdf->ConvertColor(preg_replace('/\*/',',',$p[4]));
737
+ }
738
+ }
739
+ }
740
+ if (!$new['col']) { $new['col'] = $this->mpdf->ConvertColor('#888888'); }
741
+ if (isset($new['y'])) { array_unshift($sh, $new); }
742
+ }
743
+ return $sh;
744
+ }
745
+
746
+ function setCSStextshadow($v) {
747
+ $sh = array();
748
+ $c = preg_match_all('/(rgba|rgb|device-cmyka|cmyka|device-cmyk|cmyk|hsla|hsl)\(.*?\)/',$v,$x); // mPDF 5.6.05
749
+ for($i=0; $i<$c; $i++) {
750
+ $col = preg_replace('/,/','*',$x[0][$i]);
751
+ $v = preg_replace('/'.preg_quote($x[0][$i],'/').'/',$col,$v);
752
+ }
753
+ $ss = explode(',',$v);
754
+ foreach ($ss AS $s) {
755
+ $new = array('blur'=>0);
756
+ $p = explode(' ',trim($s));
757
+ if (isset($p[0])) { $new['x'] = $this->mpdf->ConvertSize(trim($p[0]),$this->mpdf->blk[$this->mpdf->blklvl-1]['inner_width'],$this->mpdf->FontSize,false); }
758
+ if (isset($p[1])) { $new['y'] = $this->mpdf->ConvertSize(trim($p[1]),$this->mpdf->blk[$this->mpdf->blklvl-1]['inner_width'],$this->mpdf->FontSize,false); }
759
+ if (isset($p[2])) {
760
+ if (preg_match('/^\s*[\.\-0-9]/',$p[2])) {
761
+ $new['blur'] = $this->mpdf->ConvertSize(trim($p[2]),$this->mpdf->blk[$this->mpdf->blklvl-1]['inner_width'],$this->mpdf->FontSize,false);
762
+ }
763
+ else { $new['col'] = $this->mpdf->ConvertColor(preg_replace('/\*/',',',$p[2])); }
764
+ if (isset($p[3])) {
765
+ $new['col'] = $this->mpdf->ConvertColor(preg_replace('/\*/',',',$p[3]));
766
+ }
767
+ }
768
+ if (!$new['col']) { $new['col'] = $this->mpdf->ConvertColor('#888888'); }
769
+ if (isset($new['y'])) { array_unshift($sh, $new); }
770
+ }
771
+ return $sh;
772
+ }
773
+
774
+ function parseCSSbackground($s) {
775
+ $bg = array('c'=>false, 'i'=>false, 'r'=>false, 'p'=>false, );
776
+ /*-- BACKGROUNDS --*/
777
+ if (preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient\(.*\)/i',$s,$m)) {
778
+ $bg['i'] = $m[0];
779
+ }
780
+ else
781
+ /*-- END BACKGROUNDS --*/
782
+ if (preg_match('/url\(/i',$s)) {
783
+ // If color, set and strip it off
784
+ // mPDF 5.6.05
785
+ if (preg_match('/^\s*(#[0-9a-fA-F]{3,6}|(rgba|rgb|device-cmyka|cmyka|device-cmyk|cmyk|hsla|hsl|spot)\(.*?\)|[a-zA-Z]{3,})\s+(url\(.*)/i',$s,$m)) {
786
+ $bg['c'] = strtolower($m[1]);
787
+ $s = $m[3];
788
+ }
789
+ /*-- BACKGROUNDS --*/
790
+ if (preg_match('/url\([\'\"]{0,1}(.*?)[\'\"]{0,1}\)\s*(.*)/i',$s,$m)) {
791
+ $bg['i'] = $m[1];
792
+ $s = strtolower($m[2]);
793
+ if (preg_match('/(repeat-x|repeat-y|no-repeat|repeat)/',$s,$m)) {
794
+ $bg['r'] = $m[1];
795
+ }
796
+ // Remove repeat, attachment (discarded) and also any inherit
797
+ $s = preg_replace('/(repeat-x|repeat-y|no-repeat|repeat|scroll|fixed|inherit)/','',$s);
798
+ $bits = preg_split('/\s+/',trim($s));
799
+ // These should be Position x1 or x2
800
+ if (count($bits)==1) {
801
+ if (preg_match('/bottom/',$bits[0])) { $bg['p'] = '50% 100%'; }
802
+ else if (preg_match('/top/',$bits[0])) { $bg['p'] = '50% 0%'; }
803
+ else { $bg['p'] = $bits[0] . ' 50%'; }
804
+ }
805
+ else if (count($bits)==2) {
806
+ // Can be either right center or center right
807
+ if (preg_match('/(top|bottom)/',$bits[0]) || preg_match('/(left|right)/',$bits[1])) {
808
+ $bg['p'] = $bits[1] . ' '.$bits[0];
809
+ }
810
+ else {
811
+ $bg['p'] = $bits[0] . ' '.$bits[1];
812
+ }
813
+ }
814
+ if ($bg['p']) {
815
+ $bg['p'] = preg_replace('/(left|top)/','0%',$bg['p']);
816
+ $bg['p'] = preg_replace('/(right|bottom)/','100%',$bg['p']);
817
+ $bg['p'] = preg_replace('/(center)/','50%',$bg['p']);
818
+ if (!preg_match('/[\-]{0,1}\d+(in|cm|mm|pt|pc|em|ex|px|%)* [\-]{0,1}\d+(in|cm|mm|pt|pc|em|ex|px|%)*/',$bg['p'])) {
819
+ $bg['p'] = false;
820
+ }
821
+ }
822
+ }
823
+ /*-- END BACKGROUNDS --*/
824
+ }
825
+ else if (preg_match('/^\s*(#[0-9a-fA-F]{3,6}|(rgba|rgb|device-cmyka|cmyka|device-cmyk|cmyk|hsla|hsl|spot)\(.*?\)|[a-zA-Z]{3,})/i',$s,$m)) { $bg['c'] = strtolower($m[1]); } // mPDF 5.6.05
826
+ return ($bg);
827
+ }
828
+
829
+
830
+ function expand24($mp) {
831
+ $prop = preg_split('/\s+/',trim($mp));
832
+ if (count($prop) == 1 ) {
833
+ return array('T' => $prop[0], 'R' => $prop[0], 'B' => $prop[0], 'L'=> $prop[0]);
834
+ }
835
+ if (count($prop) == 2 ) {
836
+ return array('T' => $prop[0], 'R' => $prop[1], 'B' => $prop[0], 'L'=> $prop[1]);
837
+ }
838
+
839
+ if (count($prop) == 3 ) {
840
+ return array('T' => $prop[0], 'R' => $prop[1], 'B' => $prop[2], 'L'=> $prop[1]);
841
+ }
842
+ if (count($prop) == 4 ) {
843
+ return array('T' => $prop[0], 'R' => $prop[1], 'B' => $prop[2], 'L'=> $prop[3]);
844
+ }
845
+ return array();
846
+ }
847
+
848
+ /*-- BORDER-RADIUS --*/
849
+ function border_radius_expand($val,$k) {
850
+ $b = array();
851
+ if ($k == 'BORDER-RADIUS') {
852
+ $hv = explode('/',trim($val));
853
+ $prop = preg_split('/\s+/',trim($hv[0]));
854
+ if (count($prop)==1) {
855
+ $b['TL-H'] = $b['TR-H'] = $b['BR-H'] = $b['BL-H'] = $prop[0];
856
+ }
857
+ else if (count($prop)==2) {
858
+ $b['TL-H'] = $b['BR-H'] = $prop[0];
859
+ $b['TR-H'] = $b['BL-H'] = $prop[1];
860
+ }
861
+ else if (count($prop)==3) {
862
+ $b['TL-H'] = $prop[0];
863
+ $b['TR-H'] = $b['BL-H'] = $prop[1];
864
+ $b['BR-H'] = $prop[2];
865
+ }
866
+ else if (count($prop)==4) {
867
+ $b['TL-H'] = $prop[0];
868
+ $b['TR-H'] = $prop[1];
869
+ $b['BR-H'] = $prop[2];
870
+ $b['BL-H'] = $prop[3];
871
+ }
872
+ if (count($hv)==2) {
873
+ $prop = preg_split('/\s+/',trim($hv[1]));
874
+ if (count($prop)==1) {
875
+ $b['TL-V'] = $b['TR-V'] = $b['BR-V'] = $b['BL-V'] = $prop[0];
876
+ }
877
+ else if (count($prop)==2) {
878
+ $b['TL-V'] = $b['BR-V'] = $prop[0];
879
+ $b['TR-V'] = $b['BL-V'] = $prop[1];
880
+ }
881
+ else if (count($prop)==3) {
882
+ $b['TL-V'] = $prop[0];
883
+ $b['TR-V'] = $b['BL-V'] = $prop[1];
884
+ $b['BR-V'] = $prop[2];
885
+ }
886
+ else if (count($prop)==4) {
887
+ $b['TL-V'] = $prop[0];
888
+ $b['TR-V'] = $prop[1];
889
+ $b['BR-V'] = $prop[2];
890
+ $b['BL-V'] = $prop[3];
891
+ }
892
+ }
893
+ else {
894
+ $b['TL-V'] = $b['TL-H'];
895
+ $b['TR-V'] = $b['TR-H'];
896
+ $b['BL-V'] = $b['BL-H'];
897
+ $b['BR-V'] = $b['BR-H'];
898
+ }
899
+ return $b;
900
+ }
901
+
902
+ // Parse 2
903
+ $h = 0;
904
+ $v = 0;
905
+ $prop = preg_split('/\s+/',trim($val));
906
+ if (count($prop)==1) { $h = $v = $val; }
907
+ else { $h = $prop[0]; $v = $prop[1]; }
908
+ if ($h==0 || $v==0) { $h = $v = 0; }
909
+ if ($k == 'BORDER-TOP-LEFT-RADIUS') {
910
+ $b['TL-H'] = $h;
911
+ $b['TL-V'] = $v;
912
+ }
913
+ else if ($k == 'BORDER-TOP-RIGHT-RADIUS') {
914
+ $b['TR-H'] = $h;
915
+ $b['TR-V'] = $v;
916
+ }
917
+ else if ($k == 'BORDER-BOTTOM-LEFT-RADIUS') {
918
+ $b['BL-H'] = $h;
919
+ $b['BL-V'] = $v;
920
+ }
921
+ else if ($k == 'BORDER-BOTTOM-RIGHT-RADIUS') {
922
+ $b['BR-H'] = $h;
923
+ $b['BR-V'] = $v;
924
+ }
925
+ return $b;
926
+
927
+ }
928
+ /*-- END BORDER-RADIUS --*/
929
+
930
+ function _mergeCSS($p, &$t) {
931
+ // Save Cascading CSS e.g. "div.topic p" at this block level
932
+ if (isset($p) && $p) {
933
+ if ($t) {
934
+ $t = $this->array_merge_recursive_unique($t, $p);
935
+ }
936
+ else { $t = $p; }
937
+ }
938
+ }
939
+
940
+ // for CSS handling
941
+ function array_merge_recursive_unique($array1, $array2) {
942
+ $arrays = func_get_args();
943
+ $narrays = count($arrays);
944
+ $ret = $arrays[0];
945
+ for ($i = 1; $i < $narrays; $i ++) {
946
+ foreach ($arrays[$i] as $key => $value) {
947
+ if (((string) $key) === ((string) intval($key))) { // integer or string as integer key - append
948
+ $ret[] = $value;
949
+ }
950
+ else { // string key - merge
951
+ if (is_array($value) && isset($ret[$key])) {
952
+ $ret[$key] = $this->array_merge_recursive_unique($ret[$key], $value);
953
+ }
954
+ else {
955
+ $ret[$key] = $value;
956
+ }
957
+ }
958
+ }
959
+ }
960
+ return $ret;
961
+ }
962
+
963
+
964
+
965
+ function _mergeFullCSS($p, &$t, $tag, $classes, $id) {
966
+ $this->_mergeCSS($p[$tag], $t);
967
+ // STYLESHEET CLASS e.g. .smallone{} .redletter{}
968
+ foreach($classes AS $class) {
969
+ $this->_mergeCSS($p['CLASS>>'.$class], $t);
970
+ }
971
+ // STYLESHEET nth-child SELECTOR e.g. tr:nth-child(odd) td:nth-child(2n+1)
972
+ if ($tag=='TR' && isset($p) && $p) {
973
+ foreach($p AS $k=>$val) {
974
+ if (preg_match('/'.$tag.'>>SELECTORNTHCHILD>>(.*)/',$k, $m)) {
975
+ $select = false;
976
+ if ($tag=='TR') {
977
+ $row = $this->mpdf->row;
978
+ $thnr = (isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_thead']) ? count($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_thead']) : 0);
979
+ $tfnr = (isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_tfoot']) ? count($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_tfoot']) : 0);
980
+ if ($this->mpdf->tabletfoot) { $row -= $thnr; }
981
+ else if (!$this->mpdf->tablethead) { $row -= ($thnr + $tfnr); }
982
+ if ($m[1]=='ODD' && ($row % 2) == 0) { $select = true; }
983
+ else if ($m[1]=='EVEN' && ($row % 2) == 1) { $select = true; }
984
+ else if (preg_match('/(\d+)N\+(\d+)/',$m[1],$a)) {
985
+ if ((($row + 1) % $a[1]) == $a[2]) { $select = true; }
986
+ }
987
+ }
988
+ else if ($tag=='TD' || $tag=='TH') {
989
+ if ($m[1]=='ODD' && ($this->mpdf->col % 2) == 0) { $select = true; }
990
+ else if ($m[1]=='EVEN' && ($this->mpdf->col % 2) == 1) { $select = true; }
991
+ else if (preg_match('/(\d+)N\+(\d+)/',$m[1],$a)) {
992
+ if ((($this->mpdf->col + 1) % $a[1]) == $a[2]) { $select = true; }
993
+ }
994
+ }
995
+ if ($select) {
996
+ $this->_mergeCSS($p[$tag.'>>SELECTORNTHCHILD>>'.$m[1]], $t);
997
+ }
998
+ }
999
+ }
1000
+ }
1001
+ // STYLESHEET CLASS e.g. #smallone{} #redletter{}
1002
+ if (isset($id) && $id) {
1003
+ $this->_mergeCSS($p['ID>>'.$id], $t);
1004
+ }
1005
+ // STYLESHEET CLASS e.g. .smallone{} .redletter{}
1006
+ foreach($classes AS $class) {
1007
+ $this->_mergeCSS($p[$tag.'>>CLASS>>'.$class], $t);
1008
+ }
1009
+ // STYLESHEET CLASS e.g. #smallone{} #redletter{}
1010
+ if (isset($id)) {
1011
+ $this->_mergeCSS($p[$tag.'>>ID>>'.$id], $t);
1012
+ }
1013
+ }
1014
+
1015
+ function setBorderDominance($prop, $val) {
1016
+ if (isset($prop['BORDER-LEFT']) && $prop['BORDER-LEFT']) { $this->cell_border_dominance_L = $val; }
1017
+ if (isset($prop['BORDER-RIGHT']) && $prop['BORDER-RIGHT']) { $this->cell_border_dominance_R = $val; }
1018
+ if (isset($prop['BORDER-TOP']) && $prop['BORDER-TOP']) { $this->cell_border_dominance_T = $val; }
1019
+ if (isset($prop['BORDER-BOTTOM']) && $prop['BORDER-BOTTOM']) { $this->cell_border_dominance_B = $val; }
1020
+ }
1021
+
1022
+ function _set_mergedCSS(&$m, &$p, $d=true, $bd=false) {
1023
+ if (isset($m)) {
1024
+ if ((isset($m['depth']) && $m['depth']>1) || $d==false) { // include check for 'depth'
1025
+ if ($bd) { $this->setBorderDominance($m, $bd); } // *TABLES*
1026
+ if (is_array($m)) {
1027
+ $p = array_merge($p,$m);
1028
+ $this->_mergeBorders($p,$m);
1029
+ }
1030
+ }
1031
+ }
1032
+ }
1033
+
1034
+
1035
+ function _mergeBorders(&$b, &$a) { // Merges $a['BORDER-TOP-STYLE'] to $b['BORDER-TOP'] etc.
1036
+ foreach(array('TOP','RIGHT','BOTTOM','LEFT') AS $side) {
1037
+ foreach(array('STYLE','WIDTH','COLOR') AS $el) {
1038
+ if (isset($a['BORDER-'.$side.'-'.$el])) { // e.g. $b['BORDER-TOP-STYLE']
1039
+ $s = trim($a['BORDER-'.$side.'-'.$el]);
1040
+ if (isset($b['BORDER-'.$side])) { // e.g. $b['BORDER-TOP']
1041
+ $p = trim($b['BORDER-'.$side]);
1042
+ }
1043
+ else { $p = ''; }
1044
+ if ($el=='STYLE') {
1045
+ if ($p) { $b['BORDER-'.$side] = preg_replace('/(\S+)\s+(\S+)\s+(\S+)/', '\\1 '.$s.' \\3', $p); }
1046
+ else { $b['BORDER-'.$side] = '0px '.$s.' #000000'; }
1047
+ }
1048
+ else if ($el=='WIDTH') {
1049
+ if ($p) { $b['BORDER-'.$side] = preg_replace('/(\S+)\s+(\S+)\s+(\S+)/', $s.' \\2 \\3', $p); }
1050
+ else { $b['BORDER-'.$side] = $s.' none #000000'; }
1051
+ }
1052
+ else if ($el=='COLOR') {
1053
+ if ($p) { $b['BORDER-'.$side] = preg_replace('/(\S+)\s+(\S+)\s+(\S+)/', '\\1 \\2 '.$s, $p); }
1054
+ else { $b['BORDER-'.$side] = '0px none '.$s; }
1055
+ }
1056
+ }
1057
+ }
1058
+ }
1059
+ }
1060
+
1061
+
1062
+ function MergeCSS($inherit,$tag,$attr) {
1063
+ $p = array();
1064
+ $zp = array();
1065
+
1066
+ $classes = array();
1067
+ if (isset($attr['CLASS'])) {
1068
+ $classes = preg_split('/\s+/',$attr['CLASS']);
1069
+ }
1070
+ if (!isset($attr['ID'])) { $attr['ID']=''; }
1071
+ //===============================================
1072
+ /*-- TABLES --*/
1073
+ // Set Inherited properties
1074
+ if ($inherit == 'TOPTABLE') { // $tag = TABLE
1075
+ //===============================================
1076
+ // Save Cascading CSS e.g. "div.topic p" at this block level
1077
+
1078
+ if (isset($this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'])) {
1079
+ $this->tablecascadeCSS[0] = $this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'];
1080
+ }
1081
+ else {
1082
+ $this->tablecascadeCSS[0] = $this->cascadeCSS;
1083
+ }
1084
+ }
1085
+ //===============================================
1086
+ // Set Inherited properties
1087
+ if ($inherit == 'TOPTABLE' || $inherit == 'TABLE') {
1088
+ //Cascade everything from last level that is not an actual property, or defined by current tag/attributes
1089
+ if (isset($this->tablecascadeCSS[$this->tbCSSlvl-1]) && is_array($this->tablecascadeCSS[$this->tbCSSlvl-1])) {
1090
+ foreach($this->tablecascadeCSS[$this->tbCSSlvl-1] AS $k=>$v) {
1091
+ $this->tablecascadeCSS[$this->tbCSSlvl][$k] = $v;
1092
+ }
1093
+ }
1094
+ $this->_mergeFullCSS($this->cascadeCSS, $this->tablecascadeCSS[$this->tbCSSlvl], $tag, $classes, $attr['ID']);
1095
+ //===============================================
1096
+ // Cascading forward CSS e.g. "table.topic td" for this table in $this->tablecascadeCSS
1097
+ //===============================================
1098
+ // STYLESHEET TAG e.g. table
1099
+ $this->_mergeFullCSS($this->tablecascadeCSS[$this->tbCSSlvl-1], $this->tablecascadeCSS[$this->tbCSSlvl], $tag, $classes, $attr['ID']);
1100
+ //===============================================
1101
+ }
1102
+ /*-- END TABLES --*/
1103
+ //===============================================
1104
+ /*-- LISTS --*/
1105
+ // Set Inherited properties
1106
+ if ($inherit == 'TOPLIST') { // $tag = UL,OL
1107
+ //===============================================
1108
+ // Save Cascading CSS e.g. "div.topic p" at this block level
1109
+ if (isset($this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'])) {
1110
+ $this->listcascadeCSS[0] = $this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'];
1111
+ }
1112
+ else {
1113
+ $this->listcascadeCSS[0] = $this->cascadeCSS;
1114
+ }
1115
+ }
1116
+ //===============================================
1117
+ // Set Inherited properties
1118
+ if ($inherit == 'TOPLIST' || $inherit == 'LIST') {
1119
+ //Cascade everything from last level that is not an actual property, or defined by current tag/attributes
1120
+ if (isset($this->listcascadeCSS[$this->listCSSlvl-1]) && is_array($this->listcascadeCSS[$this->listCSSlvl-1])) {
1121
+ foreach($this->listcascadeCSS[$this->listCSSlvl-1] AS $k=>$v) {
1122
+ $this->listcascadeCSS[$this->listCSSlvl][$k] = $v;
1123
+ }
1124
+ }
1125
+ $this->_mergeFullCSS($this->cascadeCSS, $this->listcascadeCSS[$this->listCSSlvl], $tag, $classes, $attr['ID']);
1126
+ //===============================================
1127
+ // Cascading forward CSS e.g. "table.topic td" for this list in $this->listcascadeCSS
1128
+ //===============================================
1129
+ // STYLESHEET TAG e.g. table
1130
+ $this->_mergeFullCSS($this->listcascadeCSS[$this->listCSSlvl-1], $this->listcascadeCSS[$this->listCSSlvl], $tag, $classes, $attr['ID']);
1131
+ //===============================================
1132
+ }
1133
+ /*-- END LISTS --*/
1134
+ //===============================================
1135
+ // Set Inherited properties
1136
+ if ($inherit == 'BLOCK') {
1137
+ if (isset($this->mpdf->blk[$this->mpdf->blklvl-1]['cascadeCSS']) && is_array($this->mpdf->blk[$this->mpdf->blklvl-1]['cascadeCSS'])) {
1138
+ foreach($this->mpdf->blk[$this->mpdf->blklvl-1]['cascadeCSS'] AS $k=>$v) {
1139
+ $this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'][$k] = $v;
1140
+
1141
+ }
1142
+ }
1143
+
1144
+ //===============================================
1145
+ // Save Cascading CSS e.g. "div.topic p" at this block level
1146
+ $this->_mergeFullCSS($this->cascadeCSS, $this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'], $tag, $classes, $attr['ID']);
1147
+ //===============================================
1148
+ // Cascading forward CSS
1149
+ //===============================================
1150
+ $this->_mergeFullCSS($this->mpdf->blk[$this->mpdf->blklvl-1]['cascadeCSS'], $this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'], $tag, $classes, $attr['ID']);
1151
+ //===============================================
1152
+ // Block properties
1153
+ if (isset($this->mpdf->blk[$this->mpdf->blklvl-1]['margin_collapse']) && $this->mpdf->blk[$this->mpdf->blklvl-1]['margin_collapse']) { $p['MARGIN-COLLAPSE'] = 'COLLAPSE'; } // custom tag, but follows CSS principle that border-collapse is inherited
1154
+ if (isset($this->mpdf->blk[$this->mpdf->blklvl-1]['line_height']) && $this->mpdf->blk[$this->mpdf->blklvl-1]['line_height']) { $p['LINE-HEIGHT'] = $this->mpdf->blk[$this->mpdf->blklvl-1]['line_height']; }
1155
+
1156
+ if (isset($this->mpdf->blk[$this->mpdf->blklvl-1]['direction']) && $this->mpdf->blk[$this->mpdf->blklvl-1]['direction']) { $p['DIRECTION'] = $this->mpdf->blk[$this->mpdf->blklvl-1]['direction']; }
1157
+
1158
+ if (isset($this->mpdf->blk[$this->mpdf->blklvl-1]['align']) && $this->mpdf->blk[$this->mpdf->blklvl-1]['align']) {
1159
+ if ($this->mpdf->blk[$this->mpdf->blklvl-1]['align'] == 'L') { $p['TEXT-ALIGN'] = 'left'; }
1160
+ else if ($this->mpdf->blk[$this->mpdf->blklvl-1]['align'] == 'J') { $p['TEXT-ALIGN'] = 'justify'; }
1161
+ else if ($this->mpdf->blk[$this->mpdf->blklvl-1]['align'] == 'R') { $p['TEXT-ALIGN'] = 'right'; }
1162
+ else if ($this->mpdf->blk[$this->mpdf->blklvl-1]['align'] == 'C') { $p['TEXT-ALIGN'] = 'center'; }
1163
+ }
1164
+ if ($this->mpdf->ColActive || $this->mpdf->keep_block_together) {
1165
+ if (isset($this->mpdf->blk[$this->mpdf->blklvl-1]['bgcolor']) && $this->mpdf->blk[$this->mpdf->blklvl-1]['bgcolor']) { // Doesn't officially inherit, but default value is transparent (?=inherited)
1166
+ $cor = $this->mpdf->blk[$this->mpdf->blklvl-1]['bgcolorarray' ];
1167
+ $p['BACKGROUND-COLOR'] = $this->mpdf->_colAtoString($cor);
1168
+ }
1169
+ }
1170
+
1171
+ if (isset($this->mpdf->blk[$this->mpdf->blklvl-1]['text_indent']) && ($this->mpdf->blk[$this->mpdf->blklvl-1]['text_indent'] || $this->mpdf->blk[$this->mpdf->blklvl-1]['text_indent']===0)) { $p['TEXT-INDENT'] = $this->mpdf->blk[$this->mpdf->blklvl-1]['text_indent']; }
1172
+ if (isset($this->mpdf->blk[$this->mpdf->blklvl-1]['InlineProperties'])) {
1173
+ $biilp = $this->mpdf->blk[$this->mpdf->blklvl-1]['InlineProperties'];
1174
+ }
1175
+ else { $biilp = null; }
1176
+ if (isset($biilp[ 'family' ]) && $biilp[ 'family' ]) { $p['FONT-FAMILY'] = $biilp[ 'family' ]; }
1177
+ if (isset($biilp[ 'I' ]) && $biilp[ 'I' ]) { $p['FONT-STYLE'] = 'italic'; }
1178
+ if (isset($biilp[ 'sizePt' ]) && $biilp[ 'sizePt' ]) { $p['FONT-SIZE'] = $biilp[ 'sizePt' ] . 'pt'; }
1179
+ if (isset($biilp[ 'B' ]) && $biilp[ 'B' ]) { $p['FONT-WEIGHT'] = 'bold'; }
1180
+ if (isset($biilp[ 'colorarray' ]) && $biilp[ 'colorarray' ]) {
1181
+ $cor = $biilp[ 'colorarray' ];
1182
+ $p['COLOR'] = $this->mpdf->_colAtoString($cor);
1183
+ }
1184
+ if (isset($biilp[ 'fontkerning' ])) {
1185
+ if ($biilp[ 'fontkerning' ]) { $p['FONT-KERNING'] = 'normal'; }
1186
+ else { $p['FONT-KERNING'] = 'none'; }
1187
+ }
1188
+ if (isset($biilp[ 'lSpacingCSS' ]) && $biilp[ 'lSpacingCSS' ]) { $p['LETTER-SPACING'] = $biilp[ 'lSpacingCSS' ]; }
1189
+ if (isset($biilp[ 'wSpacingCSS' ]) && $biilp[ 'wSpacingCSS' ]) { $p['WORD-SPACING'] = $biilp[ 'wSpacingCSS' ]; }
1190
+ if (isset($biilp[ 'toupper' ]) && $biilp[ 'toupper' ]) { $p['TEXT-TRANSFORM'] = 'uppercase'; }
1191
+ else if (isset($biilp[ 'tolower' ]) && $biilp[ 'tolower' ]) { $p['TEXT-TRANSFORM'] = 'lowercase'; }
1192
+ else if (isset($biilp[ 'capitalize' ]) && $biilp[ 'capitalize' ]) { $p['TEXT-TRANSFORM'] = 'capitalize'; }
1193
+ // CSS says text-decoration is not inherited, but IE7 does??
1194
+ if (isset($biilp[ 'underline' ]) && $biilp[ 'underline' ]) { $p['TEXT-DECORATION'] = 'underline'; }
1195
+ if (isset($biilp[ 'smCaps' ]) && $biilp[ 'smCaps' ]) { $p['FONT-VARIANT'] = 'small-caps'; }
1196
+
1197
+ }
1198
+ //===============================================
1199
+ //===============================================
1200
+ /*-- LISTS --*/
1201
+ // Set Inherited properties
1202
+ if ($inherit == 'TOPLIST') {
1203
+ if ($this->listCSSlvl == 1) {
1204
+ $bilp = $this->mpdf->blk[$this->mpdf->blklvl]['InlineProperties'];
1205
+ if (isset($bilp[ 'family' ]) && $bilp[ 'family' ]) { $p['FONT-FAMILY'] = $bilp[ 'family' ]; }
1206
+ if (isset($bilp[ 'I' ]) && $bilp[ 'I' ]) { $p['FONT-STYLE'] = 'italic'; }
1207
+ if (isset($bilp[ 'sizePt' ]) && $bilp[ 'sizePt' ]) { $p['FONT-SIZE'] = $bilp[ 'sizePt' ] . 'pt'; }
1208
+ if (isset($bilp[ 'B' ]) && $bilp[ 'B' ]) { $p['FONT-WEIGHT'] = 'bold'; }
1209
+ if (isset($bilp[ 'colorarray' ]) && $bilp[ 'colorarray' ]) {
1210
+ $cor = $bilp[ 'colorarray' ];
1211
+ $p['COLOR'] = $this->mpdf->_colAtoString($cor);
1212
+ }
1213
+ if (isset($bilp[ 'toupper' ]) && $bilp[ 'toupper' ]) { $p['TEXT-TRANSFORM'] = 'uppercase'; }
1214
+ else if (isset($bilp[ 'tolower' ]) && $bilp[ 'tolower' ]) { $p['TEXT-TRANSFORM'] = 'lowercase'; }
1215
+ else if (isset($bilp[ 'capitalize' ]) && $bilp[ 'capitalize' ]) { $p['TEXT-TRANSFORM'] = 'capitalize'; }
1216
+ if (isset($bilp[ 'fontkerning' ])) {
1217
+ if ($bilp[ 'fontkerning' ]) { $p['FONT-KERNING'] = 'normal'; }
1218
+ else { $p['FONT-KERNING'] = 'none'; }
1219
+ }
1220
+ if (isset($bilp[ 'lSpacingCSS' ]) && $bilp[ 'lSpacingCSS' ]) { $p['LETTER-SPACING'] = $bilp[ 'lSpacingCSS' ]; }
1221
+ if (isset($bilp[ 'wSpacingCSS' ]) && $bilp[ 'wSpacingCSS' ]) { $p['WORD-SPACING'] = $bilp[ 'wSpacingCSS' ]; }
1222
+ // CSS says text-decoration is not inherited, but IE7 does??
1223
+ if (isset($bilp[ 'underline' ]) && $bilp[ 'underline' ]) { $p['TEXT-DECORATION'] = 'underline'; }
1224
+ if (isset($bilp[ 'smCaps' ]) && $bilp[ 'smCaps' ]) { $p['FONT-VARIANT'] = 'small-caps'; }
1225
+ if ($tag=='LI') {
1226
+ // Note to self - this should never work, as TOPLIST is not called when LI (see code removed in v5.3)
1227
+ $this->mpdf->Error("If you see this message, please report this as a bug to the mPDF Forum.");
1228
+ }
1229
+ }
1230
+ }
1231
+ /*-- END LISTS --*/
1232
+ //===============================================
1233
+ //===============================================
1234
+ // DEFAULT for this TAG set in DefaultCSS
1235
+ if (isset($this->mpdf->defaultCSS[$tag])) {
1236
+ $zp = $this->fixCSS($this->mpdf->defaultCSS[$tag]);
1237
+ if (is_array($zp)) { // Default overwrites Inherited
1238
+ $p = array_merge($p,$zp); // !! Note other way round !!
1239
+ $this->_mergeBorders($p,$zp);
1240
+ }
1241
+ }
1242
+ //===============================================
1243
+ /*-- TABLES --*/
1244
+ // cellPadding overwrites TD/TH default but not specific CSS set on cell
1245
+ if (($tag=='TD' || $tag=='TH') && isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['cell_padding']) && ($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['cell_padding'] || $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['cell_padding']===0)) {
1246
+ $p['PADDING-LEFT'] = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['cell_padding'];
1247
+ $p['PADDING-RIGHT'] = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['cell_padding'];
1248
+ $p['PADDING-TOP'] = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['cell_padding'];
1249
+ $p['PADDING-BOTTOM'] = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['cell_padding'];
1250
+ }
1251
+ /*-- END TABLES --*/
1252
+ //===============================================
1253
+ // STYLESHEET TAG e.g. h1 p div table
1254
+ if (isset($this->CSS[$tag]) && $this->CSS[$tag]) {
1255
+ $zp = $this->CSS[$tag];
1256
+ if ($tag=='TD' || $tag=='TH') { $this->setBorderDominance($zp, 9); } // *TABLES* // *TABLES-ADVANCED-BORDERS*
1257
+ if (is_array($zp)) {
1258
+ $p = array_merge($p,$zp);
1259
+ $this->_mergeBorders($p,$zp);
1260
+ }
1261
+ }
1262
+ //===============================================
1263
+ // STYLESHEET CLASS e.g. .smallone{} .redletter{}
1264
+ foreach($classes AS $class) {
1265
+ $zp = array();
1266
+ if (isset($this->CSS['CLASS>>'.$class]) && $this->CSS['CLASS>>'.$class]) { $zp = $this->CSS['CLASS>>'.$class]; }
1267
+ if ($tag=='TD' || $tag=='TH') { $this->setBorderDominance($zp, 9); } // *TABLES* // *TABLES-ADVANCED-BORDERS*
1268
+ if (is_array($zp)) {
1269
+ $p = array_merge($p,$zp);
1270
+ $this->_mergeBorders($p,$zp);
1271
+ }
1272
+ }
1273
+ //===============================================
1274
+ /*-- TABLES --*/
1275
+ // STYLESHEET nth-child SELECTOR e.g. tr:nth-child(odd) td:nth-child(2n+1)
1276
+ if ($tag=='TR' || $tag=='TD' || $tag=='TH') {
1277
+ foreach($this->CSS AS $k=>$val) {
1278
+ if (preg_match('/'.$tag.'>>SELECTORNTHCHILD>>(.*)/',$k, $m)) {
1279
+ $select = false;
1280
+ if ($tag=='TR') {
1281
+ $row = $this->mpdf->row;
1282
+ $thnr = (isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_thead']) ? count($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_thead']) : 0);
1283
+ $tfnr = (isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_tfoot']) ? count($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_tfoot']) : 0);
1284
+ if ($this->mpdf->tabletfoot) { $row -= $thnr; }
1285
+ else if (!$this->mpdf->tablethead) { $row -= ($thnr + $tfnr); }
1286
+ if ($m[1]=='ODD' && ($row % 2) == 0) { $select = true; }
1287
+ else if ($m[1]=='EVEN' && ($row % 2) == 1) { $select = true; }
1288
+ else if (preg_match('/(\d+)N\+(\d+)/',$m[1],$a)) {
1289
+ if ((($row + 1) % $a[1]) == $a[2]) { $select = true; }
1290
+ }
1291
+ }
1292
+ else if ($tag=='TD' || $tag=='TH') {
1293
+ if ($m[1]=='ODD' && ($this->mpdf->col % 2) == 0) { $select = true; }
1294
+ else if ($m[1]=='EVEN' && ($this->mpdf->col % 2) == 1) { $select = true; }
1295
+ else if (preg_match('/(\d+)N\+(\d+)/',$m[1],$a)) {
1296
+ if ((($this->mpdf->col+1) % $a[1]) == $a[2]) { $select = true; }
1297
+ }
1298
+ }
1299
+ if ($select) {
1300
+ $zp = $this->CSS[$tag.'>>SELECTORNTHCHILD>>'.$m[1]];
1301
+ if ($tag=='TD' || $tag=='TH') { $this->setBorderDominance($zp, 9); }
1302
+ if (is_array($zp)) {
1303
+ $p = array_merge($p,$zp);
1304
+ $this->_mergeBorders($p,$zp);
1305
+ }
1306
+ }
1307
+ }
1308
+ }
1309
+ }
1310
+ /*-- END TABLES --*/
1311
+ //===============================================
1312
+ // STYLESHEET ID e.g. #smallone{} #redletter{}
1313
+ if (isset($attr['ID']) && isset($this->CSS['ID>>'.$attr['ID']]) && $this->CSS['ID>>'.$attr['ID']]) {
1314
+ $zp = $this->CSS['ID>>'.$attr['ID']];
1315
+ if ($tag=='TD' || $tag=='TH') { $this->setBorderDominance($zp, 9); } // *TABLES* // *TABLES-ADVANCED-BORDERS*
1316
+ if (is_array($zp)) {
1317
+ $p = array_merge($p,$zp);
1318
+ $this->_mergeBorders($p,$zp);
1319
+ }
1320
+ }
1321
+ //===============================================
1322
+ // STYLESHEET CLASS e.g. p.smallone{} div.redletter{}
1323
+ foreach($classes AS $class) {
1324
+ $zp = array();
1325
+ if (isset($this->CSS[$tag.'>>CLASS>>'.$class]) && $this->CSS[$tag.'>>CLASS>>'.$class]) { $zp = $this->CSS[$tag.'>>CLASS>>'.$class]; }
1326
+ if ($tag=='TD' || $tag=='TH') { $this->setBorderDominance($zp, 9); } // *TABLES* // *TABLES-ADVANCED-BORDERS*
1327
+ if (is_array($zp)) {
1328
+ $p = array_merge($p,$zp);
1329
+ $this->_mergeBorders($p,$zp);
1330
+ }
1331
+ }
1332
+ //===============================================
1333
+ // STYLESHEET CLASS e.g. p#smallone{} div#redletter{}
1334
+ if (isset($attr['ID']) && isset($this->CSS[$tag.'>>ID>>'.$attr['ID']]) && $this->CSS[$tag.'>>ID>>'.$attr['ID']]) {
1335
+ $zp = $this->CSS[$tag.'>>ID>>'.$attr['ID']];
1336
+ if ($tag=='TD' || $tag=='TH') { $this->setBorderDominance($zp, 9); } // *TABLES* // *TABLES-ADVANCED-BORDERS*
1337
+ if (is_array($zp)) {
1338
+ $p = array_merge($p,$zp);
1339
+ $this->_mergeBorders($p,$zp);
1340
+ }
1341
+ }
1342
+ //===============================================
1343
+ // Cascaded e.g. div.class p only works for block level
1344
+ if ($inherit == 'BLOCK') {
1345
+ $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl-1]['cascadeCSS'][$tag], $p);
1346
+ foreach($classes AS $class) {
1347
+ $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl-1]['cascadeCSS']['CLASS>>'.$class], $p);
1348
+ }
1349
+ $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl-1]['cascadeCSS']['ID>>'.$attr['ID']], $p);
1350
+ foreach($classes AS $class) {
1351
+ $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl-1]['cascadeCSS'][$tag.'>>CLASS>>'.$class], $p);
1352
+ }
1353
+ $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl-1]['cascadeCSS'][$tag.'>>ID>>'.$attr['ID']], $p);
1354
+ }
1355
+ else if ($inherit == 'INLINE') {
1356
+ $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'][$tag], $p);
1357
+ foreach($classes AS $class) {
1358
+ $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS']['CLASS>>'.$class], $p);
1359
+ }
1360
+ $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS']['ID>>'.$attr['ID']], $p);
1361
+ foreach($classes AS $class) {
1362
+ $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'][$tag.'>>CLASS>>'.$class], $p);
1363
+ }
1364
+ $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'][$tag.'>>ID>>'.$attr['ID']], $p);
1365
+ }
1366
+ /*-- TABLES --*/
1367
+ else if ($inherit == 'TOPTABLE' || $inherit == 'TABLE') { // NB looks at $this->tablecascadeCSS-1 for cascading CSS
1368
+ // false, 9 = don't check for 'depth' and do set border dominance
1369
+ $this->_set_mergedCSS($this->tablecascadeCSS[$this->tbCSSlvl-1][$tag], $p, false, 9);
1370
+ foreach($classes AS $class) {
1371
+ $this->_set_mergedCSS($this->tablecascadeCSS[$this->tbCSSlvl-1]['CLASS>>'.$class], $p, false, 9);
1372
+ }
1373
+ // STYLESHEET nth-child SELECTOR e.g. tr:nth-child(odd) td:nth-child(2n+1)
1374
+ if ($tag=='TR' || $tag=='TD' || $tag=='TH') {
1375
+ foreach($this->tablecascadeCSS[$this->tbCSSlvl-1] AS $k=>$val) {
1376
+ if (preg_match('/'.$tag.'>>SELECTORNTHCHILD>>(.*)/',$k, $m)) {
1377
+ $select = false;
1378
+ if ($tag=='TR') {
1379
+ $row = $this->mpdf->row;
1380
+ $thnr = (isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_thead']) ? count($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_thead']) : 0);
1381
+ $tfnr = (isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_tfoot']) ? count($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_tfoot']) : 0);
1382
+ if ($this->mpdf->tabletfoot) { $row -= $thnr; }
1383
+ else if (!$this->mpdf->tablethead) { $row -= ($thnr + $tfnr); }
1384
+ if ($m[1]=='ODD' && ($row % 2) == 0) { $select = true; }
1385
+ else if ($m[1]=='EVEN' && ($row % 2) == 1) { $select = true; }
1386
+ else if (preg_match('/(\d+)N\+(\d+)/',$m[1],$a)) {
1387
+ if ((($row + 1) % $a[1]) == $a[2]) { $select = true; }
1388
+ }
1389
+ }
1390
+ else if ($tag=='TD' || $tag=='TH') {
1391
+ if ($m[1]=='ODD' && ($this->mpdf->col % 2) == 0) { $select = true; }
1392
+ else if ($m[1]=='EVEN' && ($this->mpdf->col % 2) == 1) { $select = true; }
1393
+ else if (preg_match('/(\d+)N\+(\d+)/',$m[1],$a)) {
1394
+ if ((($this->mpdf->col + 1) % $a[1]) == $a[2]) { $select = true; }
1395
+ }
1396
+ }
1397
+ if ($select) {
1398
+ $this->_set_mergedCSS($this->tablecascadeCSS[$this->tbCSSlvl-1][$tag.'>>SELECTORNTHCHILD>>'.$m[1]], $p, false, 9);
1399
+ }
1400
+ }
1401
+ }
1402
+ }
1403
+ $this->_set_mergedCSS($this->tablecascadeCSS[$this->tbCSSlvl-1]['ID>>'.$attr['ID']], $p, false, 9);
1404
+ foreach($classes AS $class) {
1405
+ $this->_set_mergedCSS($this->tablecascadeCSS[$this->tbCSSlvl-1][$tag.'>>CLASS>>'.$class], $p, false, 9);
1406
+ }
1407
+ $this->_set_mergedCSS($this->tablecascadeCSS[$this->tbCSSlvl-1][$tag.'>>ID>>'.$attr['ID']], $p, false, 9);
1408
+ }
1409
+ /*-- END TABLES --*/
1410
+ //===============================================
1411
+ /*-- LISTS --*/
1412
+ else if ($inherit == 'TOPLIST' || $inherit == 'LIST') { // NB looks at $this->listcascadeCSS-1 for cascading CSS
1413
+ // false = don't check for 'depth'
1414
+ $this->_set_mergedCSS($this->listcascadeCSS[$this->listCSSlvl-1][$tag], $p, false);
1415
+ foreach($classes AS $class) {
1416
+ $this->_set_mergedCSS($this->listcascadeCSS[$this->listCSSlvl-1]['CLASS>>'.$class], $p, false);
1417
+ }
1418
+ $this->_set_mergedCSS($this->listcascadeCSS[$this->listCSSlvl-1]['ID>>'.$attr['ID']], $p, false);
1419
+ foreach($classes AS $class) {
1420
+ $this->_set_mergedCSS($this->listcascadeCSS[$this->listCSSlvl-1][$tag.'>>CLASS>>'.$class], $p, false);
1421
+ }
1422
+ $this->_set_mergedCSS($this->listcascadeCSS[$this->listCSSlvl-1][$tag.'>>ID>>'.$attr['ID']], $p, false);
1423
+ }
1424
+ /*-- END LISTS --*/
1425
+ //===============================================
1426
+ //===============================================
1427
+ // INLINE STYLE e.g. style="CSS:property"
1428
+ if (isset($attr['STYLE'])) {
1429
+ $zp = $this->readInlineCSS($attr['STYLE']);
1430
+ if ($tag=='TD' || $tag=='TH') { $this->setBorderDominance($zp, 9); } // *TABLES* // *TABLES-ADVANCED-BORDERS*
1431
+ if (is_array($zp)) {
1432
+ $p = array_merge($p,$zp);
1433
+ $this->_mergeBorders($p,$zp);
1434
+ }
1435
+ }
1436
+ //===============================================
1437
+ //===============================================
1438
+ // INLINE ATTRIBUTES e.g. .. ALIGN="CENTER">
1439
+ if (isset($attr['LANG']) and $attr['LANG']!='') {
1440
+ $p['LANG'] = $attr['LANG'];
1441
+ }
1442
+ if (isset($attr['COLOR']) and $attr['COLOR']!='') {
1443
+ $p['COLOR'] = $attr['COLOR'];
1444
+ }
1445
+ if ($tag != 'INPUT') {
1446
+ if (isset($attr['WIDTH']) and $attr['WIDTH']!='') {
1447
+ $p['WIDTH'] = $attr['WIDTH'];
1448
+ }
1449
+ if (isset($attr['HEIGHT']) and $attr['HEIGHT']!='') {
1450
+ $p['HEIGHT'] = $attr['HEIGHT'];
1451
+ }
1452
+ }
1453
+ if ($tag == 'FONT') {
1454
+ if (isset($attr['FACE'])) {
1455
+ $p['FONT-FAMILY'] = $attr['FACE'];
1456
+ }
1457
+ if (isset($attr['SIZE']) and $attr['SIZE']!='') {
1458
+ $s = '';
1459
+ if ($attr['SIZE'] === '+1') { $s = '120%'; }
1460
+ else if ($attr['SIZE'] === '-1') { $s = '86%'; }
1461
+ else if ($attr['SIZE'] === '1') { $s = 'XX-SMALL'; }
1462
+ else if ($attr['SIZE'] == '2') { $s = 'X-SMALL'; }
1463
+ else if ($attr['SIZE'] == '3') { $s = 'SMALL'; }
1464
+ else if ($attr['SIZE'] == '4') { $s = 'MEDIUM'; }
1465
+ else if ($attr['SIZE'] == '5') { $s = 'LARGE'; }
1466
+ else if ($attr['SIZE'] == '6') { $s = 'X-LARGE'; }
1467
+ else if ($attr['SIZE'] == '7') { $s = 'XX-LARGE'; }
1468
+ if ($s) $p['FONT-SIZE'] = $s;
1469
+ }
1470
+ }
1471
+ if (isset($attr['VALIGN']) and $attr['VALIGN']!='') {
1472
+ $p['VERTICAL-ALIGN'] = $attr['VALIGN'];
1473
+ }
1474
+ if (isset($attr['VSPACE']) and $attr['VSPACE']!='') {
1475
+ $p['MARGIN-TOP'] = $attr['VSPACE'];
1476
+ $p['MARGIN-BOTTOM'] = $attr['VSPACE'];
1477
+ }
1478
+ if (isset($attr['HSPACE']) and $attr['HSPACE']!='') {
1479
+ $p['MARGIN-LEFT'] = $attr['HSPACE'];
1480
+ $p['MARGIN-RIGHT'] = $attr['HSPACE'];
1481
+ }
1482
+ //===============================================
1483
+ return $p;
1484
+ }
1485
+
1486
+ function PreviewBlockCSS($tag,$attr) {
1487
+ // Looks ahead from current block level to a new level
1488
+ $p = array();
1489
+ $zp = array();
1490
+ $oldcascadeCSS = $this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'];
1491
+ $classes = array();
1492
+ if (isset($attr['CLASS'])) { $classes = preg_split('/\s+/',$attr['CLASS']); }
1493
+ //===============================================
1494
+ // DEFAULT for this TAG set in DefaultCSS
1495
+ if (isset($this->mpdf->defaultCSS[$tag])) {
1496
+ $zp = $this->fixCSS($this->mpdf->defaultCSS[$tag]);
1497
+ if (is_array($zp)) { $p = array_merge($zp,$p); } // Inherited overwrites default
1498
+ }
1499
+ // STYLESHEET TAG e.g. h1 p div table
1500
+ if (isset($this->CSS[$tag])) {
1501
+ $zp = $this->CSS[$tag];
1502
+ if (is_array($zp)) { $p = array_merge($p,$zp); }
1503
+ }
1504
+ // STYLESHEET CLASS e.g. .smallone{} .redletter{}
1505
+ foreach($classes AS $class) {
1506
+ $zp = array();
1507
+ if (isset($this->CSS['CLASS>>'.$class])) { $zp = $this->CSS['CLASS>>'.$class]; }
1508
+ if (is_array($zp)) { $p = array_merge($p,$zp); }
1509
+ }
1510
+ // STYLESHEET ID e.g. #smallone{} #redletter{}
1511
+ if (isset($attr['ID']) && isset($this->CSS['ID>>'.$attr['ID']])) {
1512
+ $zp = $this->CSS['ID>>'.$attr['ID']];
1513
+ if (is_array($zp)) { $p = array_merge($p,$zp); }
1514
+ }
1515
+ // STYLESHEET CLASS e.g. p.smallone{} div.redletter{}
1516
+ foreach($classes AS $class) {
1517
+ $zp = array();
1518
+ if (isset($this->CSS[$tag.'>>CLASS>>'.$class])) { $zp = $this->CSS[$tag.'>>CLASS>>'.$class]; }
1519
+ if (is_array($zp)) { $p = array_merge($p,$zp); }
1520
+ }
1521
+ // STYLESHEET CLASS e.g. p#smallone{} div#redletter{}
1522
+ if (isset($attr['ID']) && isset($this->CSS[$tag.'>>ID>>'.$attr['ID']])) {
1523
+ $zp = $this->CSS[$tag.'>>ID>>'.$attr['ID']];
1524
+ if (is_array($zp)) { $p = array_merge($p,$zp); }
1525
+ }
1526
+ //===============================================
1527
+ // STYLESHEET TAG e.g. div h1 div p
1528
+
1529
+ $this->_set_mergedCSS($oldcascadeCSS[$tag], $p);
1530
+ // STYLESHEET CLASS e.g. .smallone{} .redletter{}
1531
+ foreach($classes AS $class) {
1532
+
1533
+ $this->_set_mergedCSS($oldcascadeCSS['CLASS>>'.$class], $p);
1534
+ }
1535
+ // STYLESHEET CLASS e.g. #smallone{} #redletter{}
1536
+ if (isset($attr['ID'])) {
1537
+
1538
+ $this->_set_mergedCSS($oldcascadeCSS['ID>>'.$attr['ID']], $p);
1539
+ }
1540
+ // STYLESHEET CLASS e.g. div.smallone{} p.redletter{}
1541
+ foreach($classes AS $class) {
1542
+
1543
+ $this->_set_mergedCSS($oldcascadeCSS[$tag.'>>CLASS>>'.$class], $p);
1544
+ }
1545
+ // STYLESHEET CLASS e.g. div#smallone{} p#redletter{}
1546
+ if (isset($attr['ID'])) {
1547
+
1548
+ $this->_set_mergedCSS($oldcascadeCSS[$tag.'>>ID>>'.$attr['ID']], $p);
1549
+ }
1550
+ //===============================================
1551
+ // INLINE STYLE e.g. style="CSS:property"
1552
+ if (isset($attr['STYLE'])) {
1553
+ $zp = $this->readInlineCSS($attr['STYLE']);
1554
+ if (is_array($zp)) { $p = array_merge($p,$zp); }
1555
+ }
1556
+ //===============================================
1557
+ return $p;
1558
+ }
1559
+
1560
+
1561
+
1562
+
1563
+
1564
+ } // end of class
1565
+
1566
+ ?>
mpdf/classes/directw.php ADDED
@@ -0,0 +1,408 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class directw {
4
+
5
+ var $mpdf = null;
6
+
7
+ function directw(&$mpdf) {
8
+ $this->mpdf = $mpdf;
9
+ }
10
+
11
+
12
+ function Write($h,$txt,$currentx=0,$link='',$directionality='ltr',$align='') {
13
+ if (!$align) {
14
+ if ($directionality=='rtl') { $align = 'R'; }
15
+ else { $align = 'L'; }
16
+ }
17
+ if ($h == 0) { $this->mpdf->SetLineHeight(); $h = $this->mpdf->lineheight; }
18
+ //Output text in flowing mode
19
+ $w = $this->mpdf->w - $this->mpdf->rMargin - $this->mpdf->x;
20
+
21
+ $wmax = ($w - ($this->mpdf->cMarginL+$this->mpdf->cMarginR));
22
+ $s=str_replace("\r",'',$txt);
23
+ if ($this->mpdf->usingCoreFont) { $nb=strlen($s); }
24
+ else {
25
+ $nb=mb_strlen($s, $this->mpdf->mb_enc );
26
+ // handle single space character
27
+ if(($nb==1) && $s == " ") {
28
+ $this->mpdf->x += $this->mpdf->GetStringWidth($s);
29
+ return;
30
+ }
31
+ }
32
+ $sep=-1;
33
+ $i=0;
34
+ $j=0;
35
+ $l=0;
36
+ $nl=1;
37
+ if (!$this->mpdf->usingCoreFont) {
38
+ if (preg_match("/([".$this->mpdf->pregRTLchars."])/u", $txt)) { $this->mpdf->biDirectional = true; } // *RTL*
39
+ $checkCursive=false;
40
+ if ($this->mpdf->biDirectional) { $checkCursive=true; } // *RTL*
41
+ else if (isset($this->mpdf->CurrentFont['indic']) && $this->mpdf->CurrentFont['indic']) { $checkCursive=true; } // *INDIC*
42
+ while($i<$nb) {
43
+ //Get next character
44
+ $c = mb_substr($s,$i,1,$this->mpdf->mb_enc );
45
+ if($c == "\n") {
46
+ // WORD SPACING
47
+ $this->mpdf->ResetSpacing();
48
+ //Explicit line break
49
+ $tmp = rtrim(mb_substr($s,$j,$i-$j,$this->mpdf->mb_enc));
50
+ if ($directionality == 'rtl' && $align == 'J') { $align = 'R'; } // *RTL*
51
+ $this->mpdf->magic_reverse_dir($tmp, true, $directionality); // *RTL*
52
+ $this->mpdf->Cell($w, $h, $tmp, 0, 2, $align, $fill, $link);
53
+ $i++;
54
+ $sep = -1;
55
+ $j = $i;
56
+ $l = 0;
57
+ if($nl == 1) {
58
+ if ($currentx != 0) $this->mpdf->x=$currentx;
59
+ else $this->mpdf->x=$this->mpdf->lMargin;
60
+ $w = $this->mpdf->w - $this->mpdf->rMargin - $this->mpdf->x;
61
+ $wmax = ($w - ($this->mpdf->cMarginL+$this->mpdf->cMarginR));
62
+ }
63
+ $nl++;
64
+ continue;
65
+ }
66
+ if($c == " ") { $sep= $i; }
67
+ $l += $this->mpdf->GetCharWidthNonCore($c); // mPDF 5.3.04
68
+ if($l > $wmax) {
69
+ //Automatic line break (word wrapping)
70
+ if($sep == -1) {
71
+ // WORD SPACING
72
+ $this->mpdf->ResetSpacing();
73
+ if($this->mpdf->x > $this->mpdf->lMargin) {
74
+ //Move to next line
75
+ if ($currentx != 0) $this->mpdf->x=$currentx;
76
+ else $this->mpdf->x=$this->mpdf->lMargin;
77
+ $this->mpdf->y+=$h;
78
+ $w=$this->mpdf->w-$this->mpdf->rMargin-$this->mpdf->x;
79
+ $wmax = ($w - ($this->mpdf->cMarginL+$this->mpdf->cMarginR));
80
+ $i++;
81
+ $nl++;
82
+ continue;
83
+ }
84
+ if($i==$j) { $i++; }
85
+ $tmp = rtrim(mb_substr($s,$j,$i-$j,$this->mpdf->mb_enc));
86
+ if ($directionality == 'rtl' && $align == 'J') { $align = 'R'; } // *RTL*
87
+ $this->mpdf->magic_reverse_dir($tmp, true, $directionality); // *RTL*
88
+ $this->mpdf->Cell($w, $h, $tmp, 0, 2, $align, $fill, $link);
89
+ }
90
+ else {
91
+ $tmp = rtrim(mb_substr($s,$j,$sep-$j,$this->mpdf->mb_enc));
92
+ if ($directionality == 'rtl' && $align == 'J') { $align = 'R'; } // *RTL*
93
+ $this->mpdf->magic_reverse_dir($tmp, true, $directionality); // *RTL*
94
+
95
+ if($align=='J') {
96
+ //////////////////////////////////////////
97
+ // JUSTIFY J using Unicode fonts (Word spacing doesn't work)
98
+ // WORD SPACING
99
+ // Change NON_BREAKING SPACE to spaces so they are 'spaced' properly
100
+ $tmp = str_replace(chr(194).chr(160),chr(32),$tmp );
101
+ $len_ligne = $this->mpdf->GetStringWidth($tmp );
102
+ $nb_carac = mb_strlen( $tmp , $this->mpdf->mb_enc ) ;
103
+ $nb_spaces = mb_substr_count( $tmp ,' ', $this->mpdf->mb_enc ) ;
104
+ $inclCursive=false;
105
+ if ($checkCursive) {
106
+ if (preg_match("/([".$this->mpdf->pregRTLchars."])/u", $tmp)) { $inclCursive = true; } // *RTL*
107
+ if (preg_match("/([".$this->mpdf->pregHIchars.$this->mpdf->pregBNchars.$this->mpdf->pregPAchars."])/u", $tmp)) { $inclCursive = true; } // *INDIC*
108
+ }
109
+ list($charspacing,$ws) = $this->mpdf->GetJspacing($nb_carac,$nb_spaces,((($w-2) - $len_ligne) * _MPDFK),$inclCursive);
110
+ $this->mpdf->SetSpacing($charspacing,$ws);
111
+ //////////////////////////////////////////
112
+ }
113
+ $this->mpdf->Cell($w, $h, $tmp, 0, 2, $align, $fill, $link);
114
+ $i=$sep+1;
115
+ }
116
+ $sep = -1;
117
+ $j = $i;
118
+ $l = 0;
119
+ if($nl==1) {
120
+ if ($currentx != 0) $this->mpdf->x=$currentx;
121
+ else $this->mpdf->x=$this->mpdf->lMargin;
122
+ $w=$this->mpdf->w-$this->mpdf->rMargin-$this->mpdf->x;
123
+ $wmax = ($w - ($this->mpdf->cMarginL+$this->mpdf->cMarginR));
124
+ }
125
+ $nl++;
126
+ }
127
+ else { $i++; }
128
+ }
129
+ //Last chunk
130
+ // WORD SPACING
131
+ $this->mpdf->ResetSpacing();
132
+ }
133
+ else {
134
+ while($i<$nb) {
135
+ //Get next character
136
+ $c=$s[$i];
137
+ if($c == "\n") {
138
+ //Explicit line break
139
+ // WORD SPACING
140
+ $this->mpdf->ResetSpacing();
141
+ $this->mpdf->Cell($w, $h, substr($s, $j, $i-$j), 0, 2, $align, $fill, $link);
142
+ $i++;
143
+ $sep = -1;
144
+ $j = $i;
145
+ $l = 0;
146
+ if($nl == 1) {
147
+ if ($currentx != 0) $this->mpdf->x=$currentx;
148
+ else $this->mpdf->x=$this->mpdf->lMargin;
149
+ $w = $this->mpdf->w - $this->mpdf->rMargin - $this->mpdf->x;
150
+ $wmax=$w-($this->mpdf->cMarginL+$this->mpdf->cMarginR);
151
+ }
152
+ $nl++;
153
+ continue;
154
+ }
155
+ if($c == " ") { $sep= $i; }
156
+ $l += $this->mpdf->GetCharWidthCore($c); // mPDF 5.3.04
157
+ if($l > $wmax) {
158
+ //Automatic line break (word wrapping)
159
+ if($sep == -1) {
160
+ // WORD SPACING
161
+ $this->mpdf->ResetSpacing();
162
+ if($this->mpdf->x > $this->mpdf->lMargin) {
163
+ //Move to next line
164
+ if ($currentx != 0) $this->mpdf->x=$currentx;
165
+ else $this->mpdf->x=$this->mpdf->lMargin;
166
+ $this->mpdf->y+=$h;
167
+ $w=$this->mpdf->w-$this->mpdf->rMargin-$this->mpdf->x;
168
+ $wmax=$w-($this->mpdf->cMarginL+$this->mpdf->cMarginR);
169
+ $i++;
170
+ $nl++;
171
+ continue;
172
+ }
173
+ if($i==$j) { $i++; }
174
+ $this->mpdf->Cell($w, $h, substr($s, $j, $i-$j), 0, 2, $align, $fill, $link);
175
+ }
176
+ else {
177
+ $tmp = substr($s, $j, $sep-$j);
178
+ if($align=='J') {
179
+ //////////////////////////////////////////
180
+ // JUSTIFY J using Unicode fonts (Word spacing doesn't work)
181
+ // WORD SPACING
182
+ // Change NON_BREAKING SPACE to spaces so they are 'spaced' properly
183
+ $tmp = str_replace(chr(160),chr(32),$tmp );
184
+ $len_ligne = $this->mpdf->GetStringWidth($tmp );
185
+ $nb_carac = strlen( $tmp ) ;
186
+ $nb_spaces = substr_count( $tmp ,' ' ) ;
187
+ list($charspacing,$ws) = $this->mpdf->GetJspacing($nb_carac,$nb_spaces,((($w-2) - $len_ligne) * _MPDFK),$false);
188
+ $this->mpdf->SetSpacing($charspacing,$ws);
189
+ //////////////////////////////////////////
190
+ }
191
+ $this->mpdf->Cell($w, $h, $tmp, 0, 2, $align, $fill, $link);
192
+ $i=$sep+1;
193
+ }
194
+ $sep = -1;
195
+ $j = $i;
196
+ $l = 0;
197
+ if($nl==1) {
198
+ if ($currentx != 0) $this->mpdf->x=$currentx;
199
+ else $this->mpdf->x=$this->mpdf->lMargin;
200
+ $w=$this->mpdf->w-$this->mpdf->rMargin-$this->mpdf->x;
201
+ $wmax=$w-($this->mpdf->cMarginL+$this->mpdf->cMarginR);
202
+ }
203
+ $nl++;
204
+ }
205
+ else {
206
+ $i++;
207
+ }
208
+ }
209
+ // WORD SPACING
210
+ $this->mpdf->ResetSpacing();
211
+ }
212
+ //Last chunk
213
+ if($i!=$j) {
214
+ if ($currentx != 0) $this->mpdf->x=$currentx;
215
+ else $this->mpdf->x=$this->mpdf->lMargin;
216
+ if ($this->mpdf->usingCoreFont) { $tmp = substr($s,$j,$i-$j); }
217
+ else {
218
+ $tmp = mb_substr($s,$j,$i-$j,$this->mpdf->mb_enc);
219
+ if ($directionality == 'rtl' && $align == 'J') { $align = 'R'; } // *RTL*
220
+ $this->mpdf->magic_reverse_dir($tmp, true, $directionality); // *RTL*
221
+ }
222
+ $this->mpdf->Cell($w,$h,$tmp,0,0,$align,$fill,$link);
223
+ }
224
+ }
225
+
226
+
227
+ function CircularText($x, $y, $r, $text, $align='top', $fontfamily='', $fontsizePt=0, $fontstyle='', $kerning=120, $fontwidth=100, $divider='') { // mPDF 5.5.23
228
+ if ($font || $fontstyle || $fontsizePt) $this->mpdf->SetFont($fontfamily,$fontstyle,$fontsizePt);
229
+ $kerning/=100;
230
+ $fontwidth/=100;
231
+ if($kerning==0) $this->mpdf->Error('Please use values unequal to zero for kerning (CircularText)');
232
+ if($fontwidth==0) $this->mpdf->Error('Please use values unequal to zero for font width (CircularText)');
233
+ $text=str_replace("\r",'',$text);
234
+ //circumference
235
+ $u=($r*2)*M_PI;
236
+ // mPDF 5.5.23
237
+ $checking = true;
238
+ $autoset = false;
239
+ while($checking) {
240
+ $t=0;
241
+ $w = array();
242
+ if ($this->mpdf->usingCoreFont) {
243
+ $nb=strlen($text);
244
+ for($i=0; $i<$nb; $i++){
245
+ $w[$i]=$this->mpdf->GetStringWidth($text[$i]);
246
+ $w[$i]*=$kerning*$fontwidth;
247
+ $t+=$w[$i];
248
+ }
249
+ }
250
+ else {
251
+ $nb=mb_strlen($text, $this->mpdf->mb_enc );
252
+ $lastchar = '';
253
+ $unicode = $this->mpdf->UTF8StringToArray($text);
254
+ for($i=0; $i<$nb; $i++){
255
+ $c = mb_substr($text,$i,1,$this->mpdf->mb_enc );
256
+ $w[$i]=$this->mpdf->GetStringWidth($c);
257
+ $w[$i]*=$kerning*$fontwidth;
258
+ $char = $unicode[$i];
259
+ if ($this->mpdf->useKerning && $lastchar) {
260
+ if (isset($this->mpdf->CurrentFont['kerninfo'][$lastchar][$char])) {
261
+ $tk = $this->mpdf->CurrentFont['kerninfo'][$lastchar][$char] * ($this->mpdf->FontSize/ 1000) * $kerning * $fontwidth;
262
+ $w[$i] += $tk/2;
263
+ $w[$i-1] += $tk/2;
264
+ $t+=$tk;
265
+ }
266
+ }
267
+ $lastchar = $char;
268
+ $t+=$w[$i];
269
+ }
270
+ }
271
+ if ($fontsizePt>=0 || $autoset) { $checking = false; }
272
+ else {
273
+ $t+=$this->mpdf->GetStringWidth(' ');
274
+ if ($divider)
275
+ $t+=$this->mpdf->GetStringWidth(' ');
276
+ if ($fontsizePt==-2)
277
+ $fontsizePt = $this->mpdf->FontSizePt * 0.5 * $u/$t;
278
+ else
279
+ $fontsizePt = $this->mpdf->FontSizePt * $u/$t;
280
+ $this->mpdf->SetFontSize($fontsizePt);
281
+ $autoset = true;
282
+ }
283
+ }
284
+
285
+ //total width of string in degrees
286
+ $d=($t/$u)*360;
287
+
288
+ $this->mpdf->StartTransform();
289
+ // rotate matrix for the first letter to center the text
290
+ // (half of total degrees)
291
+ if($align=='top'){
292
+ $this->mpdf->transformRotate(-$d/2, $x, $y);
293
+ }
294
+ else{
295
+ $this->mpdf->transformRotate($d/2, $x, $y);
296
+ }
297
+ //run through the string
298
+ for($i=0; $i<$nb; $i++){
299
+ if($align=='top'){
300
+ //rotate matrix half of the width of current letter + half of the width of preceding letter
301
+ if($i==0){
302
+ $this->mpdf->transformRotate((($w[$i]/2)/$u)*360, $x, $y);
303
+ }
304
+ else{
305
+ $this->mpdf->transformRotate((($w[$i]/2+$w[$i-1]/2)/$u)*360, $x, $y);
306
+ }
307
+ if($fontwidth!=1){
308
+ $this->mpdf->StartTransform();
309
+ $this->mpdf->transformScale($fontwidth*100, 100, $x, $y);
310
+ }
311
+ $this->mpdf->SetXY($x-$w[$i]/2, $y-$r);
312
+ }
313
+ else{
314
+ //rotate matrix half of the width of current letter + half of the width of preceding letter
315
+ if($i==0){
316
+ $this->mpdf->transformRotate(-(($w[$i]/2)/$u)*360, $x, $y);
317
+ }
318
+ else{
319
+ $this->mpdf->transformRotate(-(($w[$i]/2+$w[$i-1]/2)/$u)*360, $x, $y);
320
+ }
321
+ if($fontwidth!=1){
322
+ $this->mpdf->StartTransform();
323
+ $this->mpdf->transformScale($fontwidth*100, 100, $x, $y);
324
+ }
325
+ $this->mpdf->SetXY($x-$w[$i]/2, $y+$r-($this->mpdf->FontSize));
326
+ }
327
+ if ($this->mpdf->usingCoreFont) { $c=$text[$i]; }
328
+ else { $c = mb_substr($text,$i,1,$this->mpdf->mb_enc ); }
329
+ $this->mpdf->Cell(($w[$i]),$this->mpdf->FontSize,$c,0,0,'C'); // mPDF 5.3.53
330
+ if($fontwidth!=1){
331
+ $this->mpdf->StopTransform();
332
+ }
333
+ }
334
+ $this->mpdf->StopTransform();
335
+
336
+ // mPDF 5.5.23
337
+ if($align=='top' && $divider!=''){
338
+ $wc=$this->mpdf->GetStringWidth($divider);
339
+ $wc*=$kerning*$fontwidth;
340
+
341
+ $this->mpdf->StartTransform();
342
+ $this->mpdf->transformRotate(90, $x, $y);
343
+ $this->mpdf->SetXY($x-$wc/2, $y-$r);
344
+ $this->mpdf->Cell(($wc),$this->mpdf->FontSize,$divider,0,0,'C');
345
+ $this->mpdf->StopTransform();
346
+
347
+ $this->mpdf->StartTransform();
348
+ $this->mpdf->transformRotate(-90, $x, $y);
349
+ $this->mpdf->SetXY($x-$wc/2, $y-$r);
350
+ $this->mpdf->Cell(($wc),$this->mpdf->FontSize,$divider,0,0,'C');
351
+ $this->mpdf->StopTransform();
352
+ }
353
+ }
354
+
355
+ function Shaded_box( $text,$font='',$fontstyle='B',$szfont='',$width='70%',$style='DF',$radius=2.5,$fill='#FFFFFF',$color='#000000',$pad=2 )
356
+ {
357
+ // F (shading - no line),S (line, no shading),DF (both)
358
+ if (!$font) { $font= $this->mpdf->default_font; }
359
+ if (!$szfont) { $szfont = ($this->mpdf->default_font_size * 1.8); }
360
+
361
+ $text = $this->mpdf->purify_utf8_text($text);
362
+ if ($this->mpdf->text_input_as_HTML) {
363
+ $text = $this->mpdf->all_entities_to_utf8($text);
364
+ }
365
+ if ($this->mpdf->usingCoreFont) { $text = mb_convert_encoding($text,$this->mpdf->mb_enc,'UTF-8'); }
366
+ // DIRECTIONALITY
367
+ $this->mpdf->magic_reverse_dir($text, true, $this->mpdf->directionality); // *RTL*
368
+ // Font-specific ligature substitution for Indic fonts
369
+ if (isset($this->mpdf->CurrentFont['indic']) && $this->mpdf->CurrentFont['indic']) $this->mpdf->ConvertIndic($text); // *INDIC*
370
+ $text = ' '.$text.' ';
371
+ if (!$width) { $width = $this->mpdf->pgwidth; } else { $width=$this->mpdf->ConvertSize($width,$this->mpdf->pgwidth); }
372
+ $midpt = $this->mpdf->lMargin+($this->mpdf->pgwidth/2);
373
+ $r1 = $midpt-($width/2); //($this->mpdf->w / 2) - 40;
374
+ $r2 = $r1 + $width; //$r1 + 80;
375
+ $y1 = $this->mpdf->y;
376
+
377
+
378
+ $mid = ($r1 + $r2 ) / 2;
379
+ $loop = 0;
380
+
381
+ while ( $loop == 0 )
382
+ {
383
+ $this->mpdf->SetFont( $font, $fontstyle, $szfont );
384
+ $sz = $this->mpdf->GetStringWidth( $text );
385
+ if ( ($r1+$sz) > $r2 )
386
+ $szfont --;
387
+ else
388
+ $loop ++;
389
+ }
390
+
391
+ $y2 = $this->mpdf->FontSize+($pad*2);
392
+
393
+ $this->mpdf->SetLineWidth(0.1);
394
+ $fc = $this->mpdf->ConvertColor($fill);
395
+ $tc = $this->mpdf->ConvertColor($color);
396
+ $this->mpdf->SetFColor($fc);
397
+ $this->mpdf->SetTColor($tc);
398
+ $this->mpdf->RoundedRect($r1, $y1, ($r2 - $r1), $y2, $radius, $style);
399
+ $this->mpdf->SetX( $r1);
400
+ $this->mpdf->Cell($r2-$r1, $y2, $text, 0, 1, "C" );
401
+ $this->mpdf->SetY($y1+$y2+2); // +2 = mm margin below shaded box
402
+ $this->mpdf->Reset();
403
+ }
404
+
405
+
406
+ }
407
+
408
+ ?>
mpdf/classes/grad.php ADDED
@@ -0,0 +1,723 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class grad {
4
+
5
+ var $mpdf = null;
6
+
7
+ function grad(&$mpdf) {
8
+ $this->mpdf = $mpdf;
9
+ }
10
+
11
+ // mPDF 5.3.A1
12
+ 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){
13
+ $s=' q ';
14
+ $s.=sprintf(' %.3F %.3F %.3F %.3F re W n ', $x*_MPDFK, ($this->mpdf->h-$y)*_MPDFK, $w*_MPDFK, -$h*_MPDFK);
15
+ $s.=sprintf(' %.3F 0 0 %.3F %.3F %.3F cm ', $w*_MPDFK, $h*_MPDFK, $x*_MPDFK, ($this->mpdf->h-($y+$h))*_MPDFK);
16
+ $n = count($this->mpdf->gradients)+1;
17
+ $this->mpdf->gradients[$n]['type'] = 6; //coons patch mesh
18
+ $this->mpdf->gradients[$n]['colorspace'] = $colspace; //coons patch mesh
19
+ $bpcd=65535; //16 BitsPerCoordinate
20
+ $trans = false;
21
+ $this->mpdf->gradients[$n]['stream']='';
22
+ for($i=0;$i<count($patch_array);$i++){
23
+ $this->mpdf->gradients[$n]['stream'].=chr($patch_array[$i]['f']); //start with the edge flag as 8 bit
24
+ for($j=0;$j<count($patch_array[$i]['points']);$j++){
25
+ //each point as 16 bit
26
+ if (($j % 2) == 1) { // Y coordinate (adjusted as input is From top left)
27
+ $patch_array[$i]['points'][$j]=(($patch_array[$i]['points'][$j]-$y_min)/($y_max-$y_min))*$bpcd;
28
+ $patch_array[$i]['points'][$j]=$bpcd-$patch_array[$i]['points'][$j];
29
+ }
30
+ else {
31
+ $patch_array[$i]['points'][$j]=(($patch_array[$i]['points'][$j]-$x_min)/($x_max-$x_min))*$bpcd;
32
+ }
33
+ if($patch_array[$i]['points'][$j]<0) $patch_array[$i]['points'][$j]=0;
34
+ if($patch_array[$i]['points'][$j]>$bpcd) $patch_array[$i]['points'][$j]=$bpcd;
35
+ $this->mpdf->gradients[$n]['stream'].=chr(floor($patch_array[$i]['points'][$j]/256));
36
+ $this->mpdf->gradients[$n]['stream'].=chr(floor($patch_array[$i]['points'][$j]%256));
37
+ }
38
+ for($j=0;$j<count($patch_array[$i]['colors']);$j++){
39
+ //each color component as 8 bit
40
+ if ($colspace=='RGB') {
41
+ $this->mpdf->gradients[$n]['stream'].=($patch_array[$i]['colors'][$j][1]);
42
+ $this->mpdf->gradients[$n]['stream'].=($patch_array[$i]['colors'][$j][2]);
43
+ $this->mpdf->gradients[$n]['stream'].=($patch_array[$i]['colors'][$j][3]);
44
+ if (isset($patch_array[$i]['colors'][$j][4]) && ord($patch_array[$i]['colors'][$j][4])<100) { $trans = true; }
45
+ }
46
+ else if ($colspace=='CMYK') {
47
+ $this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][1])*2.55);
48
+ $this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][2])*2.55);
49
+ $this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][3])*2.55);
50
+ $this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][4])*2.55);
51
+ if (isset($patch_array[$i]['colors'][$j][5]) && ord($patch_array[$i]['colors'][$j][5])<100) { $trans = true; }
52
+ }
53
+ else if ($colspace=='Gray') {
54
+ $this->mpdf->gradients[$n]['stream'].=($patch_array[$i]['colors'][$j][1]);
55
+ if ($patch_array[$i]['colors'][$j][2]==1) { $trans = true; } // transparency converted from rgba or cmyka()
56
+ }
57
+ }
58
+ }
59
+ // TRANSPARENCY
60
+ if ($trans) {
61
+ $this->mpdf->gradients[$n]['stream_trans']='';
62
+ for($i=0;$i<count($patch_array);$i++){
63
+ $this->mpdf->gradients[$n]['stream_trans'].=chr($patch_array[$i]['f']);
64
+ for($j=0;$j<count($patch_array[$i]['points']);$j++){
65
+ //each point as 16 bit
66
+ $this->mpdf->gradients[$n]['stream_trans'].=chr(floor($patch_array[$i]['points'][$j]/256));
67
+ $this->mpdf->gradients[$n]['stream_trans'].=chr(floor($patch_array[$i]['points'][$j]%256));
68
+ }
69
+ for($j=0;$j<count($patch_array[$i]['colors']);$j++){
70
+ //each color component as 8 bit // OPACITY
71
+ if ($colspace=='RGB') {
72
+ $this->mpdf->gradients[$n]['stream_trans'].=chr(intval(ord($patch_array[$i]['colors'][$j][4])*2.55));
73
+ }
74
+ else if ($colspace=='CMYK') {
75
+ $this->mpdf->gradients[$n]['stream_trans'].=chr(intval(ord($patch_array[$i]['colors'][$j][5])*2.55));
76
+ }
77
+ else if ($colspace=='Gray') {
78
+ $this->mpdf->gradients[$n]['stream_trans'].=chr(intval(ord($patch_array[$i]['colors'][$j][3])*2.55));
79
+ }
80
+ }
81
+ }
82
+ $this->mpdf->gradients[$n]['trans'] = true;
83
+ $s .= ' /TGS'.$n.' gs ';
84
+ }
85
+ //paint the gradient
86
+ $s .= '/Sh'.$n.' sh'."\n";
87
+ //restore previous Graphic State
88
+ $s .= 'Q'."\n";
89
+ if ($return) { return $s; }
90
+ else { $this->mpdf->_out($s); }
91
+ }
92
+
93
+
94
+ // type = linear:2; radial: 3;
95
+ // Linear: $coords - array of the form (x1, y1, x2, y2) which defines the gradient vector (see linear_gradient_coords.jpg).
96
+ // The default value is from left to right (x1=0, y1=0, x2=1, y2=0).
97
+ // Radial: $coords - array of the form (fx, fy, cx, cy, r) where (fx, fy) is the starting point of the gradient with color1,
98
+ // (cx, cy) is the center of the circle with color2, and r is the radius of the circle (see radial_gradient_coords.jpg).
99
+ // (fx, fy) should be inside the circle, otherwise some areas will not be defined
100
+ // $col = array(R,G,B/255); or array(G/255); or array(C,M,Y,K/100)
101
+ // $stops = array('col'=>$col [, 'opacity'=>0-1] [, 'offset'=>0-1])
102
+ function Gradient($x, $y, $w, $h, $type, $stops=array(), $colorspace='RGB', $coords='', $extend='', $return=false, $is_mask=false) {
103
+ if (strtoupper(substr($type,0,1)) == 'L') { $type = 2; } // linear
104
+ else if (strtoupper(substr($type,0,1)) == 'R') { $type = 3; } // radial
105
+ if ($colorspace != 'CMYK' && $colorspace != 'Gray') {
106
+ $colorspace = 'RGB';
107
+ }
108
+ $bboxw = $w;
109
+ $bboxh = $h;
110
+ $usex = $x;
111
+ $usey = $y;
112
+ $usew = $bboxw;
113
+ $useh = $bboxh;
114
+ if ($type < 1) { $type = 2; }
115
+ if ($coords[0]!==false && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$coords[0],$m)) {
116
+ $tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
117
+ if ($tmp) { $coords[0] = $tmp/$w; }
118
+ }
119
+ if ($coords[1]!==false && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$coords[1],$m)) {
120
+ $tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
121
+ if ($tmp) { $coords[1] = 1-($tmp/$h); }
122
+ }
123
+ // LINEAR
124
+ if ($type == 2) {
125
+ $angle = $coords[4];
126
+ $repeat = $coords[5];
127
+ // ALL POINTS SET (default for custom mPDF linear gradient) - no -moz
128
+ if ($coords[0]!==false && $coords[1]!==false && $coords[2]!==false && $coords[3]!==false) {
129
+ // do nothing - coords used as they are
130
+ }
131
+
132
+ // If both a <point> and <angle> are defined, the gradient axis starts from the point and runs along the angle. The end point is
133
+ // defined as before - in this case start points may not be in corners, and axis may not correctly fall in the right quadrant.
134
+ // NO end points (Angle defined & Start points)
135
+ else if ($angle!==false && $coords[0]!==false && $coords[1]!==false && $coords[2]===false && $coords[3]===false) {
136
+ if ($angle==0 || $angle==360) { $coords[3]=$coords[1]; if ($coords[0]==1) $coords[2]=2; else $coords[2]=1; }
137
+ else if ($angle==90) { $coords[2]=$coords[0]; $coords[3]=1; if ($coords[1]==1) $coords[3]=2; else $coords[3]=1; }
138
+ else if ($angle==180) { if ($coords[4]==0) $coords[2]=-1; else $coords[2]=0; $coords[3]=$coords[1]; }
139
+ else if ($angle==270) { $coords[2]=$coords[0]; if ($coords[1]==0) $coords[3]=-1; else $coords[3]=0; }
140
+ else {
141
+ $endx=1; $endy=1;
142
+ if ($angle <=90) {
143
+ if ($angle <=45) { $endy=tan(deg2rad($angle)); }
144
+ else { $endx=tan(deg2rad(90-$angle)); }
145
+ $b = atan2(($endy*$bboxh), ($endx*$bboxw));
146
+ $ny = 1 - $coords[1] - (tan($b) * (1-$coords[0]));
147
+ $tx = sin($b) * cos($b) * $ny;
148
+ $ty = cos($b) * cos($b) * $ny;
149
+ $coords[2] = 1+$tx; $coords[3] = 1-$ty;
150
+ }
151
+ else if ($angle <=180) {
152
+ if ($angle <=135) { $endx=tan(deg2rad($angle-90)); }
153
+ else { $endy=tan(deg2rad(180-$angle)); }
154
+ $b = atan2(($endy*$bboxh), ($endx*$bboxw));
155
+ $ny = 1 - $coords[1] - (tan($b) * ($coords[0]));
156
+ $tx = sin($b) * cos($b) * $ny;
157
+ $ty = cos($b) * cos($b) * $ny;
158
+ $coords[2] = -$tx; $coords[3] = 1-$ty;
159
+ }
160
+ else if ($angle <=270) {
161
+ if ($angle <=225) { $endy=tan(deg2rad($angle-180)); }
162
+ else { $endx=tan(deg2rad(270-$angle)); }
163
+ $b = atan2(($endy*$bboxh), ($endx*$bboxw));
164
+ $ny = $coords[1] - (tan($b) * ($coords[0]));
165
+ $tx = sin($b) * cos($b) * $ny;
166
+ $ty = cos($b) * cos($b) * $ny;
167
+ $coords[2] = -$tx; $coords[3] = $ty;
168
+ }
169
+ else {
170
+ if ($angle <=315) { $endx=tan(deg2rad($angle-270)); }
171
+ else { $endy=tan(deg2rad(360-$angle)); }
172
+ $b = atan2(($endy*$bboxh), ($endx*$bboxw));
173
+ $ny = $coords[1] - (tan($b) * (1-$coords[0]));
174
+ $tx = sin($b) * cos($b) * $ny;
175
+ $ty = cos($b) * cos($b) * $ny;
176
+ $coords[2] = 1+$tx; $coords[3] = $ty;
177
+
178
+ }
179
+ }
180
+ }
181
+
182
+ // -moz If the first parameter is only an <angle>, the gradient axis starts from the box's corner that would ensure the
183
+ // axis goes through the box. The axis runs along the specified angle. The end point of the axis is defined such that the
184
+ // farthest corner of the box from the starting point is perpendicular to the gradient axis at that point.
185
+ // NO end points or Start points (Angle defined)
186
+ else if ($angle!==false && $coords[0]===false && $coords[1]===false) {
187
+ if ($angle==0 || $angle==360) { $coords[0]=0; $coords[1]=0; $coords[2]=1; $coords[3]=0; }
188
+ else if ($angle==90) { $coords[0]=0; $coords[1]=0; $coords[2]=0; $coords[3]=1; }
189
+ else if ($angle==180) { $coords[0]=1; $coords[1]=0; $coords[2]=0; $coords[3]=0; }
190
+ else if ($angle==270) { $coords[0]=0; $coords[1]=1; $coords[2]=0; $coords[3]=0; }
191
+ else {
192
+ if ($angle <=90) {
193
+ $coords[0]=0; $coords[1]=0;
194
+ if ($angle <=45) { $endx=1; $endy=tan(deg2rad($angle)); }
195
+ else { $endx=tan(deg2rad(90-$angle)); $endy=1; }
196
+ }
197
+ else if ($angle <=180) {
198
+ $coords[0]=1; $coords[1]=0;
199
+ if ($angle <=135) { $endx=tan(deg2rad($angle-90)); $endy=1; }
200
+ else { $endx=1; $endy=tan(deg2rad(180-$angle)); }
201
+ }
202
+ else if ($angle <=270) {
203
+ $coords[0]=1; $coords[1]=1;
204
+ if ($angle <=225) { $endx=1; $endy=tan(deg2rad($angle-180)); }
205
+ else { $endx=tan(deg2rad(270-$angle)); $endy=1; }
206
+ }
207
+ else {
208
+ $coords[0]=0; $coords[1]=1;
209
+ if ($angle <=315) { $endx=tan(deg2rad($angle-270)); $endy=1; }
210
+ else { $endx=1; $endy=tan(deg2rad(360-$angle)); }
211
+ }
212
+ $b = atan2(($endy*$bboxh), ($endx*$bboxw));
213
+ $h2 = $bboxh - ($bboxh * tan($b));
214
+ $px = $bboxh + ($h2 * sin($b) * cos($b));
215
+ $py = ($bboxh * tan($b)) + ($h2 * sin($b) * sin($b));
216
+ $x1 = $px / $bboxh;
217
+ $y1 = $py / $bboxh;
218
+ if ($angle <=90) { $coords[2] = $x1; $coords[3] = $y1; }
219
+ else if ($angle <=180) { $coords[2] = 1-$x1; $coords[3] = $y1; }
220
+ else if ($angle <=270) { $coords[2] = 1-$x1; $coords[3] = 1-$y1; }
221
+ else { $coords[2] = $x1; $coords[3] = 1-$y1; }
222
+ }
223
+ }
224
+ // -moz If the first parameter to the gradient function is only a <point>, the gradient axis starts from the specified point,
225
+ // 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
226
+ // gradient is to be applied to.
227
+ // NO angle and NO end points (Start points defined)
228
+ else if ((!isset($angle) || $angle===false) && $coords[0]!==false && $coords[1]!==false) { // should have start and end defined
229
+ $coords[2] = 1-$coords[0]; $coords[3] = 1-$coords[1];
230
+ $angle = rad2deg(atan2($coords[3]-$coords[1],$coords[2]-$coords[0]));
231
+ if ($angle < 0) { $angle += 360; }
232
+ else if ($angle > 360) { $angle -= 360; }
233
+ if ($angle!=0 && $angle!=360 && $angle!=90 && $angle!=180 && $angle!=270) {
234
+ if ($w >= $h) {
235
+ $coords[1] *= $h/$w ;
236
+ $coords[3] *= $h/$w ;
237
+ $usew = $useh = $bboxw;
238
+ $usey -= ($w-$h);
239
+ }
240
+ else {
241
+ $coords[0] *= $w/$h ;
242
+ $coords[2] *= $w/$h ;
243
+ $usew = $useh = $bboxh;
244
+ }
245
+ }
246
+ }
247
+
248
+ // -moz If neither a <point> or <angle> is specified, i.e. the entire function consists of only <stop> values, the gradient
249
+ // axis starts from the top of the box and runs vertically downwards, ending at the bottom of the box.
250
+ else { // default values T2B
251
+ // All values are set in parseMozGradient - so won't appear here
252
+ $coords = array(0,0,1,0); // default for original linear gradient (L2R)
253
+ }
254
+ $s = ' q';
255
+ $s .= sprintf(' %.3F %.3F %.3F %.3F re W n', $x*_MPDFK, ($this->mpdf->h-$y)*_MPDFK, $w*_MPDFK, -$h*_MPDFK)."\n";
256
+ $s .= sprintf(' %.3F 0 0 %.3F %.3F %.3F cm', $usew*_MPDFK, $useh*_MPDFK, $usex*_MPDFK, ($this->mpdf->h-($usey+$useh))*_MPDFK)."\n";
257
+ }
258
+
259
+ // RADIAL
260
+ else if ($type == 3) {
261
+ $radius = $coords[4];
262
+ $angle = $coords[5]; // ?? no effect
263
+ $shape = $coords[6];
264
+ $size = $coords[7];
265
+ $repeat = $coords[8];
266
+ // ALL POINTS AND RADIUS SET (default for custom mPDF radial gradient) - no -moz
267
+ if ($coords[0]!==false && $coords[1]!==false && $coords[2]!==false && $coords[3]!==false && $coords[4]!==false) {
268
+ // do nothing - coords used as they are
269
+ }
270
+ // If a <point> is defined
271
+ else if ($shape!==false && $size!==false) {
272
+ if ($coords[2]==false) { $coords[2] = $coords[0]; }
273
+ if ($coords[3]==false) { $coords[3] = $coords[1]; }
274
+ // ELLIPSE
275
+ if ($shape=='ellipse') {
276
+ $corner1 = sqrt(pow($coords[0],2) + pow($coords[1],2));
277
+ $corner2 = sqrt(pow($coords[0],2) + pow((1-$coords[1]),2));
278
+ $corner3 = sqrt(pow((1-$coords[0]),2) + pow($coords[1],2));
279
+ $corner4 = sqrt(pow((1-$coords[0]),2) + pow((1-$coords[1]),2));
280
+ if ($size=='closest-side') { $radius = min($coords[0], $coords[1], (1-$coords[0]), (1-$coords[1])); }
281
+ else if ($size=='closest-corner') { $radius = min($corner1, $corner2, $corner3, $corner4); }
282
+ else if ($size=='farthest-side') { $radius = max($coords[0], $coords[1], (1-$coords[0]), (1-$coords[1])); }
283
+ else { $radius = max($corner1, $corner2, $corner3, $corner4); } // farthest corner (default)
284
+ }
285
+ // CIRCLE
286
+ else if ($shape=='circle') {
287
+ if ($w >= $h) {
288
+ $coords[1] = $coords[3] = ($coords[1] * $h/$w) ;
289
+ $corner1 = sqrt(pow($coords[0],2) + pow($coords[1],2));
290
+ $corner2 = sqrt(pow($coords[0],2) + pow((($h/$w)-$coords[1]),2));
291
+ $corner3 = sqrt(pow((1-$coords[0]),2) + pow($coords[1],2));
292
+ $corner4 = sqrt(pow((1-$coords[0]),2) + pow((($h/$w)-$coords[1]),2));
293
+ if ($size=='closest-side') { $radius = min($coords[0], $coords[1], (1-$coords[0]), (($h/$w)-$coords[1])); }
294
+ else if ($size=='closest-corner') { $radius = min($corner1, $corner2, $corner3, $corner4); }
295
+ else if ($size=='farthest-side') { $radius = max($coords[0], $coords[1], (1-$coords[0]), (($h/$w)-$coords[1])); }
296
+ else if ($size=='farthest-corner') { $radius = max($corner1, $corner2, $corner3, $corner4); } // farthest corner (default)
297
+ $usew = $useh = $bboxw;
298
+ $usey -= ($w-$h);
299
+ }
300
+ else {
301
+ $coords[0] = $coords[2] = ($coords[0] * $w/$h) ;
302
+ $corner1 = sqrt(pow($coords[0],2) + pow($coords[1],2));
303
+ $corner2 = sqrt(pow($coords[0],2) + pow((1-$coords[1]),2));
304
+ $corner3 = sqrt(pow((($w/$h)-$coords[0]),2) + pow($coords[1],2));
305
+ $corner4 = sqrt(pow((($w/$h)-$coords[0]),2) + pow((1-$coords[1]),2));
306
+ if ($size=='closest-side') { $radius = min($coords[0], $coords[1], (($w/$h)-$coords[0]), (1-$coords[1])); }
307
+ else if ($size=='closest-corner') { $radius = min($corner1, $corner2, $corner3, $corner4); }
308
+ else if ($size=='farthest-side') { $radius = max($coords[0], $coords[1], (($w/$h)-$coords[0]), (1-$coords[1])); }
309
+ else if ($size=='farthest-corner') { $radius = max($corner1, $corner2, $corner3, $corner4); } // farthest corner (default)
310
+ $usew = $useh = $bboxh;
311
+ }
312
+ }
313
+ if ($radius==0) { $radius=0.001; } // to prevent error
314
+ $coords[4] = $radius;
315
+ }
316
+
317
+ // -moz If entire function consists of only <stop> values
318
+ else { // default values
319
+ // All values are set in parseMozGradient - so won't appear here
320
+ $coords = array(0.5,0.5,0.5,0.5); // default for radial gradient (centred)
321
+ }
322
+ $s = ' q';
323
+ $s .= sprintf(' %.3F %.3F %.3F %.3F re W n', $x*_MPDFK, ($this->mpdf->h-$y)*_MPDFK, $w*_MPDFK, -$h*_MPDFK)."\n";
324
+ $s .= sprintf(' %.3F 0 0 %.3F %.3F %.3F cm', $usew*_MPDFK, $useh*_MPDFK, $usex*_MPDFK, ($this->mpdf->h-($usey+$useh))*_MPDFK)."\n";
325
+ }
326
+
327
+ $n = count($this->mpdf->gradients) + 1;
328
+ $this->mpdf->gradients[$n]['type'] = $type;
329
+ $this->mpdf->gradients[$n]['colorspace'] = $colorspace;
330
+ $trans = false;
331
+ $this->mpdf->gradients[$n]['is_mask'] = $is_mask;
332
+ if ($is_mask) { $trans = true; }
333
+ if (count($stops) == 1) { $stops[1] = $stops[0]; }
334
+ if (!isset($stops[0]['offset'])) { $stops[0]['offset'] = 0; }
335
+ if (!isset($stops[(count($stops)-1)]['offset'])) { $stops[(count($stops)-1)]['offset'] = 1; }
336
+
337
+ // Fix stop-offsets set as absolute lengths
338
+ if ($type==2) {
339
+ $axisx = ($coords[2]-$coords[0])*$usew;
340
+ $axisy = ($coords[3]-$coords[1])*$useh;
341
+ $axis_length = sqrt(pow($axisx,2) + pow($axisy,2));
342
+ }
343
+ else { $axis_length = $coords[4]*$usew; } // Absolute lengths are meaningless for an ellipse - Firefox uses Width as reference
344
+
345
+ for($i=0;$i<count($stops);$i++) {
346
+ if (isset($stops[$i]['offset']) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$stops[$i]['offset'],$m)) {
347
+ $tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
348
+ $stops[$i]['offset'] = $tmp/$axis_length;
349
+ }
350
+ }
351
+
352
+
353
+ if (isset($stops[0]['offset']) && $stops[0]['offset']>0) {
354
+ $firststop = $stops[0];
355
+ $firststop['offset'] = 0;
356
+ array_unshift($stops, $firststop);
357
+ }
358
+ if (!$repeat && isset($stops[(count($stops)-1)]['offset']) && $stops[(count($stops)-1)]['offset']<1) {
359
+ $endstop = $stops[(count($stops)-1)];
360
+ $endstop['offset'] = 1;
361
+ $stops[] = $endstop;
362
+ }
363
+ if ($stops[0]['offset'] > $stops[(count($stops)-1)]['offset']) {
364
+ $stops[0]['offset'] = 0;
365
+ $stops[(count($stops)-1)]['offset'] = 1;
366
+ }
367
+
368
+ for($i=0;$i<count($stops);$i++) {
369
+ // mPDF 5.3.74
370
+ if ($colorspace == 'CMYK') {
371
+ $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));
372
+ }
373
+ else if ($colorspace == 'Gray') {
374
+ $this->mpdf->gradients[$n]['stops'][$i]['col'] = sprintf('%.3F', (ord($stops[$i]['col']{1})/255));
375
+ }
376
+ else {
377
+ $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));
378
+ }
379
+ if (!isset($stops[$i]['opacity'])) { $stops[$i]['opacity'] = 1; }
380
+ else if ($stops[$i]['opacity'] > 1 || $stops[$i]['opacity'] < 0) { $stops[$i]['opacity'] = 1; }
381
+ else if ($stops[$i]['opacity'] < 1) {
382
+ $trans = true;
383
+ }
384
+ $this->mpdf->gradients[$n]['stops'][$i]['opacity'] = $stops[$i]['opacity'];
385
+ // OFFSET
386
+ if ($i>0 && $i<(count($stops)-1)) {
387
+ if (!isset($stops[$i]['offset']) || (isset($stops[$i+1]['offset']) && $stops[$i]['offset']>$stops[$i+1]['offset']) || $stops[$i]['offset']<$stops[$i-1]['offset']) {
388
+ if (isset($stops[$i-1]['offset']) && isset($stops[$i+1]['offset'])) {
389
+ $stops[$i]['offset'] = ($stops[$i-1]['offset']+$stops[$i+1]['offset'])/2;
390
+ }
391
+ else {
392
+ for($j=($i+1);$j<count($stops);$j++) {
393
+ if(isset($stops[$j]['offset'])) { break; }
394
+ }
395
+ $int = ($stops[$j]['offset'] - $stops[($i-1)]['offset'])/($j-$i+1);
396
+ for($f=0;$f<($j-$i-1);$f++) {
397
+ $stops[($i+$f)]['offset'] = $stops[($i+$f-1)]['offset'] + ($int);
398
+ }
399
+ }
400
+ }
401
+ }
402
+ $this->mpdf->gradients[$n]['stops'][$i]['offset'] = $stops[$i]['offset'];
403
+ $this->mpdf->gradients[$n]['stops'][$i]['offset'] = $stops[$i]['offset'];
404
+ }
405
+
406
+ if ($repeat) {
407
+ $ns = count($this->mpdf->gradients[$n]['stops']);
408
+ $offs = array();
409
+ for($i=0;$i<$ns;$i++) {
410
+ $offs[$i] = $this->mpdf->gradients[$n]['stops'][$i]['offset'];
411
+ }
412
+ $gp = 0;
413
+ $inside=true;
414
+ while($inside) {
415
+ $gp++;
416
+ for($i=0;$i<$ns;$i++) {
417
+ $this->mpdf->gradients[$n]['stops'][(($ns*$gp)+$i)] = $this->mpdf->gradients[$n]['stops'][(($ns*($gp-1))+$i)];
418
+ $tmp = $this->mpdf->gradients[$n]['stops'][(($ns*($gp-1))+($ns-1))]['offset']+$offs[$i] ;
419
+ if ($tmp < 1) { $this->mpdf->gradients[$n]['stops'][(($ns*$gp)+$i)]['offset'] = $tmp; }
420
+ else {
421
+ $this->mpdf->gradients[$n]['stops'][(($ns*$gp)+$i)]['offset'] = 1;
422
+ $inside = false;
423
+ break(2);
424
+ }
425
+ }
426
+ }
427
+ }
428
+
429
+ if ($trans) {
430
+ $this->mpdf->gradients[$n]['trans'] = true;
431
+ $s .= ' /TGS'.$n.' gs ';
432
+ }
433
+ if (!is_array($extend) || count($extend) <1) {
434
+ $extend=array('true', 'true'); // These are supposed to be quoted - appear in PDF file as text
435
+ }
436
+ $this->mpdf->gradients[$n]['coords'] = $coords;
437
+ $this->mpdf->gradients[$n]['extend'] = $extend;
438
+ //paint the gradient
439
+ $s .= '/Sh'.$n.' sh '."\n";
440
+ //restore previous Graphic State
441
+ $s .= ' Q '."\n";
442
+ if ($return) { return $s; }
443
+ else { $this->mpdf->_out($s); }
444
+ }
445
+
446
+
447
+ function parseMozGradient($bg) {
448
+ // background[-image]: -moz-linear-gradient(left, #c7Fdde 20%, #FF0000 );
449
+ // background[-image]: linear-gradient(left, #c7Fdde 20%, #FF0000 ); // CSS3
450
+ if (preg_match('/repeating-/',$bg)) { $repeat = true; }
451
+ else { $repeat = false; }
452
+ if (preg_match('/linear-gradient\((.*)\)/',$bg,$m)) {
453
+ $g = array();
454
+ $g['type'] = 2;
455
+ $g['colorspace'] = 'RGB';
456
+ $g['extend'] = array('true','true');
457
+ $v = trim($m[1]);
458
+ // Change commas inside e.g. rgb(x,x,x)
459
+ while(preg_match('/(\([^\)]*?),/',$v)) { $v = preg_replace('/(\([^\)]*?),/','\\1@',$v); }
460
+ // Remove spaces inside e.g. rgb(x, x, x)
461
+ while(preg_match('/(\([^\)]*?)[ ]/',$v)) { $v = preg_replace('/(\([^\)]*?)[ ]/','\\1',$v); }
462
+ $bgr = preg_split('/\s*,\s*/',$v);
463
+ for($i=0;$i<count($bgr);$i++) { $bgr[$i] = preg_replace('/@/', ',', $bgr[$i]); }
464
+ // Is first part $bgr[0] a valid point/angle?
465
+ $first = preg_split('/\s+/',trim($bgr[0]));
466
+ if (preg_match('/(left|center|right|bottom|top|deg|grad|rad)/i',$bgr[0]) && !preg_match('/(<#|rgb|rgba|hsl|hsla)/i',$bgr[0])) {
467
+ $startStops = 1;
468
+ }
469
+ else if (trim($first[(count($first)-1)]) === "0") {
470
+ $startStops = 1;
471
+ }
472
+ else {
473
+ $check = $this->mpdf->ConvertColor($first[0]);
474
+ if ($check) $startStops = 0;
475
+ else $startStops = 1;
476
+ }
477
+ // first part a valid point/angle?
478
+ if ($startStops == 1) { // default values
479
+ // [<point> || <angle>,] = [<% em px left center right bottom top> || <deg grad rad 0>,]
480
+ if (preg_match('/([\-]*[0-9\.]+)(deg|grad|rad)/i',$bgr[0],$m)) {
481
+ $angle = $m[1] + 0;
482
+ if (strtolower($m[2])=='deg') { $angle = $angle; }
483
+ else if (strtolower($m[2])=='grad') { $angle *= (360/400); }
484
+ else if (strtolower($m[2])=='rad') { $angle = rad2deg($angle); }
485
+ while($angle < 0) { $angle += 360; }
486
+ $angle = ($angle % 360);
487
+ }
488
+ else if (trim($first[(count($first)-1)]) === "0") { $angle = 0; }
489
+ if (preg_match('/left/i',$bgr[0])) { $startx = 0; }
490
+ else if (preg_match('/right/i',$bgr[0])) { $startx = 1; }
491
+ if (preg_match('/top/i',$bgr[0])) { $starty = 1; }
492
+ else if (preg_match('/bottom/i',$bgr[0])) { $starty = 0; }
493
+ // Check for %? ?% or %%
494
+ if (preg_match('/(\d+)[%]/i',$first[0],$m)) { $startx = $m[1]/100; }
495
+ else if (!isset($startx) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$first[0],$m)) {
496
+ $tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
497
+ if ($tmp) { $startx = $m[1]; }
498
+ }
499
+ if (isset($first[1]) && preg_match('/(\d+)[%]/i',$first[1],$m)) { $starty = 1 - ($m[1]/100); }
500
+ else if (!isset($starty) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$first[1],$m)) {
501
+ $tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
502
+ if ($tmp) { $starty = $m[1]; }
503
+ }
504
+ if (isset($startx) && !isset($starty)) { $starty = 0.5; }
505
+ if (!isset($startx) && isset($starty)) { $startx = 0.5; }
506
+
507
+ }
508
+ // 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.
509
+ else { // default values T2B
510
+ $starty = 1; $startx = 0.5;
511
+ $endy = 0; $endx = 0.5;
512
+ }
513
+ $coords = array();
514
+ if (!isset($startx)) { $startx = false; }
515
+ if (!isset($starty)) { $starty = false; }
516
+ if (!isset($endx)) { $endx = false; }
517
+ if (!isset($endy)) { $endy = false; }
518
+ if (!isset($angle)) { $angle = false; }
519
+ $g['coords'] = array($startx ,$starty ,$endx ,$endy, $angle, $repeat );
520
+ $g['stops'] = array();
521
+ for($i=$startStops;$i<count($bgr);$i++) {
522
+ $stop = array();
523
+ // parse stops
524
+ $el = preg_split('/\s+/',trim($bgr[$i]));
525
+ // mPDF 5.3.74
526
+ $col = $this->mpdf->ConvertColor($el[0]);
527
+ if ($col) { $stop['col'] = $col; }
528
+ else { $stop['col'] = $col = $this->mpdf->ConvertColor(255); }
529
+ if ($col{0}==1) $g['colorspace'] = 'Gray';
530
+ else if ($col{0}==4 || $col{0}==6) $g['colorspace'] = 'CMYK';
531
+ if ($col{0}==5) { $stop['opacity'] = ord($col{4})/100; } // transparency from rgba()
532
+ else if ($col{0}==6) { $stop['opacity'] = ord($col{5})/100; } // transparency from cmyka()
533
+ else if ($col{0}==1 && $col{2}==1) { $stop['opacity'] = ord($col{3})/100; } // transparency converted from rgba or cmyka()
534
+
535
+ if (isset($el[1]) && preg_match('/(\d+)[%]/',$el[1],$m)) {
536
+ $stop['offset'] = $m[1]/100;
537
+ if ($stop['offset']>1) { unset($stop['offset']); }
538
+ }
539
+ else if (isset($el[1]) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$el[1],$m)) {
540
+ $tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
541
+ if ($tmp) { $stop['offset'] = $m[1]; }
542
+ }
543
+ $g['stops'][] = $stop;
544
+ }
545
+ if (count($g['stops'] )) { return $g; }
546
+ }
547
+ else if (preg_match('/radial-gradient\((.*)\)/',$bg,$m)) {
548
+ $g = array();
549
+ $g['type'] = 3;
550
+ $g['colorspace'] = 'RGB';
551
+ $g['extend'] = array('true','true');
552
+ $v = trim($m[1]);
553
+ // Change commas inside e.g. rgb(x,x,x)
554
+ while(preg_match('/(\([^\)]*?),/',$v)) { $v = preg_replace('/(\([^\)]*?),/','\\1@',$v); }
555
+ // Remove spaces inside e.g. rgb(x, x, x)
556
+ while(preg_match('/(\([^\)]*?)[ ]/',$v)) { $v = preg_replace('/(\([^\)]*?)[ ]/','\\1',$v); }
557
+ $bgr = preg_split('/\s*,\s*/',$v);
558
+ for($i=0;$i<count($bgr);$i++) { $bgr[$i] = preg_replace('/@/', ',', $bgr[$i]); }
559
+
560
+ // Is first part $bgr[0] a valid point/angle?
561
+ $startStops = 0;
562
+ $pos_angle = false;
563
+ $shape_size = false;
564
+ $first = preg_split('/\s+/',trim($bgr[0]));
565
+ $checkCol = $this->mpdf->ConvertColor($first[0]);
566
+ if (preg_match('/(left|center|right|bottom|top|deg|grad|rad)/i',$bgr[0]) && !preg_match('/(<#|rgb|rgba|hsl|hsla)/i',$bgr[0])) {
567
+ $startStops=1;
568
+ $pos_angle = $bgr[0];
569
+ }
570
+ else if (trim($first[(count($first)-1)]) === "0") {
571
+ $startStops=1;
572
+ $pos_angle = $bgr[0];
573
+ }
574
+ else if (preg_match('/(circle|ellipse|closest-side|closest-corner|farthest-side|farthest-corner|contain|cover)/i',$bgr[0])) {
575
+ $startStops=1;
576
+ $shape_size = $bgr[0];
577
+ }
578
+ else if (!$checkCol) {
579
+ $startStops=1;
580
+ $pos_angle = $bgr[0];
581
+ }
582
+ if (preg_match('/(circle|ellipse|closest-side|closest-corner|farthest-side|farthest-corner|contain|cover)/i',$bgr[1])) {
583
+ $startStops=2;
584
+ $shape_size = $bgr[1];
585
+ }
586
+
587
+ // If valid point/angle?
588
+ if ($pos_angle) { // default values
589
+ // [<point> || <angle>,] = [<% em px left center right bottom top> || <deg grad rad 0>,]
590
+ if (preg_match('/left/i',$pos_angle)) { $startx = 0; }
591
+ else if (preg_match('/right/i',$pos_angle)) { $startx = 1; }
592
+ if (preg_match('/top/i',$pos_angle)) { $starty = 1; }
593
+ else if (preg_match('/bottom/i',$pos_angle)) { $starty = 0; }
594
+ // Check for %? ?% or %%
595
+ if (preg_match('/(\d+)[%]/i',$first[0],$m)) { $startx = $m[1]/100; }
596
+ else if (!isset($startx) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$first[0],$m)) {
597
+ $tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
598
+ if ($tmp) { $startx = $m[1]; }
599
+ }
600
+ if (isset($first[1]) && preg_match('/(\d+)[%]/i',$first[1],$m)) { $starty = 1 - ($m[1]/100); }
601
+ else if (!isset($starty) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$first[1],$m)) {
602
+ $tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
603
+ if ($tmp) { $starty = $m[1]; }
604
+ }
605
+
606
+ /*
607
+ // ?? Angle has no effect in radial gradient (does not exist in CSS3 spec.)
608
+ if (preg_match('/([\-]*[0-9\.]+)(deg|grad|rad)/i',$pos_angle,$m)) {
609
+ $angle = $m[1] + 0;
610
+ if (strtolower($m[2])=='deg') { $angle = $angle; }
611
+ else if (strtolower($m[2])=='grad') { $angle *= (360/400); }
612
+ else if (strtolower($m[2])=='rad') { $angle = rad2deg($angle); }
613
+ while($angle < 0) { $angle += 360; }
614
+ $angle = ($angle % 360);
615
+ }
616
+ */
617
+ if (!isset($starty)) { $starty = 0.5; }
618
+ if (!isset($startx)) { $startx = 0.5; }
619
+
620
+ }
621
+ // 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.
622
+ else { // default values Center
623
+ $starty = 0.5; $startx = 0.5;
624
+ $endy = 0.5; $endx = 0.5;
625
+ }
626
+
627
+ // If valid shape/size?
628
+ $shape = 'ellipse'; // default
629
+ $size = 'farthest-corner'; // default
630
+ if ($shape_size) { // default values
631
+ if (preg_match('/(circle|ellipse)/i',$shape_size, $m)) {
632
+ $shape = $m[1];
633
+ }
634
+ if (preg_match('/(closest-side|closest-corner|farthest-side|farthest-corner|contain|cover)/i',$shape_size, $m)) {
635
+ $size = $m[1];
636
+ if ($size=='contain') { $size = 'closest-side'; }
637
+ else if ($size=='cover') { $size = 'farthest-corner'; }
638
+ }
639
+ }
640
+
641
+ $coords = array();
642
+ if (!isset($startx)) { $startx = false; }
643
+ if (!isset($starty)) { $starty = false; }
644
+ if (!isset($endx)) { $endx = false; }
645
+ if (!isset($endy)) { $endy = false; }
646
+ if (!isset($radius)) { $radius = false; }
647
+ if (!isset($angle)) { $angle = 0; }
648
+ $g['coords'] = array($startx ,$starty ,$endx ,$endy, $radius, $angle, $shape, $size, $repeat );
649
+
650
+ $g['stops'] = array();
651
+ for($i=$startStops;$i<count($bgr);$i++) {
652
+ $stop = array();
653
+ // parse stops
654
+ $el = preg_split('/\s+/',trim($bgr[$i]));
655
+ // mPDF 5.3.74
656
+ $col = $this->mpdf->ConvertColor($el[0]);
657
+ if ($col) { $stop['col'] = $col; }
658
+ else { $stop['col'] = $col = $this->mpdf->ConvertColor(255); }
659
+ if ($col{0}==1) $g['colorspace'] = 'Gray';
660
+ else if ($col{0}==4 || $col{0}==6) $g['colorspace'] = 'CMYK';
661
+ if ($col{0}==5) { $stop['opacity'] = ord($col{4})/100; } // transparency from rgba()
662
+ else if ($col{0}==6) { $stop['opacity'] = ord($col{5})/100; } // transparency from cmyka()
663
+ else if ($col{0}==1 && $col{2}==1) { $stop['opacity'] = ord($col{3})/100; } // transparency converted from rgba or cmyka()
664
+
665
+ if (isset($el[1]) && preg_match('/(\d+)[%]/',$el[1],$m)) {
666
+ $stop['offset'] = $m[1]/100;
667
+ if ($stop['offset']>1) { unset($stop['offset']); }
668
+ }
669
+ else if (isset($el[1]) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$el[1],$m)) {
670
+ $tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
671
+ $stop['offset'] = $el[1];
672
+ }
673
+ $g['stops'][] = $stop;
674
+ }
675
+ if (count($g['stops'] )) { return $g; }
676
+ }
677
+ return array();
678
+ }
679
+
680
+ function parseBackgroundGradient($bg) {
681
+ // background-gradient: linear #00FFFF #FFFF00 0 0.5 1 0.5; or
682
+ // background-gradient: radial #00FFFF #FFFF00 0.5 0.5 1 1 1.2;
683
+
684
+ $v = trim($bg);
685
+ $bgr = preg_split('/\s+/',$v);
686
+ $g = array();
687
+ if (count($bgr)> 6) {
688
+ if (strtoupper(substr($bgr[0],0,1)) == 'L' && count($bgr)==7) { // linear
689
+ $g['type'] = 2;
690
+ //$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
691
+ // Linear: $coords - array of the form (x1, y1, x2, y2) which defines the gradient vector (see linear_gradient_coords.jpg).
692
+ // The default value is from left to right (x1=0, y1=0, x2=1, y2=0).
693
+ $g['coords'] = array($bgr[3], $bgr[4], $bgr[5], $bgr[6]);
694
+ }
695
+ else if (count($bgr)==8) { // radial
696
+ $g['type'] = 3;
697
+ // Radial: $coords - array of the form (fx, fy, cx, cy, r) where (fx, fy) is the starting point of the gradient with color1,
698
+ // (cx, cy) is the center of the circle with color2, and r is the radius of the circle (see radial_gradient_coords.jpg).
699
+ // (fx, fy) should be inside the circle, otherwise some areas will not be defined
700
+ $g['coords'] = array($bgr[3], $bgr[4], $bgr[5], $bgr[6], $bgr[7]);
701
+ }
702
+ $g['colorspace'] = 'RGB';
703
+ // mPDF 5.3.74
704
+ $cor = $this->mpdf->ConvertColor($bgr[1]);
705
+ if ($cor{0}==1) $g['colorspace'] = 'Gray';
706
+ else if ($cor{0}==4 || $cor{0}==6) $g['colorspace'] = 'CMYK';
707
+ if ($cor) { $g['col'] = $cor; }
708
+ else { $g['col'] = $this->mpdf->ConvertColor(255); }
709
+ $cor = $this->mpdf->ConvertColor($bgr[2]);
710
+ if ($cor) { $g['col2'] = $cor; }
711
+ else { $g['col2'] = $this->mpdf->ConvertColor(255); }
712
+ $g['extend'] = array('true','true');
713
+ $g['stops'] = array(array('col'=>$g['col'], 'opacity'=>1, 'offset'=>0), array('col'=>$g['col2'], 'opacity'=>1, 'offset'=>1));
714
+ return $g;
715
+ }
716
+ return false;
717
+ }
718
+
719
+
720
+
721
+ }
722
+
723
+ ?>
mpdf/classes/ttfontsuni.php ADDED
@@ -0,0 +1,2065 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*******************************************************************************
4
+ * TTFontFile class *
5
+ * *
6
+ * Version: 2.01 *
7
+ * Date: 2012-02-25 *
8
+ * Author: Ian Back <ianb@bpm1.com> *
9
+ * License: LGPL *
10
+ * Copyright (c) Ian Back, 2010 *
11
+ * This class is based on The ReportLab Open Source PDF library *
12
+ * written in Python - http://www.reportlab.com/software/opensource/ *
13
+ * together with ideas from the OpenOffice source code and others. *
14
+ * This header must be retained in any redistribution or *
15
+ * modification of the file. *
16
+ * *
17
+ *******************************************************************************/
18
+
19
+ // Define the value used in the "head" table of a created TTF file
20
+ // 0x74727565 "true" for Mac
21
+ // 0x00010000 for Windows
22
+ // Either seems to work for a font embedded in a PDF file
23
+ // when read by Adobe Reader on a Windows PC(!)
24
+ if (!defined('_TTF_MAC_HEADER')) define("_TTF_MAC_HEADER", false);
25
+
26
+ // Recalculate correct metadata/profiles when making subset fonts (not SIP/SMP)
27
+ // e.g. xMin, xMax, maxNContours
28
+ if (!defined('_RECALC_PROFILE')) define("_RECALC_PROFILE", false);
29
+
30
+ // TrueType Font Glyph operators
31
+ define("GF_WORDS",(1 << 0));
32
+ define("GF_SCALE",(1 << 3));
33
+ define("GF_MORE",(1 << 5));
34
+ define("GF_XYSCALE",(1 << 6));
35
+ define("GF_TWOBYTWO",(1 << 7));
36
+
37
+
38
+
39
+ class TTFontFile {
40
+
41
+ var $unAGlyphs; // mPDF 5.4.05
42
+ var $panose;
43
+ var $maxUni;
44
+ var $sFamilyClass;
45
+ var $sFamilySubClass;
46
+ var $sipset;
47
+ var $smpset;
48
+ var $_pos;
49
+ var $numTables;
50
+ var $searchRange;
51
+ var $entrySelector;
52
+ var $rangeShift;
53
+ var $tables;
54
+ var $otables;
55
+ var $filename;
56
+ var $fh;
57
+ var $glyphPos;
58
+ var $charToGlyph;
59
+ var $ascent;
60
+ var $descent;
61
+ var $name;
62
+ var $familyName;
63
+ var $styleName;
64
+ var $fullName;
65
+ var $uniqueFontID;
66
+ var $unitsPerEm;
67
+ var $bbox;
68
+ var $capHeight;
69
+ var $stemV;
70
+ var $italicAngle;
71
+ var $flags;
72
+ var $underlinePosition;
73
+ var $underlineThickness;
74
+ var $charWidths;
75
+ var $defaultWidth;
76
+ var $maxStrLenRead;
77
+ var $numTTCFonts;
78
+ var $TTCFonts;
79
+ var $maxUniChar;
80
+ var $kerninfo;
81
+
82
+ function TTFontFile() {
83
+ $this->maxStrLenRead = 200000; // Maximum size of glyf table to read in as string (otherwise reads each glyph from file)
84
+ }
85
+
86
+
87
+ function getMetrics($file, $TTCfontID=0, $debug=false, $BMPonly=false, $kerninfo=false, $unAGlyphs=false) { // mPDF 5.4.05
88
+ $this->unAGlyphs = $unAGlyphs; // mPDF 5.4.05
89
+ $this->filename = $file;
90
+ $this->fh = fopen($file,'rb') or die('Can\'t open file ' . $file);
91
+ $this->_pos = 0;
92
+ $this->charWidths = '';
93
+ $this->glyphPos = array();
94
+ $this->charToGlyph = array();
95
+ $this->tables = array();
96
+ $this->otables = array();
97
+ $this->kerninfo = array();
98
+ $this->ascent = 0;
99
+ $this->descent = 0;
100
+ $this->numTTCFonts = 0;
101
+ $this->TTCFonts = array();
102
+ $this->version = $version = $this->read_ulong();
103
+ $this->panose = array();
104
+ if ($version==0x4F54544F)
105
+ die("Postscript outlines are not supported");
106
+ if ($version==0x74746366 && !$TTCfontID)
107
+ die("ERROR - You must define the TTCfontID for a TrueType Collection in config_fonts.php (". $file.")");
108
+ if (!in_array($version, array(0x00010000,0x74727565)) && !$TTCfontID)
109
+ die("Not a TrueType font: version=".$version);
110
+ if ($TTCfontID > 0) {
111
+ $this->version = $version = $this->read_ulong(); // TTC Header version now
112
+ if (!in_array($version, array(0x00010000,0x00020000)))
113
+ die("ERROR - Error parsing TrueType Collection: version=".$version." - " . $file);
114
+ $this->numTTCFonts = $this->read_ulong();
115
+ for ($i=1; $i<=$this->numTTCFonts; $i++) {
116
+ $this->TTCFonts[$i]['offset'] = $this->read_ulong();
117
+ }
118
+ $this->seek($this->TTCFonts[$TTCfontID]['offset']);
119
+ $this->version = $version = $this->read_ulong(); // TTFont version again now
120
+ }
121
+ $this->readTableDirectory($debug);
122
+ $this->extractInfo($debug, $BMPonly, $kerninfo);
123
+ fclose($this->fh);
124
+ }
125
+
126
+
127
+ function readTableDirectory($debug=false) {
128
+ $this->numTables = $this->read_ushort();
129
+ $this->searchRange = $this->read_ushort();
130
+ $this->entrySelector = $this->read_ushort();
131
+ $this->rangeShift = $this->read_ushort();
132
+ $this->tables = array();
133
+ for ($i=0;$i<$this->numTables;$i++) {
134
+ $record = array();
135
+ $record['tag'] = $this->read_tag();
136
+ $record['checksum'] = array($this->read_ushort(),$this->read_ushort());
137
+ $record['offset'] = $this->read_ulong();
138
+ $record['length'] = $this->read_ulong();
139
+ $this->tables[$record['tag']] = $record;
140
+ }
141
+ if ($debug) $this->checksumTables();
142
+ }
143
+
144
+ function checksumTables() {
145
+ // Check the checksums for all tables
146
+ foreach($this->tables AS $t) {
147
+ if ($t['length'] > 0 && $t['length'] < $this->maxStrLenRead) { // 1.02
148
+ $table = $this->get_chunk($t['offset'], $t['length']);
149
+ $checksum = $this->calcChecksum($table);
150
+ if ($t['tag'] == 'head') {
151
+ $up = unpack('n*', substr($table,8,4));
152
+ $adjustment[0] = $up[1];
153
+ $adjustment[1] = $up[2];
154
+ $checksum = $this->sub32($checksum, $adjustment);
155
+ }
156
+ $xchecksum = $t['checksum'];
157
+ if ($xchecksum != $checksum)
158
+ 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])));
159
+ }
160
+ }
161
+ }
162
+
163
+ function sub32($x, $y) {
164
+ $xlo = $x[1];
165
+ $xhi = $x[0];
166
+ $ylo = $y[1];
167
+ $yhi = $y[0];
168
+ if ($ylo > $xlo) { $xlo += 1 << 16; $yhi += 1; }
169
+ $reslo = $xlo-$ylo;
170
+ if ($yhi > $xhi) { $xhi += 1 << 16; }
171
+ $reshi = $xhi-$yhi;
172
+ $reshi = $reshi & 0xFFFF;
173
+ return array($reshi, $reslo);
174
+ }
175
+
176
+ function calcChecksum($data) {
177
+ if (strlen($data) % 4) { $data .= str_repeat("\0",(4-(strlen($data) % 4))); }
178
+ $len = strlen($data);
179
+ $hi=0x0000;
180
+ $lo=0x0000;
181
+ for($i=0;$i<$len;$i+=4) {
182
+ $hi += (ord($data[$i])<<8) + ord($data[$i+1]);
183
+ $lo += (ord($data[$i+2])<<8) + ord($data[$i+3]);
184
+ $hi += ($lo >> 16) & 0xFFFF;
185
+ $lo = $lo & 0xFFFF;
186
+ }
187
+ return array($hi, $lo);
188
+ }
189
+
190
+ function get_table_pos($tag) {
191
+ $offset = $this->tables[$tag]['offset'];
192
+ $length = $this->tables[$tag]['length'];
193
+ return array($offset, $length);
194
+ }
195
+
196
+ function seek($pos) {
197
+ $this->_pos = $pos;
198
+ fseek($this->fh,$this->_pos);
199
+ }
200
+
201
+ function skip($delta) {
202
+ $this->_pos = $this->_pos + $delta;
203
+ fseek($this->fh,$delta,SEEK_CUR);
204
+ }
205
+
206
+ function seek_table($tag, $offset_in_table = 0) {
207
+ $tpos = $this->get_table_pos($tag);
208
+ $this->_pos = $tpos[0] + $offset_in_table;
209
+ fseek($this->fh, $this->_pos);
210
+ return $this->_pos;
211
+ }
212
+
213
+ function read_tag() {
214
+ $this->_pos += 4;
215
+ return fread($this->fh,4);
216
+ }
217
+
218
+ function read_short() {
219
+ $this->_pos += 2;
220
+ $s = fread($this->fh,2);
221
+ $a = (ord($s[0])<<8) + ord($s[1]);
222
+ if ($a & (1 << 15) ) {
223
+ $a = ($a - (1 << 16));
224
+ }
225
+ return $a;
226
+ }
227
+
228
+ function unpack_short($s) {
229
+ $a = (ord($s[0])<<8) + ord($s[1]);
230
+ if ($a & (1 << 15) ) {
231
+ $a = ($a - (1 << 16));
232
+ }
233
+ return $a;
234
+ }
235
+
236
+ function read_ushort() {
237
+ $this->_pos += 2;
238
+ $s = fread($this->fh,2);
239
+ return (ord($s[0])<<8) + ord($s[1]);
240
+ }
241
+
242
+ function read_ulong() {
243
+ $this->_pos += 4;
244
+ $s = fread($this->fh,4);
245
+ // if large uInt32 as an integer, PHP converts it to -ve
246
+ return (ord($s[0])*16777216) + (ord($s[1])<<16) + (ord($s[2])<<8) + ord($s[3]); // 16777216 = 1<<24
247
+ }
248
+
249
+ function get_ushort($pos) {
250
+ fseek($this->fh,$pos);
251
+ $s = fread($this->fh,2);
252
+ return (ord($s[0])<<8) + ord($s[1]);
253
+ }
254
+
255
+ function get_ulong($pos) {
256
+ fseek($this->fh,$pos);
257
+ $s = fread($this->fh,4);
258
+ // iF large uInt32 as an integer, PHP converts it to -ve
259
+ return (ord($s[0])*16777216) + (ord($s[1])<<16) + (ord($s[2])<<8) + ord($s[3]); // 16777216 = 1<<24
260
+ }
261
+
262
+ function pack_short($val) {
263
+ if ($val<0) {
264
+ $val = abs($val);
265
+ $val = ~$val;
266
+ $val += 1;
267
+ }
268
+ return pack("n",$val);
269
+ }
270
+
271
+ function splice($stream, $offset, $value) {
272
+ return substr($stream,0,$offset) . $value . substr($stream,$offset+strlen($value));
273
+ }
274
+
275
+ function _set_ushort($stream, $offset, $value) {
276
+ $up = pack("n", $value);
277
+ return $this->splice($stream, $offset, $up);
278
+ }
279
+
280
+ function _set_short($stream, $offset, $val) {
281
+ if ($val<0) {
282
+ $val = abs($val);
283
+ $val = ~$val;
284
+ $val += 1;
285
+ }
286
+ $up = pack("n",$val);
287
+ return $this->splice($stream, $offset, $up);
288
+ }
289
+
290
+ function get_chunk($pos, $length) {
291
+ fseek($this->fh,$pos);
292
+ if ($length <1) { return ''; }
293
+ return (fread($this->fh,$length));
294
+ }
295
+
296
+ function get_table($tag) {
297
+ list($pos, $length) = $this->get_table_pos($tag);
298
+ if ($length == 0) { return ''; }
299
+ fseek($this->fh,$pos);
300
+ return (fread($this->fh,$length));
301
+ }
302
+
303
+ function add($tag, $data) {
304
+ if ($tag == 'head') {
305
+ $data = $this->splice($data, 8, "\0\0\0\0");
306
+ }
307
+ $this->otables[$tag] = $data;
308
+ }
309
+
310
+
311
+
312
+ /////////////////////////////////////////////////////////////////////////////////////////
313
+ function getCTG($file, $TTCfontID=0, $debug=false, $unAGlyphs=false) { // mPDF 5.4.05
314
+ $this->unAGlyphs = $unAGlyphs; // mPDF 5.4.05
315
+ $this->filename = $file;
316
+ $this->fh = fopen($file,'rb') or die('Can\'t open file ' . $file);
317
+ $this->_pos = 0;
318
+ $this->charWidths = '';
319
+ $this->glyphPos = array();
320
+ $this->charToGlyph = array();
321
+ $this->tables = array();
322
+ $this->numTTCFonts = 0;
323
+ $this->TTCFonts = array();
324
+ $this->skip(4);
325
+ if ($TTCfontID > 0) {
326
+ $this->version = $version = $this->read_ulong(); // TTC Header version now
327
+ if (!in_array($version, array(0x00010000,0x00020000)))
328
+ die("ERROR - Error parsing TrueType Collection: version=".$version." - " . $file);
329
+ $this->numTTCFonts = $this->read_ulong();
330
+ for ($i=1; $i<=$this->numTTCFonts; $i++) {
331
+ $this->TTCFonts[$i]['offset'] = $this->read_ulong();
332
+ }
333
+ $this->seek($this->TTCFonts[$TTCfontID]['offset']);
334
+ $this->version = $version = $this->read_ulong(); // TTFont version again now
335
+ }
336
+ $this->readTableDirectory($debug);
337
+
338
+
339
+ // cmap - Character to glyph index mapping table
340
+ $cmap_offset = $this->seek_table("cmap");
341
+ $this->skip(2);
342
+ $cmapTableCount = $this->read_ushort();
343
+ $unicode_cmap_offset = 0;
344
+ for ($i=0;$i<$cmapTableCount;$i++) {
345
+ $platformID = $this->read_ushort();
346
+ $encodingID = $this->read_ushort();
347
+ $offset = $this->read_ulong();
348
+ $save_pos = $this->_pos;
349
+ if ($platformID == 3 && $encodingID == 1) { // Microsoft, Unicode
350
+ $format = $this->get_ushort($cmap_offset + $offset);
351
+ if ($format == 4) {
352
+ $unicode_cmap_offset = $cmap_offset + $offset;
353
+ break;
354
+ }
355
+ }
356
+ else if ($platformID == 0) { // Unicode -- assume all encodings are compatible
357
+ $format = $this->get_ushort($cmap_offset + $offset);
358
+ if ($format == 4) {
359
+ $unicode_cmap_offset = $cmap_offset + $offset;
360
+ break;
361
+ }
362
+ }
363
+ $this->seek($save_pos );
364
+ }
365
+
366
+ $glyphToChar = array();
367
+ $charToGlyph = array();
368
+ $this->getCMAP4($unicode_cmap_offset, $glyphToChar, $charToGlyph );
369
+
370
+ fclose($this->fh);
371
+ return ($charToGlyph);
372
+ }
373
+
374
+ /////////////////////////////////////////////////////////////////////////////////////////
375
+ function getTTCFonts($file) {
376
+ $this->filename = $file;
377
+ $this->fh = fopen($file,'rb');
378
+ if (!$this->fh) { return ('ERROR - Can\'t open file ' . $file); }
379
+ $this->numTTCFonts = 0;
380
+ $this->TTCFonts = array();
381
+ $this->version = $version = $this->read_ulong();
382
+ if ($version==0x74746366) {
383
+ $this->version = $version = $this->read_ulong(); // TTC Header version now
384
+ if (!in_array($version, array(0x00010000,0x00020000)))
385
+ return("ERROR - Error parsing TrueType Collection: version=".$version." - " . $file);
386
+ }
387
+ else {
388
+ return("ERROR - Not a TrueType Collection: version=".$version." - " . $file);
389
+ }
390
+ $this->numTTCFonts = $this->read_ulong();
391
+ for ($i=1; $i<=$this->numTTCFonts; $i++) {
392
+ $this->TTCFonts[$i]['offset'] = $this->read_ulong();
393
+ }
394
+ }
395
+
396
+
397
+
398
+ /////////////////////////////////////////////////////////////////////////////////////////
399
+
400
+ /////////////////////////////////////////////////////////////////////////////////////////
401
+
402
+ function extractInfo($debug=false, $BMPonly=false, $kerninfo=false) {
403
+ $this->panose = array();
404
+ $this->sFamilyClass = 0;
405
+ $this->sFamilySubClass = 0;
406
+ ///////////////////////////////////
407
+ // name - Naming table
408
+ ///////////////////////////////////
409
+ $name_offset = $this->seek_table("name");
410
+ $format = $this->read_ushort();
411
+ if ($format != 0 && $format != 1)
412
+ die("Unknown name table format ".$format);
413
+ $numRecords = $this->read_ushort();
414
+ $string_data_offset = $name_offset + $this->read_ushort();
415
+ $names = array(1=>'',2=>'',3=>'',4=>'',6=>'');
416
+ $K = array_keys($names);
417
+ $nameCount = count($names);
418
+ for ($i=0;$i<$numRecords; $i++) {
419
+ $platformId = $this->read_ushort();
420
+ $encodingId = $this->read_ushort();
421
+ $languageId = $this->read_ushort();
422
+ $nameId = $this->read_ushort();
423
+ $length = $this->read_ushort();
424
+ $offset = $this->read_ushort();
425
+ if (!in_array($nameId,$K)) continue;
426
+ $N = '';
427
+ if ($platformId == 3 && $encodingId == 1 && $languageId == 0x409) { // Microsoft, Unicode, US English, PS Name
428
+ $opos = $this->_pos;
429
+ $this->seek($string_data_offset + $offset);
430
+ if ($length % 2 != 0)
431
+ die("PostScript name is UTF-16BE string of odd length");
432
+ $length /= 2;
433
+ $N = '';
434
+ while ($length > 0) {
435
+ $char = $this->read_ushort();
436
+ $N .= (chr($char));
437
+ $length -= 1;
438
+ }
439
+ $this->_pos = $opos;
440
+ $this->seek($opos);
441
+ }
442
+ else if ($platformId == 1 && $encodingId == 0 && $languageId == 0) { // Macintosh, Roman, English, PS Name
443
+ $opos = $this->_pos;
444
+ $N = $this->get_chunk($string_data_offset + $offset, $length);
445
+ $this->_pos = $opos;
446
+ $this->seek($opos);
447
+ }
448
+ if ($N && $names[$nameId]=='') {
449
+ $names[$nameId] = $N;
450
+ $nameCount -= 1;
451
+ if ($nameCount==0) break;
452
+ }
453
+ }
454
+ if ($names[6])
455
+ $psName = $names[6];
456
+ else if ($names[4])
457
+ $psName = preg_replace('/ /','-',$names[4]);
458
+ else if ($names[1])
459
+ $psName = preg_replace('/ /','-',$names[1]);
460
+ else
461
+ $psName = '';
462
+ if (!$psName)
463
+ die("Could not find PostScript font name: ".$this->filename);
464
+ if ($debug) {
465
+ for ($i=0;$i<count($psName);$i++) {
466
+ $c = $psName[$i];
467
+ $oc = ord($c);
468
+ if ($oc>126 || strpos(' [](){}<>/%',$c)!==false)
469
+ die("psName=".$psName." contains invalid character ".$c." ie U+".ord(c));
470
+ }
471
+ }
472
+ $this->name = $psName;
473
+ if ($names[1]) { $this->familyName = $names[1]; } else { $this->familyName = $psName; }
474
+ if ($names[2]) { $this->styleName = $names[2]; } else { $this->styleName = 'Regular'; }
475
+ if ($names[4]) { $this->fullName = $names[4]; } else { $this->fullName = $psName; }
476
+ if ($names[3]) { $this->uniqueFontID = $names[3]; } else { $this->uniqueFontID = $psName; }
477
+
478
+ if ($names[6]) { $this->fullName = $names[6]; }
479
+
480
+ ///////////////////////////////////
481
+ // head - Font header table
482
+ ///////////////////////////////////
483
+ $this->seek_table("head");
484
+ if ($debug) {
485
+ $ver_maj = $this->read_ushort();
486
+ $ver_min = $this->read_ushort();
487
+ if ($ver_maj != 1)
488
+ die('Unknown head table version '. $ver_maj .'.'. $ver_min);
489
+ $this->fontRevision = $this->read_ushort() . $this->read_ushort();
490
+
491
+ $this->skip(4);
492
+ $magic = $this->read_ulong();
493
+ if ($magic != 0x5F0F3CF5)
494
+ die('Invalid head table magic ' .$magic);
495
+ $this->skip(2);
496
+ }
497
+ else {
498
+ $this->skip(18);
499
+ }
500
+ $this->unitsPerEm = $unitsPerEm = $this->read_ushort();
501
+ $scale = 1000 / $unitsPerEm;
502
+ $this->skip(16);
503
+ $xMin = $this->read_short();
504
+ $yMin = $this->read_short();
505
+ $xMax = $this->read_short();
506
+ $yMax = $this->read_short();
507
+ $this->bbox = array(($xMin*$scale), ($yMin*$scale), ($xMax*$scale), ($yMax*$scale));
508
+ $this->skip(3*2);
509
+ $indexToLocFormat = $this->read_ushort();
510
+ $glyphDataFormat = $this->read_ushort();
511
+ if ($glyphDataFormat != 0)
512
+ die('Unknown glyph data format '.$glyphDataFormat);
513
+
514
+ ///////////////////////////////////
515
+ // hhea metrics table
516
+ ///////////////////////////////////
517
+ // ttf2t1 seems to use this value rather than the one in OS/2 - so put in for compatibility
518
+ if (isset($this->tables["hhea"])) {
519
+ $this->seek_table("hhea");
520
+ $this->skip(4);
521
+ $hheaAscender = $this->read_short();
522
+ $hheaDescender = $this->read_short();
523
+ $this->ascent = ($hheaAscender *$scale);
524
+ $this->descent = ($hheaDescender *$scale);
525
+ }
526
+
527
+ ///////////////////////////////////
528
+ // OS/2 - OS/2 and Windows metrics table
529
+ ///////////////////////////////////
530
+ if (isset($this->tables["OS/2"])) {
531
+ $this->seek_table("OS/2");
532
+ $version = $this->read_ushort();
533
+ $this->skip(2);
534
+ $usWeightClass = $this->read_ushort();
535
+ $this->skip(2);
536
+ $fsType = $this->read_ushort();
537
+ if ($fsType == 0x0002 || ($fsType & 0x0300) != 0) {
538
+ global $overrideTTFFontRestriction;
539
+ if (!$overrideTTFFontRestriction) die('ERROR - Font file '.$this->filename.' cannot be embedded due to copyright restrictions.');
540
+ $this->restrictedUse = true;
541
+ }
542
+ $this->skip(20);
543
+ $sF = $this->read_short();
544
+ $this->sFamilyClass = ($sF >> 8);
545
+ $this->sFamilySubClass = ($sF & 0xFF);
546
+ $this->_pos += 10; //PANOSE = 10 byte length
547
+ $panose = fread($this->fh,10);
548
+ $this->panose = array();
549
+ for ($p=0;$p<strlen($panose);$p++) { $this->panose[] = ord($panose[$p]); }
550
+ $this->skip(26);
551
+ $sTypoAscender = $this->read_short();
552
+ $sTypoDescender = $this->read_short();
553
+ if (!$this->ascent) $this->ascent = ($sTypoAscender*$scale);
554
+ if (!$this->descent) $this->descent = ($sTypoDescender*$scale);
555
+ if ($version > 1) {
556
+ $this->skip(16);
557
+ $sCapHeight = $this->read_short();
558
+ $this->capHeight = ($sCapHeight*$scale);
559
+ }
560
+ else {
561
+ $this->capHeight = $this->ascent;
562
+ }
563
+ }
564
+ else {
565
+ $usWeightClass = 500;
566
+ if (!$this->ascent) $this->ascent = ($yMax*$scale);
567
+ if (!$this->descent) $this->descent = ($yMin*$scale);
568
+ $this->capHeight = $this->ascent;
569
+ }
570
+ $this->stemV = 50 + intval(pow(($usWeightClass / 65.0),2));
571
+
572
+ ///////////////////////////////////
573
+ // post - PostScript table
574
+ ///////////////////////////////////
575
+ $this->seek_table("post");
576
+ if ($debug) {
577
+ $ver_maj = $this->read_ushort();
578
+ $ver_min = $this->read_ushort();
579
+ if ($ver_maj <1 || $ver_maj >4)
580
+ die('Unknown post table version '.$ver_maj);
581
+ }
582
+ else {
583
+ $this->skip(4);
584
+ }
585
+ $this->italicAngle = $this->read_short() + $this->read_ushort() / 65536.0;
586
+ $this->underlinePosition = $this->read_short() * $scale;
587
+ $this->underlineThickness = $this->read_short() * $scale;
588
+ $isFixedPitch = $this->read_ulong();
589
+
590
+ $this->flags = 4;
591
+
592
+ if ($this->italicAngle!= 0)
593
+ $this->flags = $this->flags | 64;
594
+ if ($usWeightClass >= 600)
595
+ $this->flags = $this->flags | 262144;
596
+ if ($isFixedPitch)
597
+ $this->flags = $this->flags | 1;
598
+
599
+ ///////////////////////////////////
600
+ // hhea - Horizontal header table
601
+ ///////////////////////////////////
602
+ $this->seek_table("hhea");
603
+ if ($debug) {
604
+ $ver_maj = $this->read_ushort();
605
+ $ver_min = $this->read_ushort();
606
+ if ($ver_maj != 1)
607
+ die('Unknown hhea table version '.$ver_maj);
608
+ $this->skip(28);
609
+ }
610
+ else {
611
+ $this->skip(32);
612
+ }
613
+ $metricDataFormat = $this->read_ushort();
614
+ if ($metricDataFormat != 0)
615
+ die('Unknown horizontal metric data format '.$metricDataFormat);
616
+ $numberOfHMetrics = $this->read_ushort();
617
+ if ($numberOfHMetrics == 0)
618
+ die('Number of horizontal metrics is 0');
619
+
620
+ ///////////////////////////////////
621
+ // maxp - Maximum profile table
622
+ ///////////////////////////////////
623
+ $this->seek_table("maxp");
624
+ if ($debug) {
625
+ $ver_maj = $this->read_ushort();
626
+ $ver_min = $this->read_ushort();
627
+ if ($ver_maj != 1)
628
+ die('Unknown maxp table version '.$ver_maj);
629
+ }
630
+ else {
631
+ $this->skip(4);
632
+ }
633
+ $numGlyphs = $this->read_ushort();
634
+
635
+
636
+ ///////////////////////////////////
637
+ // cmap - Character to glyph index mapping table
638
+ ///////////////////////////////////
639
+ $cmap_offset = $this->seek_table("cmap");
640
+ $this->skip(2);
641
+ $cmapTableCount = $this->read_ushort();
642
+ $unicode_cmap_offset = 0;
643
+ for ($i=0;$i<$cmapTableCount;$i++) {
644
+ $platformID = $this->read_ushort();
645
+ $encodingID = $this->read_ushort();
646
+ $offset = $this->read_ulong();
647
+ $save_pos = $this->_pos;
648
+ if (($platformID == 3 && $encodingID == 1) || $platformID == 0) { // Microsoft, Unicode
649
+ $format = $this->get_ushort($cmap_offset + $offset);
650
+ if ($format == 4) {
651
+ if (!$unicode_cmap_offset) $unicode_cmap_offset = $cmap_offset + $offset;
652
+ if ($BMPonly) break;
653
+ }
654
+ }
655
+ // Microsoft, Unicode Format 12 table HKCS
656
+ else if ((($platformID == 3 && $encodingID == 10) || $platformID == 0) && !$BMPonly) {
657
+ $format = $this->get_ushort($cmap_offset + $offset);
658
+ if ($format == 12) {
659
+ $unicode_cmap_offset = $cmap_offset + $offset;
660
+ break;
661
+ }
662
+ }
663
+ $this->seek($save_pos );
664
+ }
665
+ if (!$unicode_cmap_offset)
666
+ die('Font ('.$this->filename .') does not have cmap for Unicode (platform 3, encoding 1, format 4, or platform 0, any encoding, format 4)');
667
+
668
+
669
+ $sipset = false;
670
+ $smpset = false;
671
+ // Format 12 CMAP does characters above Unicode BMP i.e. some HKCS characters U+20000 and above
672
+ if ($format == 12 && !$BMPonly) {
673
+ $this->maxUniChar = 0;
674
+ $this->seek($unicode_cmap_offset + 4);
675
+ $length = $this->read_ulong();
676
+ $limit = $unicode_cmap_offset + $length;
677
+ $this->skip(4);
678
+
679
+ $nGroups = $this->read_ulong();
680
+
681
+ $glyphToChar = array();
682
+ $charToGlyph = array();
683
+ for($i=0; $i<$nGroups ; $i++) {
684
+ $startCharCode = $this->read_ulong();
685
+ $endCharCode = $this->read_ulong();
686
+ $startGlyphCode = $this->read_ulong();
687
+ if (($endCharCode > 0x20000 && $endCharCode < 0x2A6DF) || ($endCharCode > 0x2F800 && $endCharCode < 0x2FA1F)) {
688
+ $sipset = true;
689
+ }
690
+ else if ($endCharCode > 0x10000 && $endCharCode < 0x1FFFF) {
691
+ $smpset = true;
692
+ }
693
+ $offset = 0;
694
+ for ($unichar=$startCharCode;$unichar<=$endCharCode;$unichar++) {
695
+ $glyph = $startGlyphCode + $offset ;
696
+ $offset++;
697
+ $charToGlyph[$unichar] = $glyph;
698
+ if ($unichar < 196608) { $this->maxUniChar = max($unichar,$this->maxUniChar); }
699
+ $glyphToChar[$glyph][] = $unichar;
700
+ }
701
+ }
702
+ }
703
+ else {
704
+
705
+ $glyphToChar = array();
706
+ $charToGlyph = array();
707
+ $this->getCMAP4($unicode_cmap_offset, $glyphToChar, $charToGlyph );
708
+
709
+ }
710
+ $this->sipset = $sipset ;
711
+ $this->smpset = $smpset ;
712
+
713
+ ///////////////////////////////////
714
+ // hmtx - Horizontal metrics table
715
+ ///////////////////////////////////
716
+ $this->getHMTX($numberOfHMetrics, $numGlyphs, $glyphToChar, $scale);
717
+
718
+ ///////////////////////////////////
719
+ // kern - Kerning pair table
720
+ ///////////////////////////////////
721
+ if ($kerninfo) {
722
+ // Recognises old form of Kerning table - as required by Windows - Format 0 only
723
+ $kern_offset = $this->seek_table("kern");
724
+ $version = $this->read_ushort();
725
+ $nTables = $this->read_ushort();
726
+ // subtable header
727
+ $sversion = $this->read_ushort();
728
+ $slength = $this->read_ushort();
729
+ $scoverage = $this->read_ushort();
730
+ $format = $scoverage >> 8;
731
+ if ($kern_offset && $version==0 && $format==0) {
732
+ // Format 0
733
+ $nPairs = $this->read_ushort();
734
+ $this->skip(6);
735
+ for ($i=0; $i<$nPairs; $i++) {
736
+ $left = $this->read_ushort();
737
+ $right = $this->read_ushort();
738
+ $val = $this->read_short();
739
+ if (count($glyphToChar[$left])==1 && count($glyphToChar[$right])==1) {
740
+ if ($left != 32 && $right != 32) {
741
+ $this->kerninfo[$glyphToChar[$left][0]][$glyphToChar[$right][0]] = intval($val*$scale);
742
+ }
743
+ }
744
+ }
745
+ }
746
+ }
747
+ }
748
+
749
+
750
+ /////////////////////////////////////////////////////////////////////////////////////////
751
+
752
+
753
+ function makeSubset($file, &$subset, $TTCfontID=0, $debug=false, $unAGlyphs=false) { // mPDF 5.4.05
754
+ $this->unAGlyphs = $unAGlyphs; // mPDF 5.4.05
755
+ $this->filename = $file;
756
+ $this->fh = fopen($file ,'rb') or die('Can\'t open file ' . $file);
757
+ $this->_pos = 0;
758
+ $this->charWidths = '';
759
+ $this->glyphPos = array();
760
+ $this->charToGlyph = array();
761
+ $this->tables = array();
762
+ $this->otables = array();
763
+ $this->ascent = 0;
764
+ $this->descent = 0;
765
+ $this->numTTCFonts = 0;
766
+ $this->TTCFonts = array();
767
+ $this->skip(4);
768
+ $this->maxUni = 0;
769
+ if ($TTCfontID > 0) {
770
+ $this->version = $version = $this->read_ulong(); // TTC Header version now
771
+ if (!in_array($version, array(0x00010000,0x00020000)))
772
+ die("ERROR - Error parsing TrueType Collection: version=".$version." - " . $file);
773
+ $this->numTTCFonts = $this->read_ulong();
774
+ for ($i=1; $i<=$this->numTTCFonts; $i++) {
775
+ $this->TTCFonts[$i]['offset'] = $this->read_ulong();
776
+ }
777
+ $this->seek($this->TTCFonts[$TTCfontID]['offset']);
778
+ $this->version = $version = $this->read_ulong(); // TTFont version again now
779
+ }
780
+ $this->readTableDirectory($debug);
781
+
782
+ ///////////////////////////////////
783
+ // head - Font header table
784
+ ///////////////////////////////////
785
+ $this->seek_table("head");
786
+ $this->skip(50);
787
+ $indexToLocFormat = $this->read_ushort();
788
+ $glyphDataFormat = $this->read_ushort();
789
+
790
+ ///////////////////////////////////
791
+ // hhea - Horizontal header table
792
+ ///////////////////////////////////
793
+ $this->seek_table("hhea");
794
+ $this->skip(32);
795
+ $metricDataFormat = $this->read_ushort();
796
+ $orignHmetrics = $numberOfHMetrics = $this->read_ushort();
797
+
798
+ ///////////////////////////////////
799
+ // maxp - Maximum profile table
800
+ ///////////////////////////////////
801
+ $this->seek_table("maxp");
802
+ $this->skip(4);
803
+ $numGlyphs = $this->read_ushort();
804
+
805
+
806
+ ///////////////////////////////////
807
+ // cmap - Character to glyph index mapping table
808
+ ///////////////////////////////////
809
+ $cmap_offset = $this->seek_table("cmap");
810
+ $this->skip(2);
811
+ $cmapTableCount = $this->read_ushort();
812
+ $unicode_cmap_offset = 0;
813
+ for ($i=0;$i<$cmapTableCount;$i++) {
814
+ $platformID = $this->read_ushort();
815
+ $encodingID = $this->read_ushort();
816
+ $offset = $this->read_ulong();
817
+ $save_pos = $this->_pos;
818
+ if (($platformID == 3 && $encodingID == 1) || $platformID == 0) { // Microsoft, Unicode
819
+ $format = $this->get_ushort($cmap_offset + $offset);
820
+ if ($format == 4) {
821
+ $unicode_cmap_offset = $cmap_offset + $offset;
822
+ break;
823
+ }
824
+ }
825
+ $this->seek($save_pos );
826
+ }
827
+
828
+ if (!$unicode_cmap_offset)
829
+ die('Font ('.$this->filename .') does not have Unicode cmap (platform 3, encoding 1, format 4, or platform 0 [any encoding] format 4)');
830
+
831
+
832
+ $glyphToChar = array();
833
+ $charToGlyph = array();
834
+ $this->getCMAP4($unicode_cmap_offset, $glyphToChar, $charToGlyph );
835
+
836
+ $this->charToGlyph = $charToGlyph;
837
+
838
+
839
+ ///////////////////////////////////
840
+ // hmtx - Horizontal metrics table
841
+ ///////////////////////////////////
842
+ $scale = 1; // not used
843
+ $this->getHMTX($numberOfHMetrics, $numGlyphs, $glyphToChar, $scale);
844
+
845
+ ///////////////////////////////////
846
+ // loca - Index to location
847
+ ///////////////////////////////////
848
+ $this->getLOCA($indexToLocFormat, $numGlyphs);
849
+
850
+ $subsetglyphs = array(0=>0, 1=>1, 2=>2);
851
+ $subsetCharToGlyph = array();
852
+ foreach($subset AS $code) {
853
+ if (isset($this->charToGlyph[$code])) {
854
+ $subsetglyphs[$this->charToGlyph[$code]] = $code; // Old Glyph ID => Unicode
855
+ $subsetCharToGlyph[$code] = $this->charToGlyph[$code]; // Unicode to old GlyphID
856
+
857
+ }
858
+ $this->maxUni = max($this->maxUni, $code);
859
+ }
860
+
861
+ list($start,$dummy) = $this->get_table_pos('glyf');
862
+
863
+ $glyphSet = array();
864
+ ksort($subsetglyphs);
865
+ $n = 0;
866
+ $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.
867
+ foreach($subsetglyphs AS $originalGlyphIdx => $uni) {
868
+ $fsLastCharIndex = max($fsLastCharIndex , $uni);
869
+ $glyphSet[$originalGlyphIdx] = $n; // old glyphID to new glyphID
870
+ $n++;
871
+ }
872
+
873
+ ksort($subsetCharToGlyph);
874
+ foreach($subsetCharToGlyph AS $uni => $originalGlyphIdx) {
875
+ $codeToGlyph[$uni] = $glyphSet[$originalGlyphIdx] ;
876
+ }
877
+ $this->codeToGlyph = $codeToGlyph;
878
+
879
+ ksort($subsetglyphs);
880
+ foreach($subsetglyphs AS $originalGlyphIdx => $uni) {
881
+ $this->getGlyphs($originalGlyphIdx, $start, $glyphSet, $subsetglyphs);
882
+ }
883
+
884
+ $numGlyphs = $numberOfHMetrics = count($subsetglyphs );
885
+
886
+ ///////////////////////////////////
887
+ // name - table copied from the original
888
+ ///////////////////////////////////
889
+ $this->add('name', $this->get_table('name'));
890
+
891
+ ///////////////////////////////////
892
+ //tables copied from the original
893
+ ///////////////////////////////////
894
+ $tags = array ('cvt ', 'fpgm', 'prep', 'gasp');
895
+ foreach($tags AS $tag) {
896
+ if (isset($this->tables[$tag])) { $this->add($tag, $this->get_table($tag)); }
897
+ }
898
+
899
+ ///////////////////////////////////
900
+ // post - PostScript
901
+ ///////////////////////////////////
902
+ if (isset($this->tables['post'])) {
903
+ $opost = $this->get_table('post');
904
+ $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";
905
+ $this->add('post', $post);
906
+ }
907
+
908
+ ///////////////////////////////////
909
+ // Sort CID2GID map into segments of contiguous codes
910
+ ///////////////////////////////////
911
+ ksort($codeToGlyph);
912
+ unset($codeToGlyph[0]);
913
+ //unset($codeToGlyph[65535]);
914
+ $rangeid = 0;
915
+ $range = array();
916
+ $prevcid = -2;
917
+ $prevglidx = -1;
918
+ // for each character
919
+ foreach ($codeToGlyph as $cid => $glidx) {
920
+ if ($cid == ($prevcid + 1) && $glidx == ($prevglidx + 1)) {
921
+ $range[$rangeid][] = $glidx;
922
+ } else {
923
+ // new range
924
+ $rangeid = $cid;
925
+ $range[$rangeid] = array();
926
+ $range[$rangeid][] = $glidx;
927
+ }
928
+ $prevcid = $cid;
929
+ $prevglidx = $glidx;
930
+ }
931
+
932
+
933
+
934
+ ///////////////////////////////////
935
+ // CMap table
936
+ ///////////////////////////////////
937
+ // cmap - Character to glyph mapping
938
+ $segCount = count($range) + 1; // + 1 Last segment has missing character 0xFFFF
939
+ $searchRange = 1;
940
+ $entrySelector = 0;
941
+ while ($searchRange * 2 <= $segCount ) {
942
+ $searchRange = $searchRange * 2;
943
+ $entrySelector = $entrySelector + 1;
944
+ }
945
+ $searchRange = $searchRange * 2;
946
+ $rangeShift = $segCount * 2 - $searchRange;
947
+ $length = 16 + (8*$segCount ) + ($numGlyphs+1);
948
+ $cmap = array(0, 3, // Index : version, number of encoding subtables
949
+ 0, 0, // Encoding Subtable : platform (UNI=0), encoding 0
950
+ 0, 28, // Encoding Subtable : offset (hi,lo)
951
+ 0, 3, // Encoding Subtable : platform (UNI=0), encoding 3
952
+ 0, 28, // Encoding Subtable : offset (hi,lo)
953
+ 3, 1, // Encoding Subtable : platform (MS=3), encoding 1
954
+ 0, 28, // Encoding Subtable : offset (hi,lo)
955
+ 4, $length, 0, // Format 4 Mapping subtable: format, length, language
956
+ $segCount*2,
957
+ $searchRange,
958
+ $entrySelector,
959
+ $rangeShift);
960
+
961
+ // endCode(s)
962
+ foreach($range AS $start=>$subrange) {
963
+ $endCode = $start + (count($subrange)-1);
964
+ $cmap[] = $endCode; // endCode(s)
965
+ }
966
+ $cmap[] = 0xFFFF; // endCode of last Segment
967
+ $cmap[] = 0; // reservedPad
968
+
969
+ // startCode(s)
970
+ foreach($range AS $start=>$subrange) {
971
+ $cmap[] = $start; // startCode(s)
972
+ }
973
+ $cmap[] = 0xFFFF; // startCode of last Segment
974
+ // idDelta(s)
975
+ foreach($range AS $start=>$subrange) {
976
+ $idDelta = -($start-$subrange[0]);
977
+ $n += count($subrange);
978
+ $cmap[] = $idDelta; // idDelta(s)
979
+ }
980
+ $cmap[] = 1; // idDelta of last Segment
981
+ // idRangeOffset(s)
982
+ foreach($range AS $subrange) {
983
+ $cmap[] = 0; // idRangeOffset[segCount] Offset in bytes to glyph indexArray, or 0
984
+
985
+ }
986
+ $cmap[] = 0; // idRangeOffset of last Segment
987
+ foreach($range AS $subrange) {
988
+ foreach($subrange AS $glidx) {
989
+ $cmap[] = $glidx;
990
+ }
991
+ }
992
+ $cmap[] = 0; // Mapping for last character
993
+ $cmapstr = '';
994
+ foreach($cmap AS $cm) { $cmapstr .= pack("n",$cm); }
995
+ $this->add('cmap', $cmapstr);
996
+
997
+
998
+ ///////////////////////////////////
999
+ // glyf - Glyph data
1000
+ ///////////////////////////////////
1001
+ list($glyfOffset,$glyfLength) = $this->get_table_pos('glyf');
1002
+ if ($glyfLength < $this->maxStrLenRead) {
1003
+ $glyphData = $this->get_table('glyf');
1004
+ }
1005
+
1006
+ $offsets = array();
1007
+ $glyf = '';
1008
+ $pos = 0;
1009
+ $hmtxstr = '';
1010
+ $xMinT = 0;
1011
+ $yMinT = 0;
1012
+ $xMaxT = 0;
1013
+ $yMaxT = 0;
1014
+ $advanceWidthMax = 0;
1015
+ $minLeftSideBearing = 0;
1016
+ $minRightSideBearing = 0;
1017
+ $xMaxExtent = 0;
1018
+ $maxPoints = 0; // points in non-compound glyph
1019
+ $maxContours = 0; // contours in non-compound glyph
1020
+ $maxComponentPoints = 0; // points in compound glyph
1021
+ $maxComponentContours = 0; // contours in compound glyph
1022
+ $maxComponentElements = 0; // number of glyphs referenced at top level
1023
+ $maxComponentDepth = 0; // levels of recursion, set to 0 if font has only simple glyphs
1024
+ $this->glyphdata = array();
1025
+
1026
+ foreach($subsetglyphs AS $originalGlyphIdx => $uni) {
1027
+ // hmtx - Horizontal Metrics
1028
+ $hm = $this->getHMetric($orignHmetrics, $originalGlyphIdx);
1029
+ $hmtxstr .= $hm;
1030
+
1031
+ $offsets[] = $pos;
1032
+ $glyphPos = $this->glyphPos[$originalGlyphIdx];
1033
+ $glyphLen = $this->glyphPos[$originalGlyphIdx + 1] - $glyphPos;
1034
+ if ($glyfLength < $this->maxStrLenRead) {
1035
+ $data = substr($glyphData,$glyphPos,$glyphLen);
1036
+ }
1037
+ else {
1038
+ if ($glyphLen > 0) $data = $this->get_chunk($glyfOffset+$glyphPos,$glyphLen);
1039
+ else $data = '';
1040
+ }
1041
+
1042
+ if ($glyphLen > 0) {
1043
+ if (_RECALC_PROFILE) {
1044
+ $xMin = $this->unpack_short(substr($data,2,2));
1045
+ $yMin = $this->unpack_short(substr($data,4,2));
1046
+ $xMax = $this->unpack_short(substr($data,6,2));
1047
+ $yMax = $this->unpack_short(substr($data,8,2));
1048
+ $xMinT = min($xMinT,$xMin);
1049
+ $yMinT = min($yMinT,$yMin);
1050
+ $xMaxT = max($xMaxT,$xMax);
1051
+ $yMaxT = max($yMaxT,$yMax);
1052
+ $aw = $this->unpack_short(substr($hm,0,2));
1053
+ $lsb = $this->unpack_short(substr($hm,2,2));
1054
+ $advanceWidthMax = max($advanceWidthMax,$aw);
1055
+ $minLeftSideBearing = min($minLeftSideBearing,$lsb);
1056
+ $minRightSideBearing = min($minRightSideBearing,($aw - $lsb - ($xMax - $xMin)));
1057
+ $xMaxExtent = max($xMaxExtent,($lsb + ($xMax - $xMin)));
1058
+ }
1059
+ $up = unpack("n", substr($data,0,2));
1060
+ }
1061
+ if ($glyphLen > 2 && ($up[1] & (1 << 15)) ) { // If number of contours <= -1 i.e. composiste glyph
1062
+ $pos_in_glyph = 10;
1063
+ $flags = GF_MORE;
1064
+ $nComponentElements = 0;
1065
+ while ($flags & GF_MORE) {
1066
+ $nComponentElements += 1; // number of glyphs referenced at top level
1067
+ $up = unpack("n", substr($data,$pos_in_glyph,2));
1068
+ $flags = $up[1];
1069
+ $up = unpack("n", substr($data,$pos_in_glyph+2,2));
1070
+ $glyphIdx = $up[1];
1071
+ $this->glyphdata[$originalGlyphIdx]['compGlyphs'][] = $glyphIdx;
1072
+ $data = $this->_set_ushort($data, $pos_in_glyph + 2, $glyphSet[$glyphIdx]);
1073
+ $pos_in_glyph += 4;
1074
+ if ($flags & GF_WORDS) { $pos_in_glyph += 4; }
1075
+ else { $pos_in_glyph += 2; }
1076
+ if ($flags & GF_SCALE) { $pos_in_glyph += 2; }
1077
+ else if ($flags & GF_XYSCALE) { $pos_in_glyph += 4; }
1078
+ else if ($flags & GF_TWOBYTWO) { $pos_in_glyph += 8; }
1079
+ }
1080
+ $maxComponentElements = max($maxComponentElements, $nComponentElements);
1081
+ }
1082
+ // Simple Glyph
1083
+ else if (_RECALC_PROFILE && $glyphLen > 2 && $up[1] < (1 << 15) && $up[1] > 0) { // Number of contours > 0 simple glyph
1084
+ $nContours = $up[1];
1085
+ $this->glyphdata[$originalGlyphIdx]['nContours'] = $nContours;
1086
+ $maxContours = max($maxContours, $nContours);
1087
+
1088
+ // Count number of points in simple glyph
1089
+ $pos_in_glyph = 10 + ($nContours * 2) - 2; // Last endContourPoint
1090
+ $up = unpack("n", substr($data,$pos_in_glyph,2));
1091
+ $points = $up[1]+1;
1092
+ $this->glyphdata[$originalGlyphIdx]['nPoints'] = $points;
1093
+ $maxPoints = max($maxPoints, $points);
1094
+ }
1095
+
1096
+ $glyf .= $data;
1097
+ $pos += $glyphLen;
1098
+ if ($pos % 4 != 0) {
1099
+ $padding = 4 - ($pos % 4);
1100
+ $glyf .= str_repeat("\0",$padding);
1101
+ $pos += $padding;
1102
+ }
1103
+ }
1104
+
1105
+ if (_RECALC_PROFILE) {
1106
+ foreach($this->glyphdata AS $originalGlyphIdx => $val) {
1107
+ $maxdepth = $depth = -1;
1108
+ $points = 0;
1109
+ $contours = 0;
1110
+ $this->getGlyphData($originalGlyphIdx, $maxdepth, $depth, $points, $contours) ;
1111
+ $maxComponentDepth = max($maxComponentDepth , $maxdepth);
1112
+ $maxComponentPoints = max($maxComponentPoints , $points);
1113
+ $maxComponentContours = max($maxComponentContours , $contours);
1114
+ }
1115
+ }
1116
+
1117
+
1118
+ $offsets[] = $pos;
1119
+ $this->add('glyf', $glyf);
1120
+
1121
+ ///////////////////////////////////
1122
+ // hmtx - Horizontal Metrics
1123
+ ///////////////////////////////////
1124
+ $this->add('hmtx', $hmtxstr);
1125
+
1126
+
1127
+ ///////////////////////////////////
1128
+ // loca - Index to location
1129
+ ///////////////////////////////////
1130
+ $locastr = '';
1131
+ if ((($pos + 1) >> 1) > 0xFFFF) {
1132
+ $indexToLocFormat = 1; // long format
1133
+ foreach($offsets AS $offset) { $locastr .= pack("N",$offset); }
1134
+ }
1135
+ else {
1136
+ $indexToLocFormat = 0; // short format
1137
+ foreach($offsets AS $offset) { $locastr .= pack("n",($offset/2)); }
1138
+ }
1139
+ $this->add('loca', $locastr);
1140
+
1141
+ ///////////////////////////////////
1142
+ // head - Font header
1143
+ ///////////////////////////////////
1144
+ $head = $this->get_table('head');
1145
+ $head = $this->_set_ushort($head, 50, $indexToLocFormat);
1146
+ if (_RECALC_PROFILE) {
1147
+ $head = $this->_set_short($head, 36, $xMinT); // for all glyph bounding boxes
1148
+ $head = $this->_set_short($head, 38, $yMinT); // for all glyph bounding boxes
1149
+ $head = $this->_set_short($head, 40, $xMaxT); // for all glyph bounding boxes
1150
+ $head = $this->_set_short($head, 42, $yMaxT); // for all glyph bounding boxes
1151
+ $head[17] = chr($head[17] & ~(1 << 4)); // Unset Bit 4 (as hdmx/LTSH tables not included)
1152
+ }
1153
+ $this->add('head', $head);
1154
+
1155
+
1156
+ ///////////////////////////////////
1157
+ // hhea - Horizontal Header
1158
+ ///////////////////////////////////
1159
+ $hhea = $this->get_table('hhea');
1160
+ $hhea = $this->_set_ushort($hhea, 34, $numberOfHMetrics);
1161
+ if (_RECALC_PROFILE) {
1162
+ $hhea = $this->_set_ushort($hhea, 10, $advanceWidthMax);
1163
+ $hhea = $this->_set_short($hhea, 12, $minLeftSideBearing);
1164
+ $hhea = $this->_set_short($hhea, 14, $minRightSideBearing);
1165
+ $hhea = $this->_set_short($hhea, 16, $xMaxExtent);
1166
+ }
1167
+ $this->add('hhea', $hhea);
1168
+
1169
+ ///////////////////////////////////
1170
+ // maxp - Maximum Profile
1171
+ ///////////////////////////////////
1172
+ $maxp = $this->get_table('maxp');
1173
+ $maxp = $this->_set_ushort($maxp, 4, $numGlyphs);
1174
+ if (_RECALC_PROFILE) {
1175
+ $maxp = $this->_set_ushort($maxp, 6, $maxPoints); // points in non-compound glyph
1176
+ $maxp = $this->_set_ushort($maxp, 8, $maxContours); // contours in non-compound glyph
1177
+ $maxp = $this->_set_ushort($maxp, 10, $maxComponentPoints); // points in compound glyph
1178
+ $maxp = $this->_set_ushort($maxp, 12, $maxComponentContours); // contours in compound glyph
1179
+ $maxp = $this->_set_ushort($maxp, 28, $maxComponentElements); // number of glyphs referenced at top level
1180
+ $maxp = $this->_set_ushort($maxp, 30, $maxComponentDepth); // levels of recursion, set to 0 if font has only simple glyphs
1181
+ }
1182
+ $this->add('maxp', $maxp);
1183
+
1184
+
1185
+ ///////////////////////////////////
1186
+ // OS/2 - OS/2
1187
+ ///////////////////////////////////
1188
+ if (isset($this->tables['OS/2'])) {
1189
+ $os2_offset = $this->seek_table("OS/2");
1190
+ if (_RECALC_PROFILE) {
1191
+ $fsSelection = $this->get_ushort($os2_offset+62);
1192
+ $fsSelection = ($fsSelection & ~(1 << 6)); // 2-byte bit field containing information concerning the nature of the font patterns
1193
+ // bit#0 = Italic; bit#5=Bold
1194
+ // Match name table's font subfamily string
1195
+ // Clear bit#6 used for 'Regular' and optional
1196
+ }
1197
+
1198
+ // NB Currently this method never subsets characters above BMP
1199
+ // Could set nonBMP bit according to $this->maxUni
1200
+ $nonBMP = $this->get_ushort($os2_offset+46);
1201
+ $nonBMP = ($nonBMP & ~(1 << 9)); // Unset Bit 57 (indicates non-BMP) - for interactive forms
1202
+
1203
+ $os2 = $this->get_table('OS/2');
1204
+ if (_RECALC_PROFILE) {
1205
+ $os2 = $this->_set_ushort($os2, 62, $fsSelection);
1206
+ $os2 = $this->_set_ushort($os2, 66, $fsLastCharIndex);
1207
+ $os2 = $this->_set_ushort($os2, 42, 0x0000); // ulCharRange (ulUnicodeRange) bits 24-31 | 16-23
1208
+ $os2 = $this->_set_ushort($os2, 44, 0x0000); // ulCharRange (Unicode ranges) bits 8-15 | 0-7
1209
+ $os2 = $this->_set_ushort($os2, 46, $nonBMP); // ulCharRange (Unicode ranges) bits 56-63 | 48-55
1210
+ $os2 = $this->_set_ushort($os2, 48, 0x0000); // ulCharRange (Unicode ranges) bits 40-47 | 32-39
1211
+ $os2 = $this->_set_ushort($os2, 50, 0x0000); // ulCharRange (Unicode ranges) bits 88-95 | 80-87
1212
+ $os2 = $this->_set_ushort($os2, 52, 0x0000); // ulCharRange (Unicode ranges) bits 72-79 | 64-71
1213
+ $os2 = $this->_set_ushort($os2, 54, 0x0000); // ulCharRange (Unicode ranges) bits 120-127 | 112-119
1214
+ $os2 = $this->_set_ushort($os2, 56, 0x0000); // ulCharRange (Unicode ranges) bits 104-111 | 96-103
1215
+ }
1216
+ $os2 = $this->_set_ushort($os2, 46, $nonBMP); // Unset Bit 57 (indicates non-BMP) - for interactive forms
1217
+
1218
+ $this->add('OS/2', $os2 );
1219
+ }
1220
+
1221
+ fclose($this->fh);
1222
+ // Put the TTF file together
1223
+ $stm = '';
1224
+ $this->endTTFile($stm);
1225
+ //file_put_contents('testfont.ttf', $stm); exit;
1226
+ return $stm ;
1227
+ }
1228
+
1229
+ //================================================================================
1230
+
1231
+ // Also does SMP
1232
+ function makeSubsetSIP($file, &$subset, $TTCfontID=0, $debug=false) {
1233
+ $this->fh = fopen($file ,'rb') or die('Can\'t open file ' . $file);
1234
+ $this->filename = $file;
1235
+ $this->_pos = 0;
1236
+ $this->unAGlyphs = false; // mPDF 5.4.05
1237
+ $this->charWidths = '';
1238
+ $this->glyphPos = array();
1239
+ $this->charToGlyph = array();
1240
+ $this->tables = array();
1241
+ $this->otables = array();
1242
+ $this->ascent = 0;
1243
+ $this->descent = 0;
1244
+ $this->numTTCFonts = 0;
1245
+ $this->TTCFonts = array();
1246
+ $this->skip(4);
1247
+ if ($TTCfontID > 0) {
1248
+ $this->version = $version = $this->read_ulong(); // TTC Header version now
1249
+ if (!in_array($version, array(0x00010000,0x00020000)))
1250
+ die("ERROR - Error parsing TrueType Collection: version=".$version." - " . $file);
1251
+ $this->numTTCFonts = $this->read_ulong();
1252
+ for ($i=1; $i<=$this->numTTCFonts; $i++) {
1253
+ $this->TTCFonts[$i]['offset'] = $this->read_ulong();
1254
+ }
1255
+ $this->seek($this->TTCFonts[$TTCfontID]['offset']);
1256
+ $this->version = $version = $this->read_ulong(); // TTFont version again now
1257
+ }
1258
+ $this->readTableDirectory($debug);
1259
+
1260
+
1261
+
1262
+ ///////////////////////////////////
1263
+ // head - Font header table
1264
+ ///////////////////////////////////
1265
+ $this->seek_table("head");
1266
+ $this->skip(50);
1267
+ $indexToLocFormat = $this->read_ushort();
1268
+ $glyphDataFormat = $this->read_ushort();
1269
+
1270
+ ///////////////////////////////////
1271
+ // hhea - Horizontal header table
1272
+ ///////////////////////////////////
1273
+ $this->seek_table("hhea");
1274
+ $this->skip(32);
1275
+ $metricDataFormat = $this->read_ushort();
1276
+ $orignHmetrics = $numberOfHMetrics = $this->read_ushort();
1277
+
1278
+ ///////////////////////////////////
1279
+ // maxp - Maximum profile table
1280
+ ///////////////////////////////////
1281
+ $this->seek_table("maxp");
1282
+ $this->skip(4);
1283
+ $numGlyphs = $this->read_ushort();
1284
+
1285
+
1286
+ ///////////////////////////////////
1287
+ // cmap - Character to glyph index mapping table
1288
+ ///////////////////////////////////
1289
+
1290
+ $cmap_offset = $this->seek_table("cmap");
1291
+ $this->skip(2);
1292
+ $cmapTableCount = $this->read_ushort();
1293
+ $unicode_cmap_offset = 0;
1294
+ for ($i=0;$i<$cmapTableCount;$i++) {
1295
+ $platformID = $this->read_ushort();
1296
+ $encodingID = $this->read_ushort();
1297
+ $offset = $this->read_ulong();
1298
+ $save_pos = $this->_pos;
1299
+ if (($platformID == 3 && $encodingID == 10) || $platformID == 0) { // Microsoft, Unicode Format 12 table HKCS
1300
+ $format = $this->get_ushort($cmap_offset + $offset);
1301
+ if ($format == 12) {
1302
+ $unicode_cmap_offset = $cmap_offset + $offset;
1303
+ break;
1304
+ }
1305
+ }
1306
+ $this->seek($save_pos );
1307
+ }
1308
+
1309
+ if (!$unicode_cmap_offset)
1310
+ die('Font does not have cmap for Unicode (platform 3, encoding 1, format 4, or platform 0, any encoding, format 4)');
1311
+ // Format 12 CMAP does characters above Unicode BMP i.e. some HKCS characters U+20000 and above
1312
+ if ($format == 12) {
1313
+ $this->maxUniChar = 0;
1314
+ $this->seek($unicode_cmap_offset + 4);
1315
+ $length = $this->read_ulong();
1316
+ $limit = $unicode_cmap_offset + $length;
1317
+ $this->skip(4);
1318
+
1319
+ $nGroups = $this->read_ulong();
1320
+
1321
+ $glyphToChar = array();
1322
+ $charToGlyph = array();
1323
+ for($i=0; $i<$nGroups ; $i++) {
1324
+ $startCharCode = $this->read_ulong();
1325
+ $endCharCode = $this->read_ulong();
1326
+ $startGlyphCode = $this->read_ulong();
1327
+ $offset = 0;
1328
+ for ($unichar=$startCharCode;$unichar<=$endCharCode;$unichar++) {
1329
+ $glyph = $startGlyphCode + $offset ;
1330
+ $offset++;
1331
+ $charToGlyph[$unichar] = $glyph;
1332
+ if ($unichar < 196608) { $this->maxUniChar = max($unichar,$this->maxUniChar); }
1333
+ $glyphToChar[$glyph][] = $unichar;
1334
+ }
1335
+ }
1336
+ }
1337
+ else
1338
+ die('Font does not have cmap for Unicode (format 12)');
1339
+
1340
+
1341
+ ///////////////////////////////////
1342
+ // hmtx - Horizontal metrics table
1343
+ ///////////////////////////////////
1344
+ $scale = 1; // not used here
1345
+ $this->getHMTX($numberOfHMetrics, $numGlyphs, $glyphToChar, $scale);
1346
+
1347
+ ///////////////////////////////////
1348
+ // loca - Index to location
1349
+ ///////////////////////////////////
1350
+ $this->getLOCA($indexToLocFormat, $numGlyphs);
1351
+
1352
+ ///////////////////////////////////////////////////////////////////
1353
+
1354
+ $glyphMap = array(0=>0);
1355
+ $glyphSet = array(0=>0);
1356
+ $codeToGlyph = array();
1357
+ // Set a substitute if ASCII characters do not have glyphs
1358
+ if (isset($charToGlyph[0x3F])) { $subs = $charToGlyph[0x3F]; } // Question mark
1359
+ else { $subs = $charToGlyph[32]; }
1360
+ foreach($subset AS $code) {
1361
+ if (isset($charToGlyph[$code]))
1362
+ $originalGlyphIdx = $charToGlyph[$code];
1363
+ else if ($code<128) {
1364
+ $originalGlyphIdx = $subs;
1365
+ }
1366
+ else { $originalGlyphIdx = 0; }
1367
+ if (!isset($glyphSet[$originalGlyphIdx])) {
1368
+ $glyphSet[$originalGlyphIdx] = count($glyphMap);
1369
+ $glyphMap[] = $originalGlyphIdx;
1370
+ }
1371
+ $codeToGlyph[$code] = $glyphSet[$originalGlyphIdx];
1372
+ }
1373
+
1374
+ list($start,$dummy) = $this->get_table_pos('glyf');
1375
+
1376
+ $n = 0;
1377
+ while ($n < count($glyphMap)) {
1378
+ $originalGlyphIdx = $glyphMap[$n];
1379
+ $glyphPos = $this->glyphPos[$originalGlyphIdx];
1380
+ $glyphLen = $this->glyphPos[$originalGlyphIdx + 1] - $glyphPos;
1381
+ $n += 1;
1382
+ if (!$glyphLen) continue;
1383
+ $this->seek($start + $glyphPos);
1384
+ $numberOfContours = $this->read_short();
1385
+ if ($numberOfContours < 0) {
1386
+ $this->skip(8);
1387
+ $flags = GF_MORE;
1388
+ while ($flags & GF_MORE) {
1389
+ $flags = $this->read_ushort();
1390
+ $glyphIdx = $this->read_ushort();
1391
+ if (!isset($glyphSet[$glyphIdx])) {
1392
+ $glyphSet[$glyphIdx] = count($glyphMap);
1393
+ $glyphMap[] = $glyphIdx;
1394
+ }
1395
+ if ($flags & GF_WORDS)
1396
+ $this->skip(4);
1397
+ else
1398
+ $this->skip(2);
1399
+ if ($flags & GF_SCALE)
1400
+ $this->skip(2);
1401
+ else if ($flags & GF_XYSCALE)
1402
+ $this->skip(4);
1403
+ else if ($flags & GF_TWOBYTWO)
1404
+ $this->skip(8);
1405
+ }
1406
+ }
1407
+ }
1408
+
1409
+ $numGlyphs = $n = count($glyphMap);
1410
+ $numberOfHMetrics = $n;
1411
+
1412
+ ///////////////////////////////////
1413
+ // name
1414
+ ///////////////////////////////////
1415
+ // Needs to have a name entry in 3,0 (e.g. symbol) - original font will be 3,1 (i.e. Unicode)
1416
+ $name = $this->get_table('name');
1417
+ $name_offset = $this->seek_table("name");
1418
+ $format = $this->read_ushort();
1419
+ $numRecords = $this->read_ushort();
1420
+ $string_data_offset = $name_offset + $this->read_ushort();
1421
+ for ($i=0;$i<$numRecords; $i++) {
1422
+ $platformId = $this->read_ushort();
1423
+ $encodingId = $this->read_ushort();
1424
+ if ($platformId == 3 && $encodingId == 1) {
1425
+ $pos = 6 + ($i * 12) + 2;
1426
+ $name = $this->_set_ushort($name, $pos, 0x00); // Change encoding to 3,0 rather than 3,1
1427
+ }
1428
+ $this->skip(8);
1429
+ }
1430
+ $this->add('name', $name);
1431
+
1432
+ ///////////////////////////////////
1433
+ // OS/2
1434
+ ///////////////////////////////////
1435
+ if (isset($this->tables['OS/2'])) {
1436
+ $os2 = $this->get_table('OS/2');
1437
+ $os2 = $this->_set_ushort($os2, 42, 0x00); // ulCharRange (Unicode ranges)
1438
+ $os2 = $this->_set_ushort($os2, 44, 0x00); // ulCharRange (Unicode ranges)
1439
+ $os2 = $this->_set_ushort($os2, 46, 0x00); // ulCharRange (Unicode ranges)
1440
+ $os2 = $this->_set_ushort($os2, 48, 0x00); // ulCharRange (Unicode ranges)
1441
+
1442
+ $os2 = $this->_set_ushort($os2, 50, 0x00); // ulCharRange (Unicode ranges)
1443
+ $os2 = $this->_set_ushort($os2, 52, 0x00); // ulCharRange (Unicode ranges)
1444
+ $os2 = $this->_set_ushort($os2, 54, 0x00); // ulCharRange (Unicode ranges)
1445
+ $os2 = $this->_set_ushort($os2, 56, 0x00); // ulCharRange (Unicode ranges)
1446
+ // Set Symbol character only in ulCodePageRange
1447
+ $os2 = $this->_set_ushort($os2, 78, 0x8000); // ulCodePageRange = Bit #31 Symbol **** 78 = Bit 16-31
1448
+ $os2 = $this->_set_ushort($os2, 80, 0x0000); // ulCodePageRange = Bit #31 Symbol **** 80 = Bit 0-15
1449
+ $os2 = $this->_set_ushort($os2, 82, 0x0000); // ulCodePageRange = Bit #32- Symbol **** 82 = Bits 48-63
1450
+ $os2 = $this->_set_ushort($os2, 84, 0x0000); // ulCodePageRange = Bit #32- Symbol **** 84 = Bits 32-47
1451
+
1452
+ $os2 = $this->_set_ushort($os2, 64, 0x01); // FirstCharIndex
1453
+ $os2 = $this->_set_ushort($os2, 66, count($subset)); // LastCharIndex
1454
+ // Set PANOSE first bit to 5 for Symbol
1455
+ $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));
1456
+ $this->add('OS/2', $os2 );
1457
+ }
1458
+
1459
+
1460
+ ///////////////////////////////////
1461
+ //tables copied from the original
1462
+ ///////////////////////////////////
1463
+ $tags = array ('cvt ', 'fpgm', 'prep', 'gasp');
1464
+ foreach($tags AS $tag) { // 1.02
1465
+ if (isset($this->tables[$tag])) { $this->add($tag, $this->get_table($tag)); }
1466
+ }
1467
+
1468
+ ///////////////////////////////////
1469
+ // post - PostScript
1470
+ ///////////////////////////////////
1471
+ if (isset($this->tables['post'])) {
1472
+ $opost = $this->get_table('post');
1473
+ $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";
1474
+ }
1475
+ $this->add('post', $post);
1476
+
1477
+ ///////////////////////////////////
1478
+ // hhea - Horizontal Header
1479
+ ///////////////////////////////////
1480
+ $hhea = $this->get_table('hhea');
1481
+ $hhea = $this->_set_ushort($hhea, 34, $numberOfHMetrics);
1482
+ $this->add('hhea', $hhea);
1483
+
1484
+ ///////////////////////////////////
1485
+ // maxp - Maximum Profile
1486
+ ///////////////////////////////////
1487
+ $maxp = $this->get_table('maxp');
1488
+ $maxp = $this->_set_ushort($maxp, 4, $numGlyphs);
1489
+ $this->add('maxp', $maxp);
1490
+
1491
+
1492
+ ///////////////////////////////////
1493
+ // CMap table Formats [1,0,]6 and [3,0,]4
1494
+ ///////////////////////////////////
1495
+ ///////////////////////////////////
1496
+ // Sort CID2GID map into segments of contiguous codes
1497
+ ///////////////////////////////////
1498
+ $rangeid = 0;
1499
+ $range = array();
1500
+ $prevcid = -2;
1501
+ $prevglidx = -1;
1502
+ // for each character
1503
+ foreach ($subset as $cid => $code) {
1504
+ $glidx = $codeToGlyph[$code];
1505
+ if ($cid == ($prevcid + 1) && $glidx == ($prevglidx + 1)) {
1506
+ $range[$rangeid][] = $glidx;
1507
+ } else {
1508
+ // new range
1509
+ $rangeid = $cid;
1510
+ $range[$rangeid] = array();
1511
+ $range[$rangeid][] = $glidx;
1512
+ }
1513
+ $prevcid = $cid;
1514
+ $prevglidx = $glidx;
1515
+ }
1516
+ // cmap - Character to glyph mapping
1517
+ $segCount = count($range) + 1; // + 1 Last segment has missing character 0xFFFF
1518
+ $searchRange = 1;
1519
+ $entrySelector = 0;
1520
+ while ($searchRange * 2 <= $segCount ) {
1521
+ $searchRange = $searchRange * 2;
1522
+ $entrySelector = $entrySelector + 1;
1523
+ }
1524
+ $searchRange = $searchRange * 2;
1525
+ $rangeShift = $segCount * 2 - $searchRange;
1526
+ $length = 16 + (8*$segCount ) + ($numGlyphs+1);
1527
+ $cmap = array(
1528
+ 4, $length, 0, // Format 4 Mapping subtable: format, length, language
1529
+ $segCount*2,
1530
+ $searchRange,
1531
+ $entrySelector,
1532
+ $rangeShift);
1533
+
1534
+ // endCode(s)
1535
+ foreach($range AS $start=>$subrange) {
1536
+ $endCode = $start + (count($subrange)-1);
1537
+ $cmap[] = $endCode; // endCode(s)
1538
+ }
1539
+ $cmap[] = 0xFFFF; // endCode of last Segment
1540
+ $cmap[] = 0; // reservedPad
1541
+
1542
+ // startCode(s)
1543
+ foreach($range AS $start=>$subrange) {
1544
+ $cmap[] = $start; // startCode(s)
1545
+ }
1546
+ $cmap[] = 0xFFFF; // startCode of last Segment
1547
+ // idDelta(s)
1548
+ foreach($range AS $start=>$subrange) {
1549
+ $idDelta = -($start-$subrange[0]);
1550
+ $n += count($subrange);
1551
+ $cmap[] = $idDelta; // idDelta(s)
1552
+ }
1553
+ $cmap[] = 1; // idDelta of last Segment
1554
+ // idRangeOffset(s)
1555
+ foreach($range AS $subrange) {
1556
+ $cmap[] = 0; // idRangeOffset[segCount] Offset in bytes to glyph indexArray, or 0
1557
+
1558
+ }
1559
+ $cmap[] = 0; // idRangeOffset of last Segment
1560
+ foreach($range AS $subrange) {
1561
+ foreach($subrange AS $glidx) {
1562
+ $cmap[] = $glidx;
1563
+ }
1564
+ }
1565
+ $cmap[] = 0; // Mapping for last character
1566
+ $cmapstr4 = '';
1567
+ foreach($cmap AS $cm) { $cmapstr4 .= pack("n",$cm); }
1568
+
1569
+ ///////////////////////////////////
1570
+ // cmap - Character to glyph mapping
1571
+ ///////////////////////////////////
1572
+ $entryCount = count($subset);
1573
+ $length = 10 + $entryCount * 2;
1574
+
1575
+ $off = 20 + $length;
1576
+ $hoff = $off >> 16;
1577
+ $loff = $off & 0xFFFF;
1578
+
1579
+ $cmap = array(0, 2, // Index : version, number of subtables
1580
+ 1, 0, // Subtable : platform, encoding
1581
+ 0, 20, // offset (hi,lo)
1582
+ 3, 0, // Subtable : platform, encoding
1583
+ $hoff, $loff, // offset (hi,lo)
1584
+ 6, $length, // Format 6 Mapping table: format, length
1585
+ 0, 1, // language, First char code
1586
+ $entryCount
1587
+ );
1588
+ $cmapstr = '';
1589
+ foreach($subset AS $code) { $cmap[] = $codeToGlyph[$code]; }
1590
+ foreach($cmap AS $cm) { $cmapstr .= pack("n",$cm); }
1591
+ $cmapstr .= $cmapstr4;
1592
+ $this->add('cmap', $cmapstr);
1593
+
1594
+ ///////////////////////////////////
1595
+ // hmtx - Horizontal Metrics
1596
+ ///////////////////////////////////
1597
+ $hmtxstr = '';
1598
+ for($n=0;$n<$numGlyphs;$n++) {
1599
+ $originalGlyphIdx = $glyphMap[$n];
1600
+ $hm = $this->getHMetric($orignHmetrics, $originalGlyphIdx);
1601
+ $hmtxstr .= $hm;
1602
+ }
1603
+ $this->add('hmtx', $hmtxstr);
1604
+
1605
+ ///////////////////////////////////
1606
+ // glyf - Glyph data
1607
+ ///////////////////////////////////
1608
+ list($glyfOffset,$glyfLength) = $this->get_table_pos('glyf');
1609
+ if ($glyfLength < $this->maxStrLenRead) {
1610
+ $glyphData = $this->get_table('glyf');
1611
+ }
1612
+
1613
+ $offsets = array();
1614
+ $glyf = '';
1615
+ $pos = 0;
1616
+ for ($n=0;$n<$numGlyphs;$n++) {
1617
+ $offsets[] = $pos;
1618
+ $originalGlyphIdx = $glyphMap[$n];
1619
+ $glyphPos = $this->glyphPos[$originalGlyphIdx];
1620
+ $glyphLen = $this->glyphPos[$originalGlyphIdx + 1] - $glyphPos;
1621
+ if ($glyfLength < $this->maxStrLenRead) {
1622
+ $data = substr($glyphData,$glyphPos,$glyphLen);
1623
+ }
1624
+ else {
1625
+ if ($glyphLen > 0) $data = $this->get_chunk($glyfOffset+$glyphPos,$glyphLen);
1626
+ else $data = '';
1627
+ }
1628
+ if ($glyphLen > 0) $up = unpack("n", substr($data,0,2));
1629
+ if ($glyphLen > 2 && ($up[1] & (1 << 15)) ) {
1630
+ $pos_in_glyph = 10;
1631
+ $flags = GF_MORE;
1632
+ while ($flags & GF_MORE) {
1633
+ $up = unpack("n", substr($data,$pos_in_glyph,2));
1634
+ $flags = $up[1];
1635
+ $up = unpack("n", substr($data,$pos_in_glyph+2,2));
1636
+ $glyphIdx = $up[1];
1637
+ $data = $this->_set_ushort($data, $pos_in_glyph + 2, $glyphSet[$glyphIdx]);
1638
+ $pos_in_glyph += 4;
1639
+ if ($flags & GF_WORDS) { $pos_in_glyph += 4; }
1640
+ else { $pos_in_glyph += 2; }
1641
+ if ($flags & GF_SCALE) { $pos_in_glyph += 2; }
1642
+ else if ($flags & GF_XYSCALE) { $pos_in_glyph += 4; }
1643
+ else if ($flags & GF_TWOBYTWO) { $pos_in_glyph += 8; }
1644
+ }
1645
+ }
1646
+ $glyf .= $data;
1647
+ $pos += $glyphLen;
1648
+ if ($pos % 4 != 0) {
1649
+ $padding = 4 - ($pos % 4);
1650
+ $glyf .= str_repeat("\0",$padding);
1651
+ $pos += $padding;
1652
+ }
1653
+ }
1654
+ $offsets[] = $pos;
1655
+ $this->add('glyf', $glyf);
1656
+
1657
+ ///////////////////////////////////
1658
+ // loca - Index to location
1659
+ ///////////////////////////////////
1660
+ $locastr = '';
1661
+ if ((($pos + 1) >> 1) > 0xFFFF) {
1662
+ $indexToLocFormat = 1; // long format
1663
+ foreach($offsets AS $offset) { $locastr .= pack("N",$offset); }
1664
+ }
1665
+ else {
1666
+ $indexToLocFormat = 0; // short format
1667
+ foreach($offsets AS $offset) { $locastr .= pack("n",($offset/2)); }
1668
+ }
1669
+ $this->add('loca', $locastr);
1670
+
1671
+ ///////////////////////////////////
1672
+ // head - Font header
1673
+ ///////////////////////////////////
1674
+ $head = $this->get_table('head');
1675
+ $head = $this->_set_ushort($head, 50, $indexToLocFormat);
1676
+ $this->add('head', $head);
1677
+
1678
+ fclose($this->fh);
1679
+
1680
+ // Put the TTF file together
1681
+ $stm = '';
1682
+ $this->endTTFile($stm);
1683
+ //file_put_contents('testfont.ttf', $stm); exit;
1684
+ return $stm ;
1685
+ }
1686
+
1687
+ //////////////////////////////////////////////////////////////////////////////////
1688
+ // Recursively get composite glyph data
1689
+ function getGlyphData($originalGlyphIdx, &$maxdepth, &$depth, &$points, &$contours) {
1690
+ $depth++;
1691
+ $maxdepth = max($maxdepth, $depth);
1692
+ if (count($this->glyphdata[$originalGlyphIdx]['compGlyphs'])) {
1693
+ foreach($this->glyphdata[$originalGlyphIdx]['compGlyphs'] AS $glyphIdx) {
1694
+ $this->getGlyphData($glyphIdx, $maxdepth, $depth, $points, $contours);
1695
+ }
1696
+ }
1697
+ else if (($this->glyphdata[$originalGlyphIdx]['nContours'] > 0) && $depth > 0) { // simple
1698
+ $contours += $this->glyphdata[$originalGlyphIdx]['nContours'];
1699
+ $points += $this->glyphdata[$originalGlyphIdx]['nPoints'];
1700
+ }
1701
+ $depth--;
1702
+ }
1703
+
1704
+
1705
+ //////////////////////////////////////////////////////////////////////////////////
1706
+ // Recursively get composite glyphs
1707
+ function getGlyphs($originalGlyphIdx, &$start, &$glyphSet, &$subsetglyphs) {
1708
+ $glyphPos = $this->glyphPos[$originalGlyphIdx];
1709
+ $glyphLen = $this->glyphPos[$originalGlyphIdx + 1] - $glyphPos;
1710
+ if (!$glyphLen) {
1711
+ return;
1712
+ }
1713
+ $this->seek($start + $glyphPos);
1714
+ $numberOfContours = $this->read_short();
1715
+ if ($numberOfContours < 0) {
1716
+ $this->skip(8);
1717
+ $flags = GF_MORE;
1718
+ while ($flags & GF_MORE) {
1719
+ $flags = $this->read_ushort();
1720
+ $glyphIdx = $this->read_ushort();
1721
+ if (!isset($glyphSet[$glyphIdx])) {
1722
+ $glyphSet[$glyphIdx] = count($subsetglyphs); // old glyphID to new glyphID
1723
+ $subsetglyphs[$glyphIdx] = true;
1724
+ }
1725
+ $savepos = ftell($this->fh);
1726
+ $this->getGlyphs($glyphIdx, $start, $glyphSet, $subsetglyphs);
1727
+ $this->seek($savepos);
1728
+ if ($flags & GF_WORDS)
1729
+ $this->skip(4);
1730
+ else
1731
+ $this->skip(2);
1732
+ if ($flags & GF_SCALE)
1733
+ $this->skip(2);
1734
+ else if ($flags & GF_XYSCALE)
1735
+ $this->skip(4);
1736
+ else if ($flags & GF_TWOBYTWO)
1737
+ $this->skip(8);
1738
+ }
1739
+ }
1740
+ }
1741
+
1742
+ //////////////////////////////////////////////////////////////////////////////////
1743
+
1744
+ function getHMTX($numberOfHMetrics, $numGlyphs, &$glyphToChar, $scale) {
1745
+ $start = $this->seek_table("hmtx");
1746
+ $aw = 0;
1747
+ $this->charWidths = str_pad('', 256*256*2, "\x00");
1748
+ if ($this->maxUniChar > 65536) { $this->charWidths .= str_pad('', 256*256*2, "\x00"); } // Plane 1 SMP
1749
+ if ($this->maxUniChar > 131072) { $this->charWidths .= str_pad('', 256*256*2, "\x00"); } // Plane 2 SMP
1750
+ $nCharWidths = 0;
1751
+ if (($numberOfHMetrics*4) < $this->maxStrLenRead) {
1752
+ $data = $this->get_chunk($start,($numberOfHMetrics*4));
1753
+ $arr = unpack("n*", $data);
1754
+ }
1755
+ else { $this->seek($start); }
1756
+ for( $glyph=0; $glyph<$numberOfHMetrics; $glyph++) {
1757
+ if (($numberOfHMetrics*4) < $this->maxStrLenRead) {
1758
+ $aw = $arr[($glyph*2)+1];
1759
+ }
1760
+ else {
1761
+ $aw = $this->read_ushort();
1762
+ $lsb = $this->read_ushort();
1763
+ }
1764
+ if (isset($glyphToChar[$glyph]) || $glyph == 0) {
1765
+
1766
+ if ($aw >= (1 << 15) ) { $aw = 0; } // 1.03 Some (arabic) fonts have -ve values for width
1767
+ // although should be unsigned value - comes out as e.g. 65108 (intended -50)
1768
+ if ($glyph == 0) {
1769
+ $this->defaultWidth = $scale*$aw;
1770
+ continue;
1771
+ }
1772
+ foreach($glyphToChar[$glyph] AS $char) {
1773
+ //$this->charWidths[$char] = intval(round($scale*$aw));
1774
+ if ($char != 0 && $char != 65535) {
1775
+ $w = intval(round($scale*$aw));
1776
+ if ($w == 0) { $w = 65535; }
1777
+ if ($char < 196608) {
1778
+ $this->charWidths[$char*2] = chr($w >> 8);
1779
+ $this->charWidths[$char*2 + 1] = chr($w & 0xFF);
1780
+ $nCharWidths++;
1781
+ }
1782
+ }
1783
+ }
1784
+ }
1785
+ }
1786
+ $data = $this->get_chunk(($start+$numberOfHMetrics*4),($numGlyphs*2));
1787
+ $arr = unpack("n*", $data);
1788
+ $diff = $numGlyphs-$numberOfHMetrics;
1789
+ $w = intval(round($scale*$aw));
1790
+ if ($w == 0) { $w = 65535; }
1791
+ for( $pos=0; $pos<$diff; $pos++) {
1792
+ $glyph = $pos + $numberOfHMetrics;
1793
+ if (isset($glyphToChar[$glyph])) {
1794
+ foreach($glyphToChar[$glyph] AS $char) {
1795
+ if ($char != 0 && $char != 65535) {
1796
+ if ($char < 196608) {
1797
+ $this->charWidths[$char*2] = chr($w >> 8);
1798
+ $this->charWidths[$char*2 + 1] = chr($w & 0xFF);
1799
+ $nCharWidths++;
1800
+ }
1801
+ }
1802
+ }
1803
+ }
1804
+ }
1805
+ // NB 65535 is a set width of 0
1806
+ // First bytes define number of chars in font
1807
+ $this->charWidths[0] = chr($nCharWidths >> 8);
1808
+ $this->charWidths[1] = chr($nCharWidths & 0xFF);
1809
+ }
1810
+
1811
+ function getHMetric($numberOfHMetrics, $gid) {
1812
+ $start = $this->seek_table("hmtx");
1813
+ if ($gid < $numberOfHMetrics) {
1814
+ $this->seek($start+($gid*4));
1815
+ $hm = fread($this->fh,4);
1816
+ }
1817
+ else {
1818
+ $this->seek($start+(($numberOfHMetrics-1)*4));
1819
+ $hm = fread($this->fh,2);
1820
+ $this->seek($start+($numberOfHMetrics*2)+($gid*2));
1821
+ $hm .= fread($this->fh,2);
1822
+ }
1823
+ return $hm;
1824
+ }
1825
+
1826
+ function getLOCA($indexToLocFormat, $numGlyphs) {
1827
+ $start = $this->seek_table('loca');
1828
+ $this->glyphPos = array();
1829
+ if ($indexToLocFormat == 0) {
1830
+ $data = $this->get_chunk($start,($numGlyphs*2)+2);
1831
+ $arr = unpack("n*", $data);
1832
+ for ($n=0; $n<=$numGlyphs; $n++) {
1833
+ $this->glyphPos[] = ($arr[$n+1] * 2);
1834
+ }
1835
+ }
1836
+ else if ($indexToLocFormat == 1) {
1837
+ $data = $this->get_chunk($start,($numGlyphs*4)+4);
1838
+ $arr = unpack("N*", $data);
1839
+ for ($n=0; $n<=$numGlyphs; $n++) {
1840
+ $this->glyphPos[] = ($arr[$n+1]);
1841
+ }
1842
+ }
1843
+ else
1844
+ die('Unknown location table format '.$indexToLocFormat);
1845
+ }
1846
+
1847
+
1848
+ // CMAP Format 4
1849
+ function getCMAP4($unicode_cmap_offset, &$glyphToChar, &$charToGlyph ) {
1850
+ $this->maxUniChar = 0;
1851
+ $this->seek($unicode_cmap_offset + 2);
1852
+ $length = $this->read_ushort();
1853
+ $limit = $unicode_cmap_offset + $length;
1854
+ $this->skip(2);
1855
+
1856
+ $segCount = $this->read_ushort() / 2;
1857
+ $this->skip(6);
1858
+ $endCount = array();
1859
+ for($i=0; $i<$segCount; $i++) { $endCount[] = $this->read_ushort(); }
1860
+ $this->skip(2);
1861
+ $startCount = array();
1862
+ for($i=0; $i<$segCount; $i++) { $startCount[] = $this->read_ushort(); }
1863
+ $idDelta = array();
1864
+ for($i=0; $i<$segCount; $i++) { $idDelta[] = $this->read_short(); } // ???? was unsigned short
1865
+ $idRangeOffset_start = $this->_pos;
1866
+ $idRangeOffset = array();
1867
+ for($i=0; $i<$segCount; $i++) { $idRangeOffset[] = $this->read_ushort(); }
1868
+
1869
+ for ($n=0;$n<$segCount;$n++) {
1870
+ $endpoint = ($endCount[$n] + 1);
1871
+ for ($unichar=$startCount[$n];$unichar<$endpoint;$unichar++) {
1872
+ if ($idRangeOffset[$n] == 0)
1873
+ $glyph = ($unichar + $idDelta[$n]) & 0xFFFF;
1874
+ else {
1875
+ $offset = ($unichar - $startCount[$n]) * 2 + $idRangeOffset[$n];
1876
+ $offset = $idRangeOffset_start + 2 * $n + $offset;
1877
+ if ($offset >= $limit)
1878
+ $glyph = 0;
1879
+ else {
1880
+ $glyph = $this->get_ushort($offset);
1881
+ if ($glyph != 0)
1882
+ $glyph = ($glyph + $idDelta[$n]) & 0xFFFF;
1883
+ }
1884
+ }
1885
+ $charToGlyph[$unichar] = $glyph;
1886
+ if ($unichar < 196608) { $this->maxUniChar = max($unichar,$this->maxUniChar); }
1887
+ $glyphToChar[$glyph][] = $unichar;
1888
+ }
1889
+ }
1890
+
1891
+ // mPDF 5.4.05
1892
+ if ($this->unAGlyphs) {
1893
+ if (isset($this->tables['post'])) {
1894
+ $this->seek_table("post");
1895
+ $formata = $this->read_ushort();
1896
+ $formatb = $this->read_ushort();
1897
+ // Only works on Format 2.0
1898
+ if ($formata != 2 || $formatb != 0) { die("Cannot set unAGlyphs for this font (".$file."). POST table must be in Format 2."); }
1899
+ $this->skip(28);
1900
+ $nGlyfs = $this->read_ushort();
1901
+ $glyphNameIndex = array();
1902
+ for ($i=0; $i<$nGlyfs; $i++) {
1903
+ $glyphNameIndex[($this->read_ushort())] = $i;
1904
+ }
1905
+
1906
+ $opost = $this->get_table('post');
1907
+ $ptr = 34+($nGlyfs*2);
1908
+ for ($i=0; $i<$nGlyfs; $i++) {
1909
+ $len = ord(substr($opost,$ptr,1));
1910
+ $ptr++;
1911
+ $name = substr($opost,$ptr,$len);
1912
+ $gid = $glyphNameIndex[$i+258];
1913
+ // Select uni0600.xxx(x) - uni06FF.xxx(x)
1914
+ if (preg_match('/^uni(06[0-9a-f]{2})\.(fina|medi|init|fin|med|ini)$/i',$name,$m)) {
1915
+ if (!isset($glyphToChar[$gid]) || (isset($glyphToChar[$gid]) && is_array($glyphToChar[$gid]) && count($glyphToChar[$gid])==1 && $glyphToChar[$gid][0]>57343 && $glyphToChar[$gid][0]<63489)) { // if set in PUA private use area E000-F8FF, or NOT Unicode mapped
1916
+ $uni = hexdec($m[1]);
1917
+ $form = strtoupper(substr($m[2],0,1));
1918
+ // Assign new PUA Unicode between F500 - F7FF
1919
+ $bit = $uni & 0xFF;
1920
+ if ($form == 'I') { $bit += 0xF600; }
1921
+ else if ($form == 'M') { $bit += 0xF700; }
1922
+ else { $bit += 0xF500; }
1923
+ // ADD TO CMAP
1924
+ $glyphToChar[$gid][] = $bit;
1925
+ $charToGlyph[$bit] = $gid;
1926
+ }
1927
+ }
1928
+ // LAM with ALEF ligatures (Mandatory ligatures)
1929
+ else if (preg_match('/^uni064406(22|23|25|27)(\.fina|\.fin){0,1}$/i',$name,$m)) {
1930
+ if ($m[1]=='22') {
1931
+ if ($m[2]) { $uni = hexdec('FEF6'); } else { $uni = hexdec('FEF5'); }
1932
+ }
1933
+ else if ($m[1]=='23') {
1934
+ if ($m[2]) { $uni = hexdec('FEF8'); } else { $uni = hexdec('FEF7'); }
1935
+ }
1936
+ else if ($m[1]=='25') {
1937
+ if ($m[2]) { $uni = hexdec('FEFA'); } else { $uni = hexdec('FEF9'); }
1938
+ }
1939
+ else if ($m[1]=='27') {
1940
+ if ($m[2]) { $uni = hexdec('FEFC'); } else { $uni = hexdec('FEFB'); }
1941
+ }
1942
+ if (!isset($glyphToChar[$gid]) || (isset($glyphToChar[$gid]) && is_array($glyphToChar[$gid]) && count($glyphToChar[$gid])==1 && $glyphToChar[$gid][0]>57343 && $glyphToChar[$gid][0]<63489)) { // if set in PUA private use area E000-F8FF, or NOT Unicode mapped
1943
+ // ADD TO CMAP
1944
+ $glyphToChar[$gid][] = $uni;
1945
+ $charToGlyph[$uni] = $gid;
1946
+ }
1947
+ }
1948
+ $ptr += $len;
1949
+ }
1950
+ }
1951
+ }
1952
+
1953
+ }
1954
+
1955
+
1956
+ // Put the TTF file together
1957
+ function endTTFile(&$stm) {
1958
+ $stm = '';
1959
+ $numTables = count($this->otables);
1960
+ $searchRange = 1;
1961
+ $entrySelector = 0;
1962
+ while ($searchRange * 2 <= $numTables) {
1963
+ $searchRange = $searchRange * 2;
1964
+ $entrySelector = $entrySelector + 1;
1965
+ }
1966
+ $searchRange = $searchRange * 16;
1967
+ $rangeShift = $numTables * 16 - $searchRange;
1968
+
1969
+ // Header
1970
+ if (_TTF_MAC_HEADER) {
1971
+ $stm .= (pack("Nnnnn", 0x74727565, $numTables, $searchRange, $entrySelector, $rangeShift)); // Mac
1972
+ }
1973
+ else {
1974
+ $stm .= (pack("Nnnnn", 0x00010000 , $numTables, $searchRange, $entrySelector, $rangeShift)); // Windows
1975
+ }
1976
+
1977
+ // Table directory
1978
+ $tables = $this->otables;
1979
+ ksort ($tables);
1980
+ $offset = 12 + $numTables * 16;
1981
+ foreach ($tables AS $tag=>$data) {
1982
+ if ($tag == 'head') { $head_start = $offset; }
1983
+ $stm .= $tag;
1984
+ $checksum = $this->calcChecksum($data);
1985
+ $stm .= pack("nn", $checksum[0],$checksum[1]);
1986
+ $stm .= pack("NN", $offset, strlen($data));
1987
+ $paddedLength = (strlen($data)+3)&~3;
1988
+ $offset = $offset + $paddedLength;
1989
+ }
1990
+
1991
+ // Table data
1992
+ foreach ($tables AS $tag=>$data) {
1993
+ $data .= "\0\0\0";
1994
+ $stm .= substr($data,0,(strlen($data)&~3));
1995
+ }
1996
+
1997
+ $checksum = $this->calcChecksum($stm);
1998
+ $checksum = $this->sub32(array(0xB1B0,0xAFBA), $checksum);
1999
+ $chk = pack("nn", $checksum[0],$checksum[1]);
2000
+ $stm = $this->splice($stm,($head_start + 8),$chk);
2001
+ return $stm ;
2002
+ }
2003
+
2004
+
2005
+ function repackageTTF($file, $TTCfontID=0, $debug=false, $unAGlyphs=false) { // mPDF 5.4.05
2006
+ $this->unAGlyphs = $unAGlyphs; // mPDF 5.4.05
2007
+ $this->filename = $file;
2008
+ $this->fh = fopen($file ,'rb') or die('Can\'t open file ' . $file);
2009
+ $this->_pos = 0;
2010
+ $this->charWidths = '';
2011
+ $this->glyphPos = array();
2012
+ $this->charToGlyph = array();
2013
+ $this->tables = array();
2014
+ $this->otables = array();
2015
+ $this->ascent = 0;
2016
+ $this->descent = 0;
2017
+ $this->numTTCFonts = 0;
2018
+ $this->TTCFonts = array();
2019
+ $this->skip(4);
2020
+ $this->maxUni = 0;
2021
+ if ($TTCfontID > 0) {
2022
+ $this->version = $version = $this->read_ulong(); // TTC Header version now
2023
+ if (!in_array($version, array(0x00010000,0x00020000)))
2024
+ die("ERROR - Error parsing TrueType Collection: version=".$version." - " . $file);
2025
+ $this->numTTCFonts = $this->read_ulong();
2026
+ for ($i=1; $i<=$this->numTTCFonts; $i++) {
2027
+ $this->TTCFonts[$i]['offset'] = $this->read_ulong();
2028
+ }
2029
+ $this->seek($this->TTCFonts[$TTCfontID]['offset']);
2030
+ $this->version = $version = $this->read_ulong(); // TTFont version again now
2031
+ }
2032
+ $this->readTableDirectory($debug);
2033
+ $tags = array ('OS/2', 'cmap', 'glyf', 'head', 'hhea', 'hmtx', 'loca', 'maxp', 'name', 'post', 'cvt ', 'fpgm', 'gasp', 'prep');
2034
+ /*
2035
+ Tables which require glyphIndex
2036
+ hdmx
2037
+ kern
2038
+ LTSH
2039
+
2040
+ Tables which do NOT require glyphIndex
2041
+ VDMX
2042
+
2043
+ GDEF
2044
+ GPOS
2045
+ GSUB
2046
+ JSTF
2047
+
2048
+ DSIG
2049
+ PCLT - not recommended
2050
+ */
2051
+
2052
+ foreach($tags AS $tag) {
2053
+ if (isset($this->tables[$tag])) { $this->add($tag, $this->get_table($tag)); }
2054
+ }
2055
+ fclose($this->fh);
2056
+ $stm = '';
2057
+ $this->endTTFile($stm);
2058
+ return $stm ;
2059
+ }
2060
+
2061
+
2062
+ }
2063
+
2064
+
2065
+ ?>
mpdf/config.php ADDED
@@ -0,0 +1,572 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // mPDF 5.7
4
+ // Specify whether to automatically generate bookmarks or ToC entries from h1 - h6 tags
5
+ $this->h2bookmarks = array();
6
+ $this->h2toc = array();
7
+ /* Define arrays with e.g. the tag=>ToC-level
8
+ Remember bookmark and ToC levels start at 0
9
+ (does not work inside tables)
10
+ Only the default ToC will be used if > 1 ToCs are defined for the document
11
+ H1 - H6 must be uppercase
12
+ $this->h2toc = array('H1'=>0, 'H2'=>1, 'H3'=>2);
13
+ $this->h2bookmarks = array('H1'=>0, 'H2'=>1, 'H3'=>2);
14
+ */
15
+
16
+ // mPDF 5.7
17
+ // Text-align on decimal marks
18
+ // Allowed characters for alignment on decimal marks. Additional codes must start with D
19
+ // Non-ASCII characters should be in utf-8 encoding
20
+ // DM - middot U+00B7
21
+ // DA - arabic decimal mark U+066B
22
+ $this->decimal_align = array('DP'=>'.', 'DC'=>',', 'DM'=>"\xc2\xb7", 'DA'=>"\xd9\xab", 'DD'=>'-');
23
+
24
+ // PAGING
25
+ $this->mirrorMargins = 0;
26
+ $this->restoreBlockPagebreaks = false;
27
+ $this->forcePortraitMargins = false;
28
+ $this->displayDefaultOrientation = false;
29
+ $this->printers_info = false; // Adds date and page info for printer when using @page and "marks:crop;"
30
+ $this->bleedMargin = 5;
31
+ $this->crossMarkMargin = 5; // Distance of cross mark from margin in mm
32
+ $this->cropMarkMargin = 8; // Distance of crop mark from margin in mm
33
+ $this->cropMarkLength = 18; // Default length in mm of crop line
34
+ $this->nonPrintMargin = 8; // Non-printable border at edge of paper sheet in mm
35
+ // mPDF 5.5
36
+ // Avoid just the border/background-color of the end of a block being moved on to next page
37
+ $this->margBuffer = 2; // Allows an (empty) end of block to extend beyond the bottom margin by this amount (mm)
38
+
39
+
40
+ // PAGE NUMBERING
41
+ $this->pagenumPrefix;
42
+ $this->pagenumSuffix;
43
+ $this->nbpgPrefix;
44
+ $this->nbpgSuffix;
45
+
46
+
47
+ // FONTS, LANGUAGES & CHARACTER SETS
48
+ // Set maximum size of TTF font file to allow non-subsets - in kB
49
+ // Used to avoid e.g. Arial Unicode MS (perhaps used for substitutions) to ever be fully embedded
50
+ // NB Free serif is 1.5MB, most files are <= 600kB (most 200-400KB)
51
+ $this->maxTTFFilesize = 2000;
52
+
53
+ // this value determines whether to subset or not
54
+ // 0 - 100 = percent characters
55
+ // i.e. if ==40, mPDF will embed whole font if >40% characters in that font
56
+ // or embed subset if <40% characters
57
+ // 0 will force whole file to be embedded (NO subsetting)
58
+ // 100 will force always to subset
59
+ // This value is overridden if you set new mPDF('s)
60
+ // and/or Can set at runtime
61
+ $this->percentSubset = 30;
62
+
63
+ $this->useAdobeCJK = false; // Uses Adobe CJK fonts for CJK languages
64
+ // default TRUE; only set false if you have defined some available fonts that support CJK
65
+ // If true this will not stop use of other CJK fonts if specified by font-family:
66
+ // and vice versa i.e. only dictates behaviour when specified by lang="" incl. AutoFont()
67
+
68
+ // When embedding full TTF font files, remakes the font file using only core tables
69
+ // May improve function with some PostScript printers (GhostScript/GSView)
70
+ // Does not work with TTC font collections
71
+ // Slightly smaller file; increased processing time
72
+ $this->repackageTTF = false;
73
+
74
+ // Allows automatic character set conversion if "charset=xxx" detected in html header (WriteHTML() )
75
+ $this->allow_charset_conversion = true;
76
+ $this->biDirectional=false; // automatically determine BIDI text in LTR page
77
+ $this->autoFontGroupSize = 2; // 1: individual words are spanned; 2: words+; 3: as big chunks as possible.
78
+ $this->useLang = true; // Default changed in mPDF 4.0
79
+
80
+ $this->useSubstitutions = false; // Substitute missing characters in UTF-8(multibyte) documents - from other fonts
81
+ $this->falseBoldWeight = 5; // Weight for bold text when using an artificial (outline) bold; value 0 (off) - 10 (rec. max)
82
+
83
+ // CONFIGURATION
84
+ $this->allow_output_buffering = false;
85
+
86
+ $this->enableImports = false; // Adding mPDFI functions
87
+
88
+ $this->collapseBlockMargins = true; // Allows top and bottom margins to collapse between block elements
89
+ $this->progressBar = 0; // Shows progress-bars whilst generating file 0 off, 1 simple, 2 advanced
90
+ $this->progbar_heading = 'mPDF file progress';
91
+ $this->progbar_altHTML = ''; // Should include <html> and <body> but NOT end tags
92
+ // Can incude <head> and link to stylesheet etc.
93
+ // e.g. '<html><body><p><img src="loading.gif" /> Creating PDF file. Please wait...</p>';
94
+
95
+ $this->dpi = 96; // To interpret "px" pixel values in HTML/CSS (see img_dpi below)
96
+
97
+ // Automatically correct for tags where HTML specifies optional end tags e.g. P,LI,DD,TD
98
+ // If you are confident input html is valid XHTML, turning this off may make it more reliable(?)
99
+ $this->allow_html_optional_endtags = true;
100
+
101
+ $this->ignore_invalid_utf8 = false;
102
+ $this->text_input_as_HTML = false; // Converts all entities in Text inputs to UTF-8 before encoding
103
+ $this->useGraphs = false;
104
+
105
+
106
+ // When writing a block element with position:fixed and overflow:auto, mPDF scales it down to fit in the space
107
+ // by repeatedly rewriting it and making adjustments. These values give the adjustments used, depending how far out
108
+ // the previous guess was. The lower the number, the quicker it will finish, but the less accurate the fit may be.
109
+ // FPR1 is for coarse adjustments, and FPR4 for fine adjustments when it is getting closer.
110
+ $this->incrementFPR1 = 10; // i.e. will alter by 1/[10]th of width and try again until within closer limits
111
+ $this->incrementFPR2 = 20;
112
+ $this->incrementFPR3 = 30;
113
+ $this->incrementFPR4 = 50; // i.e. will alter by 1/[50]th of width and try again when it nearly fits
114
+
115
+
116
+ // COLORSPACE
117
+ // 1 - allow GRAYSCALE only [convert CMYK/RGB->gray]
118
+ // 2 - allow RGB / SPOT COLOR / Grayscale [convert CMYK->RGB]
119
+ // 3 - allow CMYK / SPOT COLOR / Grayscale [convert RGB->CMYK]
120
+ $this->restrictColorSpace = 0;
121
+
122
+ // PDFX/1-a Compliant files
123
+ $this->PDFX = false; // true=Forces compliance with PDFX-1a spec
124
+ // Cannot be used with $this->restrictColorSpace (i.e. no RGB)
125
+ $this->PDFXauto = false; // Overrides warnings making changes when possible to force PDFX1-a compliance
126
+
127
+
128
+ // PDFA1-b Compliant files
129
+ $this->PDFA = false; // true=Forces compliance with PDFA-1b spec
130
+ // Can use with $this->restrictColorSpace=3 (for a CMYK file)
131
+ // Any other settings, uses RGB profile
132
+ $this->PDFAauto = false; // Overrides warnings making changes when possible to force PDFA1-b compliance
133
+ $this->ICCProfile = ''; // Colour profile OutputIntent
134
+ // sRGB_IEC61966-2-1 (=default if blank and PDFA), or other added .icc profile
135
+ // Must be CMYK for PDFX, or appropriate type for PDFA(RGB or CMYK)
136
+
137
+
138
+
139
+ // DEBUGGING & DEVELOPERS
140
+ $this->showStats = false;
141
+ $this->debug = false;
142
+ $this->debugfonts = false; // Checks and reports on errors when parsing TTF files - adds significantly to processing time
143
+ $this->showImageErrors = false;
144
+ $this->table_error_report = false; // Die and report error if table is too wide to contain whole words
145
+ $this->table_error_report_param = ''; // Parameter which can be passed to show in error report i.e. chapter number being processed//
146
+
147
+
148
+ // ANNOTATIONS
149
+ $this->title2annots = false;
150
+ $this->annotSize = 0.5; // default mm for Adobe annotations - nominal
151
+ $this->annotMargin; // default position for Annotations
152
+ $this->annotOpacity = 0.5; // default opacity for Annotations
153
+
154
+ // BOOKMARKS
155
+ $this->anchor2Bookmark = 0; // makes <a name=""> into a bookmark as well as internal link target; 1 = just name; 2 = name (p.34)
156
+ // Set an optional array to specify appearance of Bookmarks (by level)
157
+ // Default values are Black and normal style
158
+ /*
159
+ Example:
160
+ $this->bookmarkStyles = array(
161
+ 0 => array('color'=> array(0,64,128), 'style'=>'B'),
162
+ 1 => array('color'=> array(128,0,0), 'style'=>''),
163
+ 2 => array('color'=> array(0,128,0), 'style'=>'I'),
164
+ );
165
+ */
166
+ $this->bookmarkStyles = array();
167
+
168
+
169
+ // CSS & STYLES
170
+ $this->CSSselectMedia='print'; // screen, print, or any other CSS @media type (not "all")
171
+
172
+
173
+ // PAGE HEADERS & FOOTERS
174
+ $this->forcePortraitHeaders = false;
175
+ // Values used if simple FOOTER/HEADER given i.e. not array
176
+ $this->defaultheaderfontsize = 8; // pt
177
+ $this->defaultheaderfontstyle = 'BI'; // '', or 'B' or 'I' or 'BI'
178
+ $this->defaultheaderline = 1; // 1 or 0 - line under the header
179
+ $this->defaultfooterfontsize = 8; // pt
180
+ $this->defaultfooterfontstyle = 'BI'; // '', or 'B' or 'I' or 'BI'
181
+ $this->defaultfooterline = 1; // 1 or 0 - line over the footer
182
+ $this->header_line_spacing = 0.25; // spacing between bottom of header and line (if present) - function of fontsize
183
+ $this->footer_line_spacing = 0.25; // spacing between bottom of header and line (if present) - function of fontsize
184
+ // If 'pad' margin-top sets fixed distance in mm (padding) between bottom of header and top of text.
185
+ // If 'stretch' margin-top sets a minimum distance in mm between top of page and top of text, which expands if header is too large to fit.
186
+ $this->setAutoTopMargin = false;
187
+ $this->setAutoBottomMargin = false;
188
+ $this->autoMarginPadding = 2; // distance in mm used as padding if 'stretch' mode is used
189
+
190
+
191
+
192
+ // TABLES
193
+ $this->simpleTables = false; // Forces all cells to have same border, background etc. Improves performance
194
+ $this->packTableData = false; // Reduce memory usage processing tables (but with increased processing time)
195
+ // Using disk to cache table data can reduce memory usage dramatically, but at a cost of increased
196
+ // executon time and disk access (read and write)
197
+ $this->cacheTables = false;
198
+
199
+ $this->ignore_table_percents = false;
200
+ $this->ignore_table_widths = false;
201
+ $this->keep_table_proportions = false; // If table width set > page width, force resizing but keep relative sizes
202
+ // Also forces respect of cell widths set by %
203
+ $this->shrink_tables_to_fit = 1.4; // automatically reduce fontsize in table if words would have to split ( not in CJK)
204
+ // 0 or false to disable; value (if set) gives maximum factor to reduce fontsize
205
+
206
+ $this->tableMinSizePriority = false; // If page-break-inside:avoid but cannot fit on full page without
207
+ // exceeding autosize; setting this value to true will force respsect for
208
+ // autosize, and disable the page-break-inside:avoid
209
+
210
+ $this->use_kwt = false; // "Keep-with-table"
211
+ $this->iterationCounter = false; // Set to TRUE to use table Head iteration counter
212
+ $this->splitTableBorderWidth = 0; // Use table border (using this width in mm) when table breaks across pages
213
+ // Recommended to use small value e.g. 0.01
214
+
215
+
216
+ // IMAGES
217
+ $this->img_dpi = 96; // Default dpi to output images if size not defined
218
+ // See also above "dpi"
219
+
220
+ // TEXT SPACING & JUSTIFICATION
221
+ $this->useKerning = false; // true to use kerning
222
+ $this->justifyB4br = false; // In justified text, <BR> does not cause the preceding text to be justified in browsers
223
+ // Change to true to force justification (as in MS Word)
224
+
225
+ $this->tabSpaces = 8; // Number of spaces to replace for a TAB in <pre> sections
226
+ // Notepad uses 6, HTML specification recommends 8
227
+ $this->jSWord = 0.4; // Proportion (/1) of space (when justifying margins) to allocate to Word vs. Character
228
+ $this->jSmaxChar = 2; // Maximum spacing to allocate to character spacing. (0 = no maximum)
229
+
230
+ $this->jSmaxCharLast = 1; // Maximum character spacing allowed (carried over) when finishing a last line
231
+ $this->jSmaxWordLast = 2; // Maximum word spacing allowed (carried over) when finishing a last line
232
+ $this->normalLineheight = 1.33; // Value used for line-height when CSS specified as 'normal' (default)
233
+
234
+ // Small Caps
235
+ $this->smCapsScale = 0.75; // Factor of 1 to scale capital letters
236
+ $this->smCapsStretch = 110; // % to stretch small caps horizontally (i.e. 100 = no stretch)
237
+
238
+ // CJK Line-breaking
239
+ $this->allowCJKorphans = true; // FALSE=always wrap to next line; TRUE=squeeze or overflow
240
+ $this->allowCJKoverflow = false; // FALSE=squeeze; TRUE=overflow (only some characters, and disabled in tables)
241
+ $this->CJKforceend = false; // Forces overflowng punctuation to hang outside right margin mPDF 5.6.40
242
+
243
+ // HYPHENATION
244
+ $this->SHYlang = "en"; // Should be one of: 'en','de','es','fi','fr','it','nl','pl','ru','sv'
245
+ $this->SHYleftmin = 2;
246
+ $this->SHYrightmin = 2;
247
+ $this->SHYcharmin = 2;
248
+ $this->SHYcharmax = 10;
249
+
250
+ // COLUMNS
251
+ $this->keepColumns = false; // Set to go to the second column only when the first is full of text etc.
252
+ $this->max_colH_correction = 1.15; // Maximum ratio to adjust column height when justifying - too large a value can give ugly results
253
+ $this->ColGap=5;
254
+
255
+
256
+ // LISTS
257
+ $this->list_align_style = 'R'; // Determines alignment of numbers in numbered lists
258
+ $this->list_indent_first_level = 0; // 1/0 yex/no to indent first level of list
259
+ $this->list_number_suffix = '.'; // Content to follow a numbered list marker e.g. '.' gives 1. or IV.; ')' gives 1) or a)
260
+
261
+ // ACTIVE FORMS
262
+ $this->useActiveForms = false;
263
+
264
+ // WATERMARKS
265
+ $this->watermarkImgBehind = false;
266
+ $this->showWatermarkText = 0;
267
+ $this->showWatermarkImage = 0;
268
+ $this->watermarkText = '';
269
+ $this->watermarkImage = '';
270
+ $this->watermark_font = '';
271
+ $this->watermarkTextAlpha = 0.2;
272
+ $this->watermarkImageAlpha = 0.2;
273
+ $this->watermarkImgAlphaBlend = 'Normal';
274
+ // Accepts any PDF spec. value: Normal, Multiply, Screen, Overlay, Darken, Lighten, ColorDodge, ColorBurn,
275
+ // HardLight, SoftLight, Difference, Exclusion
276
+ // "Multiply" works well for watermark image on top
277
+
278
+ // BORDERS
279
+ $this->autoPadding = false; // Automatically increases padding in block elements when border-radius set - if required
280
+
281
+
282
+ //////////////////////////////////////////////
283
+
284
+ // Default values if no style sheet offered (cf. http://www.w3.org/TR/CSS21/sample.html)
285
+ $this->defaultCSS = array(
286
+ 'BODY' => array(
287
+ 'FONT-FAMILY' => 'serif',
288
+ 'FONT-SIZE' => '11pt',
289
+ 'TEXT-INDENT' => '0pt',
290
+ 'LINE-HEIGHT' => 'normal',
291
+ 'MARGIN-COLLAPSE' => 'collapse', /* Custom property to collapse top/bottom margins at top/bottom of page - ignored in tables/lists */
292
+ 'HYPHENS' => 'manual', /* mPDF 5.6.08 */
293
+ ),
294
+ 'P' => array(
295
+ 'MARGIN' => '1.12em 0',
296
+ ),
297
+ 'H1' => array(
298
+ 'FONT-SIZE' => '2em',
299
+ 'FONT-WEIGHT' => 'bold',
300
+ 'MARGIN' => '0.67em 0',
301
+ 'PAGE-BREAK-AFTER' => 'avoid',
302
+ ),
303
+ 'H2' => array(
304
+ 'FONT-SIZE' => '1.5em',
305
+ 'FONT-WEIGHT' => 'bold',
306
+ 'MARGIN' => '0.75em 0',
307
+ 'PAGE-BREAK-AFTER' => 'avoid',
308
+ ),
309
+ 'H3' => array(
310
+ 'FONT-SIZE' => '1.17em',
311
+ 'FONT-WEIGHT' => 'bold',
312
+ 'MARGIN' => '0.83em 0',
313
+ 'PAGE-BREAK-AFTER' => 'avoid',
314
+ ),
315
+ 'H4' => array(
316
+ 'FONT-WEIGHT' => 'bold',
317
+ 'MARGIN' => '1.12em 0',
318
+ 'PAGE-BREAK-AFTER' => 'avoid',
319
+ ),
320
+ 'H5' => array(
321
+ 'FONT-SIZE' => '0.83em',
322
+ 'FONT-WEIGHT' => 'bold',
323
+ 'MARGIN' => '1.5em 0',
324
+ 'PAGE-BREAK-AFTER' => 'avoid',
325
+ ),
326
+ 'H6' => array(
327
+ 'FONT-SIZE' => '0.75em',
328
+ 'FONT-WEIGHT' => 'bold',
329
+ 'MARGIN' => '1.67em 0',
330
+ 'PAGE-BREAK-AFTER' => 'avoid',
331
+ ),
332
+ 'HR' => array(
333
+ 'COLOR' => '#888888',
334
+ 'TEXT-ALIGN' => 'center',
335
+ 'WIDTH' => '100%',
336
+ 'HEIGHT' => '0.2mm',
337
+ 'MARGIN-TOP' => '0.83em',
338
+ 'MARGIN-BOTTOM' => '0.83em',
339
+ ),
340
+ 'PRE' => array(
341
+ 'MARGIN' => '0.83em 0',
342
+ 'FONT-FAMILY' => 'monospace',
343
+ ),
344
+ 'S' => array(
345
+ 'TEXT-DECORATION' => 'line-through',
346
+ ),
347
+ 'STRIKE' => array(
348
+ 'TEXT-DECORATION' => 'line-through',
349
+ ),
350
+ 'DEL' => array(
351
+ 'TEXT-DECORATION' => 'line-through',
352
+ ),
353
+ 'SUB' => array(
354
+ 'VERTICAL-ALIGN' => 'sub',
355
+ 'FONT-SIZE' => '55%', /* Recommended 0.83em */
356
+ ),
357
+ 'SUP' => array(
358
+ 'VERTICAL-ALIGN' => 'super',
359
+ 'FONT-SIZE' => '55%', /* Recommended 0.83em */
360
+ ),
361
+ 'U' => array(
362
+ 'TEXT-DECORATION' => 'underline',
363
+ ),
364
+ 'INS' => array(
365
+ 'TEXT-DECORATION' => 'underline',
366
+ ),
367
+ 'B' => array(
368
+ 'FONT-WEIGHT' => 'bold',
369
+ ),
370
+ 'STRONG' => array(
371
+ 'FONT-WEIGHT' => 'bold',
372
+ ),
373
+ 'I' => array(
374
+ 'FONT-STYLE' => 'italic',
375
+ ),
376
+ 'CITE' => array(
377
+ 'FONT-STYLE' => 'italic',
378
+ ),
379
+ 'Q' => array(
380
+ 'FONT-STYLE' => 'italic',
381
+ ),
382
+ 'EM' => array(
383
+ 'FONT-STYLE' => 'italic',
384
+ ),
385
+ 'VAR' => array(
386
+ 'FONT-STYLE' => 'italic',
387
+ ),
388
+ 'SAMP' => array(
389
+ 'FONT-FAMILY' => 'monospace',
390
+ ),
391
+ 'CODE' => array(
392
+ 'FONT-FAMILY' => 'monospace',
393
+ ),
394
+ 'KBD' => array(
395
+ 'FONT-FAMILY' => 'monospace',
396
+ ),
397
+ 'TT' => array(
398
+ 'FONT-FAMILY' => 'monospace',
399
+ ),
400
+ 'SMALL' => array(
401
+ 'FONT-SIZE' => '83%',
402
+ ),
403
+ 'BIG' => array(
404
+ 'FONT-SIZE' => '117%',
405
+ ),
406
+ 'ACRONYM' => array(
407
+ 'FONT-SIZE' => '77%',
408
+ 'FONT-WEIGHT' => 'bold',
409
+ ),
410
+ 'ADDRESS' => array(
411
+ 'FONT-STYLE' => 'italic',
412
+ ),
413
+ 'BLOCKQUOTE' => array(
414
+ 'MARGIN-LEFT' => '40px',
415
+ 'MARGIN-RIGHT' => '40px',
416
+ 'MARGIN-TOP' => '1.12em',
417
+ 'MARGIN-BOTTOM' => '1.12em',
418
+ ),
419
+ 'A' => array(
420
+ 'COLOR' => '#0000FF',
421
+ 'TEXT-DECORATION' => 'underline',
422
+ ),
423
+ 'UL' => array(
424
+ 'MARGIN' => '0.83em 0', /* only applied to top-level of nested lists */
425
+ 'TEXT-INDENT' => '1.3em', /* Custom effect - list indent */
426
+ ),
427
+ 'OL' => array(
428
+ 'MARGIN' => '0.83em 0', /* only applied to top-level of nested lists */
429
+ 'TEXT-INDENT' => '1.3em', /* Custom effect - list indent */
430
+ ),
431
+ 'DL' => array(
432
+ 'MARGIN' => '1.67em 0',
433
+ ),
434
+ 'DT' => array(
435
+ ),
436
+ 'DD' => array(
437
+ 'PADDING-LEFT' => '40px',
438
+ ),
439
+ 'TABLE' => array(
440
+ 'MARGIN' => '0',
441
+ 'BORDER-COLLAPSE' => 'separate',
442
+ 'BORDER-SPACING' => '2px',
443
+ 'EMPTY-CELLS' => 'show',
444
+ 'LINE-HEIGHT' => '1.2',
445
+ 'VERTICAL-ALIGN' => 'middle',
446
+ ),
447
+ 'THEAD' => array(
448
+ ),
449
+ 'TFOOT' => array(
450
+ ),
451
+ 'TH' => array(
452
+ 'FONT-WEIGHT' => 'bold',
453
+ 'TEXT-ALIGN' => 'center',
454
+ 'PADDING-LEFT' => '0.1em',
455
+ 'PADDING-RIGHT' => '0.1em',
456
+ 'PADDING-TOP' => '0.1em',
457
+ 'PADDING-BOTTOM' => '0.1em',
458
+ ),
459
+ 'TD' => array(
460
+ 'PADDING-LEFT' => '0.1em',
461
+ 'PADDING-RIGHT' => '0.1em',
462
+ 'PADDING-TOP' => '0.1em',
463
+ 'PADDING-BOTTOM' => '0.1em',
464
+ ),
465
+ 'CAPTION' => array(
466
+ 'TEXT-ALIGN' => 'center',
467
+ ),
468
+ 'IMG' => array(
469
+ 'MARGIN' => '0',
470
+ 'VERTICAL-ALIGN' => 'baseline',
471
+ ),
472
+ 'INPUT' => array(
473
+ 'FONT-FAMILY' => 'sans-serif',
474
+ 'VERTICAL-ALIGN' => 'middle',
475
+ 'FONT-SIZE' => '0.9em',
476
+ ),
477
+ 'SELECT' => array(
478
+ 'FONT-FAMILY' => 'sans-serif',
479
+ 'FONT-SIZE' => '0.9em',
480
+ 'VERTICAL-ALIGN' => 'middle',
481
+ ),
482
+ 'TEXTAREA' => array(
483
+ 'FONT-FAMILY' => 'monospace',
484
+ 'FONT-SIZE' => '0.9em',
485
+ 'VERTICAL-ALIGN' => 'text-bottom',
486
+ ),
487
+ 'MARK' => array( /* mPDF 5.5.09 */
488
+ 'BACKGROUND-COLOR' => 'yellow',
489
+ ),
490
+ );
491
+
492
+
493
+ //////////////////////////////////////////////////
494
+ // VALUES ONLY LIKELY TO BE CHANGED BY DEVELOPERS
495
+ //////////////////////////////////////////////////
496
+ $this->pdf_version = '1.4';
497
+
498
+ // Hyphenation
499
+ $this->SHYlanguages = array('en','de','es','fi','fr','it','nl','pl','ru','sv'); // existing defined patterns
500
+
501
+ $this->default_lineheight_correction=1.2; // Value 1 sets lineheight=fontsize height;
502
+ // Value used if line-height not set by CSS (usuallly is)
503
+
504
+ $this->fontsizes = array('XX-SMALL'=>0.7, 'X-SMALL'=>0.77, 'SMALL'=>0.86, 'MEDIUM'=>1, 'LARGE'=>1.2, 'X-LARGE'=>1.5, 'XX-LARGE'=>2);
505
+
506
+ // CHARACTER PATTERN MATCHES TO DETECT LANGUAGES
507
+ // pattern used to detect RTL characters -> force RTL
508
+ $this->pregRTLchars = "\x{0590}-\x{06FF}\x{0700}-\x{083E}\x{FB00}-\x{FDFD}\x{FE70}-\x{FEFF}";
509
+
510
+ // CJK Chars which require changing and are distinctive of specific charset
511
+ $this->pregUHCchars = "\x{1100}-\x{11FF}\x{3130}-\x{318F}\x{AC00}-\x{D7AF}";
512
+ $this->pregSJISchars = "\x{3040}-\x{309F}\x{30A0}-\x{30FF}\x{3190}-\x{319F}\x{31F0}-\x{31FF}";
513
+
514
+ // Chars which distinguish CJK but not between different
515
+ $this->pregCJKchars = "\x{1100}-\x{11FF}\x{2E80}-\x{A4CF}\x{A800}-\x{D7AF}\x{F900}-\x{FAFF}\x{FE30}-\x{FE6F}\x{FF00}-\x{FFEF}\x{20000}-\x{2FA1F}";
516
+
517
+ // For CJK Line-breaking
518
+ //Leading characters - Not allowed at end of line
519
+ $this->CJKleading = "\$\(\*\[\{\x{00a3}\x{00a5}\x{00ab}\x{00b7}\x{2018}\x{201c}\x{2035}\x{3005}\x{3007}\x{3008}\x{300a}\x{300c}\x{300e}\x{3010}\x{3014}\x{3016}\x{3018}\x{301d}\x{fe34}\x{fe57}\x{fe59}\x{fe5b}\x{ff04}\x{ff08}\x{ff0e}\x{ff3b}\x{ff5b}\x{ff5f}\x{ffe1}\x{ffe5}\x{ffe6}";
520
+ // Following characters - Not allowed at start
521
+ $this->CJKfollowing = "!%\),\.:;>\?\]\}\x{00a2}\x{00a8}\x{00b0}\x{00b7}\x{00bb}\x{02c7}\x{02c9}\x{2010}\x{2013}-\x{2016}\x{2019}\x{201d}-\x{201f}\x{2020}-\x{2022}\x{2025}\x{2027}\x{203a}\x{203c}\x{2047}-\x{2049}\x{2103}\x{2236}\x{2574}\x{3001}-\x{3003}\x{3005}\x{3006}\x{3009}\x{300b}\x{300d}\x{300f}\x{3011}\x{3015}\x{3017}\x{3019}\x{301c}\x{301e}\x{301f}\x{303b}\x{3041}\x{3043}\x{3045}\x{3047}\x{3049}\x{3063}\x{3083}\x{3085}\x{3087}\x{308e}\x{3095}\x{3096}\x{30a0}\x{30a1}\x{30a3}\x{30a5}\x{30a7}\x{30a9}\x{30c3}\x{30e3}\x{30e5}\x{30e7}\x{30ee}\x{30f5}\x{30f6}\x{30fb}-\x{30fe}\x{31f0}-\x{31ff}\x{fe30}-\x{fe33}\x{fe50}-\x{fe56}\x{fe58}\x{fe5a}\x{fe5c}\x{ff01}\x{ff02}\x{ff05}\x{ff07}\x{ff09}\x{ff0c}\x{ff0e}\x{ff1a}\x{ff1b}\x{ff1f}\x{ff3d}\x{ff40}\x{ff5c}-\x{ff5e}\x{ff60}\x{ff64}";
522
+ // Characters which are allowed to overflow the right margin
523
+ $this->CJKoverflow = "\.,\x{ff61}\x{ff64}\x{3001}\x{3002}\x{ff0c}\x{ff0e}";
524
+
525
+
526
+
527
+ // ASCII Chars which shouldn't break string
528
+ // Use for very specific words
529
+ $this->pregASCIIchars1 = "\x{0021}-\x{002E}\x{0030}-\x{003B}?"; // no [SPACE]
530
+ // Use for words+
531
+ $this->pregASCIIchars2 = "\x{0020}-\x{002E}\x{0030}-\x{003B}?"; // [SPACE] punctuation and 0-9
532
+ // Use for chunks > words
533
+ $this->pregASCIIchars3 = "\x{0000}-\x{002E}\x{0030}-\x{003B}\x{003F}-\x{007E}"; // all except <>
534
+ // Vietnamese - specific
535
+ $this->pregVIETchars = "\x{01A0}\x{01A1}\x{01AF}\x{01B0}\x{1EA0}-\x{1EF1}";
536
+ // Vietnamese - Chars which shouldn't break string
537
+ $this->pregVIETPluschars = "\x{0000}-\x{003B}\x{003F}-\x{00FF}\x{0300}-\x{036F}\x{0102}\x{0103}\x{0110}\x{0111}\x{0128}\x{0129}\x{0168}\x{0169}\x{1EF1}-\x{1EF9}"; // omits < >
538
+
539
+ // Arabic
540
+ $this->pregARABICchars = "\x{0600}-\x{06FF}\x{0750}-\x{077F}\x{FB50}-\x{FDFD}\x{FE70}-\x{FEFF}";
541
+ // Characters of Urdu, Pashto, Sindhi (but NOT arabic or persian/farsi) [not covered by DejavuSans font]
542
+ $this->pregNonARABICchars = "\x{0671}-\x{067D}\x{067F}-\x{0685}\x{0687}-\x{0697}\x{0699}-\x{06A8}\x{06AA}-\x{06AE}\x{06B0}-\x{06CB}\x{06CD}-\x{06D3}";
543
+
544
+ $this->pregHEBchars = "\x{0590}-\x{05FF}\x{FB00}-\x{FB49}"; // Hebrew
545
+
546
+ // INDIC
547
+ $this->pregHIchars = "\x{0900}-\x{0963}\x{0966}-\x{097F}"; // Devanagari (Hindi) minus the common indic punctuation 0964,0965
548
+ $this->pregBNchars = "\x{0980}-\x{09FF}"; // Bengali
549
+ $this->pregPAchars = "\x{0A00}-\x{0A7F}"; // Gurmukhi (Punjabi)
550
+ $this->pregGUchars = "\x{0A80}-\x{0AFF}"; // Gujarati
551
+ $this->pregORchars = "\x{0B00}-\x{0B7F}"; // Oriya
552
+ $this->pregTAchars = "\x{0B80}-\x{0BFF}"; // Tamil
553
+ $this->pregTEchars = "\x{0C00}-\x{0C7F}"; // Telugu
554
+ $this->pregKNchars = "\x{0C80}-\x{0CFF}"; // Kannada
555
+ $this->pregMLchars = "\x{0D00}-\x{0D7F}"; // Malayalam
556
+ $this->pregSHchars = "\x{0D80}-\x{0DFF}"; // Sinhala
557
+
558
+ $this->pregINDextra = "\x{200B}-\x{200D}\x{0964}\x{0965}\x{0020}-\x{0022}\x{0024}-\x{002E}\x{003A}-\x{003F}\x{005B}-\x{0060}\x{007B}-\x{007E}\x{00A0}";
559
+ // 200B-D=Zero-width joiners; 0964,0965=Generic Indic punctuation; NBSP & general punctuation (excludes # and / so can use in autoFont() )
560
+
561
+ $this->allowedCSStags = 'DIV|P|H1|H2|H3|H4|H5|H6|FORM|IMG|A|BODY|TABLE|HR|THEAD|TFOOT|TBODY|TH|TR|TD|UL|OL|LI|PRE|BLOCKQUOTE|ADDRESS|DL|DT|DD';
562
+ $this->allowedCSStags .= '|ARTICLE|ASIDE|FIGURE|FIGCAPTION|FOOTER|HEADER|HGROUP|NAV|SECTION|MARK|DETAILS|SUMMARY|METER|PROGRESS|TIME'; // mPDF 5.5.09
563
+ $this->allowedCSStags .= '|SPAN|TT|I|B|BIG|SMALL|EM|STRONG|DFN|CODE|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|STRIKE|S|U|DEL|INS|Q|FONT';
564
+ $this->allowedCSStags .= '|SELECT|INPUT|TEXTAREA|CAPTION|FIELDSET|LEGEND'; // mPDF 5.4.18
565
+ $this->allowedCSStags .= '|TEXTCIRCLE|DOTTAB'; // mPDF 5.5.23 // mPDF 5.6.33
566
+
567
+ $this->outerblocktags = array('DIV','FORM','CENTER','DL','FIELDSET','ARTICLE','ASIDE','FIGURE','FIGCAPTION', 'FOOTER','HEADER','HGROUP','NAV','SECTION','DETAILS','SUMMARY'); // mPDF 5.5.09 // mPDF 5.5.22
568
+ $this->innerblocktags = array('P','BLOCKQUOTE','ADDRESS','PRE','H1','H2','H3','H4','H5','H6','DT','DD','CAPTION');
569
+
570
+
571
+
572
+ ?>
mpdf/config_cp.php ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ function GetLangOpts($llcc, $adobeCJK) {
5
+ if (strlen($llcc) == 5) {
6
+ $lang = substr(strtolower($llcc),0,2);
7
+ $country = substr(strtoupper($llcc),3,2);
8
+ }
9
+ else { $lang = strtolower($llcc); $country = ''; }
10
+ $unifonts = "";
11
+ $coreSuitable = false;
12
+
13
+ switch($lang){
14
+ CASE "en":
15
+ CASE "ca":
16
+ CASE "cy":
17
+ CASE "da":
18
+ CASE "de":
19
+ CASE "es":
20
+ CASE "eu":
21
+ CASE "fr":
22
+ CASE "ga":
23
+ CASE "fi":
24
+ CASE "is":
25
+ CASE "it":
26
+ CASE "nl":
27
+ CASE "no":
28
+ CASE "pt":
29
+ CASE "sv":
30
+ // Edit this value to define how mPDF behaves when using new mPDF('-x')
31
+ // If set to TRUE, mPDF will use Adobe core fonts only when it recognises the languages above
32
+ $coreSuitable = true; break;
33
+
34
+
35
+
36
+ // RTL Languages
37
+ CASE "he":
38
+ CASE "yi":
39
+ $unifonts = "dejavusans,dejavusansB,dejavusansI,dejavusansBI"; break;
40
+
41
+ // Arabic
42
+ CASE "ar":
43
+ $unifonts = "xbriyaz,xbriyazB,xbriyazI,xbriyazBI,xbzar,xbzarB,xbzarI,xbzarBI"; break;
44
+ CASE "fa":
45
+ $unifonts = "xbriyaz,xbriyazB,xbriyazI,xbriyazBI,xbzar,xbzarB,xbzarI,xbzarBI"; break;
46
+ CASE "ps":
47
+ $unifonts = "xbriyaz,xbriyazB,xbriyazI,xbriyazBI,xbzar,xbzarB,xbzarI,xbzarBI"; break;
48
+ CASE "ur":
49
+ $unifonts = "xbriyaz,xbriyazB,xbriyazI,xbriyazBI,xbzar,xbzarB,xbzarI,xbzarBI"; break;
50
+
51
+ // Sindhi (can be Arabic or Devanagari)
52
+ CASE "sd":
53
+ if ($country == "IN") { $unifonts = "ind_hi_1_001"; }
54
+ // else if ($country == "PK") { $unifonts = ""; }
55
+ // else { $unifonts = ""; }
56
+ break;
57
+
58
+
59
+ // INDIC
60
+ // Assamese
61
+ CASE "as": $unifonts = "ind_bn_1_001"; break;
62
+ // Bengali
63
+ CASE "bn": $unifonts = "ind_bn_1_001"; break;
64
+ // Gujarati
65
+ CASE "gu": $unifonts = "ind_gu_1_001"; break;
66
+ // Hindi (Devanagari)
67
+ CASE "hi": $unifonts = "ind_hi_1_001"; break;
68
+ // Kannada
69
+ CASE "kn": $unifonts = "ind_kn_1_001"; break;
70
+ // Kashmiri
71
+ CASE "ks": $unifonts = "ind_hi_1_001"; break;
72
+ // Malayalam
73
+ CASE "ml": $unifonts = "ind_ml_1_001"; break;
74
+ // Nepali (Devanagari)
75
+ CASE "ne": $unifonts = "ind_hi_1_001"; break;
76
+ // Oriya
77
+ CASE "or": $unifonts = "ind_or_1_001"; break;
78
+ // Punjabi (Gurmukhi)
79
+ CASE "pa": $unifonts = "ind_pa_1_001"; break;
80
+ // Tamil
81
+ CASE "ta": $unifonts = "ind_ta_1_001"; break;
82
+ // Telegu
83
+ CASE "te": $unifonts = "ind_te_1_001"; break;
84
+
85
+ // THAI
86
+ CASE "th": $unifonts = "garuda,garudaB,garudaI,garudaBI,norasi,norasiB,norasiI,norasiBI"; break;
87
+
88
+ // VIETNAMESE
89
+ CASE "vi":
90
+ $unifonts = "dejavusanscondensed,dejavusanscondensedB,dejavusanscondensedI,dejavusanscondensedBI,dejavusans,dejavusansB,dejavusansI,dejavusansBI"; break;
91
+
92
+ // CJK Langauges
93
+ CASE "ja":
94
+ if ($adobeCJK) {
95
+ $unifonts = "sjis,sjisB,sjisI,sjisBI";
96
+ }
97
+ /* Uncomment these lines if CJK fonts available */
98
+ // else {
99
+ // $unifonts = "sun-exta,sun-extb,hannoma,hannomb";
100
+ // }
101
+ break;
102
+
103
+ CASE "ko":
104
+ if ($adobeCJK) {
105
+ $unifonts = "uhc,uhcB,uhcI,uhcBI";
106
+ }
107
+ /* Uncomment these lines if CJK fonts available */
108
+ // else {
109
+ // $unifonts = "unbatang_0613";
110
+ // }
111
+ break;
112
+
113
+ CASE "zh":
114
+ if ($country == "HK" || $country == "TW") {
115
+ if ($adobeCJK) {
116
+ $unifonts = "big5,big5B,big5I,big5BI";
117
+ }
118
+ /* Uncomment these lines if CJK fonts available */
119
+ // else {
120
+ // $unifonts = "sun-exta,sun-extb,hannoma,hannomb";
121
+ // }
122
+ }
123
+ else if ($country == "CN") {
124
+ if ($adobeCJK) {
125
+ $unifonts = "gb,gbB,gbI,gbBI";
126
+ }
127
+ /* Uncomment these lines if CJK fonts available */
128
+ // else {
129
+ // $unifonts = "sun-exta,sun-extb,hannoma,hannomb";
130
+ // }
131
+ }
132
+ else {
133
+ if ($adobeCJK) {
134
+ $unifonts = "gb,gbB,gbI,gbBI";
135
+ }
136
+ /* Uncomment these lines if CJK fonts available */
137
+ // else {
138
+ // $unifonts = "sun-exta,sun-extb,hannoma,hannomb";
139
+ // }
140
+ }
141
+ break;
142
+
143
+ }
144
+
145
+
146
+ $unifonts_arr = array();
147
+ if ($unifonts) {
148
+ $unifonts_arr = preg_split('/\s*,\s*/',$unifonts);
149
+ }
150
+ return array($coreSuitable ,$unifonts_arr);
151
+ }
152
+
153
+ ?>
mpdf/config_fonts.php ADDED
@@ -0,0 +1,304 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ // Optionally define a folder which contains TTF fonts
5
+ // mPDF will look here before looking in the usual _MPDF_TTFONTPATH
6
+ // Useful if you already have a folder for your fonts
7
+ // e.g. on Windows: define("_MPDF_SYSTEM_TTFONTS", 'C:/Windows/Fonts/');
8
+ // Leave undefined if not required
9
+
10
+ // define("_MPDF_SYSTEM_TTFONTS", '');
11
+
12
+
13
+ // Optionally set font(s) (names as defined below in $this->fontdata) to use for missing characters
14
+ // when using useSubstitutions. Use a font with wide coverage - dejavusanscondensed is a good start
15
+ // only works using subsets (otherwise would add very large file)
16
+ // doesn't do Indic or arabic
17
+ // More than 1 font can be specified but each will add to the processing time of the script
18
+
19
+ $this->backupSubsFont = array('dejavusanscondensed');
20
+
21
+
22
+ // Optionally set a font (name as defined below in $this->fontdata) to use for CJK characters
23
+ // in Plane 2 Unicode (> U+20000) when using useSubstitutions.
24
+ // Use a font like hannomb or sun-extb if available
25
+ // only works using subsets (otherwise would add very large file)
26
+ // Leave undefined or blank if not not required
27
+
28
+ // $this->backupSIPFont = 'sun-extb';
29
+
30
+
31
+ /*
32
+ This array defines translations from font-family in CSS or HTML
33
+ to the internal font-family name used in mPDF.
34
+ Can include as many as want, regardless of which fonts are installed.
35
+ By default mPDF will take a CSS/HTML font-family and remove spaces
36
+ and change to lowercase e.g. "Arial Unicode MS" will be recognised as
37
+ "arialunicodems"
38
+ You only need to define additional translations.
39
+ You can also use it to define specific substitutions e.g.
40
+ 'frutiger55roman' => 'arial'
41
+ Generic substitutions (i.e. to a sans-serif or serif font) are set
42
+ by including the font-family in $this->sans_fonts below
43
+ To aid backwards compatability some are included:
44
+ */
45
+ $this->fonttrans = array(
46
+ 'helvetica' => 'arial',
47
+ 'times' => 'timesnewroman',
48
+ 'courier' => 'couriernew',
49
+ 'trebuchet' => 'trebuchetms',
50
+ 'comic' => 'comicsansms',
51
+ 'franklin' => 'franklingothicbook',
52
+ 'albertus' => 'albertusmedium',
53
+ 'arialuni' => 'arialunicodems',
54
+ 'zn_hannom_a' => 'hannoma',
55
+ 'ocr-b' => 'ocrb',
56
+ 'ocr-b10bt' => 'ocrb',
57
+
58
+
59
+ );
60
+
61
+ /*
62
+ This array lists the file names of the TrueType .ttf or .otf font files
63
+ for each variant of the (internal mPDF) font-family name.
64
+ ['R'] = Regular (Normal), others are Bold, Italic, and Bold-Italic
65
+ Each entry must contain an ['R'] entry, but others are optional.
66
+ Only the font (files) entered here will be available to use in mPDF.
67
+ Put preferred default first in order.
68
+ This will be used if a named font cannot be found in any of
69
+ $this->sans_fonts, $this->serif_fonts or $this->mono_fonts
70
+
71
+ ['indic'] = true; for special mPDF fonts containing Indic characters
72
+ ['sip-ext'] = 'hannomb'; name a related font file containing SIP characters
73
+
74
+ If a .ttc TrueType collection file is referenced, the number of the font
75
+ within the collection is required. Fonts in the collection are numbered
76
+ starting at 1, as they appear in the .ttc file e.g.
77
+ "cambria" => array(
78
+ 'R' => "cambria.ttc",
79
+ 'B' => "cambriab.ttf",
80
+ 'I' => "cambriai.ttf",
81
+ 'BI' => "cambriaz.ttf",
82
+ 'TTCfontID' => array(
83
+ 'R' => 1,
84
+ ),
85
+ ),
86
+ "cambriamath" => array(
87
+ 'R' => "cambria.ttc",
88
+ 'TTCfontID' => array(
89
+ 'R' => 2,
90
+ ),
91
+ ),
92
+ */
93
+
94
+ $this->fontdata = array(
95
+ "dejavusanscondensed" => array(
96
+ 'R' => "DejaVuSansCondensed.ttf",
97
+ 'B' => "DejaVuSansCondensed-Bold.ttf",
98
+ 'I' => "DejaVuSansCondensed-Oblique.ttf",
99
+ 'BI' => "DejaVuSansCondensed-BoldOblique.ttf",
100
+ ),
101
+ "dejavusans" => array(
102
+ 'R' => "DejaVuSans.ttf",
103
+ 'B' => "DejaVuSans-Bold.ttf",
104
+ 'I' => "DejaVuSans-Oblique.ttf",
105
+ 'BI' => "DejaVuSans-BoldOblique.ttf",
106
+ ),
107
+ "dejavuserif" => array(
108
+ 'R' => "DejaVuSerif.ttf",
109
+ 'B' => "DejaVuSerif-Bold.ttf",
110
+ 'I' => "DejaVuSerif-Italic.ttf",
111
+ 'BI' => "DejaVuSerif-BoldItalic.ttf",
112
+ ),
113
+ "dejavuserifcondensed" => array(
114
+ 'R' => "DejaVuSerifCondensed.ttf",
115
+ 'B' => "DejaVuSerifCondensed-Bold.ttf",
116
+ 'I' => "DejaVuSerifCondensed-Italic.ttf",
117
+ 'BI' => "DejaVuSerifCondensed-BoldItalic.ttf",
118
+ ),
119
+ "dejavusansmono" => array(
120
+ 'R' => "DejaVuSansMono.ttf",
121
+ 'B' => "DejaVuSansMono-Bold.ttf",
122
+ 'I' => "DejaVuSansMono-Oblique.ttf",
123
+ 'BI' => "DejaVuSansMono-BoldOblique.ttf",
124
+ ),
125
+
126
+
127
+ /* OCR-B font for Barcodes */
128
+ "ocrb" => array(
129
+ 'R' => "ocrb10.ttf",
130
+ ),
131
+
132
+ /* Thai fonts */
133
+ "garuda" => array(
134
+ 'R' => "Garuda.ttf",
135
+ 'B' => "Garuda-Bold.ttf",
136
+ 'I' => "Garuda-Oblique.ttf",
137
+ 'BI' => "Garuda-BoldOblique.ttf",
138
+ ),
139
+ "norasi" => array(
140
+ 'R' => "Norasi.ttf",
141
+ 'B' => "Norasi-Bold.ttf",
142
+ 'I' => "Norasi-Oblique.ttf",
143
+ 'BI' => "Norasi-BoldOblique.ttf",
144
+ ),
145
+
146
+
147
+ /* Indic fonts */
148
+ "ind_bn_1_001" => array(
149
+ 'R' => "ind_bn_1_001.ttf",
150
+ 'indic' => true,
151
+ ),
152
+ "ind_hi_1_001" => array(
153
+ 'R' => "ind_hi_1_001.ttf",
154
+ 'indic' => true,
155
+ ),
156
+ "ind_ml_1_001" => array(
157
+ 'R' => "ind_ml_1_001.ttf",
158
+ 'indic' => true,
159
+ ),
160
+ "ind_kn_1_001" => array(
161
+ 'R' => "ind_kn_1_001.ttf",
162
+ 'indic' => true,
163
+ ),
164
+ "ind_gu_1_001" => array(
165
+ 'R' => "ind_gu_1_001.ttf",
166
+ 'indic' => true,
167
+ ),
168
+ "ind_or_1_001" => array(
169
+ 'R' => "ind_or_1_001.ttf",
170
+ 'indic' => true,
171
+ ),
172
+ "ind_ta_1_001" => array(
173
+ 'R' => "ind_ta_1_001.ttf",
174
+ 'indic' => true,
175
+ ),
176
+ "ind_te_1_001" => array(
177
+ 'R' => "ind_te_1_001.ttf",
178
+ 'indic' => true,
179
+ ),
180
+ "ind_pa_1_001" => array(
181
+ 'R' => "ind_pa_1_001.ttf",
182
+ 'indic' => true,
183
+ ),
184
+
185
+
186
+ /* XW Zar Arabic fonts */
187
+ "xbriyaz" => array(
188
+ 'R' => "XB Riyaz.ttf",
189
+ 'B' => "XB RiyazBd.ttf",
190
+ 'I' => "XB RiyazIt.ttf",
191
+ 'BI' => "XB RiyazBdIt.ttf",
192
+ 'unAGlyphs' => true,
193
+ ),
194
+ "xbzar" => array(
195
+ 'R' => "XB Zar.ttf",
196
+ 'B' => "XB Zar Bd.ttf",
197
+ 'I' => "XB Zar It.ttf",
198
+ 'BI' => "XB Zar BdIt.ttf",
199
+ 'unAGlyphs' => true,
200
+ ),
201
+
202
+
203
+
204
+
205
+ /* Examples of some CJK fonts */
206
+ /*
207
+ "unbatang_0613" => array(
208
+ 'R' => "UnBatang_0613.ttf",
209
+ ),
210
+ "sun-exta" => array(
211
+ 'R' => "Sun-ExtA.ttf",
212
+ 'sip-ext' => 'sun-extb',
213
+ ),
214
+ "sun-extb" => array(
215
+ 'R' => "Sun-ExtB.ttf",
216
+ ),
217
+ "hannoma" => array(
218
+ 'R' => "HAN NOM A.ttf",
219
+ 'sip-ext' => 'hannomb',
220
+ ),
221
+ "hannomb" => array(
222
+ 'R' => "HAN NOM B.ttf",
223
+ ),
224
+
225
+
226
+ 'mingliu' => array (
227
+ 'R' => 'mingliu.ttc',
228
+ 'TTCfontID' => array (
229
+ 'R' => 1,
230
+ ),
231
+ 'sip-ext' => 'mingliu-extb',
232
+ ),
233
+ 'pmingliu' => array (
234
+ 'R' => 'mingliu.ttc',
235
+ 'TTCfontID' => array (
236
+ 'R' => 2,
237
+ ),
238
+ 'sip-ext' => 'pmingliu-extb',
239
+ ),
240
+ 'mingliu_hkscs' => array (
241
+ 'R' => 'mingliu.ttc',
242
+ 'TTCfontID' => array (
243
+ 'R' => 3,
244
+ ),
245
+ 'sip-ext' => 'mingliu_hkscs-extb',
246
+ ),
247
+ 'mingliu-extb' => array (
248
+ 'R' => 'mingliub.ttc',
249
+ 'TTCfontID' => array (
250
+ 'R' => 1,
251
+ ),
252
+ ),
253
+ 'pmingliu-extb' => array (
254
+ 'R' => 'mingliub.ttc',
255
+ 'TTCfontID' => array (
256
+ 'R' => 2,
257
+ ),
258
+ ),
259
+ 'mingliu_hkscs-extb' => array (
260
+ 'R' => 'mingliub.ttc',
261
+ 'TTCfontID' => array (
262
+ 'R' => 3,
263
+ ),
264
+ ),
265
+ */
266
+
267
+ );
268
+
269
+
270
+ // Add fonts to this array if they contain characters in the SIP or SMP Unicode planes
271
+ // but you do not require them. This allows a more efficient form of subsetting to be used.
272
+ $this->BMPonly = array(
273
+ "dejavusanscondensed",
274
+ "dejavusans",
275
+ "dejavuserifcondensed",
276
+ "dejavuserif",
277
+ "dejavusansmono",
278
+ );
279
+
280
+ // These next 3 arrays do two things:
281
+ // 1. If a font referred to in HTML/CSS is not available to mPDF, these arrays will determine whether
282
+ // a serif/sans-serif or monospace font is substituted
283
+ // 2. The first font in each array will be the font which is substituted in circumstances as above
284
+ // (Otherwise the order is irrelevant)
285
+ // Use the mPDF font-family names i.e. lowercase and no spaces (after any translations in $fonttrans)
286
+ // Always include "sans-serif", "serif" and "monospace" etc.
287
+ $this->sans_fonts = array('dejavusanscondensed','dejavusans','freesans','liberationsans','sans','sans-serif','cursive','fantasy',
288
+ 'arial','helvetica','verdana','geneva','lucida','arialnarrow','arialblack','arialunicodems',
289
+ 'franklin','franklingothicbook','tahoma','garuda','calibri','trebuchet','lucidagrande','microsoftsansserif',
290
+ 'trebuchetms','lucidasansunicode','franklingothicmedium','albertusmedium','xbriyaz','albasuper','quillscript'
291
+
292
+ );
293
+
294
+ $this->serif_fonts = array('dejavuserifcondensed','dejavuserif','freeserif','liberationserif','serif',
295
+ 'timesnewroman','times','centuryschoolbookl','palatinolinotype','centurygothic',
296
+ 'bookmanoldstyle','bookantiqua','cyberbit','cambria',
297
+ 'norasi','charis','palatino','constantia','georgia','albertus','xbzar','algerian','garamond',
298
+ );
299
+
300
+ $this->mono_fonts = array('dejavusansmono','freemono','liberationmono','courier', 'mono','monospace','ocrb','ocr-b','lucidaconsole',
301
+ 'couriernew','monotypecorsiva'
302
+ );
303
+
304
+ ?>
mpdf/font/ccourier.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ for($i=0;$i<=255;$i++)
3
+ $cw[chr($i)]=600;
4
+
5
+ $desc=array('Ascent'=>629,'Descent'=>-157,'CapHeight'=>562,'FontBBox'=>'[-23 -250 715 805]');
6
+ $up=-100;
7
+ $ut=50;
8
+
9
+ ?>
mpdf/font/ccourierb.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ for($i=0;$i<=255;$i++)
3
+ $cw[chr($i)]=600;
4
+ $desc=array('Ascent'=>629,'Descent'=>-157,'CapHeight'=>562,'FontBBox'=>'[-113 -250 749 801]');
5
+ $up=-100;
6
+ $ut=50;
7
+
8
+
9
+ ?>
mpdf/font/ccourierbi.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ for($i=0;$i<=255;$i++)
3
+ $cw[chr($i)]=600;
4
+ $desc=array('Ascent'=>629,'Descent'=>-157,'CapHeight'=>562,'FontBBox'=>'[-57 -250 869 801]');
5
+ $up=-100;
6
+ $ut=50;
7
+
8
+
9
+ ?>
mpdf/font/ccourieri.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ for($i=0;$i<=255;$i++)
3
+ $cw[chr($i)]=600;
4
+ $desc=array('Ascent'=>629,'Descent'=>-157,'CapHeight'=>562,'FontBBox'=>'[-27 -250 849 805]');
5
+ $up=-100;
6
+ $ut=50;
7
+
8
+
9
+ ?>
mpdf/font/chelvetica.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $cw=array(
3
+ chr(0)=>278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278,
4
+ chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>278,'"'=>355,'#'=>556,'$'=>556,'%'=>889,'&'=>667,'\''=>191,'('=>333,')'=>333,'*'=>389,'+'=>584,
5
+ ','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>278,';'=>278,'<'=>584,'='=>584,'>'=>584,'?'=>556,'@'=>1015,'A'=>667,
6
+ 'B'=>667,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>500,'K'=>667,'L'=>556,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944,
7
+ 'X'=>667,'Y'=>667,'Z'=>611,'['=>278,'\\'=>278,']'=>278,'^'=>469,'_'=>556,'`'=>333,'a'=>556,'b'=>556,'c'=>500,'d'=>556,'e'=>556,'f'=>278,'g'=>556,'h'=>556,'i'=>222,'j'=>222,'k'=>500,'l'=>222,'m'=>833,
8
+ 'n'=>556,'o'=>556,'p'=>556,'q'=>556,'r'=>333,'s'=>500,'t'=>278,'u'=>556,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>500,'{'=>334,'|'=>260,'}'=>334,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>222,chr(131)=>556,
9
+ chr(132)=>333,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>222,chr(146)=>222,chr(147)=>333,chr(148)=>333,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000,
10
+ chr(154)=>500,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>260,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333,
11
+ chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>556,chr(182)=>537,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>667,chr(193)=>667,chr(194)=>667,chr(195)=>667,chr(196)=>667,chr(197)=>667,
12
+ chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722,
13
+ chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>500,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>556,chr(241)=>556,
14
+ chr(242)=>556,chr(243)=>556,chr(244)=>556,chr(245)=>556,chr(246)=>556,chr(247)=>584,chr(248)=>611,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>500,chr(254)=>556,chr(255)=>500);
15
+
16
+ $desc=array('Ascent'=>718,'Descent'=>-207,'CapHeight'=>718,'FontBBox'=>'[-166 -225 1000 931]');
17
+ $up=-100;
18
+ $ut=50;
19
+ $kerninfo=array ( chr(49)=> array ( chr(49)=> -74, ), chr(65)=> array ( chr(84)=> -74, chr(86)=> -74, chr(87)=> -37, chr(89)=> -74, chr(118)=> -18, chr(119)=> -18, chr(121)=> -18, chr(146)=> -74, ), chr(70)=> array ( chr(44)=> -110, chr(46)=> -110, chr(65)=> -55, ), chr(76)=> array ( chr(84)=> -74, chr(86)=> -74, chr(87)=> -74, chr(89)=> -74, chr(121)=> -37, chr(146)=> -55, ), chr(80)=> array ( chr(44)=> -128, chr(46)=> -128, chr(65)=> -74, ), chr(82)=> array ( chr(84)=> -18, chr(86)=> -18, chr(87)=> -18, chr(89)=> -18, ), chr(84)=> array ( chr(44)=> -110, chr(46)=> -110, chr(58)=> -110, chr(65)=> -74, chr(79)=> -18, chr(97)=> -110, chr(99)=> -110, chr(101)=> -110, chr(105)=> -37, chr(111)=> -110, chr(114)=> -37, chr(115)=> -110, chr(117)=> -37, chr(119)=> -55, chr(121)=> -55, ), chr(86)=> array ( chr(44)=> -91, chr(46)=> -91, chr(58)=> -37, chr(65)=> -74, chr(97)=> -74, chr(101)=> -55, chr(105)=> -18, chr(111)=> -55, chr(114)=> -37, chr(117)=> -37, chr(121)=> -37, ), chr(87)=> array ( chr(44)=> -55, chr(46)=> -55, chr(58)=> -18, chr(65)=> -37, chr(97)=> -37, chr(101)=> -18, chr(105)=> 0, chr(111)=> -18, chr(114)=> -18, chr(117)=> -18, chr(121)=> -8, ), chr(89)=> array ( chr(44)=> -128, chr(46)=> -128, chr(58)=> -55, chr(65)=> -74, chr(97)=> -74, chr(101)=> -91, chr(105)=> -37, chr(111)=> -91, chr(112)=> -74, chr(113)=> -91, chr(117)=> -55, chr(118)=> -55, ), chr(102)=> array ( chr(102)=> -18, chr(146)=> 18, ), chr(114)=> array ( chr(44)=> -55, chr(46)=> -55, chr(146)=> 37, ), chr(118)=> array ( chr(44)=> -74, chr(46)=> -74, ), chr(119)=> array ( chr(44)=> -55, chr(46)=> -55, ), chr(121)=> array ( chr(44)=> -74, chr(46)=> -74, ), chr(145)=> array ( chr(145)=> -18, ), chr(146)=> array ( chr(115)=> -18, chr(146)=> -18, ), );
20
+ ?>
mpdf/font/chelveticab.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $cw=array(
3
+ chr(0)=>278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278,
4
+ chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>333,'"'=>474,'#'=>556,'$'=>556,'%'=>889,'&'=>722,'\''=>238,'('=>333,')'=>333,'*'=>389,'+'=>584,
5
+ ','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>333,';'=>333,'<'=>584,'='=>584,'>'=>584,'?'=>611,'@'=>975,'A'=>722,
6
+ 'B'=>722,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>556,'K'=>722,'L'=>611,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944,
7
+ 'X'=>667,'Y'=>667,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>584,'_'=>556,'`'=>333,'a'=>556,'b'=>611,'c'=>556,'d'=>611,'e'=>556,'f'=>333,'g'=>611,'h'=>611,'i'=>278,'j'=>278,'k'=>556,'l'=>278,'m'=>889,
8
+ 'n'=>611,'o'=>611,'p'=>611,'q'=>611,'r'=>389,'s'=>556,'t'=>333,'u'=>611,'v'=>556,'w'=>778,'x'=>556,'y'=>556,'z'=>500,'{'=>389,'|'=>280,'}'=>389,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>278,chr(131)=>556,
9
+ chr(132)=>500,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>278,chr(146)=>278,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000,
10
+ chr(154)=>556,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>280,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333,
11
+ chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>611,chr(182)=>556,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722,
12
+ chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722,
13
+ chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>556,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>611,chr(241)=>611,
14
+ chr(242)=>611,chr(243)=>611,chr(244)=>611,chr(245)=>611,chr(246)=>611,chr(247)=>584,chr(248)=>611,chr(249)=>611,chr(250)=>611,chr(251)=>611,chr(252)=>611,chr(253)=>556,chr(254)=>611,chr(255)=>556);
15
+
16
+ $desc=array('Ascent'=>718,'Descent'=>-207,'CapHeight'=>718,'FontBBox'=>'[-170 -228 1003 962]');
17
+ $up=-100;
18
+ $ut=50;
19
+ $kerninfo=array ( chr(49)=> array ( chr(49)=> -55, ), chr(65)=> array ( chr(84)=> -74, chr(86)=> -74, chr(87)=> -55, chr(89)=> -91, chr(118)=> -37, chr(119)=> -18, chr(121)=> -37, chr(146)=> -55, ), chr(70)=> array ( chr(44)=> -110, chr(46)=> -110, chr(65)=> -55, ), chr(76)=> array ( chr(84)=> -74, chr(86)=> -74, chr(87)=> -55, chr(89)=> -91, chr(121)=> -37, chr(146)=> -55, ), chr(80)=> array ( chr(44)=> -128, chr(46)=> -128, chr(65)=> -74, ), chr(82)=> array ( chr(86)=> -18, chr(87)=> -18, chr(89)=> -37, ), chr(84)=> array ( chr(44)=> -110, chr(46)=> -110, chr(58)=> -110, chr(65)=> -74, chr(79)=> -18, chr(97)=> -74, chr(99)=> -74, chr(101)=> -74, chr(105)=> -18, chr(111)=> -74, chr(114)=> -55, chr(115)=> -74, chr(117)=> -74, chr(119)=> -74, chr(121)=> -74, ), chr(86)=> array ( chr(44)=> -91, chr(46)=> -91, chr(58)=> -55, chr(65)=> -74, chr(97)=> -55, chr(101)=> -55, chr(105)=> -18, chr(111)=> -74, chr(114)=> -55, chr(117)=> -37, chr(121)=> -37, ), chr(87)=> array ( chr(44)=> -55, chr(46)=> -55, chr(58)=> -18, chr(65)=> -55, chr(97)=> -37, chr(101)=> -18, chr(105)=> -8, chr(111)=> -18, chr(114)=> -18, chr(117)=> -18, chr(121)=> -18, ), chr(89)=> array ( chr(44)=> -110, chr(46)=> -110, chr(58)=> -74, chr(65)=> -91, chr(97)=> -55, chr(101)=> -55, chr(105)=> -37, chr(111)=> -74, chr(112)=> -55, chr(113)=> -74, chr(117)=> -55, chr(118)=> -55, ), chr(102)=> array ( chr(146)=> 18, ), chr(114)=> array ( chr(44)=> -55, chr(46)=> -55, chr(146)=> 37, ), chr(118)=> array ( chr(44)=> -74, chr(46)=> -74, ), chr(119)=> array ( chr(44)=> -37, chr(46)=> -37, ), chr(121)=> array ( chr(44)=> -74, chr(46)=> -74, ), chr(145)=> array ( chr(145)=> -37, ), chr(146)=> array ( chr(115)=> -37, chr(146)=> -37, ), );
20
+
21
+ ?>
mpdf/font/chelveticabi.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $cw=array(
3
+ chr(0)=>278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278,
4
+ chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>333,'"'=>474,'#'=>556,'$'=>556,'%'=>889,'&'=>722,'\''=>238,'('=>333,')'=>333,'*'=>389,'+'=>584,
5
+ ','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>333,';'=>333,'<'=>584,'='=>584,'>'=>584,'?'=>611,'@'=>975,'A'=>722,
6
+ 'B'=>722,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>556,'K'=>722,'L'=>611,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944,
7
+ 'X'=>667,'Y'=>667,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>584,'_'=>556,'`'=>333,'a'=>556,'b'=>611,'c'=>556,'d'=>611,'e'=>556,'f'=>333,'g'=>611,'h'=>611,'i'=>278,'j'=>278,'k'=>556,'l'=>278,'m'=>889,
8
+ 'n'=>611,'o'=>611,'p'=>611,'q'=>611,'r'=>389,'s'=>556,'t'=>333,'u'=>611,'v'=>556,'w'=>778,'x'=>556,'y'=>556,'z'=>500,'{'=>389,'|'=>280,'}'=>389,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>278,chr(131)=>556,
9
+ chr(132)=>500,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>278,chr(146)=>278,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000,
10
+ chr(154)=>556,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>280,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333,
11
+ chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>611,chr(182)=>556,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722,
12
+ chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722,
13
+ chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>556,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>611,chr(241)=>611,
14
+ chr(242)=>611,chr(243)=>611,chr(244)=>611,chr(245)=>611,chr(246)=>611,chr(247)=>584,chr(248)=>611,chr(249)=>611,chr(250)=>611,chr(251)=>611,chr(252)=>611,chr(253)=>556,chr(254)=>611,chr(255)=>556);
15
+
16
+ $desc=array('Ascent'=>718,'Descent'=>-207,'CapHeight'=>718,'FontBBox'=>'[-174 -228 1114 962]');
17
+ $up=-100;
18
+ $ut=50;
19
+ $kerninfo=array ( chr(49)=> array ( chr(49)=> -74, ), chr(65)=> array ( chr(84)=> -74, chr(86)=> -74, chr(87)=> -55, chr(89)=> -74, chr(146)=> -55, ), chr(70)=> array ( chr(44)=> -110, chr(46)=> -110, chr(65)=> -55, ), chr(76)=> array ( chr(84)=> -74, chr(86)=> -55, chr(87)=> -55, chr(89)=> -74, chr(146)=> -74, ), chr(80)=> array ( chr(44)=> -128, chr(46)=> -128, chr(65)=> -74, ), chr(82)=> array ( chr(84)=> -18, chr(87)=> -18, chr(89)=> -18, ), chr(84)=> array ( chr(44)=> -74, chr(46)=> -74, chr(58)=> -74, chr(65)=> -74, chr(79)=> -18, chr(97)=> -37, chr(99)=> -37, chr(101)=> -37, chr(105)=> -18, chr(111)=> -37, chr(114)=> -18, chr(115)=> -37, chr(117)=> -18, chr(119)=> -37, chr(121)=> -37, ), chr(86)=> array ( chr(44)=> -91, chr(46)=> -91, chr(58)=> -37, chr(65)=> -74, chr(97)=> -37, chr(101)=> -37, chr(105)=> -37, chr(111)=> -37, chr(114)=> -18, chr(117)=> -18, chr(121)=> -18, ), chr(87)=> array ( chr(44)=> -74, chr(46)=> -74, chr(58)=> -37, chr(65)=> -55, chr(97)=> -18, chr(101)=> -18, chr(105)=> -8, chr(111)=> -18, chr(114)=> -18, chr(117)=> -18, chr(121)=> -18, ), chr(89)=> array ( chr(44)=> -91, chr(46)=> -91, chr(58)=> -55, chr(65)=> -74, chr(97)=> -37, chr(101)=> -37, chr(105)=> -37, chr(111)=> -37, chr(112)=> -37, chr(113)=> -37, chr(117)=> -37, chr(118)=> -37, ), chr(102)=> array ( chr(102)=> -18, chr(146)=> 18, ), chr(114)=> array ( chr(44)=> -55, chr(46)=> -55, chr(146)=> 37, ), chr(118)=> array ( chr(44)=> -55, chr(46)=> -55, ), chr(119)=> array ( chr(44)=> -37, chr(46)=> -37, ), chr(121)=> array ( chr(44)=> -37, chr(46)=> -37, ), chr(145)=> array ( chr(145)=> -37, ), chr(146)=> array ( chr(115)=> -18, chr(116)=> 18, chr(146)=> -37, ), );
20
+
21
+ ?>
mpdf/font/chelveticai.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $cw=array(
3
+ chr(0)=>278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278,
4
+ chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>278,'"'=>355,'#'=>556,'$'=>556,'%'=>889,'&'=>667,'\''=>191,'('=>333,')'=>333,'*'=>389,'+'=>584,
5
+ ','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>278,';'=>278,'<'=>584,'='=>584,'>'=>584,'?'=>556,'@'=>1015,'A'=>667,
6
+ 'B'=>667,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>500,'K'=>667,'L'=>556,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944,
7
+ 'X'=>667,'Y'=>667,'Z'=>611,'['=>278,'\\'=>278,']'=>278,'^'=>469,'_'=>556,'`'=>333,'a'=>556,'b'=>556,'c'=>500,'d'=>556,'e'=>556,'f'=>278,'g'=>556,'h'=>556,'i'=>222,'j'=>222,'k'=>500,'l'=>222,'m'=>833,
8
+ 'n'=>556,'o'=>556,'p'=>556,'q'=>556,'r'=>333,'s'=>500,'t'=>278,'u'=>556,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>500,'{'=>334,'|'=>260,'}'=>334,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>222,chr(131)=>556,
9
+ chr(132)=>333,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>222,chr(146)=>222,chr(147)=>333,chr(148)=>333,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000,
10
+ chr(154)=>500,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>260,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333,
11
+ chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>556,chr(182)=>537,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>667,chr(193)=>667,chr(194)=>667,chr(195)=>667,chr(196)=>667,chr(197)=>667,
12
+ chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722,
13
+ chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>500,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>556,chr(241)=>556,
14
+ chr(242)=>556,chr(243)=>556,chr(244)=>556,chr(245)=>556,chr(246)=>556,chr(247)=>584,chr(248)=>611,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>500,chr(254)=>556,chr(255)=>500);
15
+
16
+ $desc=array('Ascent'=>718,'Descent'=>-207,'CapHeight'=>718,'FontBBox'=>'[-170 -225 1116 931]');
17
+ $up=-100;
18
+ $ut=50;
19
+ $kerninfo=array ( chr(49)=> array ( chr(49)=> -74, ), chr(65)=> array ( chr(84)=> -74, chr(86)=> -55, chr(87)=> -18, chr(89)=> -74, chr(118)=> -18, chr(119)=> -18, chr(121)=> -8, chr(146)=> -37, ), chr(70)=> array ( chr(44)=> -128, chr(46)=> -128, chr(65)=> -74, ), chr(76)=> array ( chr(84)=> -74, chr(86)=> -55, chr(87)=> -37, chr(89)=> -91, chr(121)=> -18, chr(146)=> -55, ), chr(80)=> array ( chr(44)=> -128, chr(46)=> -128, chr(65)=> -74, ), chr(82)=> array ( chr(84)=> -18, chr(86)=> -18, chr(87)=> -18, chr(89)=> -37, ), chr(84)=> array ( chr(44)=> -91, chr(46)=> -91, chr(58)=> -74, chr(65)=> -74, chr(79)=> -18, chr(97)=> -91, chr(99)=> -91, chr(101)=> -91, chr(105)=> -8, chr(111)=> -91, chr(114)=> -74, chr(115)=> -91, chr(117)=> -74, chr(119)=> -74, chr(121)=> -74, ), chr(86)=> array ( chr(44)=> -74, chr(46)=> -74, chr(58)=> -18, chr(65)=> -55, chr(97)=> -37, chr(101)=> -37, chr(105)=> -18, chr(111)=> -37, chr(114)=> -18, chr(117)=> -18, chr(121)=> -18, ), chr(87)=> array ( chr(44)=> -37, chr(46)=> -37, chr(65)=> -18, chr(97)=> -18, chr(101)=> -18, chr(105)=> -8, ), chr(89)=> array ( chr(44)=> -91, chr(46)=> -91, chr(58)=> -37, chr(65)=> -55, chr(97)=> -74, chr(101)=> -55, chr(105)=> -18, chr(111)=> -55, chr(112)=> -55, chr(113)=> -55, chr(117)=> -37, chr(118)=> -37, ), chr(102)=> array ( chr(146)=> 37, ), chr(114)=> array ( chr(44)=> -55, chr(46)=> -37, chr(146)=> 37, ), chr(118)=> array ( chr(44)=> -74, chr(46)=> -74, ), chr(119)=> array ( chr(44)=> -55, chr(46)=> -55, ), chr(121)=> array ( chr(44)=> -74, chr(46)=> -74, ), chr(145)=> array ( chr(145)=> -37, ), chr(146)=> array ( chr(115)=> -18, chr(146)=> -37, ), );
20
+
21
+ ?>
mpdf/font/csymbol.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $cw=array(
3
+ chr(0)=>250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250,
4
+ chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>713,'#'=>500,'$'=>549,'%'=>833,'&'=>778,'\''=>439,'('=>333,')'=>333,'*'=>500,'+'=>549,
5
+ ','=>250,'-'=>549,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>278,';'=>278,'<'=>549,'='=>549,'>'=>549,'?'=>444,'@'=>549,'A'=>722,
6
+ 'B'=>667,'C'=>722,'D'=>612,'E'=>611,'F'=>763,'G'=>603,'H'=>722,'I'=>333,'J'=>631,'K'=>722,'L'=>686,'M'=>889,'N'=>722,'O'=>722,'P'=>768,'Q'=>741,'R'=>556,'S'=>592,'T'=>611,'U'=>690,'V'=>439,'W'=>768,
7
+ 'X'=>645,'Y'=>795,'Z'=>611,'['=>333,'\\'=>863,']'=>333,'^'=>658,'_'=>500,'`'=>500,'a'=>631,'b'=>549,'c'=>549,'d'=>494,'e'=>439,'f'=>521,'g'=>411,'h'=>603,'i'=>329,'j'=>603,'k'=>549,'l'=>549,'m'=>576,
8
+ 'n'=>521,'o'=>549,'p'=>549,'q'=>521,'r'=>549,'s'=>603,'t'=>439,'u'=>576,'v'=>713,'w'=>686,'x'=>493,'y'=>686,'z'=>494,'{'=>480,'|'=>200,'}'=>480,'~'=>549,chr(127)=>0,chr(128)=>0,chr(129)=>0,chr(130)=>0,chr(131)=>0,
9
+ chr(132)=>0,chr(133)=>0,chr(134)=>0,chr(135)=>0,chr(136)=>0,chr(137)=>0,chr(138)=>0,chr(139)=>0,chr(140)=>0,chr(141)=>0,chr(142)=>0,chr(143)=>0,chr(144)=>0,chr(145)=>0,chr(146)=>0,chr(147)=>0,chr(148)=>0,chr(149)=>0,chr(150)=>0,chr(151)=>0,chr(152)=>0,chr(153)=>0,
10
+ chr(154)=>0,chr(155)=>0,chr(156)=>0,chr(157)=>0,chr(158)=>0,chr(159)=>0,chr(160)=>750,chr(161)=>620,chr(162)=>247,chr(163)=>549,chr(164)=>167,chr(165)=>713,chr(166)=>500,chr(167)=>753,chr(168)=>753,chr(169)=>753,chr(170)=>753,chr(171)=>1042,chr(172)=>987,chr(173)=>603,chr(174)=>987,chr(175)=>603,
11
+ chr(176)=>400,chr(177)=>549,chr(178)=>411,chr(179)=>549,chr(180)=>549,chr(181)=>713,chr(182)=>494,chr(183)=>460,chr(184)=>549,chr(185)=>549,chr(186)=>549,chr(187)=>549,chr(188)=>1000,chr(189)=>603,chr(190)=>1000,chr(191)=>658,chr(192)=>823,chr(193)=>686,chr(194)=>795,chr(195)=>987,chr(196)=>768,chr(197)=>768,
12
+ chr(198)=>823,chr(199)=>768,chr(200)=>768,chr(201)=>713,chr(202)=>713,chr(203)=>713,chr(204)=>713,chr(205)=>713,chr(206)=>713,chr(207)=>713,chr(208)=>768,chr(209)=>713,chr(210)=>790,chr(211)=>790,chr(212)=>890,chr(213)=>823,chr(214)=>549,chr(215)=>250,chr(216)=>713,chr(217)=>603,chr(218)=>603,chr(219)=>1042,
13
+ chr(220)=>987,chr(221)=>603,chr(222)=>987,chr(223)=>603,chr(224)=>494,chr(225)=>329,chr(226)=>790,chr(227)=>790,chr(228)=>786,chr(229)=>713,chr(230)=>384,chr(231)=>384,chr(232)=>384,chr(233)=>384,chr(234)=>384,chr(235)=>384,chr(236)=>494,chr(237)=>494,chr(238)=>494,chr(239)=>494,chr(240)=>0,chr(241)=>329,
14
+ chr(242)=>274,chr(243)=>686,chr(244)=>686,chr(245)=>686,chr(246)=>384,chr(247)=>384,chr(248)=>384,chr(249)=>384,chr(250)=>384,chr(251)=>384,chr(252)=>494,chr(253)=>494,chr(254)=>494,chr(255)=>0);
15
+
16
+ $desc=array('FontBBox'=>'[-180 -293 1090 1010]');
17
+ $up=-100;
18
+ $ut=50;
19
+
20
+
21
+ ?>
mpdf/font/ctimes.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $cw=array(
3
+ chr(0)=>250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250,
4
+ chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>408,'#'=>500,'$'=>500,'%'=>833,'&'=>778,'\''=>180,'('=>333,')'=>333,'*'=>500,'+'=>564,
5
+ ','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>278,';'=>278,'<'=>564,'='=>564,'>'=>564,'?'=>444,'@'=>921,'A'=>722,
6
+ 'B'=>667,'C'=>667,'D'=>722,'E'=>611,'F'=>556,'G'=>722,'H'=>722,'I'=>333,'J'=>389,'K'=>722,'L'=>611,'M'=>889,'N'=>722,'O'=>722,'P'=>556,'Q'=>722,'R'=>667,'S'=>556,'T'=>611,'U'=>722,'V'=>722,'W'=>944,
7
+ 'X'=>722,'Y'=>722,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>469,'_'=>500,'`'=>333,'a'=>444,'b'=>500,'c'=>444,'d'=>500,'e'=>444,'f'=>333,'g'=>500,'h'=>500,'i'=>278,'j'=>278,'k'=>500,'l'=>278,'m'=>778,
8
+ 'n'=>500,'o'=>500,'p'=>500,'q'=>500,'r'=>333,'s'=>389,'t'=>278,'u'=>500,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>444,'{'=>480,'|'=>200,'}'=>480,'~'=>541,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500,
9
+ chr(132)=>444,chr(133)=>1000,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>556,chr(139)=>333,chr(140)=>889,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>444,chr(148)=>444,chr(149)=>350,chr(150)=>500,chr(151)=>1000,chr(152)=>333,chr(153)=>980,
10
+ chr(154)=>389,chr(155)=>333,chr(156)=>722,chr(157)=>350,chr(158)=>444,chr(159)=>722,chr(160)=>250,chr(161)=>333,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>200,chr(167)=>500,chr(168)=>333,chr(169)=>760,chr(170)=>276,chr(171)=>500,chr(172)=>564,chr(173)=>333,chr(174)=>760,chr(175)=>333,
11
+ chr(176)=>400,chr(177)=>564,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>500,chr(182)=>453,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>310,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>444,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722,
12
+ chr(198)=>889,chr(199)=>667,chr(200)=>611,chr(201)=>611,chr(202)=>611,chr(203)=>611,chr(204)=>333,chr(205)=>333,chr(206)=>333,chr(207)=>333,chr(208)=>722,chr(209)=>722,chr(210)=>722,chr(211)=>722,chr(212)=>722,chr(213)=>722,chr(214)=>722,chr(215)=>564,chr(216)=>722,chr(217)=>722,chr(218)=>722,chr(219)=>722,
13
+ chr(220)=>722,chr(221)=>722,chr(222)=>556,chr(223)=>500,chr(224)=>444,chr(225)=>444,chr(226)=>444,chr(227)=>444,chr(228)=>444,chr(229)=>444,chr(230)=>667,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>500,
14
+ chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>564,chr(248)=>500,chr(249)=>500,chr(250)=>500,chr(251)=>500,chr(252)=>500,chr(253)=>500,chr(254)=>500,chr(255)=>500);
15
+
16
+ $desc=array('Ascent'=>683,'Descent'=>-217,'CapHeight'=>662,'FontBBox'=>'[-168 -218 1000 898]');
17
+ $up=-100;
18
+ $ut=50;
19
+ $kerninfo=array ( chr(49)=> array ( chr(49)=> -37, ), chr(65)=> array ( chr(84)=> -110, chr(86)=> -128, chr(87)=> -80, chr(89)=> -91, chr(118)=> -74, chr(119)=> -91, chr(121)=> -91, chr(146)=> -110, ), chr(70)=> array ( chr(44)=> -80, chr(46)=> -80, chr(65)=> -74, ), chr(76)=> array ( chr(84)=> -91, chr(86)=> -91, chr(87)=> -74, chr(89)=> -100, chr(121)=> -55, chr(146)=> -91, ), chr(80)=> array ( chr(44)=> -110, chr(46)=> -110, chr(65)=> -91, ), chr(82)=> array ( chr(84)=> -60, chr(86)=> -80, chr(87)=> -55, chr(89)=> -55, chr(121)=> -40, ), chr(84)=> array ( chr(44)=> -74, chr(46)=> -74, chr(58)=> -49, chr(65)=> -80, chr(79)=> -18, chr(97)=> -69, chr(99)=> -69, chr(101)=> -69, chr(105)=> -35, chr(111)=> -69, chr(114)=> -35, chr(115)=> -69, chr(117)=> -35, chr(119)=> -69, chr(121)=> -69, ), chr(86)=> array ( chr(44)=> -128, chr(46)=> -128, chr(58)=> -74, chr(65)=> -128, chr(97)=> -110, chr(101)=> -110, chr(105)=> -60, chr(111)=> -128, chr(114)=> -60, chr(117)=> -60, chr(121)=> -110, ), chr(87)=> array ( chr(44)=> -91, chr(46)=> -91, chr(58)=> -37, chr(65)=> -110, chr(97)=> -80, chr(101)=> -80, chr(105)=> -40, chr(111)=> -80, chr(114)=> -40, chr(117)=> -40, chr(121)=> -60, ), chr(89)=> array ( chr(44)=> -128, chr(46)=> -128, chr(58)=> -91, chr(65)=> -110, chr(97)=> -100, chr(101)=> -100, chr(105)=> -55, chr(111)=> -100, chr(112)=> -91, chr(113)=> -110, chr(117)=> -110, chr(118)=> -100, ), chr(102)=> array ( chr(102)=> -18, chr(146)=> 55, ), chr(114)=> array ( chr(44)=> -40, chr(46)=> -55, chr(103)=> -18, chr(146)=> 37, ), chr(118)=> array ( chr(44)=> -64, chr(46)=> -64, ), chr(119)=> array ( chr(44)=> -64, chr(46)=> -64, ), chr(121)=> array ( chr(44)=> -64, chr(46)=> -64, ), chr(145)=> array ( chr(145)=> -74, ), chr(146)=> array ( chr(115)=> -55, chr(116)=> -18, chr(146)=> -74, ), );
20
+
21
+ ?>
mpdf/font/ctimesb.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $cw=array(
3
+ chr(0)=>250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250,
4
+ chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>555,'#'=>500,'$'=>500,'%'=>1000,'&'=>833,'\''=>278,'('=>333,')'=>333,'*'=>500,'+'=>570,
5
+ ','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>333,';'=>333,'<'=>570,'='=>570,'>'=>570,'?'=>500,'@'=>930,'A'=>722,
6
+ 'B'=>667,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>778,'I'=>389,'J'=>500,'K'=>778,'L'=>667,'M'=>944,'N'=>722,'O'=>778,'P'=>611,'Q'=>778,'R'=>722,'S'=>556,'T'=>667,'U'=>722,'V'=>722,'W'=>1000,
7
+ 'X'=>722,'Y'=>722,'Z'=>667,'['=>333,'\\'=>278,']'=>333,'^'=>581,'_'=>500,'`'=>333,'a'=>500,'b'=>556,'c'=>444,'d'=>556,'e'=>444,'f'=>333,'g'=>500,'h'=>556,'i'=>278,'j'=>333,'k'=>556,'l'=>278,'m'=>833,
8
+ 'n'=>556,'o'=>500,'p'=>556,'q'=>556,'r'=>444,'s'=>389,'t'=>333,'u'=>556,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>444,'{'=>394,'|'=>220,'}'=>394,'~'=>520,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500,
9
+ chr(132)=>500,chr(133)=>1000,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>556,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>667,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>500,chr(151)=>1000,chr(152)=>333,chr(153)=>1000,
10
+ chr(154)=>389,chr(155)=>333,chr(156)=>722,chr(157)=>350,chr(158)=>444,chr(159)=>722,chr(160)=>250,chr(161)=>333,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>220,chr(167)=>500,chr(168)=>333,chr(169)=>747,chr(170)=>300,chr(171)=>500,chr(172)=>570,chr(173)=>333,chr(174)=>747,chr(175)=>333,
11
+ chr(176)=>400,chr(177)=>570,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>556,chr(182)=>540,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>330,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>500,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722,
12
+ chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>389,chr(205)=>389,chr(206)=>389,chr(207)=>389,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>570,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722,
13
+ chr(220)=>722,chr(221)=>722,chr(222)=>611,chr(223)=>556,chr(224)=>500,chr(225)=>500,chr(226)=>500,chr(227)=>500,chr(228)=>500,chr(229)=>500,chr(230)=>722,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>556,
14
+ chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>570,chr(248)=>500,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>500,chr(254)=>556,chr(255)=>500);
15
+
16
+ $desc=array('Ascent'=>683,'Descent'=>-217,'CapHeight'=>676,'FontBBox'=>'[-168 -218 1000 935]');
17
+ $up=-100;
18
+ $ut=50;
19
+ $kerninfo=array ( chr(49)=> array ( chr(49)=> -55, ), chr(65)=> array ( chr(84)=> -74, chr(86)=> -128, chr(87)=> -110, chr(89)=> -91, chr(118)=> -74, chr(119)=> -74, chr(121)=> -74, chr(146)=> -74, ), chr(70)=> array ( chr(44)=> -91, chr(46)=> -91, chr(65)=> -74, ), chr(76)=> array ( chr(84)=> -91, chr(86)=> -91, chr(87)=> -91, chr(89)=> -91, chr(121)=> -55, chr(146)=> -91, ), chr(80)=> array ( chr(44)=> -91, chr(46)=> -91, chr(65)=> -74, ), chr(82)=> array ( chr(84)=> -35, chr(86)=> -35, chr(87)=> -35, chr(89)=> -35, chr(121)=> -35, ), chr(84)=> array ( chr(44)=> -74, chr(46)=> -74, chr(58)=> -74, chr(65)=> -74, chr(79)=> -18, chr(97)=> -91, chr(99)=> -91, chr(101)=> -91, chr(105)=> -18, chr(111)=> -91, chr(114)=> -74, chr(115)=> -91, chr(117)=> -91, chr(119)=> -74, chr(121)=> -74, ), chr(86)=> array ( chr(44)=> -128, chr(46)=> -128, chr(58)=> -91, chr(65)=> -128, chr(79)=> -20, chr(97)=> -91, chr(101)=> -91, chr(105)=> -37, chr(111)=> -91, chr(114)=> -74, chr(117)=> -91, chr(121)=> -91, ), chr(87)=> array ( chr(44)=> -91, chr(46)=> -91, chr(58)=> -55, chr(65)=> -110, chr(97)=> -55, chr(101)=> -55, chr(105)=> -18, chr(111)=> -55, chr(114)=> -18, chr(117)=> -18, chr(121)=> -37, ), chr(89)=> array ( chr(44)=> -91, chr(46)=> -91, chr(58)=> -91, chr(65)=> -91, chr(97)=> -110, chr(101)=> -110, chr(105)=> -37, chr(111)=> -110, chr(112)=> -91, chr(113)=> -110, chr(117)=> -91, chr(118)=> -110, ), chr(102)=> array ( chr(102)=> 0, chr(146)=> 55, ), chr(114)=> array ( chr(44)=> -91, chr(46)=> -91, chr(99)=> -18, chr(101)=> -18, chr(104)=> 0, chr(111)=> -18, chr(113)=> -18, chr(116)=> 0, chr(119)=> 0, chr(120)=> 0, chr(121)=> 0, chr(122)=> 0, chr(146)=> 18, ), chr(118)=> array ( chr(44)=> -55, chr(46)=> -55, ), chr(119)=> array ( chr(44)=> -55, chr(46)=> -55, ), chr(121)=> array ( chr(44)=> -55, chr(46)=> -55, ), chr(145)=> array ( chr(145)=> -74, ), chr(146)=> array ( chr(115)=> -37, chr(146)=> -74, ), );
20
+
21
+ ?>
mpdf/font/ctimesbi.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $cw=array(
3
+ chr(0)=>250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250,
4
+ chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>389,'"'=>555,'#'=>500,'$'=>500,'%'=>833,'&'=>778,'\''=>278,'('=>333,')'=>333,'*'=>500,'+'=>570,
5
+ ','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>333,';'=>333,'<'=>570,'='=>570,'>'=>570,'?'=>500,'@'=>832,'A'=>667,
6
+ 'B'=>667,'C'=>667,'D'=>722,'E'=>667,'F'=>667,'G'=>722,'H'=>778,'I'=>389,'J'=>500,'K'=>667,'L'=>611,'M'=>889,'N'=>722,'O'=>722,'P'=>611,'Q'=>722,'R'=>667,'S'=>556,'T'=>611,'U'=>722,'V'=>667,'W'=>889,
7
+ 'X'=>667,'Y'=>611,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>570,'_'=>500,'`'=>333,'a'=>500,'b'=>500,'c'=>444,'d'=>500,'e'=>444,'f'=>333,'g'=>500,'h'=>556,'i'=>278,'j'=>278,'k'=>500,'l'=>278,'m'=>778,
8
+ 'n'=>556,'o'=>500,'p'=>500,'q'=>500,'r'=>389,'s'=>389,'t'=>278,'u'=>556,'v'=>444,'w'=>667,'x'=>500,'y'=>444,'z'=>389,'{'=>348,'|'=>220,'}'=>348,'~'=>570,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500,
9
+ chr(132)=>500,chr(133)=>1000,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>556,chr(139)=>333,chr(140)=>944,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>500,chr(151)=>1000,chr(152)=>333,chr(153)=>1000,
10
+ chr(154)=>389,chr(155)=>333,chr(156)=>722,chr(157)=>350,chr(158)=>389,chr(159)=>611,chr(160)=>250,chr(161)=>389,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>220,chr(167)=>500,chr(168)=>333,chr(169)=>747,chr(170)=>266,chr(171)=>500,chr(172)=>606,chr(173)=>333,chr(174)=>747,chr(175)=>333,
11
+ chr(176)=>400,chr(177)=>570,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>576,chr(182)=>500,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>300,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>500,chr(192)=>667,chr(193)=>667,chr(194)=>667,chr(195)=>667,chr(196)=>667,chr(197)=>667,
12
+ chr(198)=>944,chr(199)=>667,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>389,chr(205)=>389,chr(206)=>389,chr(207)=>389,chr(208)=>722,chr(209)=>722,chr(210)=>722,chr(211)=>722,chr(212)=>722,chr(213)=>722,chr(214)=>722,chr(215)=>570,chr(216)=>722,chr(217)=>722,chr(218)=>722,chr(219)=>722,
13
+ chr(220)=>722,chr(221)=>611,chr(222)=>611,chr(223)=>500,chr(224)=>500,chr(225)=>500,chr(226)=>500,chr(227)=>500,chr(228)=>500,chr(229)=>500,chr(230)=>722,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>556,
14
+ chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>570,chr(248)=>500,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>444,chr(254)=>500,chr(255)=>444);
15
+
16
+ $desc=array('Ascent'=>683,'Descent'=>-217,'CapHeight'=>669,'FontBBox'=>'[-200 -218 996 921]');
17
+ $up=-100;
18
+ $ut=50;
19
+ $kerninfo=array ( chr(49)=> array ( chr(49)=> -55, ), chr(65)=> array ( chr(84)=> -55, chr(86)=> -74, chr(87)=> -91, chr(89)=> -55, chr(118)=> -74, chr(119)=> -74, chr(121)=> -74, chr(146)=> -74, ), chr(70)=> array ( chr(44)=> -128, chr(46)=> -128, chr(65)=> -91, ), chr(76)=> array ( chr(84)=> -18, chr(86)=> -37, chr(87)=> -37, chr(89)=> -37, chr(121)=> -37, chr(146)=> -55, ), chr(80)=> array ( chr(44)=> -128, chr(46)=> -128, chr(65)=> -74, ), chr(82)=> array ( chr(86)=> -18, chr(87)=> -18, chr(89)=> -18, chr(121)=> -18, ), chr(84)=> array ( chr(44)=> -91, chr(46)=> -91, chr(58)=> -74, chr(65)=> -55, chr(79)=> -18, chr(97)=> -91, chr(99)=> -91, chr(101)=> -91, chr(105)=> -37, chr(111)=> -91, chr(114)=> -37, chr(115)=> -91, chr(117)=> -37, chr(119)=> -37, chr(121)=> -37, ), chr(86)=> array ( chr(44)=> -128, chr(46)=> -128, chr(58)=> -74, chr(65)=> -74, chr(97)=> -110, chr(101)=> -110, chr(105)=> -55, chr(111)=> -110, chr(114)=> -55, chr(117)=> -55, chr(121)=> -74, ), chr(87)=> array ( chr(44)=> -74, chr(46)=> -74, chr(58)=> -55, chr(65)=> -74, chr(97)=> -74, chr(101)=> -74, chr(105)=> -37, chr(111)=> -74, chr(114)=> -74, chr(117)=> -55, chr(121)=> -55, ), chr(89)=> array ( chr(44)=> -91, chr(46)=> -74, chr(58)=> -91, chr(65)=> -74, chr(97)=> -91, chr(101)=> -110, chr(105)=> -55, chr(111)=> -110, chr(112)=> -74, chr(113)=> -110, chr(117)=> -91, chr(118)=> -91, ), chr(102)=> array ( chr(102)=> -18, chr(146)=> 55, ), chr(114)=> array ( chr(44)=> -55, chr(46)=> -55, chr(146)=> 37, ), chr(118)=> array ( chr(44)=> -37, chr(46)=> -37, ), chr(119)=> array ( chr(44)=> -37, chr(46)=> -37, ), chr(121)=> array ( chr(44)=> -37, chr(46)=> -37, ), chr(145)=> array ( chr(145)=> -74, ), chr(146)=> array ( chr(115)=> -74, chr(116)=> -37, chr(146)=> -74, ), );
20
+
21
+ ?>
mpdf/font/ctimesi.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $cw=array(
3
+ chr(0)=>250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250,
4
+ chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>420,'#'=>500,'$'=>500,'%'=>833,'&'=>778,'\''=>214,'('=>333,')'=>333,'*'=>500,'+'=>675,
5
+ ','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>333,';'=>333,'<'=>675,'='=>675,'>'=>675,'?'=>500,'@'=>920,'A'=>611,
6
+ 'B'=>611,'C'=>667,'D'=>722,'E'=>611,'F'=>611,'G'=>722,'H'=>722,'I'=>333,'J'=>444,'K'=>667,'L'=>556,'M'=>833,'N'=>667,'O'=>722,'P'=>611,'Q'=>722,'R'=>611,'S'=>500,'T'=>556,'U'=>722,'V'=>611,'W'=>833,
7
+ 'X'=>611,'Y'=>556,'Z'=>556,'['=>389,'\\'=>278,']'=>389,'^'=>422,'_'=>500,'`'=>333,'a'=>500,'b'=>500,'c'=>444,'d'=>500,'e'=>444,'f'=>278,'g'=>500,'h'=>500,'i'=>278,'j'=>278,'k'=>444,'l'=>278,'m'=>722,
8
+ 'n'=>500,'o'=>500,'p'=>500,'q'=>500,'r'=>389,'s'=>389,'t'=>278,'u'=>500,'v'=>444,'w'=>667,'x'=>444,'y'=>444,'z'=>389,'{'=>400,'|'=>275,'}'=>400,'~'=>541,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500,
9
+ chr(132)=>556,chr(133)=>889,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>500,chr(139)=>333,chr(140)=>944,chr(141)=>350,chr(142)=>556,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>556,chr(148)=>556,chr(149)=>350,chr(150)=>500,chr(151)=>889,chr(152)=>333,chr(153)=>980,
10
+ chr(154)=>389,chr(155)=>333,chr(156)=>667,chr(157)=>350,chr(158)=>389,chr(159)=>556,chr(160)=>250,chr(161)=>389,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>275,chr(167)=>500,chr(168)=>333,chr(169)=>760,chr(170)=>276,chr(171)=>500,chr(172)=>675,chr(173)=>333,chr(174)=>760,chr(175)=>333,
11
+ chr(176)=>400,chr(177)=>675,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>500,chr(182)=>523,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>310,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>500,chr(192)=>611,chr(193)=>611,chr(194)=>611,chr(195)=>611,chr(196)=>611,chr(197)=>611,
12
+ chr(198)=>889,chr(199)=>667,chr(200)=>611,chr(201)=>611,chr(202)=>611,chr(203)=>611,chr(204)=>333,chr(205)=>333,chr(206)=>333,chr(207)=>333,chr(208)=>722,chr(209)=>667,chr(210)=>722,chr(211)=>722,chr(212)=>722,chr(213)=>722,chr(214)=>722,chr(215)=>675,chr(216)=>722,chr(217)=>722,chr(218)=>722,chr(219)=>722,
13
+ chr(220)=>722,chr(221)=>556,chr(222)=>611,chr(223)=>500,chr(224)=>500,chr(225)=>500,chr(226)=>500,chr(227)=>500,chr(228)=>500,chr(229)=>500,chr(230)=>667,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>500,
14
+ chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>675,chr(248)=>500,chr(249)=>500,chr(250)=>500,chr(251)=>500,chr(252)=>500,chr(253)=>444,chr(254)=>500,chr(255)=>444);
15
+
16
+ $desc=array('Ascent'=>683,'Descent'=>-217,'CapHeight'=>653,'FontBBox'=>'[-169 -217 1010 883]');
17
+ $up=-100;
18
+ $ut=50;
19
+ $kerninfo=array ( chr(49)=> array ( chr(49)=> -74, ), chr(65)=> array ( chr(84)=> -37, chr(86)=> -49, chr(87)=> -37, chr(89)=> -55, chr(118)=> -55, chr(119)=> -55, chr(121)=> -55, chr(146)=> -37, ), chr(70)=> array ( chr(44)=> -128, chr(46)=> -128, chr(65)=> -128, ), chr(76)=> array ( chr(84)=> -20, chr(86)=> -37, chr(87)=> -37, chr(89)=> -20, chr(121)=> -29, chr(146)=> -37, ), chr(80)=> array ( chr(44)=> -128, chr(46)=> -128, chr(65)=> -128, ), chr(82)=> array ( chr(84)=> 0, chr(86)=> -18, chr(87)=> -18, chr(89)=> -18, chr(121)=> -18, ), chr(84)=> array ( chr(44)=> -74, chr(46)=> -74, chr(58)=> -55, chr(65)=> -74, chr(79)=> -18, chr(97)=> -91, chr(99)=> -91, chr(101)=> -91, chr(105)=> -55, chr(111)=> -91, chr(114)=> -55, chr(115)=> -91, chr(117)=> -55, chr(119)=> -74, chr(121)=> -74, ), chr(86)=> array ( chr(44)=> -128, chr(46)=> -128, chr(58)=> -64, chr(65)=> -74, chr(79)=> -29, chr(97)=> -110, chr(101)=> -110, chr(105)=> -74, chr(111)=> -110, chr(114)=> -74, chr(117)=> -74, chr(121)=> -91, ), chr(87)=> array ( chr(44)=> -91, chr(46)=> -91, chr(58)=> -64, chr(65)=> -69, chr(97)=> -91, chr(101)=> -91, chr(105)=> -55, chr(111)=> -91, chr(114)=> -55, chr(117)=> -55, chr(121)=> -91, ), chr(89)=> array ( chr(44)=> -91, chr(46)=> -91, chr(58)=> -64, chr(65)=> -69, chr(97)=> -91, chr(101)=> -91, chr(105)=> -74, chr(111)=> -91, chr(112)=> -91, chr(113)=> -110, chr(117)=> -91, chr(118)=> -91, ), chr(102)=> array ( chr(146)=> 91, ), chr(114)=> array ( chr(44)=> -110, chr(46)=> -110, chr(99)=> -37, chr(100)=> -37, chr(101)=> -37, chr(103)=> -37, chr(104)=> -18, chr(111)=> -37, chr(113)=> -37, chr(114)=> 0, chr(116)=> 0, chr(117)=> 0, chr(118)=> 0, chr(119)=> 0, chr(120)=> 0, chr(121)=> 0, chr(146)=> 37, ), chr(118)=> array ( chr(44)=> -74, chr(46)=> -74, ), chr(119)=> array ( chr(44)=> -74, chr(46)=> -74, ), chr(121)=> array ( chr(44)=> -55, chr(46)=> -55, ), chr(145)=> array ( chr(145)=> -110, ), chr(146)=> array ( chr(115)=> -128, chr(116)=> -110, chr(146)=> -110, ), );
20
+
21
+ ?>
mpdf/font/czapfdingbats.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $cw=array(
3
+ chr(0)=>0,chr(1)=>0,chr(2)=>0,chr(3)=>0,chr(4)=>0,chr(5)=>0,chr(6)=>0,chr(7)=>0,chr(8)=>0,chr(9)=>0,chr(10)=>0,chr(11)=>0,chr(12)=>0,chr(13)=>0,chr(14)=>0,chr(15)=>0,chr(16)=>0,chr(17)=>0,chr(18)=>0,chr(19)=>0,chr(20)=>0,chr(21)=>0,
4
+ chr(22)=>0,chr(23)=>0,chr(24)=>0,chr(25)=>0,chr(26)=>0,chr(27)=>0,chr(28)=>0,chr(29)=>0,chr(30)=>0,chr(31)=>0,' '=>278,'!'=>974,'"'=>961,'#'=>974,'$'=>980,'%'=>719,'&'=>789,'\''=>790,'('=>791,')'=>690,'*'=>960,'+'=>939,
5
+ ','=>549,'-'=>855,'.'=>911,'/'=>933,'0'=>911,'1'=>945,'2'=>974,'3'=>755,'4'=>846,'5'=>762,'6'=>761,'7'=>571,'8'=>677,'9'=>763,':'=>760,';'=>759,'<'=>754,'='=>494,'>'=>552,'?'=>537,'@'=>577,'A'=>692,
6
+ 'B'=>786,'C'=>788,'D'=>788,'E'=>790,'F'=>793,'G'=>794,'H'=>816,'I'=>823,'J'=>789,'K'=>841,'L'=>823,'M'=>833,'N'=>816,'O'=>831,'P'=>923,'Q'=>744,'R'=>723,'S'=>749,'T'=>790,'U'=>792,'V'=>695,'W'=>776,
7
+ 'X'=>768,'Y'=>792,'Z'=>759,'['=>707,'\\'=>708,']'=>682,'^'=>701,'_'=>826,'`'=>815,'a'=>789,'b'=>789,'c'=>707,'d'=>687,'e'=>696,'f'=>689,'g'=>786,'h'=>787,'i'=>713,'j'=>791,'k'=>785,'l'=>791,'m'=>873,
8
+ 'n'=>761,'o'=>762,'p'=>762,'q'=>759,'r'=>759,'s'=>892,'t'=>892,'u'=>788,'v'=>784,'w'=>438,'x'=>138,'y'=>277,'z'=>415,'{'=>392,'|'=>392,'}'=>668,'~'=>668,chr(127)=>0,chr(128)=>390,chr(129)=>390,chr(130)=>317,chr(131)=>317,
9
+ chr(132)=>276,chr(133)=>276,chr(134)=>509,chr(135)=>509,chr(136)=>410,chr(137)=>410,chr(138)=>234,chr(139)=>234,chr(140)=>334,chr(141)=>334,chr(142)=>0,chr(143)=>0,chr(144)=>0,chr(145)=>0,chr(146)=>0,chr(147)=>0,chr(148)=>0,chr(149)=>0,chr(150)=>0,chr(151)=>0,chr(152)=>0,chr(153)=>0,
10
+ chr(154)=>0,chr(155)=>0,chr(156)=>0,chr(157)=>0,chr(158)=>0,chr(159)=>0,chr(160)=>0,chr(161)=>732,chr(162)=>544,chr(163)=>544,chr(164)=>910,chr(165)=>667,chr(166)=>760,chr(167)=>760,chr(168)=>776,chr(169)=>595,chr(170)=>694,chr(171)=>626,chr(172)=>788,chr(173)=>788,chr(174)=>788,chr(175)=>788,
11
+ chr(176)=>788,chr(177)=>788,chr(178)=>788,chr(179)=>788,chr(180)=>788,chr(181)=>788,chr(182)=>788,chr(183)=>788,chr(184)=>788,chr(185)=>788,chr(186)=>788,chr(187)=>788,chr(188)=>788,chr(189)=>788,chr(190)=>788,chr(191)=>788,chr(192)=>788,chr(193)=>788,chr(194)=>788,chr(195)=>788,chr(196)=>788,chr(197)=>788,
12
+ chr(198)=>788,chr(199)=>788,chr(200)=>788,chr(201)=>788,chr(202)=>788,chr(203)=>788,chr(204)=>788,chr(205)=>788,chr(206)=>788,chr(207)=>788,chr(208)=>788,chr(209)=>788,chr(210)=>788,chr(211)=>788,chr(212)=>894,chr(213)=>838,chr(214)=>1016,chr(215)=>458,chr(216)=>748,chr(217)=>924,chr(218)=>748,chr(219)=>918,
13
+ chr(220)=>927,chr(221)=>928,chr(222)=>928,chr(223)=>834,chr(224)=>873,chr(225)=>828,chr(226)=>924,chr(227)=>924,chr(228)=>917,chr(229)=>930,chr(230)=>931,chr(231)=>463,chr(232)=>883,chr(233)=>836,chr(234)=>836,chr(235)=>867,chr(236)=>867,chr(237)=>696,chr(238)=>696,chr(239)=>874,chr(240)=>0,chr(241)=>874,
14
+ chr(242)=>760,chr(243)=>946,chr(244)=>771,chr(245)=>865,chr(246)=>771,chr(247)=>888,chr(248)=>967,chr(249)=>888,chr(250)=>831,chr(251)=>873,chr(252)=>927,chr(253)=>970,chr(254)=>918,chr(255)=>0);
15
+
16
+ $desc=array('FontBBox'=>'[-1 -143 981 820]');
17
+ $up=-100;
18
+ $ut=50;
19
+
20
+
21
+ ?>
mpdf/graph.php ADDED
@@ -0,0 +1,721 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ // mPDF 4.5.009
5
+ define("FF_USERFONT", 15); // See jpgraph_ttf.inc.php for font IDs
6
+ global $JpgUseSVGFormat;
7
+ $JpgUseSVGFormat = true;
8
+
9
+ //======================================================================================================
10
+ // DELETE OLD GRAPH FILES FIRST - Housekeeping
11
+ // First clear any files in directory that are >1 hrs old
12
+ $interval = 3600;
13
+ if ($handle = opendir(_MPDF_PATH.'graph_cache')) {
14
+ while (false !== ($file = readdir($handle))) {
15
+ if (((filemtime(_MPDF_PATH.'graph_cache/'.$file)+$interval) < time()) && ($file != "..") && ($file != ".")) {
16
+ @unlink(_MPDF_PATH.'graph_cache/'.$file); // mPDF 4.0
17
+ }
18
+ }
19
+ closedir($handle);
20
+ }
21
+ //==============================================================================================================
22
+ // LOAD GRAPHS
23
+
24
+ include_once(_JPGRAPH_PATH.'jpgraph.php');
25
+ include_once(_JPGRAPH_PATH.'jpgraph_line.php' );
26
+ include_once(_JPGRAPH_PATH.'jpgraph_log.php' );
27
+ include_once(_JPGRAPH_PATH.'jpgraph_scatter.php' );
28
+ include_once(_JPGRAPH_PATH.'jpgraph_regstat.php' );
29
+ include_once(_JPGRAPH_PATH.'jpgraph_pie.php');
30
+ include_once(_JPGRAPH_PATH.'jpgraph_pie3d.php');
31
+ include_once(_JPGRAPH_PATH.'jpgraph_bar.php');
32
+ include_once(_JPGRAPH_PATH.'jpgraph_radar.php');
33
+
34
+
35
+ //======================================================================================================
36
+ //*****************************************************************************************************
37
+ //*****************************************************************************************************
38
+ //*****************************************************************************************************
39
+ //*****************************************************************************************************
40
+ //*****************************************************************************************************
41
+ //*****************************************************************************************************
42
+ //======================================================================================================
43
+ //======================================================================================================
44
+
45
+ //======================================================================================================
46
+ //======================================================================================================
47
+
48
+ //======================================================================================================
49
+ function print_graph($g,$pgwidth) {
50
+ $splines = false;
51
+ $bandw = false;
52
+ $percent = false;
53
+ $show_percent = false;
54
+ $stacked = false;
55
+ $h = false;
56
+ $show_values = false;
57
+ $hide_grid = false;
58
+ $hide_y_axis = false;
59
+
60
+ if (isset($g['attr']['TYPE']) && $g['attr']['TYPE']) { $type = strtolower($g['attr']['TYPE']); }
61
+ if (!in_array($type,array('bar','horiz_bar','line','radar','pie','pie3d','xy','scatter'))) { $type = 'bar'; } // Default=bar
62
+
63
+ if (isset($g['attr']['STACKED']) && $g['attr']['STACKED']) { $stacked = true; } // stacked for bar or horiz_bar
64
+ if (isset($g['attr']['SPLINES']) && $g['attr']['SPLINES'] && $type=='xy') { $splines = true; } // splines for XY line graphs
65
+ if (isset($g['attr']['BANDW']) && $g['attr']['BANDW']) { $bandw = true; } // black and white
66
+ if (isset($g['attr']['LEGEND-OVERLAP']) && $g['attr']['LEGEND-OVERLAP']) { $overlap = true; } // avoid overlap of Legends over graph (line, bar, horiz_bar only)
67
+ if (isset($g['attr']['PERCENT']) && $g['attr']['PERCENT'] && $type != 'xy' && $type != 'scatter') { $percent = true; } // Show data series as percent of total in series
68
+ if (isset($g['attr']['SHOW-VALUES']) && $g['attr']['SHOW-VALUES']) { $show_values = true; } // Show the individual data values
69
+ if (isset($g['attr']['HIDE-GRID']) && $g['attr']['HIDE-GRID']) { $hide_grid = true; } // Hide the y-axis gridlines
70
+ if (isset($g['attr']['HIDE-Y-AXIS']) && $g['attr']['HIDE-Y-AXIS']) { $hide_y_axis = true; } // Hide the y-axis
71
+
72
+
73
+ // Antialias: If true - better quality curves, but graph line will only be 1px even in PDF 300dpi
74
+ // default=true for most except line and radar
75
+ if (isset($g['attr']['ANTIALIAS']) && ($g['attr']['ANTIALIAS']=='' || $g['attr']['ANTIALIAS']==0)) { $antialias = false; }
76
+ else if (isset($g['attr']['ANTIALIAS']) && $g['attr']['ANTIALIAS'] > 0) { $antialias = true; }
77
+ else if ($type=='line' || $type=='radar') { $antialias = false; }
78
+ else { $antialias = true; }
79
+
80
+ if ($g['attr']['DPI']) { $dpi = intval($g['attr']['DPI']); }
81
+ if (!$dpi || $dpi < 50 || $dpi > 2400) { $dpi = 150; } // Default dpi 150
82
+ $k = (0.2645/25.4 * $dpi);
83
+
84
+ // mPDF 4.5.009
85
+ global $JpgUseSVGFormat;
86
+ if (isset($JpgUseSVGFormat) && $JpgUseSVGFormat) {
87
+ $img_type = 'svg';
88
+ $k = 1; // Overrides as Vector scale does not need DPI
89
+ }
90
+ else {
91
+ $img_type = 'png';
92
+ }
93
+
94
+ if (isset($g['attr']['TITLE']) && $g['attr']['TITLE']) { $title = $g['attr']['TITLE']; }
95
+
96
+ if (isset($g['attr']['LABEL-X']) && $g['attr']['LABEL-X']) { $xlabel = $g['attr']['LABEL-X']; } // NOT IMPLEMENTED??????
97
+ if (isset($g['attr']['LABEL-Y']) && $g['attr']['LABEL-Y']) { $ylabel = $g['attr']['LABEL-Y']; }
98
+
99
+ if (isset($g['attr']['AXIS-X']) && $g['attr']['AXIS-X']) { $xaxis = strtolower($g['attr']['AXIS-X']); }
100
+ if (!in_array($xaxis,array('text','lin','linear','log'))) { $xaxis = 'text'; } // Default=text
101
+ if ($xaxis == 'linear') { $xaxis = 'lin'; }
102
+
103
+ if (isset($g['attr']['AXIS-Y']) && $g['attr']['AXIS-Y']) { $yaxis = strtolower($g['attr']['AXIS-Y']); }
104
+ if (!in_array($yaxis,array('lin','linear','log','percent'))) { $yaxis = 'lin'; } // Default=lin
105
+ if ($yaxis == 'percent') { $show_percent = true; $yaxis = 'lin'; } // Show percent sign on scales
106
+ if ($yaxis == 'linear') { $yaxis = 'lin'; }
107
+
108
+ if ($splines) { $xaxis = 'lin'; }
109
+ $axes = $xaxis.$yaxis; // e.g.textlin, textlog, loglog, loglin, linlog (XY)
110
+
111
+ // mPDF 4.0
112
+ if (isset($g['attr']['cWIDTH']) && $g['attr']['cWIDTH']) { $w=($g['attr']['cWIDTH'] / 0.2645); } // pixels
113
+ if (isset($g['attr']['cHEIGHT']) && $g['attr']['cHEIGHT']) { $h=($g['attr']['cHEIGHT'] / 0.2645); }
114
+
115
+
116
+ if (isset($g['attr']['SERIES']) && strtolower($g['attr']['SERIES']) == 'rows') { $dataseries = 'rows'; }
117
+ else { $dataseries = 'cols'; }
118
+
119
+ // Defaults - define data
120
+ $rowbegin = 2;
121
+ $colbegin = 2;
122
+ if($type=='scatter' || $type=='xy') {
123
+ if ($dataseries == 'rows') { $rowbegin = 1; }
124
+ else { $colbegin = 1; }
125
+ }
126
+ $rowend = 0;
127
+ $colend = 0;
128
+
129
+ if (isset($g['attr']['DATA-ROW-BEGIN']) && ($g['attr']['DATA-ROW-BEGIN'] === '0' || $g['attr']['DATA-ROW-BEGIN'] > 0)) { $rowbegin = $g['attr']['DATA-ROW-BEGIN']; }
130
+
131
+ if (isset($g['attr']['DATA-COL-BEGIN']) && ($g['attr']['DATA-COL-BEGIN'] === '0' || $g['attr']['DATA-COL-BEGIN'] > 0)) { $colbegin = $g['attr']['DATA-COL-BEGIN']; }
132
+
133
+ if (isset($g['attr']['DATA-ROW-END']) && ($g['attr']['DATA-ROW-END'] === '0' || $g['attr']['DATA-ROW-END'] <> 0)) { $rowend = $g['attr']['DATA-ROW-END']; }
134
+ if (isset($g['attr']['DATA-COL-END']) && ($g['attr']['DATA-COL-END'] === '0' || $g['attr']['DATA-COL-END'] <> 0)) { $colend = $g['attr']['DATA-COL-END']; }
135
+
136
+ $nr = count($g['data']);
137
+ $nc = 0;
138
+ foreach($g['data'] AS $r) {
139
+ $cc=0;
140
+ foreach($r AS $c) { $cc++; }
141
+ $nc = max($nc,$cc);
142
+ }
143
+ if ($colend == 0) { $colend = $nc; }
144
+ else if ($colend < 0) { $colend = $nc+$colend; }
145
+
146
+ if ($rowend == 0) { $rowend = $nr; }
147
+ else if ($rowend < 0) { $rowend = $nr+$rowend; }
148
+
149
+ if ($colend < $colbegin) { $colend = $colbegin; }
150
+ if ($rowend < $rowbegin) { $rowend = $rowbegin; }
151
+
152
+ // if ($type == 'xy' || $type=='scatter') { $colstart=0; }
153
+
154
+ // Get Data + Totals
155
+ $data = array();
156
+ $totals = array();
157
+ for ($r=($rowbegin-1);$r<$rowend;$r++) {
158
+ for ($c=($colbegin-1);$c<$colend;$c++) {
159
+ if (isset($g['data'][$r][$c])) { $g['data'][$r][$c] = floatval($g['data'][$r][$c] ); }
160
+ else { $g['data'][$r][$c] = 0; }
161
+ if ($dataseries=='rows') {
162
+ $data[($r+1-$rowbegin)][($c+1-$colbegin)] = $g['data'][$r][$c] ;
163
+ $totals[($r+1-$rowbegin)] += $g['data'][$r][$c] ;
164
+ }
165
+ else {
166
+ $data[($c+1-$colbegin)][($r+1-$rowbegin)] = $g['data'][$r][$c] ;
167
+ if (isset($totals[($c+1-$colbegin)])) { $totals[($c+1-$colbegin)] += $g['data'][$r][$c] ; }
168
+ else { $totals[($c+1-$colbegin)] = $g['data'][$r][$c] ; }
169
+ }
170
+ }
171
+ }
172
+ // PERCENT
173
+ if ($percent && $type != 'pie' && $type != 'pie3d') {
174
+ for ($r=0;$r<count($data);$r++) {
175
+ for ($c=0;$c<count($data[$r]);$c++) {
176
+ $data[$r][$c] = $data[$r][$c]/$totals[$r] * 100;
177
+ }
178
+ }
179
+ }
180
+ // Get Legends and labels
181
+ $legends = array();
182
+ $labels = array();
183
+ $longestlegend = 0;
184
+ $longestlabel = 0;
185
+ if ($dataseries=='cols') {
186
+ if ($colbegin>1) {
187
+ for ($r=($rowbegin-1);$r<$rowend;$r++) {
188
+ $legends[($r+1-$rowbegin)] = $g['data'][$r][0] ;
189
+ $longestlegend = max($longestlegend, strlen( $g['data'][$r][0] ));
190
+ }
191
+ }
192
+ if ($rowbegin>1) {
193
+ for ($c=($colbegin-1);$c<$colend;$c++) {
194
+ $labels[($c+1-$colbegin)] = $g['data'][0][$c] ;
195
+ $longestlabel = max($longestlabel , strlen( $g['data'][0][$c] ));
196
+ }
197
+ }
198
+ }
199
+ else if ($dataseries=='rows') {
200
+ if ($colbegin>1) {
201
+ for ($r=($rowbegin-1);$r<$rowend;$r++) {
202
+ $labels[($r+1-$rowbegin)] = $g['data'][$r][0] ;
203
+ $longestlabel = max($longestlabel , strlen( $g['data'][$r][0] ));
204
+ }
205
+ }
206
+ if ($rowbegin>1) {
207
+ for ($c=($colbegin-1);$c<$colend;$c++) {
208
+ $legends[($c+1-$colbegin)] = $g['data'][0][$c] ;
209
+ $longestlegend = max($longestlegend, strlen( $g['data'][0][$c] ));
210
+ }
211
+ }
212
+ }
213
+ // Default sizes
214
+ $defsize = array();
215
+ $defsize['pie'] = array('w' => 600, 'h' => 300);
216
+ $defsize['pie3d'] = array('w' => 600, 'h' => 300);
217
+ $defsize['radar'] = array('w' => 600, 'h' => 300);
218
+ $defsize['line'] = array('w' => 600, 'h' => 400);
219
+ $defsize['xy'] = array('w' => 600, 'h' => 400);
220
+ $defsize['scatter'] = array('w' => 600, 'h' => 400);
221
+ $defsize['bar'] = array('w' => 600, 'h' => 400);
222
+ $defsize['horiz_bar'] = array('w' => 600, 'h' => 500);
223
+
224
+
225
+ // Use default ratios
226
+ if ($w && !$h) { $h = $w*$defsize[$type]['h']/$defsize[$type]['w']; }
227
+ if ($h && !$w) { $w = $h*$defsize[$type]['w']/$defsize[$type]['h']; }
228
+ if (!$h && !$w) { $w = $defsize[$type]['w']; $h = $defsize[$type]['h']; }
229
+
230
+
231
+ if (count($data)>0 && $type) {
232
+ $figure_file = "graph_cache/".rand(11111,999999999).".".$img_type;
233
+ if ($bandw) { $colours = array('snow1','black','snow4','snow3','snow2','cadetblue4','cadetblue3','cadetblue1','bisque4','bisque2','beige'); }
234
+ else { $colours = array('cyan','darkorchid4','cadetblue3','khaki1','darkolivegreen2','cadetblue4','coral','cyan4','rosybrown3','wheat1'); }
235
+ $fills = array('navy','orange','red','yellow','purple','navy','orange','red','yellow','purple');
236
+ $patterns = array(PATTERN_DIAG1,PATTERN_CROSS1,PATTERN_STRIPE1,PATTERN_DIAG3,PATTERN_CROSS2,PATTERN_DIAG2,PATTERN_DIAG4,PATTERN_CROSS3, PATTERN_CROSS4,PATTERN_STRIPE1);
237
+ $markers = array(MARK_DIAMOND, MARK_SQUARE, MARK_CIRCLE, MARK_UTRIANGLE, MARK_DTRIANGLE, MARK_FILLEDCIRCLE, MARK_CROSS, MARK_STAR, MARK_X);
238
+
239
+ // LEGENDS
240
+ if ($type == 'pie' || $type == 'pie3d') {
241
+ $graph = new PieGraph (($w*$k),($h*$k));
242
+ }
243
+ else if ($type == 'radar') {
244
+ $graph = new RadarGraph(($w*$k),($h*$k));
245
+ }
246
+ else {
247
+ $graph = new Graph(($w*$k),($h*$k));
248
+ }
249
+
250
+ // mPDF 4.5.009
251
+ // $graph->img->SetImgFormat($img_type) ;
252
+ // if (strtoupper($img_type)=='JPEG') { $graph->img->SetQuality(90); }
253
+ if ($antialias) { $graph->img->SetAntiAliasing(); }
254
+ $graph->SetShadow(true, 2*$k);
255
+ $graph->SetMarginColor("white");
256
+ // TITLE
257
+ $graph->title->Set($title);
258
+ $graph->title->SetMargin(10*$k);
259
+ $graph->title->SetFont(FF_USERFONT,FS_BOLD,11*$k);
260
+ $graph->title->SetColor("black");
261
+ $graph->legend->SetLineSpacing(3*$k);
262
+ $graph->legend->SetMarkAbsSize(6*$k);
263
+ $graph->legend->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
264
+
265
+ // Set GRAPH IMAGE MARGINS
266
+ if ($type == 'pie' || $type == 'pie3d') {
267
+ $psize = 0.3;
268
+ $pposxabs = ($w/2);
269
+ $pposy = 0.55;
270
+ if ($longestlegend) { // if legend showing
271
+ $pposxabs -= ((($longestlegend * 5) + 20) / 2);
272
+ }
273
+ $pposx = ($pposxabs / $w);
274
+ $graph->legend->Pos(0.02,0.5,'right','center');
275
+ }
276
+ else if ($type == 'radar') {
277
+ $psize = 0.5;
278
+ $pposxabs = ($w/2);
279
+ $pposy = 0.55;
280
+ if ($longestlabel) { // if legend showing
281
+ $pposxabs -= ((($longestlabel * 5) + 20) / 2);
282
+ }
283
+ $pposx = ($pposxabs / $w);
284
+ $graph->legend->Pos(0.02,0.5,'right','center');
285
+ }
286
+ else if ($type == 'xy' || $type == 'scatter') {
287
+ $pml = 50;
288
+ $pmr = 20;
289
+ $pmt = 60;
290
+ $pmb = 50;
291
+ $xaxislblmargin = $pmb - 30;
292
+ $yaxislblmargin = $pml - 15;
293
+ $graph->legend->Pos(0.02,0.1,'right','top');
294
+ }
295
+ else if ($type == 'line' || $type == 'bar') {
296
+ $pml = 50;
297
+ $pmr = 20;
298
+ $pmt = 60;
299
+ $pmb = 50;
300
+ $xlangle = 0;
301
+ $ll = ($longestlegend * 5); // 45 degrees 8pt fontsize
302
+ if ($ll > 5 || ($ll>3 && count($data)>10)) {
303
+ $pmb = max($pmb, $ll + 30);
304
+ $xlangle = 50;
305
+ }
306
+ $xaxislblmargin = $pmb - 30;
307
+ $yaxislblmargin = $pml - 15;
308
+ if ($longestlabel && !$overlap) { // if legend showing
309
+ $pmr = ((($longestlabel * 5) + 40));
310
+ }
311
+ $graph->legend->Pos(0.02,0.1,'right','top');
312
+ }
313
+ else if ($type == 'horiz_bar') {
314
+ $pml = 50;
315
+ $pmr = 20;
316
+ $pmt = 50;
317
+ $pmb = 45;
318
+ $ll = ($longestlegend * 6.5); // 8pt fontsize
319
+ $pml = max($pml, $ll + 20);
320
+ $xaxislblmargin = $pml - 20;
321
+ $yaxislblmargin = $pmb - 15;
322
+ if ($longestlabel && !$overlap) { // if legend showing
323
+ $pmr = ((($longestlabel * 5) + 40));
324
+ }
325
+ $graph->legend->Pos(0.02,0.1,'right','top');
326
+ }
327
+
328
+
329
+ // DRAW THE GRAPHS
330
+ if ($type == 'pie') {
331
+ $p1 = new PiePlot($data[0]);
332
+ $p1->SetSliceColors($colours);
333
+
334
+ if ($show_values) {
335
+ $p1->value->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
336
+ if ($percent) { $p1->SetLabelType(PIE_VALUE_PERADJ); } //PIE_VAL_PER = default
337
+ else { $p1->SetLabelType(PIE_VALUE_ABS); }
338
+ if ($percent || $show_percent) { $p1->value->SetFormat("%d%%"); }
339
+ else { $p1->value->SetFormat("%s"); }
340
+ // Enable and set policy for guide-lines. Make labels line up vertically
341
+ $p1->SetGuideLines(true);
342
+ $p1->SetGuideLinesAdjust(1.5);
343
+ }
344
+ else { $p1->value->Show(false); }
345
+ $p1->SetLegends($legends);
346
+ $p1->SetSize($psize);
347
+ $p1->SetCenter($pposx, $pposy);
348
+ if ($labels[0]) {
349
+ $graph->subtitle->Set($labels[0]);
350
+ $graph->subtitle->SetMargin(10*$k);
351
+ $graph->subtitle->SetFont(FF_USERFONT,FS_BOLD,11*$k);
352
+ $graph->subtitle->SetColor("black");
353
+ }
354
+ $graph->Add($p1);
355
+ }
356
+ else if ($type == 'pie3d') {
357
+ $p1 = new PiePlot3d($data[0]);
358
+ $p1->SetSliceColors($colours);
359
+ if ($show_values) {
360
+ $p1->value->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
361
+ if ($percent) { $p1->SetLabelType(PIE_VALUE_PERADJ); } //PIE_VAL_PER = default
362
+ else { $p1->SetLabelType(PIE_VALUE_ABS); }
363
+ if ($percent || $show_percent) { $p1->value->SetFormat("%d%%"); }
364
+ else { $p1->value->SetFormat("%s"); }
365
+ }
366
+ else { $p1->value->Show(false); }
367
+ $p1->SetLegends($legends);
368
+ $p1->SetEdge();
369
+ $p1->SetSize($psize);
370
+ $p1->SetCenter($pposx, $pposy);
371
+
372
+ if ($labels[0]) {
373
+ $graph->subtitle->Set($labels[0]);
374
+ $graph->subtitle->SetMargin(10*$k);
375
+ $graph->subtitle->SetFont(FF_USERFONT,FS_BOLD,11*$k);
376
+ $graph->subtitle->SetColor("black");
377
+ }
378
+
379
+ $graph->Add( $p1);
380
+ }
381
+ // RADAR
382
+ else if ($type == 'radar') {
383
+ $graph->SetSize($psize);
384
+ $graph->SetPos($pposx, $pposy);
385
+
386
+ $graph->SetTitles( $legends); // labels each axis
387
+
388
+ $graph->axis->title->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
389
+ $graph->axis->title->SetMargin(5*$k);
390
+ $graph->axis->SetWeight(1*$k);
391
+ $graph->axis->HideLabels();
392
+ $graph->axis->SetFont(FF_USERFONT,FS_NORMAL,6*$k);
393
+ $graph->HideTickMarks();
394
+
395
+ $group = array();
396
+ foreach($data AS $series => $dat) {
397
+ $rdata = array();
398
+ foreach($data[$series] AS $row) { $rdata[] = $row; }
399
+ if (count($rdata)<3) { die("ERROR::Graph::Cannot create a Radar Plot with less than 3 data points."); }
400
+ // Create the radar plot
401
+ $bplot = new RadarPlot($rdata);
402
+ $bplot->mark->SetType($markers[$series]);
403
+ $bplot->mark->SetFillColor($colours[$series]);
404
+ $bplot->mark->SetWidth(3*$k);
405
+ $bplot->SetColor($colours[$series]);
406
+ if ($series == 0) { $bplot->SetFillColor('lightred'); }
407
+ else { $bplot->SetFill(false); }
408
+ $bplot->SetLineWeight(1*$k);
409
+ $bplot->SetLegend($labels[$series]);
410
+ if ($bandw) { $bplot->SetShadow("gray5"); }
411
+ $graph->Add($bplot);
412
+ }
413
+ }
414
+ // LINE
415
+ else if ($type == 'line') {
416
+ // Setup the graph.
417
+ $graph->img->SetMargin($pml*$k,$pmr*$k,$pmt*$k,$pmb*$k); // LRTB
418
+ $graph->SetScale($axes);
419
+ $graph->yaxis->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
420
+
421
+ if ($ylabel) {
422
+ $graph->yaxis->title->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
423
+ $graph->yaxis->SetTitle($ylabel,'middle');
424
+ $graph->yaxis->SetTitleMargin($yaxislblmargin*$k);
425
+ }
426
+
427
+ $graph->yaxis->SetLabelMargin(4*$k);
428
+ if ($percent || $show_percent) { $graph->yaxis->SetLabelFormat('%d%%'); } // Percent
429
+
430
+ // Show 0 label on Y-axis (default is not to show)
431
+ $graph->yscale->ticks->SupressZeroLabel(true);
432
+ if ($hide_y_axis) { $graph->yaxis->Hide(); }
433
+ if ($hide_grid) { $graph->ygrid->Show(false); }
434
+
435
+ // Setup X-axis labels
436
+ $graph->xaxis->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
437
+ $graph->xaxis->SetTickLabels($legends);
438
+ $graph->xaxis->SetLabelAngle($xlangle);
439
+ $graph->xaxis->SetLabelMargin(4*$k);
440
+ // X-axis title
441
+ if ($xlabel) {
442
+ $graph->xaxis->title->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
443
+ $graph->xaxis->SetTitle($xlabel,'middle');
444
+ $graph->xaxis->SetTitleMargin($xaxislblmargin*$k);
445
+ }
446
+ foreach($data AS $series => $rdata) {
447
+ $bplot = new LinePlot($rdata);
448
+ $bplot->mark->SetType($markers[$series]);
449
+ $bplot->mark->SetFillColor($colours[$series]);
450
+ $bplot->mark->SetWidth(4*$k);
451
+ if ($show_values) {
452
+ $bplot->value-> Show(); // Not if scatter
453
+ $bplot->value->SetMargin(6*$k);
454
+ $bplot->value->SetColor("darkred");
455
+ $bplot->value->SetFont( FF_USERFONT, FS_NORMAL, 8*$k);
456
+ if ($percent || $show_percent) { $bplot->value->SetFormat( '%d%%'); }
457
+ else { $bplot->value->SetFormat("%s"); }
458
+ }
459
+ // Set color for each line
460
+ $bplot->SetColor($colours[$series]);
461
+ $bplot->SetWeight(2*$k);
462
+ $bplot->SetLegend($labels[$series]);
463
+ if ($bandw) { $bplot->SetShadow("gray5"); }
464
+ // Indent the X-scale so the first and last point doesn't fall on the edges
465
+ $bplot->SetCenter();
466
+ $graph->Add($bplot);
467
+ }
468
+
469
+ }
470
+ // XY or SCATTER
471
+ else if ($type == 'xy' || $type == 'scatter') {
472
+ // Setup the graph.
473
+ $graph->img->SetMargin($pml*$k,$pmr*$k,$pmt*$k,$pmb*$k); // LRTB
474
+ $graph->SetScale($axes);
475
+ // Setup font for axis
476
+ $graph->yaxis->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
477
+ // Y-axis title
478
+ if ($labels[1]) {
479
+ $graph->yaxis->title->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
480
+ $graph->yaxis->SetTitleMargin($yaxislblmargin*$k);
481
+ $graph->yaxis->SetTitle($labels[1],'middle');
482
+ }
483
+
484
+
485
+ $graph->yaxis->SetLabelMargin(4*$k);
486
+ if ($percent || $show_percent) { $graph->yaxis->SetLabelFormat('%d%%'); } // Percent
487
+
488
+ // Show 0 label on Y-axis (default is not to show)
489
+ $graph->yscale->ticks->SupressZeroLabel(true);
490
+ // Just let the maximum be autoscaled
491
+ $graph->yaxis->scale->SetAutoMin(0);
492
+ if ($hide_y_axis) { $graph->yaxis->Hide(); }
493
+ if ($hide_grid) { $graph->ygrid->Show(false); }
494
+
495
+ // Setup X-axis labels
496
+ $graph->xaxis->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
497
+ // mPDF 2.5 Corrects labelling of x-axis
498
+ // $graph->xaxis->SetTickLabels($legends);
499
+ $graph->xaxis->SetLabelAngle(50);
500
+ $graph->xaxis->SetLabelMargin(4*$k);
501
+ // X-axis title
502
+ if ($labels[0]) {
503
+ $graph->xaxis->title->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
504
+ $graph->xaxis->SetTitleMargin($xaxislblmargin*$k);
505
+ $graph->xaxis->SetTitle($labels[0],'middle');
506
+ }
507
+
508
+ // Create the bar plot
509
+ // SPLINES
510
+ if ($splines && $type=='xy') {
511
+ $spline = new Spline($data[0],$data[1]);
512
+ list($newx,$newy) = $spline->Get(100);
513
+ }
514
+ else {
515
+ $newx = $data[0];
516
+ $newy = $data[1];
517
+ }
518
+
519
+ if ($type=='xy') {
520
+ // LINE PLOT
521
+ $bplot = new LinePlot($newy, $newx);
522
+ // Set color for each line
523
+ $bplot->SetColor($fills[0]);
524
+ $bplot->SetWeight(4*$k);
525
+ if ($bandw) { $bplot->SetShadow("gray5"); }
526
+ $graph->Add($bplot);
527
+ }
528
+
529
+ // SCATTER PLOT
530
+ $cplot = new ScatterPlot($data[1], $data[0]);
531
+
532
+ $cplot->mark->SetType($markers[0]);
533
+ $cplot->mark->SetFillColor($fills[0]);
534
+ $cplot->mark->SetWidth(8*$k);
535
+ if ($show_values) {
536
+ // mPDF 2.5
537
+ if ($type=='xy') { $cplot->value->Show(); } // Not if scatter
538
+ $cplot->value->SetMargin(8*$k);
539
+ $cplot->value->SetColor("darkred");
540
+ $cplot->value->SetFont( FF_USERFONT, FS_NORMAL, 6*$k);
541
+
542
+ if ($percent || $show_percent) { $cplot->value->SetFormat( '%d%%'); }
543
+ else { $cplot->value->SetFormat("%s"); }
544
+ }
545
+
546
+ // Set color for each line
547
+ $cplot->SetColor($fills[0]);
548
+ $cplot->SetWeight(4*$k);
549
+ if ($bandw) { $cplot->SetShadow("gray5"); }
550
+ $graph->Add($cplot);
551
+
552
+ }
553
+ // BAR
554
+ else if ($type == 'bar') {
555
+ // Setup the graph.
556
+ $graph->img->SetMargin($pml*$k,$pmr*$k,$pmt*$k,$pmb*$k); // LRTB
557
+ $graph->SetScale($axes);
558
+ // Setup y-axis
559
+ $graph->yaxis->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
560
+ if ($hide_y_axis) { $graph->yaxis->Hide(); }
561
+ if ($hide_grid) { $graph->ygrid->Show(false); }
562
+ $graph->yaxis->SetLabelMargin(4*$k);
563
+ if ($ylabel) {
564
+ $graph->yaxis->title->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
565
+ $graph->yaxis->SetTitle($ylabel,'middle');
566
+ $graph->yaxis->SetTitleMargin($yaxislblmargin*$k);
567
+ }
568
+ // Show 0 label on Y-axis (default is not to show)
569
+ $graph->yscale->ticks->SupressZeroLabel(false);
570
+ // Setup X-axis labels
571
+ $graph->xaxis->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
572
+ $graph->xaxis->SetTickLabels($legends);
573
+ $graph->xaxis->SetLabelAngle($xlangle);
574
+ $graph->xaxis->SetLabelMargin(4*$k);
575
+ // X-axis title
576
+ if ($xlabel) {
577
+ $graph->xaxis->title->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
578
+ $graph->xaxis->SetTitle($xlabel,'middle');
579
+ $graph->xaxis->SetTitleMargin($xaxislblmargin*$k);
580
+ }
581
+
582
+ $group = array();
583
+ foreach($data AS $series => $dat) {
584
+ $rdata = array();
585
+ foreach($data[$series] AS $row) { $rdata[] = $row; }
586
+
587
+ // Create the bar plot
588
+ $bplot = new BarPlot($rdata);
589
+ $bplot->SetWidth(0.6); // for SINGLE??
590
+ // Setup color for gradient fill style
591
+ if ($bandw) { $bplot->SetPattern( $patterns[$series]); }
592
+ else { $bplot->SetFillGradient($fills[$series],"#EEEEEE",GRAD_LEFT_REFLECTION); }
593
+
594
+ // Set color for the frame of each bar
595
+ $bplot->SetColor("darkgray");
596
+ $bplot->SetLegend($labels[$series]);
597
+ if ($bandw) { $bplot->SetShadow("gray5"); }
598
+ if ($show_values) {
599
+ $bplot->value->Show();
600
+ $bplot->value->SetMargin(6*$k);
601
+ $bplot->value->SetColor("darkred");
602
+ $bplot->value->SetFont( FF_USERFONT, FS_NORMAL, 8*$k);
603
+ if ($percent || $show_percent) { $bplot->value->SetFormat( '%d%%'); }
604
+ else { $bplot->value->SetFormat("%s"); }
605
+ }
606
+
607
+ $group[] = $bplot;
608
+ }
609
+ if (count($data)==1) {
610
+ $graph->Add($group[0]);
611
+ }
612
+ else {
613
+ // Create the grouped bar plot
614
+ if ($stacked) {
615
+ $gbplot = new AccBarPlot ($group);
616
+ }
617
+ else {
618
+ $gbplot = new GroupBarPlot ($group);
619
+ }
620
+ $graph->Add($gbplot);
621
+ }
622
+ }
623
+ else if ($type == 'horiz_bar') {
624
+ $graph->SetScale($axes);
625
+ $graph->Set90AndMargin($pml*$k,$pmr*$k,$pmt*$k,$pmb*$k); // LRTB
626
+
627
+ // Setup y-axis
628
+ $graph->yaxis->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
629
+ $graph->yaxis->SetLabelMargin(4*$k);
630
+
631
+ $graph->yaxis->SetPos('max'); // Intersect at top of x-axis i.e. y axis is at bottom
632
+ // First make the labels look right
633
+ $graph->yaxis->SetLabelAlign('center','top');
634
+ if ($percent || $show_percent) { $graph->yaxis->SetLabelFormat('%d%%'); }
635
+ $graph->yaxis->SetLabelSide(SIDE_RIGHT);
636
+ $graph->yaxis->scale->SetGrace(10); // sets 10% headroom
637
+ if ($hide_y_axis) { $graph->yaxis->Hide(); }
638
+ if ($hide_grid) { $graph->ygrid->Show(false); }
639
+
640
+ // The fix the tick marks
641
+ $graph->yaxis->SetTickSide(SIDE_LEFT);
642
+ if ($ylabel) {
643
+ $graph->yaxis->title->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
644
+ $graph->yaxis->SetTitle($ylabel,'middle');
645
+ $graph->yaxis->SetTitleMargin($yaxislblmargin*$k);
646
+ // Finally setup the title
647
+ $graph->yaxis->SetTitleSide(SIDE_RIGHT);
648
+ // To align the title to the right use :
649
+ $graph->yaxis->title->Align('right');
650
+ $graph->yaxis->title->SetAngle(0);
651
+
652
+ }
653
+
654
+ // Show 0 label on Y-axis (default is not to show)
655
+ $graph->yscale->ticks->SupressZeroLabel(false);
656
+ // Setup X-axis labels
657
+ $graph->xaxis->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
658
+ $graph->xaxis->title->SetAngle(90);
659
+ $graph->xaxis->SetTickLabels($legends);
660
+ $graph->xaxis->SetLabelMargin(4*$k);
661
+ // X-axis title
662
+ if ($xlabel) {
663
+ $graph->xaxis->title->SetFont(FF_USERFONT,FS_NORMAL,8*$k);
664
+ $graph->xaxis->SetTitleMargin($xaxislblmargin*$k);
665
+ $graph->xaxis->SetTitle($xlabel,'middle');
666
+ }
667
+ $group = array();
668
+ foreach($data AS $series => $dat) {
669
+ $rdata = array();
670
+ foreach($data[$series] AS $row) { $rdata[] = $row; }
671
+ // Create the bar pot
672
+ $bplot = new BarPlot($rdata);
673
+ $bplot->SetWidth(0.6); // for SINGLE??
674
+ // Setup color for gradient fill style
675
+ if ($bandw) { $bplot->SetPattern( $patterns[$series]); }
676
+ else { $bplot->SetFillGradient($fills[$series],"#EEEEEE",GRAD_LEFT_REFLECTION); }
677
+
678
+ // Set color for the frame of each bar
679
+ $bplot->SetColor("darkgray");
680
+ $bplot->SetLegend($labels[$series]);
681
+ if ($bandw) { $bplot->SetShadow("gray5"); }
682
+ if ($show_values) {
683
+ $bplot->value-> Show();
684
+ $bplot->value->SetMargin(6*$k);
685
+ $bplot->value->SetColor("darkred");
686
+ $bplot->value->SetFont( FF_USERFONT, FS_NORMAL, 8*$k);
687
+ if ($percent || $show_percent) { $bplot->value->SetFormat( '%d%%'); }
688
+ else { $bplot->value->SetFormat("%s"); }
689
+ }
690
+
691
+ $group[] = $bplot;
692
+ }
693
+ if (count($data)==1) {
694
+ $graph->Add($group[0]);
695
+ }
696
+ else {
697
+ // Create the grouped bar plot
698
+ if ($stacked) {
699
+ $gbplot = new AccBarPlot ($group);
700
+ }
701
+ else {
702
+ $gbplot = new GroupBarPlot ($group);
703
+ }
704
+ $graph->Add($gbplot);
705
+ }
706
+ }
707
+ if ($graph) {
708
+ $graph->Stroke( _MPDF_PATH.$figure_file);
709
+ $srcpath = str_replace("\\","/",dirname(__FILE__)) . "/";
710
+ $srcpath .= $figure_file;
711
+ return array('file'=>$srcpath, 'w'=>$w, 'h'=>$h);
712
+ }
713
+ }
714
+ return false;
715
+ }
716
+ //======================================================================================================
717
+ //======================================================================================================
718
+ //======================================================================================================
719
+ //======================================================================================================
720
+
721
+ ?>
mpdf/includes/functions.php ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // mPDF 5.6.23
4
+ function array_insert(&$array, $value, $offset) {
5
+ if (is_array($array)) {
6
+ $array = array_values($array);
7
+ $offset = intval($offset);
8
+ if ($offset < 0 || $offset >= count($array)) { array_push($array, $value); }
9
+ else if ($offset == 0) { array_unshift($array, $value); }
10
+ else {
11
+ $temp = array_slice($array, 0, $offset);
12
+ array_push($temp, $value);
13
+ $array = array_slice($array, $offset);
14
+ $array = array_merge($temp, $array);
15
+ }
16
+ }
17
+ else { $array = array($value); }
18
+ return count($array);
19
+ }
20
+
21
+ function urlencode_part($url) { // mPDF 5.6.02
22
+ if (!preg_match('/^[a-z]+:\/\//i',$url)) { return $url; }
23
+ $file=$url;
24
+ $query='';
25
+ if (preg_match('/[?]/',$url)) {
26
+ $bits = preg_split('/[?]/',$url,2);
27
+ $file=$bits[0];
28
+ $query='?'.$bits[1];
29
+ }
30
+ $file = str_replace(array(" ","!","$","&","'","(",")","*","+",",",";","="),array("%20","%21","%24","%26","%27","%28","%29","%2A","%2B","%2C","%3B","%3D"),$file);
31
+ return $file.$query;
32
+ }
33
+
34
+
35
+ function _strspn($str1, $str2, $start=null, $length=null) {
36
+ $numargs = func_num_args();
37
+ if ($numargs == 2) {
38
+ return strspn($str1, $str2);
39
+ }
40
+ else if ($numargs == 3) {
41
+ return strspn($str1, $str2, $start);
42
+ }
43
+ else {
44
+ return strspn($str1, $str2, $start, $length);
45
+ }
46
+ }
47
+
48
+
49
+ function _strcspn($str1, $str2, $start=null, $length=null) {
50
+ $numargs = func_num_args();
51
+ if ($numargs == 2) {
52
+ return strcspn($str1, $str2);
53
+ }
54
+ else if ($numargs == 3) {
55
+ return strcspn($str1, $str2, $start);
56
+ }
57
+ else {
58
+ return strcspn($str1, $str2, $start, $length);
59
+ }
60
+ }
61
+
62
+ function _fgets (&$h, $force=false) {
63
+ $startpos = ftell($h);
64
+ $s = fgets($h, 1024);
65
+ if ($force && preg_match("/^([^\r\n]*[\r\n]{1,2})(.)/",trim($s), $ns)) {
66
+ $s = $ns[1];
67
+ fseek($h,$startpos+strlen($s));
68
+ }
69
+ return $s;
70
+ }
71
+
72
+
73
+ // For PHP4 compatability
74
+ if(!function_exists('str_ireplace')) {
75
+ function str_ireplace($search,$replace,$subject) {
76
+ $search = preg_quote($search, "/");
77
+ return preg_replace("/".$search."/i", $replace, $subject);
78
+ }
79
+ }
80
+ if(!function_exists('htmlspecialchars_decode')) {
81
+ function htmlspecialchars_decode ($str) {
82
+ return strtr($str, array_flip(get_html_translation_table(HTML_SPECIALCHARS)));
83
+ }
84
+ }
85
+
86
+ function PreparePreText($text,$ff='//FF//') {
87
+ $text = htmlspecialchars($text);
88
+ if ($ff) { $text = str_replace($ff,'</pre><formfeed /><pre>',$text); }
89
+ return ('<pre>'.$text.'</pre>');
90
+ }
91
+
92
+ if(!function_exists('strcode2utf')){
93
+ function strcode2utf($str,$lo=true) {
94
+ //converts all the &#nnn; and &#xhhh; in a string to Unicode
95
+ if ($lo) { $lo = 1; } else { $lo = 0; }
96
+ $str = preg_replace('/\&\#([0-9]+)\;/me', "code2utf('\\1',{$lo})",$str);
97
+ $str = preg_replace('/\&\#x([0-9a-fA-F]+)\;/me', "codeHex2utf('\\1',{$lo})",$str);
98
+ return $str;
99
+ }
100
+ }
101
+
102
+ if(!function_exists('code2utf')){
103
+ function code2utf($num,$lo=true){
104
+ //Returns the utf string corresponding to the unicode value
105
+ if ($num<128) {
106
+ if ($lo) return chr($num);
107
+ else return '&#'.$num.';';
108
+ }
109
+ if ($num<2048) return chr(($num>>6)+192).chr(($num&63)+128);
110
+ if ($num<65536) return chr(($num>>12)+224).chr((($num>>6)&63)+128).chr(($num&63)+128);
111
+ if ($num<2097152) return chr(($num>>18)+240).chr((($num>>12)&63)+128).chr((($num>>6)&63)+128) .chr(($num&63)+128);
112
+ return '?';
113
+ }
114
+ }
115
+
116
+
117
+ if(!function_exists('codeHex2utf')){
118
+ function codeHex2utf($hex,$lo=true){
119
+ $num = hexdec($hex);
120
+ if (($num<128) && !$lo) return '&#x'.$hex.';';
121
+ return code2utf($num,$lo);
122
+ }
123
+ }
124
+
125
+
126
+ ?>
mpdf/includes/no_image.jpg ADDED
Binary file
mpdf/mpdf.php ADDED
@@ -0,0 +1,26153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // ******************************************************************************
4
+ // Software: mPDF, Unicode-HTML Free PDF generator *
5
+ // Version: 5.7 based on *
6
+ // FPDF by Olivier PLATHEY *
7
+ // HTML2FPDF by Renato Coelho *
8
+ // Date: 2013-07-14 *
9
+ // Author: Ian Back <ianb@bpm1.com> *
10
+ // License: GPL *
11
+ // *
12
+ // Changes: See changelog.txt *
13
+ // ******************************************************************************
14
+
15
+
16
+ define('mPDF_VERSION','5.7');
17
+
18
+ //Scale factor
19
+ define('_MPDFK', (72/25.4));
20
+
21
+ define('AUTOFONT_CJK',1);
22
+ define('AUTOFONT_THAIVIET',2);
23
+ define('AUTOFONT_RTL',4);
24
+ define('AUTOFONT_INDIC',8);
25
+ define('AUTOFONT_ALL',15);
26
+
27
+ define('_BORDER_ALL',15);
28
+ define('_BORDER_TOP',8);
29
+ define('_BORDER_RIGHT',4);
30
+ define('_BORDER_BOTTOM',2);
31
+ define('_BORDER_LEFT',1);
32
+
33
+ if (!defined('_MPDF_PATH')) define('_MPDF_PATH', dirname(preg_replace('/\\\\/','/',__FILE__)) . '/');
34
+ if (!defined('_MPDF_URI')) define('_MPDF_URI',_MPDF_PATH);
35
+
36
+ require_once(_MPDF_PATH.'includes/functions.php');
37
+ require_once(_MPDF_PATH.'config_cp.php');
38
+
39
+ if (!defined('_JPGRAPH_PATH')) define("_JPGRAPH_PATH", _MPDF_PATH.'jpgraph/');
40
+
41
+ if (!defined('_MPDF_TEMP_PATH')) define("_MPDF_TEMP_PATH", _MPDF_PATH.'tmp/');
42
+
43
+ if (!defined('_MPDF_TTFONTPATH')) { define('_MPDF_TTFONTPATH',_MPDF_PATH.'ttfonts/'); }
44
+ if (!defined('_MPDF_TTFONTDATAPATH')) { define('_MPDF_TTFONTDATAPATH',_MPDF_PATH.'ttfontdata/'); }
45
+
46
+ $errorlevel=error_reporting();
47
+ $errorlevel=error_reporting($errorlevel & ~E_NOTICE);
48
+
49
+ //error_reporting(E_ALL);
50
+
51
+ if(function_exists("date_default_timezone_set")) {
52
+ if (ini_get("date.timezone")=="") { date_default_timezone_set("Europe/London"); }
53
+ }
54
+ if (!function_exists("mb_strlen")) { die("Error - mPDF requires mb_string functions. Ensure that PHP is compiled with php_mbstring.dll enabled."); }
55
+
56
+ if (!defined('PHP_VERSION_ID')) {
57
+ $version = explode('.', PHP_VERSION);
58
+ define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));
59
+ }
60
+ // Machine dependent number of bytes used to pack "double" into binary (used in cacheTables)
61
+ $test = pack("d", 134455.474557333333666);
62
+ define("_DSIZE", strlen($test));
63
+
64
+ class mPDF
65
+ {
66
+
67
+ ///////////////////////////////
68
+ // EXTERNAL (PUBLIC) VARIABLES
69
+ // Define these in config.php
70
+ ///////////////////////////////
71
+ var $CJKforceend; // mPDF 5.6.40
72
+ // mPDF 5.6.34
73
+ var $h2bookmarks;
74
+ var $h2toc;
75
+ var $decimal_align; // mPDF 5.6.13
76
+ var $margBuffer; // mPDF 5.4.04
77
+ var $splitTableBorderWidth; // mPDF 5.4.16
78
+
79
+ var $cacheTables;
80
+ var $bookmarkStyles;
81
+ var $useActiveForms;
82
+
83
+ var $repackageTTF;
84
+ var $allowCJKorphans;
85
+ var $allowCJKoverflow;
86
+
87
+ var $useKerning;
88
+ var $restrictColorSpace;
89
+ var $bleedMargin;
90
+ var $crossMarkMargin;
91
+ var $cropMarkMargin;
92
+ var $cropMarkLength;
93
+ var $nonPrintMargin;
94
+
95
+ var $PDFX;
96
+ var $PDFXauto;
97
+
98
+ var $PDFA;
99
+ var $PDFAauto;
100
+ var $ICCProfile;
101
+
102
+ var $printers_info;
103
+ var $iterationCounter;
104
+ var $smCapsScale;
105
+ var $smCapsStretch;
106
+
107
+ var $backupSubsFont;
108
+ var $backupSIPFont;
109
+ var $debugfonts;
110
+ var $useAdobeCJK;
111
+ var $percentSubset;
112
+ var $maxTTFFilesize;
113
+ var $BMPonly;
114
+
115
+ var $tableMinSizePriority;
116
+
117
+ var $dpi;
118
+ var $watermarkImgAlphaBlend;
119
+ var $watermarkImgBehind;
120
+ var $justifyB4br;
121
+ var $packTableData;
122
+ var $pgsIns;
123
+ var $simpleTables;
124
+ var $enableImports;
125
+
126
+ var $debug;
127
+ var $showStats;
128
+ var $setAutoTopMargin;
129
+ var $setAutoBottomMargin;
130
+ var $autoMarginPadding;
131
+ var $collapseBlockMargins;
132
+ var $falseBoldWeight;
133
+ var $normalLineheight;
134
+ var $progressBar;
135
+ var $incrementFPR1;
136
+ var $incrementFPR2;
137
+ var $incrementFPR3;
138
+ var $incrementFPR4;
139
+
140
+ var $SHYlang;
141
+ var $SHYleftmin;
142
+ var $SHYrightmin;
143
+ var $SHYcharmin;
144
+ var $SHYcharmax;
145
+ var $SHYlanguages;
146
+ // PageNumber Conditional Text
147
+ var $pagenumPrefix;
148
+ var $pagenumSuffix;
149
+ var $nbpgPrefix;
150
+ var $nbpgSuffix;
151
+ var $showImageErrors;
152
+ var $allow_output_buffering;
153
+ var $autoPadding;
154
+ var $useGraphs;
155
+ var $autoFontGroupSize;
156
+ var $tabSpaces;
157
+ var $useLang;
158
+ var $restoreBlockPagebreaks;
159
+ var $watermarkTextAlpha;
160
+ var $watermarkImageAlpha;
161
+ var $watermark_size;
162
+ var $watermark_pos;
163
+ var $annotSize;
164
+ var $annotMargin;
165
+ var $annotOpacity;
166
+ var $title2annots;
167
+ var $keepColumns;
168
+ var $keep_table_proportions;
169
+ var $ignore_table_widths;
170
+ var $ignore_table_percents;
171
+ var $list_align_style;
172
+ var $list_number_suffix;
173
+ var $useSubstitutions;
174
+ var $CSSselectMedia;
175
+
176
+ var $forcePortraitHeaders;
177
+ var $forcePortraitMargins;
178
+ var $displayDefaultOrientation;
179
+ var $ignore_invalid_utf8;
180
+ var $allowedCSStags;
181
+ var $onlyCoreFonts;
182
+ var $allow_charset_conversion;
183
+
184
+ var $jSWord;
185
+ var $jSmaxChar;
186
+ var $jSmaxCharLast;
187
+ var $jSmaxWordLast;
188
+
189
+ var $max_colH_correction;
190
+
191
+
192
+ var $table_error_report;
193
+ var $table_error_report_param;
194
+ var $biDirectional;
195
+ var $text_input_as_HTML;
196
+ var $anchor2Bookmark;
197
+ var $list_indent_first_level;
198
+ var $shrink_tables_to_fit;
199
+
200
+ var $allow_html_optional_endtags;
201
+
202
+ var $img_dpi;
203
+
204
+ var $defaultheaderfontsize;
205
+ var $defaultheaderfontstyle;
206
+ var $defaultheaderline;
207
+ var $defaultfooterfontsize;
208
+ var $defaultfooterfontstyle;
209
+ var $defaultfooterline;
210
+ var $header_line_spacing;
211
+ var $footer_line_spacing;
212
+
213
+ var $pregUHCchars;
214
+ var $pregSJISchars;
215
+ var $pregCJKchars;
216
+ var $pregASCIIchars1;
217
+ var $pregASCIIchars2;
218
+ var $pregASCIIchars3;
219
+ var $pregVIETchars;
220
+ var $pregVIETPluschars;
221
+
222
+ var $pregRTLchars;
223
+ var $pregHEBchars;
224
+ var $pregARABICchars;
225
+ var $pregNonARABICchars;
226
+ // INDIC
227
+ var $pregHIchars;
228
+ var $pregBNchars;
229
+ var $pregPAchars;
230
+ var $pregGUchars;
231
+ var $pregORchars;
232
+ var $pregTAchars;
233
+ var $pregTEchars;
234
+ var $pregKNchars;
235
+ var $pregMLchars;
236
+ var $pregSHchars;
237
+ var $pregINDextra;
238
+
239
+ var $mirrorMargins;
240
+ var $default_lineheight_correction;
241
+ var $watermarkText;
242
+ var $watermarkImage;
243
+ var $showWatermarkText;
244
+ var $showWatermarkImage;
245
+
246
+ var $fontsizes;
247
+
248
+ // Aliases for backward compatability
249
+ var $UnvalidatedText; // alias = $watermarkText
250
+ var $TopicIsUnvalidated; // alias = $showWatermarkText
251
+ var $useOddEven; // alias = $mirrorMargins
252
+ var $useSubstitutionsMB; // alias = $useSubstitutions
253
+
254
+
255
+
256
+ //////////////////////
257
+ // CLASS OBJECTS
258
+ //////////////////////
259
+ var $cssmgr;
260
+ var $grad;
261
+ var $bmp;
262
+ var $wmf;
263
+ var $tocontents;
264
+ var $form;
265
+ var $directw;
266
+
267
+ //////////////////////
268
+ // INTERNAL VARIABLES
269
+ //////////////////////
270
+ var $writingToC; // mPDF 5.6.38
271
+ // mPDF 5.6.01
272
+ var $layers;
273
+ var $current_layer;
274
+ var $open_layer_pane;
275
+ var $decimal_offset; // mPDF 5.6.13
276
+ var $inMeter; // mPDF 5.5.09
277
+
278
+ var $CJKleading;
279
+ var $CJKfollowing;
280
+ var $CJKoverflow;
281
+
282
+ var $textshadow;
283
+
284
+ var $colsums;
285
+ var $spanborder;
286
+ var $spanborddet;
287
+
288
+ var $visibility;
289
+
290
+ var $useRC128encryption;
291
+ var $uniqid;
292
+
293
+ var $kerning;
294
+ var $fixedlSpacing;
295
+ var $minwSpacing;
296
+ var $lSpacingCSS;
297
+ var $wSpacingCSS;
298
+
299
+ var $listDir;
300
+ var $spotColorIDs;
301
+ var $SVGcolors;
302
+ var $spotColors;
303
+ var $defTextColor;
304
+ var $defDrawColor;
305
+ var $defFillColor;
306
+
307
+ var $tableBackgrounds;
308
+ var $inlineDisplayOff;
309
+ var $kt_y00;
310
+ var $kt_p00;
311
+ var $upperCase;
312
+ var $checkSIP;
313
+ var $checkSMP;
314
+ var $checkCJK;
315
+ var $tableCJK;
316
+
317
+ var $watermarkImgAlpha;
318
+ var $PDFAXwarnings;
319
+ var $MetadataRoot;
320
+ var $OutputIntentRoot;
321
+ var $InfoRoot;
322
+ var $current_filename;
323
+ var $parsers;
324
+ var $current_parser;
325
+ var $_obj_stack;
326
+ var $_don_obj_stack;
327
+ var $_current_obj_id;
328
+ var $tpls;
329
+ var $tpl;
330
+ var $tplprefix;
331
+ var $_res;
332
+
333
+ var $pdf_version;
334
+ var $noImageFile;
335
+ var $lastblockbottommargin;
336
+ var $baselineC;
337
+ var $subPos;
338
+ var $subArrMB;
339
+ var $ReqFontStyle;
340
+ var $tableClipPath ;
341
+ var $forceExactLineheight;
342
+ var $listOcc;
343
+
344
+ var $fullImageHeight;
345
+ var $inFixedPosBlock; // Internal flag for position:fixed block
346
+ var $fixedPosBlock; // Buffer string for position:fixed block
347
+ var $fixedPosBlockDepth;
348
+ var $fixedPosBlockBBox;
349
+ var $fixedPosBlockSave;
350
+ var $maxPosL;
351
+ var $maxPosR;
352
+
353
+ var $loaded;
354
+
355
+ var $extraFontSubsets;
356
+ var $docTemplateStart; // Internal flag for page (page no. -1) that docTemplate starts on
357
+ var $time0;
358
+
359
+ // Classes
360
+ var $indic;
361
+ var $barcode;
362
+
363
+ var $SHYpatterns;
364
+ var $loadedSHYpatterns;
365
+ var $loadedSHYdictionary;
366
+ var $SHYdictionary;
367
+ var $SHYdictionaryWords;
368
+
369
+ var $spanbgcolorarray;
370
+ var $default_font;
371
+ var $list_lineheight;
372
+ var $headerbuffer;
373
+ var $lastblocklevelchange;
374
+ var $nestedtablejustfinished;
375
+ var $linebreakjustfinished;
376
+ var $cell_border_dominance_L;
377
+ var $cell_border_dominance_R;
378
+ var $cell_border_dominance_T;
379
+ var $cell_border_dominance_B;
380
+ var $table_keep_together;
381
+ var $plainCell_properties;
382
+ var $inherit_lineheight;
383
+ var $listitemtype;
384
+ var $shrin_k1;
385
+ var $outerfilled;
386
+
387
+ var $blockContext;
388
+ var $floatDivs;
389
+
390
+
391
+ var $patterns;
392
+ var $pageBackgrounds;
393
+
394
+ var $bodyBackgroundGradient;
395
+ var $bodyBackgroundImage;
396
+ var $bodyBackgroundColor;
397
+
398
+ var $writingHTMLheader; // internal flag - used both for writing HTMLHeaders/Footers and FixedPos block
399
+ var $writingHTMLfooter;
400
+ var $autoFontGroups;
401
+ var $angle;
402
+
403
+ var $gradients;
404
+
405
+ var $kwt_Reference;
406
+ var $kwt_BMoutlines;
407
+ var $kwt_toc;
408
+
409
+ var $tbrot_Reference;
410
+ var $tbrot_BMoutlines;
411
+ var $tbrot_toc;
412
+
413
+ var $col_Reference;
414
+ var $col_BMoutlines;
415
+ var $col_toc;
416
+
417
+ var $currentGraphId;
418
+ var $graphs;
419
+
420
+ var $floatbuffer;
421
+ var $floatmargins;
422
+
423
+ var $bullet;
424
+ var $bulletarray;
425
+
426
+ var $rtlAsArabicFarsi; // DEPRACATED
427
+
428
+ var $currentLang;
429
+ var $default_lang;
430
+ var $default_available_fonts;
431
+ var $pageTemplate;
432
+ var $docTemplate;
433
+ var $docTemplateContinue;
434
+
435
+ var $arabGlyphs;
436
+ var $arabHex;
437
+ var $persianGlyphs;
438
+ var $persianHex;
439
+ var $arabVowels;
440
+ var $arabPrevLink;
441
+ var $arabNextLink;
442
+
443
+
444
+ var $formobjects; // array of Form Objects for WMF
445
+ var $InlineProperties;
446
+ var $InlineAnnots;
447
+ var $ktAnnots;
448
+ var $tbrot_Annots;
449
+ var $kwt_Annots;
450
+ var $columnAnnots;
451
+ var $columnForms;
452
+
453
+ var $PageAnnots;
454
+
455
+ var $pageDim; // Keep track of page wxh for orientation changes - set in _beginpage, used in _putannots
456
+
457
+ var $breakpoints;
458
+
459
+ var $tableLevel;
460
+ var $tbctr;
461
+ var $innermostTableLevel;
462
+ var $saveTableCounter;
463
+ var $cellBorderBuffer;
464
+
465
+ var $saveHTMLFooter_height;
466
+ var $saveHTMLFooterE_height;
467
+
468
+ var $firstPageBoxHeader;
469
+ var $firstPageBoxHeaderEven;
470
+ var $firstPageBoxFooter;
471
+ var $firstPageBoxFooterEven;
472
+
473
+ var $page_box;
474
+ var $show_marks; // crop or cross marks
475
+
476
+ var $basepathIsLocal;
477
+
478
+ var $use_kwt;
479
+ var $kwt;
480
+ var $kwt_height;
481
+ var $kwt_y0;
482
+ var $kwt_x0;
483
+ var $kwt_buffer;
484
+ var $kwt_Links;
485
+ var $kwt_moved;
486
+ var $kwt_saved;
487
+
488
+ var $PageNumSubstitutions;
489
+
490
+ var $table_borders_separate;
491
+ var $base_table_properties;
492
+ var $borderstyles;
493
+
494
+ var $listjustfinished;
495
+ var $blockjustfinished;
496
+
497
+ var $orig_bMargin;
498
+ var $orig_tMargin;
499
+ var $orig_lMargin;
500
+ var $orig_rMargin;
501
+ var $orig_hMargin;
502
+ var $orig_fMargin;
503
+
504
+ var $pageheaders;
505
+ var $pagefooters;
506
+
507
+ var $pageHTMLheaders;
508
+ var $pageHTMLfooters;
509
+
510
+ var $saveHTMLHeader;
511
+ var $saveHTMLFooter;
512
+
513
+ var $HTMLheaderPageLinks;
514
+ var $HTMLheaderPageAnnots;
515
+ var $HTMLheaderPageForms;
516
+
517
+ // See config_fonts.php for these next 5 values
518
+ var $available_unifonts;
519
+ var $sans_fonts;
520
+ var $serif_fonts;
521
+ var $mono_fonts;
522
+ var $defaultSubsFont;
523
+
524
+ // List of ALL available CJK fonts (incl. styles) (Adobe add-ons) hw removed
525
+ var $available_CJK_fonts;
526
+
527
+ var $HTMLHeader;
528
+ var $HTMLFooter;
529
+ var $HTMLHeaderE;
530
+ var $HTMLFooterE;
531
+ var $bufferoutput;
532
+
533
+ var $showdefaultpagenos; // DEPRACATED -left for backward compatability
534
+
535
+
536
+ // CJK fonts
537
+ var $Big5_widths;
538
+ var $GB_widths;
539
+ var $SJIS_widths;
540
+ var $UHC_widths;
541
+
542
+ // SetProtection
543
+ var $encrypted; //whether document is protected
544
+ var $Uvalue; //U entry in pdf document
545
+ var $Ovalue; //O entry in pdf document
546
+ var $Pvalue; //P entry in pdf document
547
+ var $enc_obj_id; //encryption object id
548
+ var $last_rc4_key; //last RC4 key encrypted (cached for optimisation)
549
+ var $last_rc4_key_c; //last RC4 computed key
550
+ var $encryption_key;
551
+ var $padding; //used for encryption
552
+
553
+
554
+ // Bookmark
555
+ var $BMoutlines;
556
+ var $OutlineRoot;
557
+ // INDEX
558
+ var $ColActive;
559
+ var $Reference;
560
+ var $CurrCol;
561
+ var $NbCol;
562
+ var $y0; //Top ordinate of columns
563
+ var $ColL;
564
+ var $ColWidth;
565
+ var $ColGap;
566
+ // COLUMNS
567
+ var $ColR;
568
+ var $ChangeColumn;
569
+ var $columnbuffer;
570
+ var $ColDetails;
571
+ var $columnLinks;
572
+ var $colvAlign;
573
+ // Substitutions
574
+ var $substitute; // Array of substitution strings e.g. <ttz>112</ttz>
575
+ var $entsearch; // Array of HTML entities (>ASCII 127) to substitute
576
+ var $entsubstitute; // Array of substitution decimal unicode for the Hi entities
577
+
578
+
579
+ // Default values if no style sheet offered (cf. http://www.w3.org/TR/CSS21/sample.html)
580
+ var $defaultCSS;
581
+
582
+ var $linemaxfontsize;
583
+ var $lineheight_correction;
584
+ var $lastoptionaltag; // Save current block item which HTML specifies optionsl endtag
585
+ var $pageoutput;
586
+ var $charset_in;
587
+ var $blk;
588
+ var $blklvl;
589
+ var $ColumnAdjust;
590
+ var $ws; // Word spacing
591
+ var $HREF;
592
+ var $pgwidth;
593
+ var $fontlist;
594
+ var $oldx;
595
+ var $oldy;
596
+ var $B;
597
+ var $U; //underlining flag
598
+ var $S; // SmallCaps flag
599
+ var $I;
600
+
601
+ var $tdbegin;
602
+ var $table;
603
+ var $cell;
604
+ var $col;
605
+ var $row;
606
+
607
+ var $divbegin;
608
+ var $divalign;
609
+ var $divwidth;
610
+ var $divheight;
611
+ var $divrevert;
612
+ var $spanbgcolor;
613
+
614
+ var $spanlvl;
615
+ var $listlvl;
616
+ var $listnum;
617
+ var $listtype;
618
+ var $listoccur;
619
+ var $listlist;
620
+ var $listitem;
621
+
622
+ var $pjustfinished;
623
+ var $ignorefollowingspaces;
624
+ var $SUP;
625
+ var $SUB;
626
+ var $SMALL;
627
+ var $BIG;
628
+ var $toupper;
629
+ var $tolower;
630
+ var $capitalize;
631
+ var $dash_on;
632
+ var $dotted_on;
633
+ var $strike;
634
+
635
+ var $textbuffer;
636
+ var $currentfontstyle;
637
+ var $currentfontfamily;
638
+ var $currentfontsize;
639
+ var $colorarray;
640
+ var $bgcolorarray;
641
+ var $internallink;
642
+ var $enabledtags;
643
+
644
+ var $lineheight;
645
+ var $basepath;
646
+ var $textparam;
647
+
648
+ var $specialcontent;
649
+ var $selectoption;
650
+ var $objectbuffer;
651
+
652
+ // Table Rotation
653
+ var $table_rotate;
654
+ var $tbrot_maxw;
655
+ var $tbrot_maxh;
656
+ var $tablebuffer;
657
+ var $tbrot_align;
658
+ var $tbrot_Links;
659
+
660
+ var $divbuffer; // Buffer used when keeping DIV on one page
661
+ var $keep_block_together; // Keep a Block from page-break-inside: avoid
662
+ var $ktLinks; // Keep-together Block links array
663
+ var $ktBlock; // Keep-together Block array
664
+ var $ktForms;
665
+ var $ktReference;
666
+ var $ktBMoutlines;
667
+ var $_kttoc;
668
+
669
+ var $tbrot_y0;
670
+ var $tbrot_x0;
671
+ var $tbrot_w;
672
+ var $tbrot_h;
673
+
674
+ var $mb_enc;
675
+ var $directionality;
676
+
677
+ var $extgstates; // Used for alpha channel - Transparency (Watermark)
678
+ var $mgl;
679
+ var $mgt;
680
+ var $mgr;
681
+ var $mgb;
682
+
683
+ var $tts;
684
+ var $ttz;
685
+ var $tta;
686
+
687
+ var $headerDetails;
688
+ var $footerDetails;
689
+
690
+ // Best to alter the below variables using default stylesheet above
691
+ var $page_break_after_avoid;
692
+ var $margin_bottom_collapse;
693
+ var $list_indent;
694
+ var $list_align;
695
+ var $list_margin_bottom;
696
+ var $default_font_size; // in pts
697
+ var $original_default_font_size; // used to save default sizes when using table default
698
+ var $original_default_font;
699
+ var $watermark_font;
700
+ var $defaultAlign;
701
+
702
+ // TABLE
703
+ var $defaultTableAlign;
704
+ var $tablethead;
705
+ var $thead_font_weight;
706
+ var $thead_font_style;
707
+ var $thead_font_smCaps;
708
+ var $thead_valign_default;
709
+ var $thead_textalign_default;
710
+ var $tabletfoot;
711
+ var $tfoot_font_weight;
712
+ var $tfoot_font_style;
713
+ var $tfoot_font_smCaps;
714
+ var $tfoot_valign_default;
715
+ var $tfoot_textalign_default;
716
+
717
+ var $trow_text_rotate;
718
+
719
+ var $cellPaddingL;
720
+ var $cellPaddingR;
721
+ var $cellPaddingT;
722
+ var $cellPaddingB;
723
+ var $table_lineheight;
724
+ var $table_border_attr_set;
725
+ var $table_border_css_set;
726
+
727
+ var $shrin_k; // factor with which to shrink tables - used internally - do not change
728
+ var $shrink_this_table_to_fit; // 0 or false to disable; value (if set) gives maximum factor to reduce fontsize
729
+ var $MarginCorrection; // corrects for OddEven Margins
730
+ var $margin_footer;
731
+ var $margin_header;
732
+
733
+ var $tabletheadjustfinished;
734
+ var $usingCoreFont;
735
+ var $charspacing;
736
+
737
+ //Private properties FROM FPDF
738
+ var $DisplayPreferences;
739
+ var $flowingBlockAttr;
740
+ var $page; //current page number
741
+ var $n; //current object number
742
+ var $offsets; //array of object offsets
743
+ var $buffer; //buffer holding in-memory PDF
744
+ var $pages; //array containing pages
745
+ var $state; //current document state
746
+ var $compress; //compression flag
747
+ var $DefOrientation; //default orientation
748
+ var $CurOrientation; //current orientation
749
+ var $OrientationChanges; //array indicating orientation changes
750
+ var $k; //scale factor (number of points in user unit)
751
+ var $fwPt;
752
+ var $fhPt; //dimensions of page format in points
753
+ var $fw;
754
+ var $fh; //dimensions of page format in user unit
755
+ var $wPt;
756
+ var $hPt; //current dimensions of page in points
757
+ var $w;
758
+ var $h; //current dimensions of page in user unit
759
+ var $lMargin; //left margin
760
+ var $tMargin; //top margin
761
+ var $rMargin; //right margin
762
+ var $bMargin; //page break margin
763
+ var $cMarginL; //cell margin Left
764
+ var $cMarginR; //cell margin Right
765
+ var $cMarginT; //cell margin Left
766
+ var $cMarginB; //cell margin Right
767
+ var $DeflMargin; //Default left margin
768
+ var $DefrMargin; //Default right margin
769
+ var $x;
770
+ var $y; //current position in user unit for cell positioning
771
+ var $lasth; //height of last cell printed
772
+ var $LineWidth; //line width in user unit
773
+ var $CoreFonts; //array of standard font names
774
+ var $fonts; //array of used fonts
775
+ var $FontFiles; //array of font files
776
+ var $images; //array of used images
777
+ var $PageLinks; //array of links in pages
778
+ var $links; //array of internal links
779
+ var $FontFamily; //current font family
780
+ var $FontStyle; //current font style
781
+ var $CurrentFont; //current font info
782
+ var $FontSizePt; //current font size in points
783
+ var $FontSize; //current font size in user unit
784
+ var $DrawColor; //commands for drawing color
785
+ var $FillColor; //commands for filling color
786
+ var $TextColor; //commands for text color
787
+ var $ColorFlag; //indicates whether fill and text colors are different
788
+ var $autoPageBreak; //automatic page breaking
789
+ var $PageBreakTrigger; //threshold used to trigger page breaks
790
+ var $InFooter; //flag set when processing footer
791
+ var $InHTMLFooter;
792
+
793
+ var $processingFooter; //flag set when processing footer - added for columns
794
+ var $processingHeader; //flag set when processing header - added for columns
795
+ var $ZoomMode; //zoom display mode
796
+ var $LayoutMode; //layout display mode
797
+ var $title; //title
798
+ var $subject; //subject
799
+ var $author; //author
800
+ var $keywords; //keywords
801
+ var $creator; //creator
802
+
803
+ var $aliasNbPg; //alias for total number of pages
804
+ var $aliasNbPgGp; //alias for total number of pages in page group
805
+ var $aliasNbPgHex;
806
+ var $aliasNbPgGpHex;
807
+
808
+ var $ispre;
809
+
810
+ var $outerblocktags;
811
+ var $innerblocktags;
812
+
813
+
814
+ // **********************************
815
+ // **********************************
816
+ // **********************************
817
+ // **********************************
818
+ // **********************************
819
+ // **********************************
820
+ // **********************************
821
+ // **********************************
822
+ // **********************************
823
+
824
+ function mPDF($mode='',$format='A4',$default_font_size=0,$default_font='',$mgl=15,$mgr=15,$mgt=16,$mgb=16,$mgh=9,$mgf=9, $orientation='P') {
825
+
826
+ if (!class_exists('grad', false)) { include(_MPDF_PATH.'classes/grad.php'); }
827
+ if (empty($this->grad)) { $this->grad = new grad($this); }
828
+
829
+ $this->time0 = microtime(true);
830
+ //Some checks
831
+ $this->_dochecks();
832
+
833
+ // Set up Aliases for backwards compatability
834
+ $this->UnvalidatedText =& $this->watermarkText;
835
+ $this->TopicIsUnvalidated =& $this->showWatermarkText;
836
+ $this->AliasNbPg =& $this->aliasNbPg;
837
+ $this->AliasNbPgGp =& $this->aliasNbPgGp;
838
+ $this->BiDirectional =& $this->biDirectional;
839
+ $this->Anchor2Bookmark =& $this->anchor2Bookmark;
840
+ $this->KeepColumns =& $this->keepColumns;
841
+ $this->useOddEven =& $this->mirrorMargins;
842
+ $this->useSubstitutionsMB =& $this->useSubstitutions;
843
+
844
+ $this->writingToC = false; // mPDF 5.6.38
845
+ // mPDF 5.6.01
846
+ $this->layers = array();
847
+ $this->current_layer = 0;
848
+ $this->open_layer_pane = false;
849
+
850
+ $this->visibility='visible';
851
+
852
+ //Initialization of properties
853
+ $this->spotColors=array();
854
+ $this->spotColorIDs = array();
855
+ $this->tableBackgrounds = array();
856
+
857
+ $this->kt_y00 = '';
858
+ $this->kt_p00 = '';
859
+ $this->iterationCounter = false;
860
+ $this->BMPonly = array();
861
+ $this->page=0;
862
+ $this->n=2;
863
+ $this->buffer='';
864
+ $this->objectbuffer = array();
865
+ $this->pages=array();
866
+ $this->OrientationChanges=array();
867
+ $this->state=0;
868
+ $this->fonts=array();
869
+ $this->FontFiles=array();
870
+ $this->images=array();
871
+ $this->links=array();
872
+ $this->InFooter=false;
873
+ $this->processingFooter=false;
874
+ $this->processingHeader=false;
875
+ $this->lasth=0;
876
+ $this->FontFamily='';
877
+ $this->FontStyle='';
878
+ $this->FontSizePt=9;
879
+ $this->U=false;
880
+ // Small Caps
881
+ $this->upperCase = array();
882
+ $this->S = false;
883
+ $this->smCapsScale = 1;
884
+ $this->smCapsStretch = 100;
885
+ $this->margBuffer = 0; // mPDF 5.4.04
886
+ $this->inMeter = false; // mPDF 5.5.09
887
+ $this->decimal_offset = 0;
888
+
889
+ $this->defTextColor = $this->TextColor = $this->SetTColor($this->ConvertColor(0),true);
890
+ $this->defDrawColor = $this->DrawColor = $this->SetDColor($this->ConvertColor(0),true);
891
+ $this->defFillColor = $this->FillColor = $this->SetFColor($this->ConvertColor(255),true);
892
+
893
+ //SVG color names array
894
+ //http://www.w3schools.com/css/css_colornames.asp
895
+ $this->SVGcolors = array('antiquewhite'=>'#FAEBD7','aqua'=>'#00FFFF','aquamarine'=>'#7FFFD4','beige'=>'#F5F5DC','black'=>'#000000',
896
+ 'blue'=>'#0000FF','brown'=>'#A52A2A','cadetblue'=>'#5F9EA0','chocolate'=>'#D2691E','cornflowerblue'=>'#6495ED','crimson'=>'#DC143C',
897
+ 'darkblue'=>'#00008B','darkgoldenrod'=>'#B8860B','darkgreen'=>'#006400','darkmagenta'=>'#8B008B','darkorange'=>'#FF8C00',
898
+ 'darkred'=>'#8B0000','darkseagreen'=>'#8FBC8F','darkslategray'=>'#2F4F4F','darkviolet'=>'#9400D3','deepskyblue'=>'#00BFFF',
899
+ 'dodgerblue'=>'#1E90FF','firebrick'=>'#B22222','forestgreen'=>'#228B22','fuchsia'=>'#FF00FF','gainsboro'=>'#DCDCDC','gold'=>'#FFD700',
900
+ 'gray'=>'#808080','green'=>'#008000','greenyellow'=>'#ADFF2F','hotpink'=>'#FF69B4','indigo'=>'#4B0082','khaki'=>'#F0E68C',
901
+ 'lavenderblush'=>'#FFF0F5','lemonchiffon'=>'#FFFACD','lightcoral'=>'#F08080','lightgoldenrodyellow'=>'#FAFAD2','lightgreen'=>'#90EE90',
902
+ 'lightsalmon'=>'#FFA07A','lightskyblue'=>'#87CEFA','lightslategray'=>'#778899','lightyellow'=>'#FFFFE0','lime'=>'#00FF00','limegreen'=>'#32CD32',
903
+ 'magenta'=>'#FF00FF','maroon'=>'#800000','mediumaquamarine'=>'#66CDAA','mediumorchid'=>'#BA55D3','mediumseagreen'=>'#3CB371',
904
+ 'mediumspringgreen'=>'#00FA9A','mediumvioletred'=>'#C71585','midnightblue'=>'#191970','mintcream'=>'#F5FFFA','moccasin'=>'#FFE4B5','navy'=>'#000080',
905
+ 'olive'=>'#808000','orange'=>'#FFA500','orchid'=>'#DA70D6','palegreen'=>'#98FB98',
906
+ 'palevioletred'=>'#D87093','peachpuff'=>'#FFDAB9','pink'=>'#FFC0CB','powderblue'=>'#B0E0E6','purple'=>'#800080',
907
+ 'red'=>'#FF0000','royalblue'=>'#4169E1','salmon'=>'#FA8072','seagreen'=>'#2E8B57','sienna'=>'#A0522D','silver'=>'#C0C0C0','skyblue'=>'#87CEEB',
908
+ 'slategray'=>'#708090','springgreen'=>'#00FF7F','steelblue'=>'#4682B4','tan'=>'#D2B48C','teal'=>'#008080','thistle'=>'#D8BFD8','turquoise'=>'#40E0D0',
909
+ 'violetred'=>'#D02090','white'=>'#FFFFFF','yellow'=>'#FFFF00',
910
+ 'aliceblue'=>'#f0f8ff', 'azure'=>'#f0ffff', 'bisque'=>'#ffe4c4', 'blanchedalmond'=>'#ffebcd', 'blueviolet'=>'#8a2be2', 'burlywood'=>'#deb887',
911
+ 'chartreuse'=>'#7fff00', 'coral'=>'#ff7f50', 'cornsilk'=>'#fff8dc', 'cyan'=>'#00ffff', 'darkcyan'=>'#008b8b', 'darkgray'=>'#a9a9a9',
912
+ 'darkgrey'=>'#a9a9a9', 'darkkhaki'=>'#bdb76b', 'darkolivegreen'=>'#556b2f', 'darkorchid'=>'#9932cc', 'darksalmon'=>'#e9967a',
913
+ 'darkslateblue'=>'#483d8b', 'darkslategrey'=>'#2f4f4f', 'darkturquoise'=>'#00ced1', 'deeppink'=>'#ff1493', 'dimgray'=>'#696969',
914
+ 'dimgrey'=>'#696969', 'floralwhite'=>'#fffaf0', 'ghostwhite'=>'#f8f8ff', 'goldenrod'=>'#daa520', 'grey'=>'#808080', 'honeydew'=>'#f0fff0',
915
+ 'indianred'=>'#cd5c5c', 'ivory'=>'#fffff0', 'lavender'=>'#e6e6fa', 'lawngreen'=>'#7cfc00', 'lightblue'=>'#add8e6', 'lightcyan'=>'#e0ffff',
916
+ 'lightgray'=>'#d3d3d3', 'lightgrey'=>'#d3d3d3', 'lightpink'=>'#ffb6c1', 'lightseagreen'=>'#20b2aa', 'lightslategrey'=>'#778899',
917
+ 'lightsteelblue'=>'#b0c4de', 'linen'=>'#faf0e6', 'mediumblue'=>'#0000cd', 'mediumpurple'=>'#9370db', 'mediumslateblue'=>'#7b68ee',
918
+ 'mediumturquoise'=>'#48d1cc', 'mistyrose'=>'#ffe4e1', 'navajowhite'=>'#ffdead', 'oldlace'=>'#fdf5e6', 'olivedrab'=>'#6b8e23', 'orangered'=>'#ff4500',
919
+ 'palegoldenrod'=>'#eee8aa', 'paleturquoise'=>'#afeeee', 'papayawhip'=>'#ffefd5', 'peru'=>'#cd853f', 'plum'=>'#dda0dd', 'rosybrown'=>'#bc8f8f',
920
+ 'saddlebrown'=>'#8b4513', 'sandybrown'=>'#f4a460', 'seashell'=>'#fff5ee', 'slateblue'=>'#6a5acd', 'slategrey'=>'#708090', 'snow'=>'#fffafa',
921
+ 'tomato'=>'#ff6347', 'violet'=>'#ee82ee', 'wheat'=>'#f5deb3', 'whitesmoke'=>'#f5f5f5', 'yellowgreen'=>'#9acd32');
922
+
923
+ $this->ColorFlag=false;
924
+ $this->extgstates = array();
925
+
926
+ $this->mb_enc='windows-1252';
927
+ $this->directionality='ltr';
928
+ $this->defaultAlign = 'L';
929
+ $this->defaultTableAlign = 'L';
930
+
931
+ $this->fixedPosBlockSave = array();
932
+ $this->extraFontSubsets = 0;
933
+
934
+ $this->SHYpatterns = array();
935
+ $this->loadedSHYdictionary = false;
936
+ $this->SHYdictionary = array();
937
+ $this->SHYdictionaryWords = array();
938
+ $this->blockContext = 1;
939
+ $this->floatDivs = array();
940
+ $this->DisplayPreferences='';
941
+
942
+ $this->patterns = array(); // Tiling patterns used for backgrounds
943
+ $this->pageBackgrounds = array();
944
+ $this->writingHTMLheader = false; // internal flag - used both for writing HTMLHeaders/Footers and FixedPos block
945
+ $this->writingHTMLfooter = false; // internal flag - used both for writing HTMLHeaders/Footers and FixedPos block
946
+ $this->gradients = array();
947
+
948
+ $this->kwt_Reference = array();
949
+ $this->kwt_BMoutlines = array();
950
+ $this->kwt_toc = array();
951
+
952
+ $this->tbrot_Reference = array();
953
+ $this->tbrot_BMoutlines = array();
954
+ $this->tbrot_toc = array();
955
+
956
+ $this->col_Reference = array();
957
+ $this->col_BMoutlines = array();
958
+ $this->col_toc = array();
959
+ $this->graphs = array();
960
+
961
+ $this->pgsIns = array();
962
+ $this->PDFAXwarnings = array();
963
+ $this->inlineDisplayOff = false;
964
+ $this->kerning = false;
965
+ $this->lSpacingCSS = '';
966
+ $this->wSpacingCSS = '';
967
+ $this->fixedlSpacing = false;
968
+ $this->minwSpacing = 0;
969
+
970
+
971
+ $this->baselineC = 0.35; // Baseline for text
972
+ $this->noImageFile = str_replace("\\","/",dirname(__FILE__)) . '/includes/no_image.jpg';
973
+ $this->subPos = 0;
974
+ $this->forceExactLineheight = false;
975
+ $this->listOcc = 0;
976
+ $this->normalLineheight = 1.3;
977
+ // These are intended as configuration variables, and should be set in config.php - which will override these values;
978
+ // set here as failsafe as will cause an error if not defined
979
+ $this->incrementFPR1 = 10;
980
+ $this->incrementFPR2 = 10;
981
+ $this->incrementFPR3 = 10;
982
+ $this->incrementFPR4 = 10;
983
+
984
+ $this->fullImageHeight = false;
985
+ $this->floatbuffer = array();
986
+ $this->floatmargins = array();
987
+ $this->autoFontGroups = 0;
988
+ $this->formobjects=array(); // array of Form Objects for WMF
989
+ $this->InlineProperties=array();
990
+ $this->InlineAnnots=array();
991
+ $this->ktAnnots=array();
992
+ $this->tbrot_Annots=array();
993
+ $this->kwt_Annots=array();
994
+ $this->columnAnnots=array();
995
+ $this->pageDim=array();
996
+ $this->breakpoints = array(); // used in columnbuffer
997
+ $this->tableLevel=0;
998
+ $this->tbctr=array(); // counter for nested tables at each level
999
+ $this->page_box = array();
1000
+ $this->show_marks = ''; // crop or cross marks
1001
+ $this->kwt = false;
1002
+ $this->kwt_height = 0;
1003
+ $this->kwt_y0 = 0;
1004
+ $this->kwt_x0 = 0;
1005
+ $this->kwt_buffer = array();
1006
+ $this->kwt_Links = array();
1007
+ $this->kwt_moved = false;
1008
+ $this->kwt_saved = false;
1009
+ $this->PageNumSubstitutions = array();
1010
+ $this->base_table_properties=array();
1011
+ $this->borderstyles = array('inset','groove','outset','ridge','dotted','dashed','solid','double');
1012
+ $this->tbrot_align = 'C';
1013
+ $this->pageheaders=array();
1014
+ $this->pagefooters=array();
1015
+
1016
+ $this->pageHTMLheaders=array();
1017
+ $this->pageHTMLfooters=array();
1018
+ $this->HTMLheaderPageLinks = array();
1019
+ $this->HTMLheaderPageAnnots = array();
1020
+
1021
+ $this->ktForms = array();
1022
+ $this->HTMLheaderPageForms = array();
1023
+ $this->columnForms = array();
1024
+ $this->tbrotForms = array();
1025
+ $this->useRC128encryption = false;
1026
+ $this->uniqid = '';
1027
+
1028
+ $this->bufferoutput = false;
1029
+ $this->encrypted=false; //whether document is protected
1030
+ $this->BMoutlines=array();
1031
+ $this->ColActive=0; //Flag indicating that columns are on (the index is being processed)
1032
+ $this->Reference=array(); //Array containing the references
1033
+ $this->CurrCol=0; //Current column number
1034
+ $this->ColL = array(0); // Array of Left pos of columns - absolute - needs Margin correction for Odd-Even
1035
+ $this->ColR = array(0); // Array of Right pos of columns - absolute pos - needs Margin correction for Odd-Even
1036
+ $this->ChangeColumn = 0;
1037
+ $this->columnbuffer = array();
1038
+ $this->ColDetails = array(); // Keeps track of some column details
1039
+ $this->columnLinks = array(); // Cross references PageLinks
1040
+ $this->substitute = array(); // Array of substitution strings e.g. <ttz>112</ttz>
1041
+ $this->entsearch = array(); // Array of HTML entities (>ASCII 127) to substitute
1042
+ $this->entsubstitute = array(); // Array of substitution decimal unicode for the Hi entities
1043
+ $this->lastoptionaltag = '';
1044
+ $this->charset_in = '';
1045
+ $this->blk = array();
1046
+ $this->blklvl = 0;
1047
+ $this->tts = false;
1048
+ $this->ttz = false;
1049
+ $this->tta = false;
1050
+ $this->ispre=false;
1051
+
1052
+ $this->checkSIP = false;
1053
+ $this->checkSMP = false;
1054
+ $this->checkCJK = false;
1055
+ $this->tableCJK = false;
1056
+
1057
+ $this->headerDetails=array();
1058
+ $this->footerDetails=array();
1059
+ $this->page_break_after_avoid = false;
1060
+ $this->margin_bottom_collapse = false;
1061
+ $this->tablethead = 0;
1062
+ $this->tabletfoot = 0;
1063
+ $this->table_border_attr_set = 0;
1064
+ $this->table_border_css_set = 0;
1065
+ $this->shrin_k = 1.0;
1066
+ $this->shrink_this_table_to_fit = 0;
1067
+ $this->MarginCorrection = 0;
1068
+
1069
+ $this->tabletheadjustfinished = false;
1070
+ $this->usingCoreFont = false;
1071
+ $this->charspacing=0;
1072
+
1073
+ $this->autoPageBreak = true;
1074
+
1075
+ require(_MPDF_PATH.'config.php'); // config data
1076
+
1077
+ $this->_setPageSize($format, $orientation);
1078
+ $this->DefOrientation=$orientation;
1079
+
1080
+ $this->margin_header=$mgh;
1081
+ $this->margin_footer=$mgf;
1082
+
1083
+ $bmargin=$mgb;
1084
+
1085
+ $this->DeflMargin = $mgl;
1086
+ $this->DefrMargin = $mgr;
1087
+
1088
+ $this->orig_tMargin = $mgt;
1089
+ $this->orig_bMargin = $bmargin;
1090
+ $this->orig_lMargin = $this->DeflMargin;
1091
+ $this->orig_rMargin = $this->DefrMargin;
1092
+ $this->orig_hMargin = $this->margin_header;
1093
+ $this->orig_fMargin = $this->margin_footer;
1094
+
1095
+ if ($this->setAutoTopMargin=='pad') { $mgt += $this->margin_header; }
1096
+ if ($this->setAutoBottomMargin=='pad') { $mgb += $this->margin_footer; }
1097
+ $this->SetMargins($this->DeflMargin,$this->DefrMargin,$mgt); // sets l r t margin
1098
+ //Automatic page break
1099
+ $this->SetAutoPageBreak($this->autoPageBreak,$bmargin); // sets $this->bMargin & PageBreakTrigger
1100
+
1101
+ $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
1102
+
1103
+ //Interior cell margin (1 mm) ? not used
1104
+ $this->cMarginL = 1;
1105
+ $this->cMarginR = 1;
1106
+ //Line width (0.2 mm)
1107
+ $this->LineWidth=.567/_MPDFK;
1108
+
1109
+ //To make the function Footer() work - replaces {nb} with page number
1110
+ $this->AliasNbPages();
1111
+ $this->AliasNbPageGroups();
1112
+
1113
+ $this->aliasNbPgHex = '{nbHEXmarker}';
1114
+ $this->aliasNbPgGpHex = '{nbpgHEXmarker}';
1115
+
1116
+ //Enable all tags as default
1117
+ $this->DisableTags();
1118
+ //Full width display mode
1119
+ $this->SetDisplayMode(100); // fullwidth? 'fullpage'
1120
+ //Compression
1121
+ $this->SetCompression(true);
1122
+ //Set default display preferences
1123
+ $this->SetDisplayPreferences('');
1124
+
1125
+ // Font data
1126
+ require(_MPDF_PATH.'config_fonts.php');
1127
+ // Available fonts
1128
+ $this->available_unifonts = array();
1129
+ foreach ($this->fontdata AS $f => $fs) {
1130
+ if (isset($fs['R']) && $fs['R']) { $this->available_unifonts[] = $f; }
1131
+ if (isset($fs['B']) && $fs['B']) { $this->available_unifonts[] = $f.'B'; }
1132
+ if (isset($fs['I']) && $fs['I']) { $this->available_unifonts[] = $f.'I'; }
1133
+ if (isset($fs['BI']) && $fs['BI']) { $this->available_unifonts[] = $f.'BI'; }
1134
+ }
1135
+
1136
+ $this->default_available_fonts = $this->available_unifonts;
1137
+
1138
+ $optcore = false;
1139
+ $onlyCoreFonts = false;
1140
+ if (preg_match('/([\-+])aCJK/i',$mode, $m)) {
1141
+ preg_replace('/([\-+])aCJK/i','',$mode);
1142
+ if ($m[1]=='+') { $this->useAdobeCJK = true; }
1143
+ else { $this->useAdobeCJK = false; }
1144
+ }
1145
+
1146
+ if (strlen($mode)==1) {
1147
+ if ($mode=='s') { $this->percentSubset = 100; $mode = ''; }
1148
+ else if ($mode=='c') { $onlyCoreFonts = true; $mode = ''; }
1149
+ }
1150
+ else if (substr($mode,-2)=='-s') {
1151
+ $this->percentSubset = 100;
1152
+ $mode = substr($mode,0,strlen($mode)-2);
1153
+ }
1154
+ else if (substr($mode,-2)=='-c') {
1155
+ $onlyCoreFonts = true;
1156
+ $mode = substr($mode,0,strlen($mode)-2);
1157
+ }
1158
+ else if (substr($mode,-2)=='-x') {
1159
+ $optcore = true;
1160
+ $mode = substr($mode,0,strlen($mode)-2);
1161
+ }
1162
+
1163
+ // Autodetect if mode is a language_country string (en-GB or en_GB or en)
1164
+ if ((strlen($mode) == 5 && $mode != 'UTF-8') || strlen($mode) == 2) {
1165
+ list ($coreSuitable,$mpdf_pdf_unifonts) = GetLangOpts($mode, $this->useAdobeCJK);
1166
+ if ($coreSuitable && $optcore) { $onlyCoreFonts = true; }
1167
+ if ($mpdf_pdf_unifonts) {
1168
+ $this->RestrictUnicodeFonts($mpdf_pdf_unifonts);
1169
+ $this->default_available_fonts = $mpdf_pdf_unifonts;
1170
+ }
1171
+ $this->currentLang = $mode;
1172
+ $this->default_lang = $mode;
1173
+ }
1174
+
1175
+ $this->onlyCoreFonts = $onlyCoreFonts;
1176
+
1177
+ if ($this->onlyCoreFonts) {
1178
+ $this->setMBencoding('windows-1252'); // sets $this->mb_enc
1179
+ }
1180
+ else {
1181
+ $this->setMBencoding('UTF-8'); // sets $this->mb_enc
1182
+ }
1183
+ @mb_regex_encoding('UTF-8'); // required only for mb_ereg... and mb_split functions
1184
+
1185
+
1186
+ // Adobe CJK fonts
1187
+ $this->available_CJK_fonts = array('gb','big5','sjis','uhc','gbB','big5B','sjisB','uhcB','gbI','big5I','sjisI','uhcI',
1188
+ 'gbBI','big5BI','sjisBI','uhcBI');
1189
+
1190
+
1191
+ //Standard fonts
1192
+ $this->CoreFonts=array('ccourier'=>'Courier','ccourierB'=>'Courier-Bold','ccourierI'=>'Courier-Oblique','ccourierBI'=>'Courier-BoldOblique',
1193
+ 'chelvetica'=>'Helvetica','chelveticaB'=>'Helvetica-Bold','chelveticaI'=>'Helvetica-Oblique','chelveticaBI'=>'Helvetica-BoldOblique',
1194
+ 'ctimes'=>'Times-Roman','ctimesB'=>'Times-Bold','ctimesI'=>'Times-Italic','ctimesBI'=>'Times-BoldItalic',
1195
+ 'csymbol'=>'Symbol','czapfdingbats'=>'ZapfDingbats');
1196
+ $this->fontlist=array("ctimes","ccourier","chelvetica","csymbol","czapfdingbats");
1197
+
1198
+ // Substitutions
1199
+ $this->setHiEntitySubstitutions();
1200
+
1201
+ if ($this->onlyCoreFonts) {
1202
+ $this->useSubstitutions = true;
1203
+ $this->SetSubstitutions();
1204
+ }
1205
+ else { $this->useSubstitutions = false; }
1206
+
1207
+
1208
+ if (!class_exists('cssmgr', false)) { include(_MPDF_PATH .'classes/cssmgr.php'); }
1209
+ $this->cssmgr = new cssmgr($this);
1210
+ if (file_exists(_MPDF_PATH.'mpdf.css')) {
1211
+ $css = file_get_contents(_MPDF_PATH.'mpdf.css');
1212
+ $css2 = $this->cssmgr->ReadDefaultCSS($css);
1213
+ $this->defaultCSS = $this->cssmgr->array_merge_recursive_unique($this->defaultCSS,$css2);
1214
+ }
1215
+
1216
+ if ($default_font=='') {
1217
+ if ($this->onlyCoreFonts) {
1218
+ if (in_array(strtolower($this->defaultCSS['BODY']['FONT-FAMILY']),$this->mono_fonts)) { $default_font = 'ccourier'; }
1219
+ else if (in_array(strtolower($this->defaultCSS['BODY']['FONT-FAMILY']),$this->sans_fonts)) { $default_font = 'chelvetica'; }
1220
+ else { $default_font = 'ctimes'; }
1221
+ }
1222
+ else { $default_font = $this->defaultCSS['BODY']['FONT-FAMILY']; }
1223
+ }
1224
+ if (!$default_font_size) {
1225
+ $mmsize = $this->ConvertSize($this->defaultCSS['BODY']['FONT-SIZE']);
1226
+ $default_font_size = $mmsize*(_MPDFK);
1227
+ }
1228
+
1229
+ if ($default_font) { $this->SetDefaultFont($default_font); }
1230
+ if ($default_font_size) { $this->SetDefaultFontSize($default_font_size); }
1231
+
1232
+ $this->SetLineHeight(); // lineheight is in mm
1233
+
1234
+ $this->SetFColor($this->ConvertColor(255));
1235
+ $this->HREF='';
1236
+ $this->oldy=-1;
1237
+ $this->B=0;
1238
+ $this->U=false;
1239
+ $this->S=false;
1240
+ $this->I=0;
1241
+
1242
+ $this->listlvl=0;
1243
+ $this->listnum=0;
1244
+ $this->listtype='';
1245
+ $this->listoccur=array();
1246
+ $this->listlist=array();
1247
+ $this->listitem=array();
1248
+
1249
+ $this->tdbegin=false;
1250
+ $this->table=array();
1251
+ $this->cell=array();
1252
+ $this->col=-1;
1253
+ $this->row=-1;
1254
+ $this->cellBorderBuffer = array();
1255
+
1256
+ $this->divbegin=false;
1257
+ $this->divalign='';
1258
+ $this->divwidth=0;
1259
+ $this->divheight=0;
1260
+ $this->spanbgcolor=false;
1261
+ $this->divrevert=false;
1262
+ $this->spanborder=false;
1263
+ $this->spanborddet=array();
1264
+
1265
+ $this->blockjustfinished=false;
1266
+ $this->listjustfinished=false;
1267
+ $this->ignorefollowingspaces = true; //in order to eliminate exceeding left-side spaces
1268
+ $this->toupper=false;
1269
+ $this->tolower=false;
1270
+ $this->capitalize=false;
1271
+ $this->dash_on=false;
1272
+ $this->dotted_on=false;
1273
+ $this->SUP=false;
1274
+ $this->SUB=false;
1275
+ $this->strike=false;
1276
+ $this->textshadow='';
1277
+
1278
+ $this->currentfontfamily='';
1279
+ $this->currentfontsize='';
1280
+ $this->currentfontstyle='';
1281
+ $this->colorarray=array();
1282
+ $this->spanbgcolorarray=array();
1283
+ $this->textbuffer=array();
1284
+ $this->internallink=array();
1285
+ $this->basepath = "";
1286
+
1287
+ $this->SetBasePath('');
1288
+
1289
+ $this->textparam = array();
1290
+
1291
+ $this->specialcontent = '';
1292
+ $this->selectoption = array();
1293
+
1294
+
1295
+ }
1296
+
1297
+
1298
+ function _setPageSize($format, &$orientation) {
1299
+ //Page format
1300
+ if(is_string($format))
1301
+ {
1302
+ if ($format=='') { $format = 'A4'; }
1303
+ $pfo = 'P';
1304
+ if(preg_match('/([0-9a-zA-Z]*)-L/i',$format,$m)) { // e.g. A4-L = A4 landscape
1305
+ $format=$m[1];
1306
+ $pfo='L';
1307
+ }
1308
+ $format = $this->_getPageFormat($format);
1309
+ if (!$format) { $this->Error('Unknown page format: '.$format); }
1310
+ else { $orientation = $pfo; }
1311
+
1312
+ $this->fwPt=$format[0];
1313
+ $this->fhPt=$format[1];
1314
+ }
1315
+ else
1316
+ {
1317
+ if (!$format[0] || !$format[1]) { $this->Error('Invalid page format: '.$format[0].' '.$format[1]); }
1318
+ $this->fwPt=$format[0]*_MPDFK;
1319
+ $this->fhPt=$format[1]*_MPDFK;
1320
+ }
1321
+ $this->fw=$this->fwPt/_MPDFK;
1322
+ $this->fh=$this->fhPt/_MPDFK;
1323
+ //Page orientation
1324
+ $orientation=strtolower($orientation);
1325
+ if($orientation=='p' or $orientation=='portrait')
1326
+ {
1327
+ $orientation='P';
1328
+ $this->wPt=$this->fwPt;
1329
+ $this->hPt=$this->fhPt;
1330
+ }
1331
+ elseif($orientation=='l' or $orientation=='landscape')
1332
+ {
1333
+ $orientation='L';
1334
+ $this->wPt=$this->fhPt;
1335
+ $this->hPt=$this->fwPt;
1336
+ }
1337
+ else $this->Error('Incorrect orientation: '.$orientation);
1338
+ $this->CurOrientation=$orientation;
1339
+
1340
+ $this->w=$this->wPt/_MPDFK;
1341
+ $this->h=$this->hPt/_MPDFK;
1342
+ }
1343
+
1344
+ function _getPageFormat($format) {
1345
+ switch (strtoupper($format)) {
1346
+ case '4A0': {$format = array(4767.87,6740.79); break;}
1347
+ case '2A0': {$format = array(3370.39,4767.87); break;}
1348
+ case 'A0': {$format = array(2383.94,3370.39); break;}
1349
+ case 'A1': {$format = array(1683.78,2383.94); break;}
1350
+ case 'A2': {$format = array(1190.55,1683.78); break;}
1351
+ case 'A3': {$format = array(841.89,1190.55); break;}
1352
+ case 'A4': default: {$format = array(595.28,841.89); break;}
1353
+ case 'A5': {$format = array(419.53,595.28); break;}
1354
+ case 'A6': {$format = array(297.64,419.53); break;}
1355
+ case 'A7': {$format = array(209.76,297.64); break;}
1356
+ case 'A8': {$format = array(147.40,209.76); break;}
1357
+ case 'A9': {$format = array(104.88,147.40); break;}
1358
+ case 'A10': {$format = array(73.70,104.88); break;}
1359
+ case 'B0': {$format = array(2834.65,4008.19); break;}
1360
+ case 'B1': {$format = array(2004.09,2834.65); break;}
1361
+ case 'B2': {$format = array(1417.32,2004.09); break;}
1362
+ case 'B3': {$format = array(1000.63,1417.32); break;}
1363
+ case 'B4': {$format = array(708.66,1000.63); break;}
1364
+ case 'B5': {$format = array(498.90,708.66); break;}
1365
+ case 'B6': {$format = array(354.33,498.90); break;}
1366
+ case 'B7': {$format = array(249.45,354.33); break;}
1367
+ case 'B8': {$format = array(175.75,249.45); break;}
1368
+ case 'B9': {$format = array(124.72,175.75); break;}
1369
+ case 'B10': {$format = array(87.87,124.72); break;}
1370
+ case 'C0': {$format = array(2599.37,3676.54); break;}
1371
+ case 'C1': {$format = array(1836.85,2599.37); break;}
1372
+ case 'C2': {$format = array(1298.27,1836.85); break;}
1373
+ case 'C3': {$format = array(918.43,1298.27); break;}
1374
+ case 'C4': {$format = array(649.13,918.43); break;}
1375
+ case 'C5': {$format = array(459.21,649.13); break;}
1376
+ case 'C6': {$format = array(323.15,459.21); break;}
1377
+ case 'C7': {$format = array(229.61,323.15); break;}
1378
+ case 'C8': {$format = array(161.57,229.61); break;}
1379
+ case 'C9': {$format = array(113.39,161.57); break;}
1380
+ case 'C10': {$format = array(79.37,113.39); break;}
1381
+ case 'RA0': {$format = array(2437.80,3458.27); break;}
1382
+ case 'RA1': {$format = array(1729.13,2437.80); break;}
1383
+ case 'RA2': {$format = array(1218.90,1729.13); break;}
1384
+ case 'RA3': {$format = array(864.57,1218.90); break;}
1385
+ case 'RA4': {$format = array(609.45,864.57); break;}
1386
+ case 'SRA0': {$format = array(2551.18,3628.35); break;}
1387
+ case 'SRA1': {$format = array(1814.17,2551.18); break;}
1388
+ case 'SRA2': {$format = array(1275.59,1814.17); break;}
1389
+ case 'SRA3': {$format = array(907.09,1275.59); break;}
1390
+ case 'SRA4': {$format = array(637.80,907.09); break;}
1391
+ case 'LETTER': {$format = array(612.00,792.00); break;}
1392
+ case 'LEGAL': {$format = array(612.00,1008.00); break;}
1393
+ case 'LEDGER': {$format = array(279.00,432.00); break;}
1394
+ case 'TABLOID': {$format = array(279.00,432.00); break;}
1395
+ case 'EXECUTIVE': {$format = array(521.86,756.00); break;}
1396
+ case 'FOLIO': {$format = array(612.00,936.00); break;}
1397
+ case 'B': {$format=array(362.83,561.26 ); break;} // 'B' format paperback size 128x198mm
1398
+ case 'A': {$format=array(314.65,504.57 ); break;} // 'A' format paperback size 111x178mm
1399
+ case 'DEMY': {$format=array(382.68,612.28 ); break;} // 'Demy' format paperback size 135x216mm
1400
+ case 'ROYAL': {$format=array(433.70,663.30 ); break;} // 'Royal' format paperback size 153x234mm
1401
+ default: $format = false;
1402
+ }
1403
+ return $format;
1404
+ }
1405
+
1406
+
1407
+
1408
+
1409
+
1410
+ function RestrictUnicodeFonts($res) {
1411
+ // $res = array of (Unicode) fonts to restrict to: e.g. norasi|norasiB - language specific
1412
+ if (count($res)) { // Leave full list of available fonts if passed blank array
1413
+ $this->available_unifonts = $res;
1414
+ }
1415
+ else { $this->available_unifonts = $this->default_available_fonts; }
1416
+ if (count($this->available_unifonts) == 0) { $this->available_unifonts[] = $this->default_available_fonts[0]; }
1417
+ $this->available_unifonts = array_values($this->available_unifonts);
1418
+ }
1419
+
1420
+
1421
+ function setMBencoding($enc) {
1422
+ if ($this->mb_enc != $enc) {
1423
+ $this->mb_enc = $enc;
1424
+ mb_internal_encoding($this->mb_enc);
1425
+ }
1426
+ }
1427
+
1428
+
1429
+ function SetMargins($left,$right,$top) {
1430
+ //Set left, top and right margins
1431
+ $this->lMargin=$left;
1432
+ $this->rMargin=$right;
1433
+ $this->tMargin=$top;
1434
+ }
1435
+
1436
+ function ResetMargins() {
1437
+ //ReSet left, top margins
1438
+ if (($this->forcePortraitHeaders || $this->forcePortraitMargins) && $this->DefOrientation=='P' && $this->CurOrientation=='L') {
1439
+ if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
1440
+ $this->tMargin=$this->orig_rMargin;
1441
+ $this->bMargin=$this->orig_lMargin;
1442
+ }
1443
+ else { // ODD // OR NOT MIRRORING MARGINS/FOOTERS
1444
+ $this->tMargin=$this->orig_lMargin;
1445
+ $this->bMargin=$this->orig_rMargin;
1446
+ }
1447
+ $this->lMargin=$this->DeflMargin;
1448
+ $this->rMargin=$this->DefrMargin;
1449
+ $this->MarginCorrection = 0;
1450
+ $this->PageBreakTrigger=$this->h-$this->bMargin;
1451
+ }
1452
+ else if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
1453
+ $this->lMargin=$this->DefrMargin;
1454
+ $this->rMargin=$this->DeflMargin;
1455
+ $this->MarginCorrection = $this->DefrMargin-$this->DeflMargin;
1456
+
1457
+ }
1458
+ else { // ODD // OR NOT MIRRORING MARGINS/FOOTERS
1459
+ $this->lMargin=$this->DeflMargin;
1460
+ $this->rMargin=$this->DefrMargin;
1461
+ if ($this->mirrorMargins) { $this->MarginCorrection = $this->DeflMargin-$this->DefrMargin; }
1462
+ }
1463
+ $this->x=$this->lMargin;
1464
+
1465
+ }
1466
+
1467
+ function SetLeftMargin($margin) {
1468
+ //Set left margin
1469
+ $this->lMargin=$margin;
1470
+ if($this->page>0 and $this->x<$margin) $this->x=$margin;
1471
+ }
1472
+
1473
+ function SetTopMargin($margin) {
1474
+ //Set top margin
1475
+ $this->tMargin=$margin;
1476
+ }
1477
+
1478
+ function SetRightMargin($margin) {
1479
+ //Set right margin
1480
+ $this->rMargin=$margin;
1481
+ }
1482
+
1483
+ function SetAutoPageBreak($auto,$margin=0) {
1484
+ //Set auto page break mode and triggering margin
1485
+ $this->autoPageBreak=$auto;
1486
+ $this->bMargin=$margin;
1487
+ $this->PageBreakTrigger=$this->h-$margin;
1488
+ }
1489
+
1490
+ function SetDisplayMode($zoom,$layout='continuous') {
1491
+ //Set display mode in viewer
1492
+ if($zoom=='fullpage' or $zoom=='fullwidth' or $zoom=='real' or $zoom=='default' or !is_string($zoom))
1493
+ $this->ZoomMode=$zoom;
1494
+ else
1495
+ $this->Error('Incorrect zoom display mode: '.$zoom);
1496
+ if($layout=='single' or $layout=='continuous' or $layout=='two' or $layout=='twoleft' or $layout=='tworight' or $layout=='default')
1497
+ $this->LayoutMode=$layout;
1498
+ else
1499
+ $this->Error('Incorrect layout display mode: '.$layout);
1500
+ }
1501
+
1502
+ function SetCompression($compress) {
1503
+ //Set page compression
1504
+ if(function_exists('gzcompress')) $this->compress=$compress;
1505
+ else $this->compress=false;
1506
+ }
1507
+
1508
+ function SetTitle($title) {
1509
+ //Title of document // Arrives as UTF-8
1510
+ $this->title = $title;
1511
+ }
1512
+
1513
+ function SetSubject($subject) {
1514
+ //Subject of document
1515
+ $this->subject= $subject;
1516
+ }
1517
+
1518
+ function SetAuthor($author) {
1519
+ //Author of document
1520
+ $this->author= $author;
1521
+ }
1522
+
1523
+ function SetKeywords($keywords) {
1524
+ //Keywords of document
1525
+ $this->keywords= $keywords;
1526
+ }
1527
+
1528
+ function SetCreator($creator) {
1529
+ //Creator of document
1530
+ $this->creator= $creator;
1531
+ }
1532
+
1533
+
1534
+ function SetAnchor2Bookmark($x) {
1535
+ $this->anchor2Bookmark = $x;
1536
+ }
1537
+
1538
+ function AliasNbPages($alias='{nb}') {
1539
+ //Define an alias for total number of pages
1540
+ $this->aliasNbPg=$alias;
1541
+ }
1542
+
1543
+ function AliasNbPageGroups($alias='{nbpg}') {
1544
+ //Define an alias for total number of pages in a group
1545
+ $this->aliasNbPgGp=$alias;
1546
+ }
1547
+
1548
+ function SetAlpha($alpha, $bm='Normal', $return=false, $mode='B') {
1549
+ // alpha: real value from 0 (transparent) to 1 (opaque)
1550
+ // bm: blend mode, one of the following:
1551
+ // Normal, Multiply, Screen, Overlay, Darken, Lighten, ColorDodge, ColorBurn,
1552
+ // HardLight, SoftLight, Difference, Exclusion, Hue, Saturation, Color, Luminosity
1553
+ // set alpha for stroking (CA) and non-stroking (ca) operations
1554
+ // mode determines F (fill) S (stroke) B (both)
1555
+ if (($this->PDFA || $this->PDFX) && $alpha!=1) {
1556
+ if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "Image opacity must be 100% (Opacity changed to 100%)"; }
1557
+ $alpha = 1;
1558
+ }
1559
+ $a = array('BM'=>'/'.$bm);
1560
+ if ($mode=='F' || $mode='B') $a['ca'] = $alpha;
1561
+ if ($mode=='S' || $mode='B') $a['CA'] = $alpha;
1562
+ $gs = $this->AddExtGState($a);
1563
+ if ($return) { return sprintf('/GS%d gs', $gs); }
1564
+ else { $this->_out(sprintf('/GS%d gs', $gs)); }
1565
+ }
1566
+
1567
+ function AddExtGState($parms) {
1568
+ $n = count($this->extgstates);
1569
+ // check if graphics state already exists
1570
+ for ($i=1; $i<=$n; $i++) {
1571
+ if (count($this->extgstates[$i]['parms']) == count($parms)) {
1572
+ $same = true;
1573
+ foreach($this->extgstates[$i]['parms'] AS $k=>$v) {
1574
+ if (!isset($parms[$k]) || $parms[$k] != $v) { $same = false; break; }
1575
+ }
1576
+ if ($same) { return $i; }
1577
+ }
1578
+ }
1579
+ $n++;
1580
+ $this->extgstates[$n]['parms'] = $parms;
1581
+ return $n;
1582
+ }
1583
+
1584
+ function SetVisibility($v) {
1585
+ if (($this->PDFA || $this->PDFX) && $this->visibility!='visible') { $this->PDFAXwarnings[] = "Cannot set visibility to anything other than full when using PDFA or PDFX"; return ''; }
1586
+ else if (!$this->PDFA && !$this->PDFX)
1587
+ $this->pdf_version='1.5';
1588
+ if($this->visibility!='visible') {
1589
+ $this->_out('EMC');
1590
+ $this->hasOC=intval($this->hasOC ); // mPDF 5.6.01
1591
+ }
1592
+ if($v=='printonly') {
1593
+ $this->_out('/OC /OC1 BDC');
1594
+ $this->hasOC=($this->hasOC | 1); // mPDF 5.6.01
1595
+ }
1596
+ elseif($v=='screenonly') {
1597
+ $this->_out('/OC /OC2 BDC');
1598
+ $this->hasOC=($this->hasOC | 2); // mPDF 5.6.01
1599
+ }
1600
+ elseif($v=='hidden') {
1601
+ $this->_out('/OC /OC3 BDC');
1602
+ $this->hasOC=($this->hasOC | 4); // mPDF 5.6.01
1603
+ }
1604
+ elseif($v!='visible')
1605
+ $this->Error('Incorrect visibility: '.$v);
1606
+ $this->visibility=$v;
1607
+ }
1608
+
1609
+ function Error($msg) {
1610
+ //Fatal error
1611
+ header('Content-Type: text/html; charset=utf-8');
1612
+ die('<B>mPDF error: </B>'.$msg);
1613
+ }
1614
+
1615
+ function Open() {
1616
+ //Begin document
1617
+ if($this->state==0) $this->_begindoc();
1618
+ }
1619
+
1620
+ function Close() {
1621
+ //Terminate document
1622
+ if($this->state==3) return;
1623
+ if($this->page==0) $this->AddPage($this->CurOrientation);
1624
+ if (count($this->cellBorderBuffer)) { $this->printcellbuffer(); } // *TABLES*
1625
+ if ($this->tablebuffer) { $this->printtablebuffer(); } // *TABLES*
1626
+ if (count($this->divbuffer)) { $this->printdivbuffer(); }
1627
+
1628
+ // BODY Backgrounds
1629
+ $s = '';
1630
+
1631
+ $s .= $this->PrintBodyBackgrounds();
1632
+
1633
+ $s .= $this->PrintPageBackgrounds();
1634
+ $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', "\n".$s."\n".'\\1', $this->pages[$this->page]);
1635
+ $this->pageBackgrounds = array();
1636
+
1637
+ if($this->visibility!='visible')
1638
+ $this->SetVisibility('visible');
1639
+ // mPDF 5.6.01 - LAYERS
1640
+ $this->EndLayer();
1641
+
1642
+ if (!$this->tocontents || !$this->tocontents->TOCmark) { //Page footer
1643
+ $this->InFooter=true;
1644
+ $this->Footer();
1645
+ $this->InFooter=false;
1646
+ }
1647
+
1648
+ //Close page
1649
+ $this->_endpage();
1650
+
1651
+ //Close document
1652
+ $this->_enddoc();
1653
+ }
1654
+
1655
+ function _resizeBackgroundImage($imw, $imh, $cw, $ch, $resize=0, $repx, $repy, $pba=array(), $size=array()) { // mPDF 5.6.10
1656
+ // pba is background positioning area (from CSS background-origin) may not always be set [x,y,w,h]
1657
+ // size is from CSS3 background-size - takes precendence over old resize
1658
+ // $w - absolute length or % or auto or cover | contain
1659
+ // $h - absolute length or % or auto or cover | contain
1660
+ // mPDF 5.6.10
1661
+ if (isset($pba['w'])) $cw = $pba['w'];
1662
+ if (isset($pba['h'])) $ch = $pba['h'];
1663
+
1664
+ $cw = $cw*_MPDFK;
1665
+ $ch = $ch*_MPDFK;
1666
+ if (empty($size) && !$resize) { return array($imw, $imh, $repx, $repy); }
1667
+
1668
+ // mPDF 5.6.10
1669
+ if (isset($size['w']) && $size['w']) {
1670
+ if ($size['w']=='contain') {
1671
+ // Scale the image, while preserving its intrinsic aspect ratio (if any), to the largest size such that both its width and its height can fit inside the background positioning area.
1672
+ // Same as resize==3
1673
+ $h = $imh * $cw/$imw;
1674
+ $w = $cw;
1675
+ if ($h > $ch) {
1676
+ $w = $w * $ch/$h;
1677
+ $h = $ch;
1678
+ }
1679
+ }
1680
+ else if ($size['w']=='cover') {
1681
+ // Scale the image, while preserving its intrinsic aspect ratio (if any), to the smallest size such that both its width and its height can completely cover the background positioning area.
1682
+ $h = $imh * $cw/$imw;
1683
+ $w = $cw;
1684
+ if ($h < $ch) {
1685
+ $w = $w * $h/$ch;
1686
+ $h = $ch;
1687
+ }
1688
+ }
1689
+ else {
1690
+ if (stristr($size['w'] ,'%')) {
1691
+ $size['w'] += 0;
1692
+ $size['w'] /= 100;
1693
+ $size['w'] = ($cw * $size['w']);
1694
+ }
1695
+ if (stristr($size['h'] ,'%')) {
1696
+ $size['h'] += 0;
1697
+ $size['h'] /= 100;
1698
+ $size['h'] = ($ch * $size['h']);
1699
+ }
1700
+ if ($size['w']=='auto' && $size['h']=='auto') {
1701
+ $w = $imw;
1702
+ $h = $imh;
1703
+ }
1704
+ else if ($size['w']=='auto' && $size['h']!='auto') {
1705
+ $w = $imw * $size['h']/$imh;
1706
+ $h = $size['h'];
1707
+ }
1708
+ else if ($size['w']!='auto' && $size['h']=='auto') {
1709
+ $h = $imh * $size['w']/$imw;
1710
+ $w = $size['w'];
1711
+ }
1712
+ else {
1713
+ $w = $size['w'];
1714
+ $h = $size['h'];
1715
+ }
1716
+ }
1717
+ return array($w, $h, $repx, $repy);
1718
+ }
1719
+ else if ($resize==1 && $imw > $cw) {
1720
+ $h = $imh * $cw/$imw;
1721
+ return array($cw, $h, $repx, $repy);
1722
+ }
1723
+ else if ($resize==2 && $imh > $ch) {
1724
+ $w = $imw * $ch/$imh;
1725
+ return array($w, $ch, $repx, $repy);
1726
+ }
1727
+ else if ($resize==3) {
1728
+ $w = $imw;
1729
+ $h = $imh;
1730
+ if ($w > $cw) {
1731
+ $h = $h * $cw/$w;
1732
+ $w = $cw;
1733
+ }
1734
+ if ($h > $ch) {
1735
+ $w = $w * $ch/$h;
1736
+ $h = $ch;
1737
+ }
1738
+ return array($w, $h, $repx, $repy);
1739
+ }
1740
+ else if ($resize==4) {
1741
+ $h = $imh * $cw/$imw;
1742
+ return array($cw, $h, $repx, $repy);
1743
+ }
1744
+ else if ($resize==5) {
1745
+ $w = $imw * $ch/$imh;
1746
+ return array($w, $ch, $repx, $repy);
1747
+ }
1748
+ else if ($resize==6) {
1749
+ return array($cw, $ch, $repx, $repy);
1750
+ }
1751
+ return array($imw, $imh, $repx, $repy);
1752
+ }
1753
+
1754
+
1755
+ function SetBackground(&$properties, &$maxwidth) {
1756
+ // mPDF 5.6.10 5.6.11
1757
+ if (isset($properties['BACKGROUND-ORIGIN']) && ($properties['BACKGROUND-ORIGIN']=='border-box' || $properties['BACKGROUND-ORIGIN']== 'content-box')) { $origin = $properties['BACKGROUND-ORIGIN']; }
1758
+ else { $origin = 'padding-box'; }
1759
+ // mPDF 5.6.10
1760
+ if (isset($properties['BACKGROUND-SIZE'])) {
1761
+ if (stristr($properties['BACKGROUND-SIZE'] ,'contain') ) { $bsw = $bsh = 'contain'; }
1762
+ else if (stristr($properties['BACKGROUND-SIZE'] ,'cover') ) { $bsw = $bsh = 'cover'; }
1763
+ else {
1764
+ $bsw = $bsh = 'auto';
1765
+ $sz = preg_split('/\s+/',trim($properties['BACKGROUND-SIZE']));
1766
+ if (count($sz)==2) { $bsw = $sz[0]; $bsh = $sz[1]; }
1767
+ else { $bsw = $sz[0]; }
1768
+ if (!stristr($bsw ,'%') && !stristr($bsw ,'auto') ) { $bsw = $this->ConvertSize($bsw ,$maxwidth,$this->FontSize); }
1769
+ if (!stristr($bsh ,'%') && !stristr($bsh ,'auto') ) { $bsh = $this->ConvertSize($bsh ,$maxwidth,$this->FontSize); }
1770
+ }
1771
+ $size = array('w'=>$bsw, 'h'=>$bsh);
1772
+ }
1773
+ if (preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/',$properties['BACKGROUND-IMAGE'])) {
1774
+ return array('gradient'=>$properties['BACKGROUND-IMAGE'], 'origin'=>$origin, 'size'=>$size ); // mPDF 5.6.10
1775
+ }
1776
+ else {
1777
+ $file = $properties['BACKGROUND-IMAGE'];
1778
+ $sizesarray = $this->Image($file,0,0,0,0,'','',false, false, false, false, true);
1779
+ if (isset($sizesarray['IMAGE_ID'])) {
1780
+ $image_id = $sizesarray['IMAGE_ID'];
1781
+ $orig_w = $sizesarray['WIDTH']*_MPDFK; // in user units i.e. mm
1782
+ $orig_h = $sizesarray['HEIGHT']*_MPDFK; // (using $this->img_dpi)
1783
+ if (isset($properties['BACKGROUND-IMAGE-RESOLUTION'])) {
1784
+ if (preg_match('/from-image/i', $properties['BACKGROUND-IMAGE-RESOLUTION']) && isset($sizesarray['set-dpi']) && $sizesarray['set-dpi']>0) {
1785
+ $orig_w *= $this->img_dpi / $sizesarray['set-dpi'];
1786
+ $orig_h *= $this->img_dpi / $sizesarray['set-dpi'];
1787
+ }
1788
+ else if (preg_match('/(\d+)dpi/i', $properties['BACKGROUND-IMAGE-RESOLUTION'], $m)) {
1789
+ $dpi = $m[1];
1790
+ if ($dpi > 0) {
1791
+ $orig_w *= $this->img_dpi / $dpi;
1792
+ $orig_h *= $this->img_dpi / $dpi;
1793
+ }
1794
+ }
1795
+ }
1796
+ $x_repeat = true;
1797
+ $y_repeat = true;
1798
+ if (isset($properties['BACKGROUND-REPEAT'])) {
1799
+ if ($properties['BACKGROUND-REPEAT']=='no-repeat' || $properties['BACKGROUND-REPEAT']=='repeat-x') { $y_repeat = false; }
1800
+ if ($properties['BACKGROUND-REPEAT']=='no-repeat' || $properties['BACKGROUND-REPEAT']=='repeat-y') { $x_repeat = false; }
1801
+ }
1802
+ $x_pos = 0;
1803
+ $y_pos = 0;
1804
+ if (isset($properties['BACKGROUND-POSITION'])) {
1805
+ $ppos = preg_split('/\s+/',$properties['BACKGROUND-POSITION']);
1806
+ $x_pos = $ppos[0];
1807
+ $y_pos = $ppos[1];
1808
+ if (!stristr($x_pos ,'%') ) { $x_pos = $this->ConvertSize($x_pos ,$maxwidth,$this->FontSize); }
1809
+ if (!stristr($y_pos ,'%') ) { $y_pos = $this->ConvertSize($y_pos ,$maxwidth,$this->FontSize); }
1810
+ }
1811
+ if (isset($properties['BACKGROUND-IMAGE-RESIZE'])) { $resize = $properties['BACKGROUND-IMAGE-RESIZE']; }
1812
+ else { $resize = 0; }
1813
+ if (isset($properties['BACKGROUND-IMAGE-OPACITY'])) { $opacity = $properties['BACKGROUND-IMAGE-OPACITY']; }
1814
+ else { $opacity = 1; }
1815
+ return array('image_id'=>$image_id, 'orig_w'=>$orig_w, 'orig_h'=>$orig_h, 'x_pos'=>$x_pos, 'y_pos'=>$y_pos, 'x_repeat'=>$x_repeat, 'y_repeat'=>$y_repeat, 'resize'=>$resize, 'opacity'=>$opacity, 'itype'=>$sizesarray['itype'], 'origin'=>$origin, 'size'=>$size );
1816
+ }
1817
+ }
1818
+ return false;
1819
+ }
1820
+
1821
+ function PrintBodyBackgrounds() {
1822
+ $s = '';
1823
+ $clx = 0;
1824
+ $cly = 0;
1825
+ $clw = $this->w;
1826
+ $clh = $this->h;
1827
+ // If using bleed and trim margins in paged media
1828
+ if ($this->pageDim[$this->page]['outer_width_LR'] || $this->pageDim[$this->page]['outer_width_TB']) {
1829
+ $clx = $this->pageDim[$this->page]['outer_width_LR'] - $this->pageDim[$this->page]['bleedMargin'];
1830
+ $cly = $this->pageDim[$this->page]['outer_width_TB'] - $this->pageDim[$this->page]['bleedMargin'];
1831
+ $clw = $this->w - 2*$clx;
1832
+ $clh = $this->h - 2*$cly;
1833
+ }
1834
+
1835
+ if ($this->bodyBackgroundColor) {
1836
+ $s .= 'q ' .$this->SetFColor($this->bodyBackgroundColor, true)."\n";
1837
+ if ($this->bodyBackgroundColor{0}==5) { // RGBa
1838
+ $s .= $this->SetAlpha(ord($this->bodyBackgroundColor{4})/100, 'Normal', true, 'F')."\n";
1839
+ }
1840
+ else if ($this->bodyBackgroundColor{0}==6) { // CMYKa
1841
+ $s .= $this->SetAlpha(ord($this->bodyBackgroundColor{5})/100, 'Normal', true, 'F')."\n";
1842
+ }
1843
+ $s .= sprintf('%.3F %.3F %.3F %.3F re f Q', ($clx*_MPDFK), ($cly*_MPDFK),$clw*_MPDFK,$clh*_MPDFK)."\n";
1844
+ }
1845
+
1846
+ if ($this->bodyBackgroundGradient) {
1847
+ $g = $this->grad->parseBackgroundGradient($this->bodyBackgroundGradient);
1848
+ if ($g) {
1849
+ $s .= $this->grad->Gradient($clx, $cly, $clw, $clh, (isset($g['gradtype']) ? $g['gradtype'] : null), $g['stops'], $g['colorspace'], $g['coords'], $g['extend'], true);
1850
+ }
1851
+ }
1852
+ if ($this->bodyBackgroundImage) {
1853
+ if ( $this->bodyBackgroundImage['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $this->bodyBackgroundImage['gradient'])) {
1854
+ $g = $this->grad->parseMozGradient( $this->bodyBackgroundImage['gradient']);
1855
+ if ($g) {
1856
+ $s .= $this->grad->Gradient($clx, $cly, $clw, $clh, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend'], true);
1857
+ }
1858
+ }
1859
+ else if ($this->bodyBackgroundImage['image_id']) { // Background pattern
1860
+ $n = count($this->patterns)+1;
1861
+ // If using resize, uses TrimBox (not including the bleed)
1862
+ list($orig_w, $orig_h, $x_repeat, $y_repeat) = $this->_resizeBackgroundImage($this->bodyBackgroundImage['orig_w'], $this->bodyBackgroundImage['orig_h'], $clw, $clh, $this->bodyBackgroundImage['resize'], $this->bodyBackgroundImage['x_repeat'], $this->bodyBackgroundImage['y_repeat']);
1863
+
1864
+ $this->patterns[$n] = array('x'=>$clx, 'y'=>$cly, 'w'=>$clw, 'h'=>$clh, 'pgh'=>$this->h, 'image_id'=>$this->bodyBackgroundImage['image_id'], 'orig_w'=>$orig_w, 'orig_h'=>$orig_h, 'x_pos'=>$this->bodyBackgroundImage['x_pos'], 'y_pos'=>$this->bodyBackgroundImage['y_pos'], 'x_repeat'=>$x_repeat, 'y_repeat'=>$y_repeat, 'itype'=>$this->bodyBackgroundImage['itype']);
1865
+ if (($this->bodyBackgroundImage['opacity']>0 || $this->bodyBackgroundImage['opacity']==='0') && $this->bodyBackgroundImage['opacity']<1) { $opac = $this->SetAlpha($this->bodyBackgroundImage['opacity'],'Normal',true); }
1866
+ else { $opac = ''; }
1867
+ $s .= sprintf('q /Pattern cs /P%d scn %s %.3F %.3F %.3F %.3F re f Q', $n, $opac, ($clx*_MPDFK), ($cly*_MPDFK),$clw*_MPDFK, $clh*_MPDFK) ."\n";
1868
+ }
1869
+ }
1870
+ return $s;
1871
+ }
1872
+
1873
+
1874
+ function PrintPageBackgrounds($adjustmenty=0) {
1875
+ $s = '';
1876
+
1877
+ ksort($this->pageBackgrounds);
1878
+ foreach($this->pageBackgrounds AS $bl=>$pbs) {
1879
+ foreach ($pbs AS $pb) {
1880
+ if ((!isset($pb['image_id']) && !isset($pb['gradient'])) || isset($pb['shadowonly'])) { // Background colour or boxshadow
1881
+ // mPDF 5.6.01 - LAYERS
1882
+ if($pb['z-index']>0) {
1883
+ $this->current_layer = $pb['z-index'];
1884
+ $s .= "\n".'/OCBZ-index /ZI'.$pb['z-index'].' BDC'."\n";
1885
+ }
1886
+
1887
+ if($pb['visibility']!='visible') {
1888
+ if($pb['visibility']=='printonly')
1889
+ $s .= '/OC /OC1 BDC'."\n";
1890
+ else if($pb['visibility']=='screenonly')
1891
+ $s .= '/OC /OC2 BDC'."\n";
1892
+ else if($pb['visibility']=='hidden')
1893
+ $s .= '/OC /OC3 BDC'."\n";
1894
+ }
1895
+ // Box shadow
1896
+ if (isset($pb['shadow']) && $pb['shadow']) { $s .= $pb['shadow']."\n"; }
1897
+ if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
1898
+ $s .= 'q '.$this->SetFColor($pb['col'], true)."\n";
1899
+ if ($pb['col']{0}==5) { // RGBa
1900
+ $s .= $this->SetAlpha(ord($pb['col']{4})/100, 'Normal', true, 'F')."\n";
1901
+ }
1902
+ else if ($pb['col']{0}==6) { // CMYKa
1903
+ $s .= $this->SetAlpha(ord($pb['col']{5})/100, 'Normal', true, 'F')."\n";
1904
+ }
1905
+ $s .= sprintf('%.3F %.3F %.3F %.3F re f Q',$pb['x']*_MPDFK,($this->h-$pb['y'])*_MPDFK,$pb['w']*_MPDFK,-$pb['h']*_MPDFK)."\n";
1906
+ if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
1907
+ if($pb['visibility']!='visible')
1908
+ $s .= 'EMC'."\n";
1909
+
1910
+ // mPDF 5.6.01 - LAYERS
1911
+ if($pb['z-index']>0) {
1912
+ $s .= "\n".'EMCBZ-index'."\n";
1913
+ $this->current_layer = 0;
1914
+ }
1915
+ }
1916
+ }
1917
+ foreach ($pbs AS $pb) {
1918
+ // mPDF 5.6.01 - LAYERS
1919
+ if ((isset($pb['gradient']) && $pb['gradient']) || (isset($pb['image_id']) && $pb['image_id'])) {
1920
+ if($pb['z-index']>0) {
1921
+ $this->current_layer = $pb['z-index'];
1922
+ $s .= "\n".'/OCGZ-index /ZI'.$pb['z-index'].' BDC'."\n";
1923
+ }
1924
+ if($pb['visibility']!='visible') {
1925
+ if($pb['visibility']=='printonly')
1926
+ $s .= '/OC /OC1 BDC'."\n";
1927
+ else if($pb['visibility']=='screenonly')
1928
+ $s .= '/OC /OC2 BDC'."\n";
1929
+ else if($pb['visibility']=='hidden')
1930
+ $s .= '/OC /OC3 BDC'."\n";
1931
+ }
1932
+ }
1933
+ if (isset($pb['gradient']) && $pb['gradient']) {
1934
+ if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
1935
+ $s .= $this->grad->Gradient($pb['x'], $pb['y'], $pb['w'], $pb['h'], $pb['gradtype'], $pb['stops'], $pb['colorspace'], $pb['coords'], $pb['extend'], true);
1936
+ if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
1937
+ }
1938
+ else if (isset($pb['image_id']) && $pb['image_id']) { // Background Image
1939
+ $pb['y'] -= $adjustmenty;
1940
+ $pb['h'] += $adjustmenty;
1941
+ $n = count($this->patterns)+1;
1942
+ list($orig_w, $orig_h, $x_repeat, $y_repeat) = $this->_resizeBackgroundImage($pb['orig_w'], $pb['orig_h'], $pb['w'], $pb['h'], $pb['resize'], $pb['x_repeat'], $pb['y_repeat'], $pb['bpa'], $pb['size']); // mPDF 5.6.10
1943
+ $this->patterns[$n] = array('x'=>$pb['x'], 'y'=>$pb['y'], 'w'=>$pb['w'], 'h'=>$pb['h'], 'pgh'=>$this->h, 'image_id'=>$pb['image_id'], 'orig_w'=>$orig_w, 'orig_h'=>$orig_h, 'x_pos'=>$pb['x_pos'], 'y_pos'=>$pb['y_pos'], 'x_repeat'=>$x_repeat, 'y_repeat'=>$y_repeat, 'itype'=>$pb['itype'], 'bpa'=>$pb['bpa']); // mPDF 5.6.10
1944
+ $x = $pb['x']*_MPDFK;
1945
+ $y = ($this->h - $pb['y'])*_MPDFK;
1946
+ $w = $pb['w']*_MPDFK;
1947
+ $h = -$pb['h']*_MPDFK;
1948
+ if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
1949
+ if ($this->writingHTMLfooter || $this->writingHTMLheader) { // Write each (tiles) image rather than use as a pattern
1950
+ $iw = $pb['orig_w']/_MPDFK;
1951
+ $ih = $pb['orig_h']/_MPDFK;
1952
+
1953
+ $w = $pb['w'];
1954
+ $h = $pb['h'];
1955
+ $x0 = $pb['x'];
1956
+ $y0 = $pb['y'];
1957
+
1958
+ // mPDF 5.6.11
1959
+ if (isset($pb['bpa']) && $pb['bpa']) {
1960
+ $w = $pb['bpa']['w'];
1961
+ $h = $pb['bpa']['h'];
1962
+ $x0 = $pb['bpa']['x'];
1963
+ $y0 = $pb['bpa']['y'];
1964
+ }
1965
+
1966
+ // mPDF 5.6.11
1967
+ if (isset($pb['size']['w']) && $pb['size']['w']) {
1968
+ $size = $pb['size'];
1969
+
1970
+ if ($size['w']=='contain') {
1971
+ // Scale the image, while preserving its intrinsic aspect ratio (if any), to the largest size such that both its width and its height can fit inside the background positioning area.
1972
+ // Same as resize==3
1973
+ $ih = $ih * $pb['bpa']['w']/$iw;
1974
+ $iw = $pb['bpa']['w'];
1975
+ if ($ih > $pb['bpa']['h']) {
1976
+ $iw = $iw * $pb['bpa']['h']/$ih;
1977
+ $ih = $pb['bpa']['h'];
1978
+ }
1979
+ }
1980
+ else if ($size['w']=='cover') {
1981
+ // Scale the image, while preserving its intrinsic aspect ratio (if any), to the smallest size such that both its width and its height can completely cover the background positioning area.
1982
+ $ih = $ih * $pb['bpa']['w']/$iw;
1983
+ $iw = $pb['bpa']['w'];
1984
+ if ($ih < $pb['bpa']['h']) {
1985
+ $iw = $iw * $ih/$pb['bpa']['h'];
1986
+ $ih = $pb['bpa']['h'];
1987
+ }
1988
+ }
1989
+ else {
1990
+ if (stristr($size['w'] ,'%')) {
1991
+ $size['w'] += 0;
1992
+ $size['w'] /= 100;
1993
+ $size['w'] = ($pb['bpa']['w'] * $size['w']);
1994
+ }
1995
+ if (stristr($size['h'] ,'%')) {
1996
+ $size['h'] += 0;
1997
+ $size['h'] /= 100;
1998
+ $size['h'] = ($pb['bpa']['h'] * $size['h']);
1999
+ }
2000
+ if ($size['w']=='auto' && $size['h']=='auto') {
2001
+ $iw = $iw;
2002
+ $ih = $ih;
2003
+ }
2004
+ else if ($size['w']=='auto' && $size['h']!='auto') {
2005
+ $iw = $iw * $size['h']/$ih;
2006
+ $ih = $size['h'];
2007
+ }
2008
+ else if ($size['w']!='auto' && $size['h']=='auto') {
2009
+ $ih = $ih * $size['w']/$iw;
2010
+ $iw = $size['w'];
2011
+ }
2012
+ else {
2013
+ $iw = $size['w'];
2014
+ $ih = $size['h'];
2015
+ }
2016
+ }
2017
+ }
2018
+
2019
+ // Number to repeat
2020
+ if ($pb['x_repeat']) { $nx = ceil($pb['w']/$iw)+1; } // mPDF 5.6.11
2021
+ else { $nx = 1; }
2022
+ if ($pb['y_repeat']) { $ny = ceil($pb['h']/$ih)+1; } // mPDF 5.6.11
2023
+ else { $ny = 1; }
2024
+
2025
+ $x_pos = $pb['x_pos'];
2026
+ if (stristr($x_pos ,'%') ) {
2027
+ $x_pos += 0;
2028
+ $x_pos /= 100;
2029
+ $x_pos = ($pb['bpa']['w'] * $x_pos) - ($iw * $x_pos); // mPDF 5.6.11
2030
+ }
2031
+ $y_pos = $pb['y_pos'];
2032
+ if (stristr($y_pos ,'%') ) {
2033
+ $y_pos += 0;
2034
+ $y_pos /= 100;
2035
+ $y_pos = ($pb['bpa']['h'] * $y_pos) - ($ih * $y_pos); // mPDF 5.6.11
2036
+ }
2037
+ if ($nx>1) {
2038
+ while($x_pos>($pb['x']-$pb['bpa']['x'])) { $x_pos -= $iw; } // mPDF 5.6.11
2039
+ }
2040
+ if ($ny>1) {
2041
+ while($y_pos>($pb['y']-$pb['bpa']['y'])) { $y_pos -= $ih; } // mPDF 5.6.11
2042
+ }
2043
+ for($xi=0;$xi<$nx;$xi++) {
2044
+ for($yi=0;$yi<$ny;$yi++) {
2045
+ $x = $x0 + $x_pos + ($iw*$xi);
2046
+ $y = $y0 + $y_pos + ($ih*$yi);
2047
+ if ($pb['opacity']>0 && $pb['opacity']<1) { $opac = $this->SetAlpha($pb['opacity'],'Normal',true); }
2048
+ else { $opac = ''; }
2049
+ $s .= sprintf("q %s %.3F 0 0 %.3F %.3F %.3F cm /I%d Do Q", $opac,$iw*_MPDFK,$ih*_MPDFK,$x*_MPDFK,($this->h-($y+$ih))*_MPDFK,$pb['image_id']) ."\n";
2050
+ }
2051
+ }
2052
+ }
2053
+ else {
2054
+ if (($pb['opacity']>0 || $pb['opacity']==='0') && $pb['opacity']<1) { $opac = $this->SetAlpha($pb['opacity'],'Normal',true); }
2055
+ else { $opac = ''; }
2056
+ $s .= sprintf('q /Pattern cs /P%d scn %s %.3F %.3F %.3F %.3F re f Q', $n, $opac, $x, $y, $w, $h) ."\n";
2057
+ }
2058
+ if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
2059
+ }
2060
+ if ((isset($pb['gradient']) && $pb['gradient']) || (isset($pb['image_id']) && $pb['image_id'])) {
2061
+ if($pb['visibility']!='visible')
2062
+ $s .= 'EMC'."\n";
2063
+
2064
+ // mPDF 5.6.01 - LAYERS
2065
+ if($pb['z-index']>0) {
2066
+ $s .= "\n".'EMCGZ-index'."\n";
2067
+ $this->current_layer = 0;
2068
+ }
2069
+ }
2070
+
2071
+ }
2072
+ }
2073
+ return $s;
2074
+ }
2075
+
2076
+ function PrintTableBackgrounds($adjustmenty=0) {
2077
+ $s = '';
2078
+ ksort($this->tableBackgrounds);
2079
+ foreach($this->tableBackgrounds AS $bl=>$pbs) {
2080
+ foreach ($pbs AS $pb) {
2081
+ if ((!isset($pb['gradient']) || !$pb['gradient']) && (!isset($pb['image_id']) || !$pb['image_id'])) {
2082
+ $s .= 'q '.$this->SetFColor($pb['col'], true)."\n";
2083
+ if ($pb['col']{0}==5) { // RGBa
2084
+ $s .= $this->SetAlpha(ord($pb['col']{4})/100, 'Normal', true, 'F')."\n";
2085
+ }
2086
+ else if ($pb['col']{0}==6) { // CMYKa
2087
+ $s .= $this->SetAlpha(ord($pb['col']{5})/100, 'Normal', true, 'F')."\n";
2088
+ }
2089
+ $s .= sprintf('%.3F %.3F %.3F %.3F re %s Q',$pb['x']*_MPDFK,($this->h-$pb['y'])*_MPDFK,$pb['w']*_MPDFK,-$pb['h']*_MPDFK,'f')."\n";
2090
+ }
2091
+ if (isset($pb['gradient']) && $pb['gradient']) {
2092
+ if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
2093
+ $s .= $this->grad->Gradient($pb['x'], $pb['y'], $pb['w'], $pb['h'], $pb['gradtype'], $pb['stops'], $pb['colorspace'], $pb['coords'], $pb['extend'], true);
2094
+ if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
2095
+ }
2096
+ if (isset($pb['image_id']) && $pb['image_id']) { // Background pattern
2097
+ $pb['y'] -= $adjustmenty;
2098
+ $pb['h'] += $adjustmenty;
2099
+ $n = count($this->patterns)+1;
2100
+ list($orig_w, $orig_h, $x_repeat, $y_repeat) = $this->_resizeBackgroundImage($pb['orig_w'], $pb['orig_h'], $pb['w'], $pb['h'], $pb['resize'], $pb['x_repeat'], $pb['y_repeat']);
2101
+ $this->patterns[$n] = array('x'=>$pb['x'], 'y'=>$pb['y'], 'w'=>$pb['w'], 'h'=>$pb['h'], 'pgh'=>$this->h, 'image_id'=>$pb['image_id'], 'orig_w'=>$orig_w, 'orig_h'=>$orig_h, 'x_pos'=>$pb['x_pos'], 'y_pos'=>$pb['y_pos'], 'x_repeat'=>$x_repeat, 'y_repeat'=>$y_repeat, 'itype'=>$pb['itype']);
2102
+ $x = $pb['x']*_MPDFK;
2103
+ $y = ($this->h - $pb['y'])*_MPDFK;
2104
+ $w = $pb['w']*_MPDFK;
2105
+ $h = -$pb['h']*_MPDFK;
2106
+ if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
2107
+ if ($pb['opacity']>0 && $pb['opacity']<1) { $opac = $this->SetAlpha($pb['opacity'],'Normal',true); }
2108
+ else { $opac = ''; }
2109
+ $s .= sprintf('q /Pattern cs /P%d scn %s %.3F %.3F %.3F %.3F re f Q', $n, $opac, $x, $y, $w, $h) ."\n";
2110
+ if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
2111
+ }
2112
+ }
2113
+ }
2114
+ return $s;
2115
+ }
2116
+
2117
+ // mPDF 5.6.01 - LAYERS
2118
+ function BeginLayer($id) {
2119
+ if($this->current_layer>0) $this->EndLayer();
2120
+ if ($id < 1) { return false; }
2121
+ if (!isset($this->layers[$id])) {
2122
+ $this->layers[$id] = array('name'=>'Layer '.($id) );
2123
+ if (($this->PDFA || $this->PDFX)) { $this->PDFAXwarnings[] = "Cannot use layers when using PDFA or PDFX"; return ''; }
2124
+ else if (!$this->PDFA && !$this->PDFX) { $this->pdf_version='1.5'; }
2125
+ }
2126
+ $this->current_layer = $id;
2127
+ $this->_out('/OCZ-index /ZI'.$id.' BDC');
2128
+
2129
+ $this->pageoutput[$this->page] = array();
2130
+ }
2131
+
2132
+ function EndLayer() {
2133
+ if($this->current_layer>0) {
2134
+ $this->_out('EMCZ-index');
2135
+ $this->current_layer = 0;
2136
+ }
2137
+ }
2138
+
2139
+
2140
+
2141
+ // Depracated - can use AddPage for all
2142
+ function AddPages($orientation='',$condition='', $resetpagenum='', $pagenumstyle='', $suppress='',$mgl='',$mgr='',$mgt='',$mgb='',$mgh='',$mgf='',$ohname='',$ehname='',$ofname='',$efname='',$ohvalue=0,$ehvalue=0,$ofvalue=0,$efvalue=0,$pagesel='',$newformat='')
2143
+ {
2144
+ $this->AddPage($orientation,$condition,$resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf, $ohname, $ehname, $ofname, $efname, $ohvalue, $ehvalue, $ofvalue, $efvalue,$pagesel,$newformat);
2145
+ }
2146
+
2147
+
2148
+ function AddPageByArray($a) {
2149
+ if (!is_array($a)) { $a = array(); }
2150
+ $orientation = (isset($a['orientation']) ? $a['orientation'] : '');
2151
+ $condition = (isset($a['condition']) ? $a['condition'] : (isset($a['type']) ? $a['type'] : ''));
2152
+ $resetpagenum = (isset($a['resetpagenum']) ? $a['resetpagenum'] : '');
2153
+ $pagenumstyle = (isset($a['pagenumstyle']) ? $a['pagenumstyle'] : '');
2154
+ $suppress = (isset($a['suppress']) ? $a['suppress'] : '');
2155
+ $mgl = (isset($a['mgl']) ? $a['mgl'] : (isset($a['margin-left']) ? $a['margin-left'] : ''));
2156
+ $mgr = (isset($a['mgr']) ? $a['mgr'] : (isset($a['margin-right']) ? $a['margin-right'] : ''));
2157
+ $mgt = (isset($a['mgt']) ? $a['mgt'] : (isset($a['margin-top']) ? $a['margin-top'] : ''));
2158
+ $mgb = (isset($a['mgb']) ? $a['mgb'] : (isset($a['margin-bottom']) ? $a['margin-bottom'] : ''));
2159
+ $mgh = (isset($a['mgh']) ? $a['mgh'] : (isset($a['margin-header']) ? $a['margin-header'] : ''));
2160
+ $mgf = (isset($a['mgf']) ? $a['mgf'] : (isset($a['margin-footer']) ? $a['margin-footer'] : ''));
2161
+ $ohname = (isset($a['ohname']) ? $a['ohname'] : (isset($a['odd-header-name']) ? $a['odd-header-name'] : ''));
2162
+ $ehname = (isset($a['ehname']) ? $a['ehname'] : (isset($a['even-header-name']) ? $a['even-header-name'] : ''));
2163
+ $ofname = (isset($a['ofname']) ? $a['ofname'] : (isset($a['odd-footer-name']) ? $a['odd-footer-name'] : ''));
2164
+ $efname = (isset($a['efname']) ? $a['efname'] : (isset($a['even-footer-name']) ? $a['even-footer-name'] : ''));
2165
+ $ohvalue = (isset($a['ohvalue']) ? $a['ohvalue'] : (isset($a['odd-header-value']) ? $a['odd-header-value'] : 0));
2166
+ $ehvalue = (isset($a['ehvalue']) ? $a['ehvalue'] : (isset($a['even-header-value']) ? $a['even-header-value'] : 0));
2167
+ $ofvalue = (isset($a['ofvalue']) ? $a['ofvalue'] : (isset($a['odd-footer-value']) ? $a['odd-footer-value'] : 0));
2168
+ $efvalue = (isset($a['efvalue']) ? $a['efvalue'] : (isset($a['even-footer-value']) ? $a['even-footer-value'] : 0));
2169
+ $pagesel = (isset($a['pagesel']) ? $a['pagesel'] : (isset($a['pageselector']) ? $a['pageselector'] : ''));
2170
+ $newformat = (isset($a['newformat']) ? $a['newformat'] : (isset($a['sheet-size']) ? $a['sheet-size'] : ''));
2171
+
2172
+ $this->AddPage($orientation,$condition,$resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf, $ohname, $ehname, $ofname, $efname, $ohvalue, $ehvalue, $ofvalue, $efvalue,$pagesel,$newformat);
2173
+
2174
+ }
2175
+
2176
+
2177
+ function AddPage($orientation='',$condition='', $resetpagenum='', $pagenumstyle='', $suppress='',$mgl='',$mgr='',$mgt='',$mgb='',$mgh='',$mgf='',$ohname='',$ehname='',$ofname='',$efname='',$ohvalue=0,$ehvalue=0,$ofvalue=0,$efvalue=0,$pagesel='',$newformat='')
2178
+ {
2179
+ // Float DIV
2180
+ // Cannot do with columns on, or if any change in page orientation/margins etc.
2181
+ // If next page already exists - i.e background /headers and footers already written
2182
+ if ($this->state > 0 && $this->page < count($this->pages)) {
2183
+ $bak_cml = $this->cMarginL;
2184
+ $bak_cmr = $this->cMarginR;
2185
+ $bak_dw = $this->divwidth;
2186
+ // Paint Div Border if necessary
2187
+ if ($this->blklvl > 0) {
2188
+ $save_tr = $this->table_rotate; // *TABLES*
2189
+ $this->table_rotate = 0; // *TABLES*
2190
+ if ($this->y == $this->blk[$this->blklvl]['y0']) { $this->blk[$this->blklvl]['startpage']++; }
2191
+ if (($this->y > $this->blk[$this->blklvl]['y0']) || $this->flowingBlockAttr['is_table'] ) { $toplvl = $this->blklvl; }
2192
+ else { $toplvl = $this->blklvl-1; }
2193
+ $sy = $this->y;
2194
+ for ($bl=1;$bl<=$toplvl;$bl++) {
2195
+ $this->PaintDivBB('pagebottom',0,$bl);
2196
+ }
2197
+ $this->y = $sy;
2198
+ $this->table_rotate = $save_tr; // *TABLES*
2199
+ }
2200
+ $s = $this->PrintPageBackgrounds();
2201
+
2202
+ // Writes after the marker so not overwritten later by page background etc.
2203
+ $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
2204
+ $this->pageBackgrounds = array();
2205
+ $family=$this->FontFamily;
2206
+ $style=$this->FontStyle.($this->U ? 'U' : '').($this->S ? 'S' : '');
2207
+ $size=$this->FontSizePt;
2208
+ $lw=$this->LineWidth;
2209
+ $dc=$this->DrawColor;
2210
+ $fc=$this->FillColor;
2211
+ $tc=$this->TextColor;
2212
+ $cf=$this->ColorFlag;
2213
+
2214
+ $this->printfloatbuffer();
2215
+
2216
+ //Move to next page
2217
+ $this->page++;
2218
+ $this->ResetMargins();
2219
+ $this->SetAutoPageBreak($this->autoPageBreak,$this->bMargin);
2220
+ $this->x=$this->lMargin;
2221
+ $this->y=$this->tMargin;
2222
+ $this->FontFamily='';
2223
+ $this->_out('2 J');
2224
+ $this->LineWidth=$lw;
2225
+ $this->_out(sprintf('%.3F w',$lw*_MPDFK));
2226
+ if($family) $this->SetFont($family,$style,$size,true,true);
2227
+ $this->DrawColor=$dc;
2228
+ if($dc!=$this->defDrawColor) $this->_out($dc);
2229
+ $this->FillColor=$fc;
2230
+ if($fc!=$this->defFillColor) $this->_out($fc);
2231
+ $this->TextColor=$tc;
2232
+ $this->ColorFlag=$cf;
2233
+ for($bl=1;$bl<=$this->blklvl;$bl++) {
2234
+ $this->blk[$bl]['y0'] = $this->y;
2235
+ // Don't correct more than once for background DIV containing a Float
2236
+ if (!isset($this->blk[$bl]['marginCorrected'][$this->page])) { $this->blk[$bl]['x0'] += $this->MarginCorrection; }
2237
+ $this->blk[$bl]['marginCorrected'][$this->page] = true;
2238
+ }
2239
+ $this->cMarginL = $bak_cml;
2240
+ $this->cMarginR = $bak_cmr;
2241
+ $this->divwidth = $bak_dw;
2242
+ return '';
2243
+ }
2244
+
2245
+ //Start a new page
2246
+ if($this->state==0) $this->Open();
2247
+
2248
+ $bak_cml = $this->cMarginL;
2249
+ $bak_cmr = $this->cMarginR;
2250
+ $bak_dw = $this->divwidth;
2251
+
2252
+
2253
+ $bak_lh = $this->lineheight;
2254
+
2255
+ $orientation = substr(strtoupper($orientation),0,1);
2256
+ $condition = strtoupper($condition);
2257
+
2258
+
2259
+ if ($condition == 'NEXT-EVEN') { // always adds at least one new page to create an Even page
2260
+ if (!$this->mirrorMargins) { $condition = ''; }
2261
+ else {
2262
+ if ($pagesel) { $pbch = $pagesel; $pagesel = ''; } // *CSS-PAGE*
2263
+ else { $pbch = false; } // *CSS-PAGE*
2264
+ $this->AddPage($this->CurOrientation,'O');
2265
+ if ($pbch ) { $pagesel = $pbch; } // *CSS-PAGE*
2266
+ $condition = '';
2267
+ }
2268
+ }
2269
+ if ($condition == 'NEXT-ODD') { // always adds at least one new page to create an Odd page
2270
+ if (!$this->mirrorMargins) { $condition = ''; }
2271
+ else {
2272
+ if ($pagesel) { $pbch = $pagesel; $pagesel = ''; } // *CSS-PAGE*
2273
+ else { $pbch = false; } // *CSS-PAGE*
2274
+ $this->AddPage($this->CurOrientation,'E');
2275
+ if ($pbch ) { $pagesel = $pbch; } // *CSS-PAGE*
2276
+ $condition = '';
2277
+ }
2278
+ }
2279
+
2280
+
2281
+ if ($condition == 'E') { // only adds new page if needed to create an Even page
2282
+ if (!$this->mirrorMargins || ($this->page)%2==0) { return false; }
2283
+ }
2284
+ if ($condition == 'O') { // only adds new page if needed to create an Odd page
2285
+ if (!$this->mirrorMargins || ($this->page)%2==1) { return false; }
2286
+ }
2287
+
2288
+ if ($resetpagenum || $pagenumstyle || $suppress) {
2289
+ $this->PageNumSubstitutions[] = array('from'=>($this->page+1), 'reset'=> $resetpagenum, 'type'=>$pagenumstyle, 'suppress'=>$suppress);
2290
+ }
2291
+
2292
+
2293
+ $save_tr = $this->table_rotate; // *TABLES*
2294
+ $this->table_rotate = 0; // *TABLES*
2295
+ $save_kwt = $this->kwt;
2296
+ $this->kwt = 0;
2297
+ // mPDF 5.6.01 - LAYERS
2298
+ $save_layer = $this->current_layer;
2299
+ $save_vis = $this->visibility;
2300
+
2301
+ if($this->visibility!='visible')
2302
+ $this->SetVisibility('visible');
2303
+ // mPDF 5.6.01 - LAYERS
2304
+ $this->EndLayer();
2305
+
2306
+ // Paint Div Border if necessary
2307
+ //PAINTS BACKGROUND COLOUR OR BORDERS for DIV - DISABLED FOR COLUMNS (cf. AcceptPageBreak) AT PRESENT in ->PaintDivBB
2308
+ if (!$this->ColActive && $this->blklvl > 0) {
2309
+ if (isset($this->blk[$this->blklvl]['y0']) && $this->y == $this->blk[$this->blklvl]['y0']) {
2310
+ if (isset($this->blk[$this->blklvl]['startpage'])) { $this->blk[$this->blklvl]['startpage']++; }
2311
+ else { $this->blk[$this->blklvl]['startpage'] = 1; }
2312
+ }
2313
+ if ((isset($this->blk[$this->blklvl]['y0']) && $this->y > $this->blk[$this->blklvl]['y0']) || $this->flowingBlockAttr['is_table'] ) { $toplvl = $this->blklvl; }
2314
+ else { $toplvl = $this->blklvl-1; }
2315
+ $sy = $this->y;
2316
+ for ($bl=1;$bl<=$toplvl;$bl++) {
2317
+
2318
+ // mPDF 5.6.01 - LAYERS
2319
+ if ($this->blk[$bl]['z-index']>0) {
2320
+ $this->BeginLayer($this->blk[$bl]['z-index']);
2321
+ }
2322
+ if (isset($this->blk[$bl]['visibility']) && $this->blk[$bl]['visibility'] && $this->blk[$bl]['visibility']!='visible') {
2323
+ $this->SetVisibility($this->blk[$bl]['visibility']);
2324
+ }
2325
+
2326
+ $this->PaintDivBB('pagebottom',0,$bl);
2327
+ }
2328
+ $this->y = $sy;
2329
+ // RESET block y0 and x0 - see below
2330
+ }
2331
+
2332
+ if($this->visibility!='visible')
2333
+ $this->SetVisibility('visible');
2334
+ // mPDF 5.6.01 - LAYERS
2335
+ $this->EndLayer();
2336
+
2337
+ // BODY Backgrounds
2338
+ if ($this->page > 0) {
2339
+ $s = '';
2340
+ $s .= $this->PrintBodyBackgrounds();
2341
+
2342
+ $s .= $this->PrintPageBackgrounds();
2343
+ $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', "\n".$s."\n".'\\1', $this->pages[$this->page]);
2344
+ $this->pageBackgrounds = array();
2345
+ }
2346
+
2347
+ $save_kt = $this->keep_block_together;
2348
+ $this->keep_block_together = 0;
2349
+
2350
+ $save_cols = false;
2351
+
2352
+
2353
+ $family=$this->FontFamily;
2354
+ $style=$this->FontStyle.($this->U ? 'U' : '').($this->S ? 'S' : '');
2355
+ $size=$this->FontSizePt;
2356
+ $this->ColumnAdjust = true; // enables column height adjustment for the page
2357
+ $lw=$this->LineWidth;
2358
+ $dc=$this->DrawColor;
2359
+ $fc=$this->FillColor;
2360
+ $tc=$this->TextColor;
2361
+ $cf=$this->ColorFlag;
2362
+ if($this->page>0)
2363
+ {
2364
+ //Page footer
2365
+ $this->InFooter=true;
2366
+
2367
+ $this->Reset();
2368
+ $this->pageoutput[$this->page] = array();
2369
+
2370
+ $this->Footer();
2371
+ //Close page
2372
+ $this->_endpage();
2373
+ }
2374
+
2375
+
2376
+ //Start new page
2377
+ $this->_beginpage($orientation,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$ohname,$ehname,$ofname,$efname,$ohvalue,$ehvalue,$ofvalue,$efvalue,$pagesel,$newformat);
2378
+ if ($this->docTemplate) {
2379
+ $pagecount = $this->SetSourceFile($this->docTemplate);
2380
+ if (($this->page - $this->docTemplateStart) > $pagecount) {
2381
+ if ($this->docTemplateContinue) {
2382
+ $tplIdx = $this->ImportPage($pagecount);
2383
+ $this->UseTemplate($tplIdx);
2384
+ }
2385
+ }
2386
+ else {
2387
+ $tplIdx = $this->ImportPage(($this->page - $this->docTemplateStart));
2388
+ $this->UseTemplate($tplIdx);
2389
+ }
2390
+ }
2391
+ if ($this->pageTemplate) {
2392
+ $this->UseTemplate($this->pageTemplate);
2393
+ }
2394
+
2395
+ // Tiling Patterns
2396
+ $this->_out('___PAGE___START'.date('jY'));
2397
+ $this->_out('___BACKGROUND___PATTERNS'.date('jY'));
2398
+ $this->_out('___HEADER___MARKER'.date('jY'));
2399
+ $this->pageBackgrounds = array();
2400
+
2401
+ //Set line cap style to square
2402
+ $this->SetLineCap(2);
2403
+ //Set line width
2404
+ $this->LineWidth=$lw;
2405
+ $this->_out(sprintf('%.3F w',$lw*_MPDFK));
2406
+ //Set font
2407
+ if($family) $this->SetFont($family,$style,$size,true,true); // forces write
2408
+ //Set colors
2409
+ $this->DrawColor=$dc;
2410
+ if($dc!=$this->defDrawColor) $this->_out($dc);
2411
+ $this->FillColor=$fc;
2412
+ if($fc!=$this->defFillColor) $this->_out($fc);
2413
+ $this->TextColor=$tc;
2414
+ $this->ColorFlag=$cf;
2415
+
2416
+ //Page header
2417
+ $this->Header();
2418
+
2419
+ //Restore line width
2420
+ if($this->LineWidth!=$lw)
2421
+ {
2422
+ $this->LineWidth=$lw;
2423
+ $this->_out(sprintf('%.3F w',$lw*_MPDFK));
2424
+ }
2425
+ //Restore font
2426
+ if($family) $this->SetFont($family,$style,$size,true,true); // forces write
2427
+ //Restore colors
2428
+ if($this->DrawColor!=$dc)
2429
+ {
2430
+ $this->DrawColor=$dc;
2431
+ $this->_out($dc);
2432
+ }
2433
+ if($this->FillColor!=$fc)
2434
+ {
2435
+ $this->FillColor=$fc;
2436
+ $this->_out($fc);
2437
+ }
2438
+ $this->TextColor=$tc;
2439
+ $this->ColorFlag=$cf;
2440
+ $this->InFooter=false;
2441
+
2442
+ // mPDF 5.6.01 - LAYERS
2443
+ if ($save_layer>0)
2444
+ $this->BeginLayer($save_layer);
2445
+
2446
+ if($save_vis!='visible')
2447
+ $this->SetVisibility($save_vis);
2448
+
2449
+
2450
+
2451
+ //RESET BLOCK BORDER TOP
2452
+ if (!$this->ColActive) {
2453
+ for($bl=1;$bl<=$this->blklvl;$bl++) {
2454
+ $this->blk[$bl]['y0'] = $this->y;
2455
+ if (isset($this->blk[$bl]['x0'])) { $this->blk[$bl]['x0'] += $this->MarginCorrection; }
2456
+ else { $this->blk[$bl]['x0'] = $this->MarginCorrection; }
2457
+ // Added mPDF 3.0 Float DIV
2458
+ $this->blk[$bl]['marginCorrected'][$this->page] = true;
2459
+ }
2460
+ }
2461
+
2462
+
2463
+ $this->table_rotate = $save_tr; // *TABLES*
2464
+ $this->kwt = $save_kwt;
2465
+
2466
+ $this->keep_block_together = $save_kt ;
2467
+
2468
+ $this->cMarginL = $bak_cml;
2469
+ $this->cMarginR = $bak_cmr;
2470
+ $this->divwidth = $bak_dw;
2471
+
2472
+ $this->lineheight = $bak_lh;
2473
+ }
2474
+
2475
+
2476
+ function PageNo() {
2477
+ //Get current page number
2478
+ return $this->page;
2479
+ }
2480
+
2481
+ function AddSpotColorsFromFile($file) {
2482
+ $colors = @file($file) or die("Cannot load spot colors file - ".$file);
2483
+ foreach($colors AS $sc) {
2484
+ list($name, $c, $m, $y, $k) = preg_split("/\t/",$sc);
2485
+ $c = intval($c);
2486
+ $m = intval($m);
2487
+ $y = intval($y);
2488
+ $k = intval($k);
2489
+ $this->AddSpotColor($name, $c, $m, $y, $k);
2490
+ }
2491
+ }
2492
+
2493
+ function AddSpotColor($name, $c, $m, $y, $k) {
2494
+ $name = strtoupper(trim($name));
2495
+ if(!isset($this->spotColors[$name])) {
2496
+ $i=count($this->spotColors)+1;
2497
+ $this->spotColors[$name]=array('i'=>$i,'c'=>$c,'m'=>$m,'y'=>$y,'k'=>$k);
2498
+ $this->spotColorIDs[$i]=$name;
2499
+ }
2500
+ }
2501
+
2502
+ function SetColor($col, $type='') {
2503
+ $out = '';
2504
+ if ($col{0}==3 || $col{0}==5) { // RGB / RGBa
2505
+ $out = sprintf('%.3F %.3F %.3F rg',ord($col{1})/255,ord($col{2})/255,ord($col{3})/255);
2506
+ }
2507
+ else if ($col{0}==1) { // GRAYSCALE
2508
+ $out = sprintf('%.3F g',ord($col{1})/255);
2509
+ }
2510
+ else if ($col{0}==2) { // SPOT COLOR
2511
+ $out = sprintf('/CS%d cs %.3F scn',ord($col{1}),ord($col{2})/100);
2512
+ }
2513
+ else if ($col{0}==4 || $col{0}==6) { // CMYK / CMYKa
2514
+ $out = sprintf('%.3F %.3F %.3F %.3F k', ord($col{1})/100, ord($col{2})/100, ord($col{3})/100, ord($col{4})/100);
2515
+ }
2516
+ if ($type=='Draw') { $out = strtoupper($out); } // e.g. rg => RG
2517
+ else if ($type=='CodeOnly') { $out = preg_replace('/\s(rg|g|k)/','',$out); }
2518
+ return $out;
2519
+ }
2520
+
2521
+
2522
+ function SetDColor($col, $return=false) {
2523
+ $out = $this->SetColor($col, 'Draw');
2524
+ if ($return) { return $out; }
2525
+ if ($out=='') { return ''; }
2526
+ $this->DrawColor = $out;
2527
+ if($this->page>0 && ((isset($this->pageoutput[$this->page]['DrawColor']) && $this->pageoutput[$this->page]['DrawColor'] != $this->DrawColor) || !isset($this->pageoutput[$this->page]['DrawColor']) || $this->keep_block_together)) { $this->_out($this->DrawColor); }
2528
+ $this->pageoutput[$this->page]['DrawColor'] = $this->DrawColor;
2529
+ }
2530
+
2531
+ function SetFColor($col, $return=false) {
2532
+ $out = $this->SetColor($col, 'Fill');
2533
+ if ($return) { return $out; }
2534
+ if ($out=='') { return ''; }
2535
+ $this->FillColor = $out;
2536
+ $this->ColorFlag = ($out != $this->TextColor);
2537
+ if($this->page>0 && ((isset($this->pageoutput[$this->page]['FillColor']) && $this->pageoutput[$this->page]['FillColor'] != $this->FillColor) || !isset($this->pageoutput[$this->page]['FillColor']) || $this->keep_block_together)) { $this->_out($this->FillColor); }
2538
+ $this->pageoutput[$this->page]['FillColor'] = $this->FillColor;
2539
+ }
2540
+
2541
+ function SetTColor($col, $return=false) {
2542
+ $out = $this->SetColor($col, 'Text');
2543
+ if ($return) { return $out; }
2544
+ if ($out=='') { return ''; }
2545
+ $this->TextColor = $out;
2546
+ $this->ColorFlag = ($this->FillColor != $out);
2547
+ }
2548
+
2549
+
2550
+ function SetDrawColor($r,$g=-1,$b=-1,$col4=-1, $return=false) {
2551
+ //Set color for all stroking operations
2552
+ $col = array();
2553
+ if(($r==0 and $g==0 and $b==0 && $col4 == -1) or $g==-1) { $col = $this->ConvertColor($r); }
2554
+ else if ($col4 == -1) { $col = $this->ConvertColor('rgb('.$r.','.$g.','.$b.')'); }
2555
+ else { $col = $this->ConvertColor('cmyk('.$r.','.$g.','.$b.','.$col4.')'); }
2556
+ $out = $this->SetDColor($col, $return);
2557
+ return $out;
2558
+ }
2559
+
2560
+ function SetFillColor($r,$g=-1,$b=-1,$col4=-1, $return=false) {
2561
+ //Set color for all filling operations
2562
+ $col = array();
2563
+ if(($r==0 and $g==0 and $b==0 && $col4 == -1) or $g==-1) { $col = $this->ConvertColor($r); }
2564
+ else if ($col4 == -1) { $col = $this->ConvertColor('rgb('.$r.','.$g.','.$b.')'); }
2565
+ else { $col = $this->ConvertColor('cmyk('.$r.','.$g.','.$b.','.$col4.')'); }
2566
+ $out = $this->SetFColor($col, $return);
2567
+ return $out;
2568
+ }
2569
+
2570
+ function SetTextColor($r,$g=-1,$b=-1,$col4=-1, $return=false) {
2571
+ //Set color for text
2572
+ $col = array();
2573
+ if(($r==0 and $g==0 and $b==0 && $col4 == -1) or $g==-1) { $col = $this->ConvertColor($r); }
2574
+ else if ($col4 == -1) { $col = $this->ConvertColor('rgb('.$r.','.$g.','.$b.')'); }
2575
+ else { $col = $this->ConvertColor('cmyk('.$r.','.$g.','.$b.','.$col4.')'); }
2576
+ $out = $this->SetTColor($col, $return);
2577
+ return $out;
2578
+ }
2579
+
2580
+ function _getCharWidth(&$cw, $u, $isdef=true) {
2581
+ if ($u==0) { $w = false; }
2582
+ else { $w = (ord($cw[$u*2]) << 8) + ord($cw[$u*2+1]); }
2583
+ if ($w == 65535) { return 0; }
2584
+ else if ($w) { return $w; }
2585
+ else if ($isdef) { return false; }
2586
+ else { return 0; }
2587
+ }
2588
+
2589
+ function _charDefined(&$cw, $u) {
2590
+ if ($u==0) { return false; }
2591
+ $w = (ord($cw[$u*2]) << 8) + ord($cw[$u*2+1]);
2592
+ if ($w) { return true; }
2593
+ else { return false; }
2594
+ }
2595
+
2596
+ function GetCharWidthCore($c) {
2597
+ //Get width of a single character in the current Core font
2598
+ $c = (string)$c;
2599
+ $w = 0;
2600
+ // Soft Hyphens chr(173)
2601
+ if ($c == chr(173) && $this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
2602
+ return 0;
2603
+ }
2604
+ else if ($this->S && isset($this->upperCase[ord($c)])) {
2605
+ $charw = $this->CurrentFont['cw'][chr($this->upperCase[ord($c)])];
2606
+ if ($charw!==false) {
2607
+ $charw = $charw*$this->smCapsScale * $this->smCapsStretch/100;
2608
+ $w+=$charw;
2609
+ }
2610
+ }
2611
+ else if (isset($this->CurrentFont['cw'][$c])) {
2612
+ $w += $this->CurrentFont['cw'][$c];
2613
+ }
2614
+ else if (isset($this->CurrentFont['cw'][ord($c)])) {
2615
+ $w += $this->CurrentFont['cw'][ord($c)];
2616
+ }
2617
+ $w *= ($this->FontSize/ 1000);
2618
+ if ($this->minwSpacing || $this->fixedlSpacing) {
2619
+ if ($c==' ') $nb_spaces = 1;
2620
+ else $nb_spaces = 0;
2621
+ $w += $this->fixedlSpacing + ($nb_spaces * $this->minwSpacing);
2622
+ }
2623
+ return ($w);
2624
+ }
2625
+
2626
+ function GetCharWidthNonCore($c, $addSubset=true) {
2627
+ //Get width of a single character in the current Non-Core font
2628
+ $c = (string)$c;
2629
+ $w = 0;
2630
+ $unicode = $this->UTF8StringToArray($c, $addSubset);
2631
+ $char = $unicode[0];
2632
+ if ($char == 173) { return 0; } // Soft Hyphens
2633
+ else if ($this->S && isset($this->upperCase[$char])) {
2634
+ $charw = $this->_getCharWidth($this->CurrentFont['cw'],$this->upperCase[$char]);
2635
+ if ($charw!==false) {
2636
+ $charw = $charw*$this->smCapsScale * $this->smCapsStretch/100;
2637
+ $w+=$charw;
2638
+ }
2639
+ elseif(isset($this->CurrentFont['desc']['MissingWidth'])) { $w += $this->CurrentFont['desc']['MissingWidth']; }
2640
+ elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
2641
+ else { $w += 500; }
2642
+ }
2643
+ else {
2644
+ $charw = $this->_getCharWidth($this->CurrentFont['cw'],$char);
2645
+ if ($charw!==false) { $w+=$charw; }
2646
+ elseif(isset($this->CurrentFont['desc']['MissingWidth'])) { $w += $this->CurrentFont['desc']['MissingWidth']; }
2647
+ elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
2648
+ else { $w += 500; }
2649
+ }
2650
+ $w *= ($this->FontSize/ 1000);
2651
+ if ($this->minwSpacing || $this->fixedlSpacing) {
2652
+ if ($c==' ') $nb_spaces = 1;
2653
+ else $nb_spaces = 0;
2654
+ $w += $this->fixedlSpacing + ($nb_spaces * $this->minwSpacing);
2655
+ }
2656
+ return ($w);
2657
+ }
2658
+
2659
+
2660
+ function GetCharWidth($c, $addSubset=true) {
2661
+ if (!$this->usingCoreFont) {
2662
+ return $this->GetCharWidthNonCore($c, $addSubset);
2663
+ }
2664
+ else {
2665
+ return $this->GetCharWidthCore($c);
2666
+ }
2667
+ }
2668
+
2669
+ function GetStringWidth($s, $addSubset=true) {
2670
+ //Get width of a string in the current font
2671
+ $s = (string)$s;
2672
+ $cw = &$this->CurrentFont['cw'];
2673
+ $w = 0;
2674
+ $kerning = 0;
2675
+ $lastchar = 0;
2676
+ $nb_carac = 0;
2677
+ $nb_spaces = 0;
2678
+ // mPDF ITERATION
2679
+ if ($this->iterationCounter) $s = preg_replace('/{iteration ([a-zA-Z0-9_]+)}/', '\\1', $s);
2680
+
2681
+ if (!$this->usingCoreFont) {
2682
+ $s = str_replace("\xc2\xad",'',$s );
2683
+ $unicode = $this->UTF8StringToArray($s, $addSubset);
2684
+ if ($this->minwSpacing || $this->fixedlSpacing) {
2685
+ $nb_carac = count($unicode);
2686
+ $nb_spaces = mb_substr_count($s,' ', $this->mb_enc);
2687
+ }
2688
+ foreach($unicode as $char) {
2689
+ if ($this->S && isset($this->upperCase[$char])) {
2690
+ $charw = $this->_getCharWidth($cw,$this->upperCase[$char]);
2691
+ if ($charw!==false) {
2692
+ $charw = $charw*$this->smCapsScale * $this->smCapsStretch/100;
2693
+ $w+=$charw;
2694
+ }
2695
+ elseif(isset($this->CurrentFont['desc']['MissingWidth'])) { $w += $this->CurrentFont['desc']['MissingWidth']; }
2696
+ elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
2697
+ else { $w += 500; }
2698
+ }
2699
+ else {
2700
+ $charw = $this->_getCharWidth($cw,$char);
2701
+ if ($charw!==false) { $w+=$charw; }
2702
+ elseif(isset($this->CurrentFont['desc']['MissingWidth'])) { $w += $this->CurrentFont['desc']['MissingWidth']; }
2703
+ elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
2704
+ else { $w += 500; }
2705
+ if ($this->kerning && $this->useKerning && $lastchar) {
2706
+ if (isset($this->CurrentFont['kerninfo'][$lastchar][$char])) {
2707
+ $kerning += $this->CurrentFont['kerninfo'][$lastchar][$char];
2708
+ }
2709
+ }
2710
+ $lastchar = $char;
2711
+ }
2712
+ }
2713
+
2714
+ }
2715
+ else {
2716
+ if ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
2717
+ $s = str_replace(chr(173),'',$s );
2718
+ }
2719
+ $nb_carac = $l = strlen($s);
2720
+ if ($this->minwSpacing || $this->fixedlSpacing) {
2721
+ $nb_spaces = substr_count($s,' ');
2722
+ }
2723
+ for($i=0; $i<$l; $i++) {
2724
+ if ($this->S && isset($this->upperCase[ord($s[$i])])) {
2725
+ $charw = $cw[chr($this->upperCase[ord($s[$i])])];
2726
+ if ($charw!==false) {
2727
+ $charw = $charw*$this->smCapsScale * $this->smCapsStretch/100;
2728
+ $w+=$charw;
2729
+ }
2730
+ }
2731
+ else if (isset($cw[$s[$i]])) {
2732
+ $w += $cw[$s[$i]];
2733
+ }
2734
+ else if (isset($cw[ord($s[$i])])) {
2735
+ $w += $cw[ord($s[$i])];
2736
+ }
2737
+ if ($this->kerning && $this->useKerning && $i>0) {
2738
+ if (isset($this->CurrentFont['kerninfo'][$s[($i-1)]][$s[$i]])) {
2739
+ $kerning += $this->CurrentFont['kerninfo'][$s[($i-1)]][$s[$i]];
2740
+ }
2741
+ }
2742
+ }
2743
+ }
2744
+ unset($cw);
2745
+ if ($this->kerning && $this->useKerning) { $w += $kerning; }
2746
+ $w *= ($this->FontSize/ 1000);
2747
+ $w += (($nb_carac + $nb_spaces) * $this->fixedlSpacing) + ($nb_spaces * $this->minwSpacing);
2748
+ return ($w);
2749
+ }
2750
+
2751
+ function SetLineWidth($width) {
2752
+ //Set line width
2753
+ $this->LineWidth=$width;
2754
+ $lwout = (sprintf('%.3F w',$width*_MPDFK));
2755
+ if($this->page>0 && ((isset($this->pageoutput[$this->page]['LineWidth']) && $this->pageoutput[$this->page]['LineWidth'] != $lwout) || !isset($this->pageoutput[$this->page]['LineWidth']) || $this->keep_block_together)) {
2756
+ $this->_out($lwout);
2757
+ }
2758
+ $this->pageoutput[$this->page]['LineWidth'] = $lwout;
2759
+ }
2760
+
2761
+ function Line($x1,$y1,$x2,$y2) {
2762
+ //Draw a line
2763
+ $this->_out(sprintf('%.3F %.3F m %.3F %.3F l S',$x1*_MPDFK,($this->h-$y1)*_MPDFK,$x2*_MPDFK,($this->h-$y2)*_MPDFK));
2764
+ }
2765
+
2766
+ function Arrow($x1,$y1,$x2,$y2,$headsize=3,$fill='B',$angle=25) {
2767
+ //F == fill //S == stroke //B == stroke and fill
2768
+ // angle = splay of arrowhead - 1 - 89 degrees
2769
+ if($fill=='F') $fill='f';
2770
+ elseif($fill=='FD' or $fill=='DF' or $fill=='B') $fill='B';
2771
+ else $fill='S';
2772
+ $a = atan2(($y2-$y1),($x2-$x1));
2773
+ $b = $a + deg2rad($angle);
2774
+ $c = $a - deg2rad($angle);
2775
+ $x3 = $x2 - ($headsize* cos($b));
2776
+ $y3 = $this->h-($y2 - ($headsize* sin($b)));
2777
+ $x4 = $x2 - ($headsize* cos($c));
2778
+ $y4 = $this->h-($y2 - ($headsize* sin($c)));
2779
+
2780
+ $x5 = $x3-($x3-$x4)/2; // mid point of base of arrowhead - to join arrow line to
2781
+ $y5 = $y3-($y3-$y4)/2;
2782
+
2783
+ $s = '';
2784
+ $s.=sprintf('%.3F %.3F m %.3F %.3F l S',$x1*_MPDFK,($this->h-$y1)*_MPDFK,$x5*_MPDFK,$y5*_MPDFK);
2785
+ $this->_out($s);
2786
+
2787
+ $s = '';
2788
+ $s.=sprintf('%.3F %.3F m %.3F %.3F l %.3F %.3F l %.3F %.3F l %.3F %.3F l ',$x5*_MPDFK,$y5*_MPDFK,$x3*_MPDFK,$y3*_MPDFK,$x2*_MPDFK,($this->h-$y2)*_MPDFK,$x4*_MPDFK,$y4*_MPDFK,$x5*_MPDFK,$y5*_MPDFK);
2789
+ $s.=$fill;
2790
+ $this->_out($s);
2791
+ }
2792
+
2793
+
2794
+ function Rect($x,$y,$w,$h,$style='') {
2795
+ //Draw a rectangle
2796
+ if($style=='F') $op='f';
2797
+ elseif($style=='FD' or $style=='DF') $op='B';
2798
+ else $op='S';
2799
+ $this->_out(sprintf('%.3F %.3F %.3F %.3F re %s',$x*_MPDFK,($this->h-$y)*_MPDFK,$w*_MPDFK,-$h*_MPDFK,$op));
2800
+ }
2801
+
2802
+ function AddFont($family,$style='') {
2803
+ if(empty($family)) { return; }
2804
+ $family = strtolower($family);
2805
+ $style=strtoupper($style);
2806
+ $style=str_replace('U','',$style);
2807
+ if($style=='IB') $style='BI';
2808
+ $fontkey = $family.$style;
2809
+ // check if the font has been already added
2810
+ if(isset($this->fonts[$fontkey])) {
2811
+ return;
2812
+ }
2813
+
2814
+
2815
+ if ($this->usingCoreFont) { die("mPDF Error - problem with Font management"); }
2816
+
2817
+ $stylekey = $style;
2818
+ if (!$style) { $stylekey = 'R'; }
2819
+
2820
+ if (!isset($this->fontdata[$family][$stylekey]) || !$this->fontdata[$family][$stylekey]) {
2821
+ die('mPDF Error - Font is not supported - '.$family.' '.$style);
2822
+ }
2823
+
2824
+ $name = '';
2825
+ $originalsize = 0;
2826
+ $sip = false;
2827
+ $smp = false;
2828
+ $unAGlyphs = false; // mPDF 5.4.05
2829
+ $haskerninfo = false;
2830
+ $BMPselected = false;
2831
+ @include(_MPDF_TTFONTDATAPATH.$fontkey.'.mtx.php');
2832
+
2833
+ $ttffile = '';
2834
+ if (defined('_MPDF_SYSTEM_TTFONTS')) {
2835
+ $ttffile = _MPDF_SYSTEM_TTFONTS.$this->fontdata[$family][$stylekey];
2836
+ if (!file_exists($ttffile)) { $ttffile = ''; }
2837
+ }
2838
+ if (!$ttffile) {
2839
+ $ttffile = _MPDF_TTFONTPATH.$this->fontdata[$family][$stylekey];
2840
+ if (!file_exists($ttffile)) { die("mPDF Error - cannot find TTF TrueType font file - ".$ttffile); }
2841
+ }
2842
+ $ttfstat = stat($ttffile);
2843
+
2844
+ if (isset($this->fontdata[$family]['TTCfontID'][$stylekey])) { $TTCfontID = $this->fontdata[$family]['TTCfontID'][$stylekey]; }
2845
+ else { $TTCfontID = 0; }
2846
+
2847
+
2848
+ $BMPonly = false;
2849
+ if (in_array($family,$this->BMPonly)) { $BMPonly = true; }
2850
+ $regenerate = false;
2851
+ if ($BMPonly && !$BMPselected) { $regenerate = true; }
2852
+ else if (!$BMPonly && $BMPselected) { $regenerate = true; }
2853
+ if ($this->useKerning && !$haskerninfo) { $regenerate = true; }
2854
+ // mPDF 5.4.05
2855
+ if (isset($this->fontdata[$family]['unAGlyphs']) && $this->fontdata[$family]['unAGlyphs'] && !$unAGlyphs) {
2856
+ $regenerate = true;
2857
+ $unAGlyphs = true;
2858
+ }
2859
+ else if ((!isset($this->fontdata[$family]['unAGlyphs']) || !$this->fontdata[$family]['unAGlyphs']) && $unAGlyphs) {
2860
+ $regenerate = true;
2861
+ $unAGlyphs = false;
2862
+ }
2863
+ if (!isset($name) || $originalsize != $ttfstat['size'] || $regenerate) {
2864
+ if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
2865
+ $ttf = new TTFontFile();
2866
+ $ttf->getMetrics($ttffile, $TTCfontID, $this->debugfonts, $BMPonly, $this->useKerning, $unAGlyphs); // mPDF 5.4.05
2867
+ $cw = $ttf->charWidths;
2868
+ $kerninfo = $ttf->kerninfo;
2869
+ $haskerninfo = true;
2870
+ $name = preg_replace('/[ ()]/','',$ttf->fullName);
2871
+ $sip = $ttf->sipset;
2872
+ $smp = $ttf->smpset;
2873
+
2874
+ $desc= array('Ascent'=>round($ttf->ascent),
2875
+ 'Descent'=>round($ttf->descent),
2876
+ 'CapHeight'=>round($ttf->capHeight),
2877
+ 'Flags'=>$ttf->flags,
2878
+ 'FontBBox'=>'['.round($ttf->bbox[0])." ".round($ttf->bbox[1])." ".round($ttf->bbox[2])." ".round($ttf->bbox[3]).']',
2879
+ 'ItalicAngle'=>$ttf->italicAngle,
2880
+ 'StemV'=>round($ttf->stemV),
2881
+ 'MissingWidth'=>round($ttf->defaultWidth));
2882
+ $panose = '';
2883
+ // mPDF 5.5.19
2884
+ if (count($ttf->panose)) {
2885
+ $panoseArray = array_merge(array($ttf->sFamilyClass, $ttf->sFamilySubClass), $ttf->panose);
2886
+ foreach($panoseArray as $value)
2887
+ $panose .= ' '.dechex($value);
2888
+ }
2889
+ $up = round($ttf->underlinePosition);
2890
+ $ut = round($ttf->underlineThickness);
2891
+ $originalsize = $ttfstat['size']+0;
2892
+ $type = 'TTF';
2893
+ //Generate metrics .php file
2894
+ $s='<?php'."\n";
2895
+ $s.='$name=\''.$name."';\n";
2896
+ $s.='$type=\''.$type."';\n";
2897
+ $s.='$desc='.var_export($desc,true).";\n";
2898
+ $s.='$up='.$up.";\n";
2899
+ $s.='$ut='.$ut.";\n";
2900
+ $s.='$ttffile=\''.$ttffile."';\n";
2901
+ $s.='$TTCfontID=\''.$TTCfontID."';\n";
2902
+ $s.='$originalsize='.$originalsize.";\n";
2903
+ if ($sip) $s.='$sip=true;'."\n";
2904
+ else $s.='$sip=false;'."\n";
2905
+ if ($smp) $s.='$smp=true;'."\n";
2906
+ else $s.='$smp=false;'."\n";
2907
+ if ($BMPonly) $s.='$BMPselected=true;'."\n";
2908
+ else $s.='$BMPselected=false;'."\n";
2909
+ $s.='$fontkey=\''.$fontkey."';\n";
2910
+ $s.='$panose=\''.$panose."';\n";
2911
+ if ($this->useKerning) {
2912
+ $s.='$kerninfo='.var_export($kerninfo,true).";\n";
2913
+ $s.='$haskerninfo=true;'."\n";
2914
+ }
2915
+ else $s.='$haskerninfo=false;'."\n";
2916
+ // mPDF 5.4.05
2917
+ if ($this->fontdata[$family]['unAGlyphs']) {
2918
+ $s.='$unAGlyphs=true;'."\n";
2919
+ }
2920
+ else $s.='$unAGlyphs=false;'."\n";
2921
+ $s.="?>";
2922
+ if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
2923
+ $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.mtx.php',"w");
2924
+ fwrite($fh,$s,strlen($s));
2925
+ fclose($fh);
2926
+ $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.cw.dat',"wb");
2927
+ fwrite($fh,$cw,strlen($cw));
2928
+ fclose($fh);
2929
+ @unlink(_MPDF_TTFONTDATAPATH.$fontkey.'.cgm');
2930
+ @unlink(_MPDF_TTFONTDATAPATH.$fontkey.'.z');
2931
+ @unlink(_MPDF_TTFONTDATAPATH.$fontkey.'.cw127.php');
2932
+ @unlink(_MPDF_TTFONTDATAPATH.$fontkey.'.cw');
2933
+ }
2934
+ else if ($this->debugfonts) { $this->Error('Cannot write to the font caching directory - '._MPDF_TTFONTDATAPATH); }
2935
+ unset($ttf);
2936
+ }
2937
+ else {
2938
+ $cw = @file_get_contents(_MPDF_TTFONTDATAPATH.$fontkey.'.cw.dat');
2939
+ }
2940
+
2941
+ if (isset($this->fontdata[$family]['indic']) && $this->fontdata[$family]['indic']) { $indic = true; }
2942
+ else { $indic = false; }
2943
+ if (isset($this->fontdata[$family]['sip-ext']) && $this->fontdata[$family]['sip-ext']) { $sipext = $this->fontdata[$family]['sip-ext']; }
2944
+ else { $sipext = ''; }
2945
+
2946
+
2947
+ $i = count($this->fonts)+$this->extraFontSubsets+1;
2948
+ if ($sip || $smp) {
2949
+ $this->fonts[$fontkey] = array('i'=>$i, 'type'=>$type, 'name'=>$name, 'desc'=>$desc, 'panose'=>$panose, 'up'=>$up, 'ut'=>$ut, 'cw'=>$cw, 'ttffile'=>$ttffile, 'fontkey'=>$fontkey, 'subsets'=>array(0=>range(0,127)), 'subsetfontids'=>array($i), 'used'=>false, 'indic'=>$indic, 'sip'=>$sip, 'sipext'=>$sipext, 'smp'=>$smp, 'TTCfontID' => $TTCfontID, 'unAGlyphs' => false); // mPDF 5.4.05
2950
+ }
2951
+ else {
2952
+ $ss = array();
2953
+ for ($s=32; $s<128; $s++) { $ss[$s] = $s; }
2954
+ $this->fonts[$fontkey] = array('i'=>$i, 'type'=>$type, 'name'=>$name, 'desc'=>$desc, 'panose'=>$panose, 'up'=>$up, 'ut'=>$ut, 'cw'=>$cw, 'ttffile'=>$ttffile, 'fontkey'=>$fontkey, 'subset'=>$ss, 'used'=>false, 'indic'=>$indic, 'sip'=>$sip, 'sipext'=>$sipext, 'smp'=>$smp, 'TTCfontID' => $TTCfontID, 'unAGlyphs' => $unAGlyphs); // mPDF 5.4.05
2955
+ }
2956
+ if ($this->useKerning && $haskerninfo) { $this->fonts[$fontkey]['kerninfo'] = $kerninfo; }
2957
+ $this->FontFiles[$fontkey]=array('length1'=>$originalsize, 'type'=>"TTF", 'ttffile'=>$ttffile, 'sip'=>$sip, 'smp'=>$smp);
2958
+ unset($cw);
2959
+ }
2960
+
2961
+
2962
+
2963
+ function SetFont($family,$style='',$size=0, $write=true, $forcewrite=false) {
2964
+ $family=strtolower($family);
2965
+ if (!$this->onlyCoreFonts) {
2966
+ if ($family == 'sans' || $family == 'sans-serif') { $family = $this->sans_fonts[0]; }
2967
+ if ($family == 'serif') { $family = $this->serif_fonts[0]; }
2968
+ if ($family == 'mono' || $family == 'monospace') { $family = $this->mono_fonts[0]; }
2969
+ }
2970
+ if (isset($this->fonttrans[$family]) && $this->fonttrans[$family]) { $family = $this->fonttrans[$family]; }
2971
+ if($family=='') {
2972
+ if ($this->FontFamily) { $family=$this->FontFamily; }
2973
+ else if ($this->default_font) { $family=$this->default_font; }
2974
+ else { $this->Error("No font or default font set!"); }
2975
+ }
2976
+ $this->ReqFontStyle = $style; // required or requested style - used later for artificial bold/italic
2977
+
2978
+ if (($family == 'csymbol') || ($family == 'czapfdingbats') || ($family == 'ctimes') || ($family == 'ccourier') || ($family == 'chelvetica')) {
2979
+ if ($this->PDFA || $this->PDFX) {
2980
+ if ($family == 'csymbol' || $family == 'czapfdingbats') {
2981
+ $this->Error("Symbol and Zapfdingbats cannot be embedded in mPDF (required for PDFA1-b or PDFX/1-a).");
2982
+ }
2983
+ if ($family == 'ctimes' || $family == 'ccourier' || $family == 'chelvetica') {
2984
+ if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "Core Adobe font ".ucfirst($family)." cannot be embedded in mPDF, which is required for PDFA1-b or PDFX/1-a. (Embedded font will be substituted.)"; }
2985
+ if ($family == 'chelvetica') { $family = 'sans'; }
2986
+ if ($family == 'ctimes') { $family = 'serif'; }
2987
+ if ($family == 'ccourier') { $family = 'mono'; }
2988
+ }
2989
+ $this->usingCoreFont = false;
2990
+ }
2991
+ else { $this->usingCoreFont = true; }
2992
+ if($family=='csymbol' || $family=='czapfdingbats') { $style=''; }
2993
+ }
2994
+ else { $this->usingCoreFont = false; }
2995
+
2996
+ $this->U=false;
2997
+ $this->S=false;
2998
+ if ($style) {
2999
+ $style=strtoupper($style);
3000
+ if(strpos($style,'U')!==false) {
3001
+ $this->U=true;
3002
+ $style=str_replace('U','',$style);
3003
+ }
3004
+ if(strpos($style,'S')!==false) {
3005
+ $this->S=true;
3006
+ // Small Caps
3007
+ if (empty($this->upperCase)) { @include(_MPDF_PATH.'includes/upperCase.php'); }
3008
+ $style=str_replace('S','',$style);
3009
+ }
3010
+ if ($style=='IB') $style='BI';
3011
+ }
3012
+ if ($size==0) $size=$this->FontSizePt;
3013
+
3014
+ $fontkey=$family.$style;
3015
+
3016
+ $stylekey = $style;
3017
+ if (!$stylekey) { $stylekey = "R"; }
3018
+
3019
+ if (!$this->onlyCoreFonts && !$this->usingCoreFont) {
3020
+ if(!isset($this->fonts[$fontkey]) || count($this->default_available_fonts) != count($this->available_unifonts) ) { // not already added
3021
+ if (!in_array($fontkey,$this->available_unifonts)) {
3022
+ // If font[nostyle] exists - set it
3023
+ if (in_array($family,$this->available_unifonts)) {
3024
+ $style = '';
3025
+ }
3026
+
3027
+ // Else if only one font available - set it (assumes if only one font available it will not have a style)
3028
+ else if (count($this->available_unifonts) == 1) {
3029
+ $family = $this->available_unifonts[0];
3030
+ $style = '';
3031
+ }
3032
+
3033
+ else {
3034
+ $found = 0;
3035
+ // else substitute font of similar type
3036
+ if (in_array($family,$this->sans_fonts)) {
3037
+ $i = array_intersect($this->sans_fonts,$this->available_unifonts);
3038
+ if (count($i)) {
3039
+ $i = array_values($i);
3040
+ // with requested style if possible
3041
+ if (!in_array(($i[0].$style),$this->available_unifonts)) {
3042
+ $style = '';
3043
+ }
3044
+ $family = $i[0];
3045
+ $found = 1;
3046
+ }
3047
+ }
3048
+ else if (in_array($family,$this->serif_fonts)) {
3049
+ $i = array_intersect($this->serif_fonts,$this->available_unifonts);
3050
+ if (count($i)) {
3051
+ $i = array_values($i);
3052
+ // with requested style if possible
3053
+ if (!in_array(($i[0].$style),$this->available_unifonts)) {
3054
+ $style = '';
3055
+ }
3056
+ $family = $i[0];
3057
+ $found = 1;
3058
+ }
3059
+ }
3060
+ else if (in_array($family,$this->mono_fonts)) {
3061
+ $i = array_intersect($this->mono_fonts,$this->available_unifonts);
3062
+ if (count($i)) {
3063
+ $i = array_values($i);
3064
+ // with requested style if possible
3065
+ if (!in_array(($i[0].$style),$this->available_unifonts)) {
3066
+ $style = '';
3067
+ }
3068
+ $family = $i[0];
3069
+ $found = 1;
3070
+ }
3071
+ }
3072
+
3073
+ if (!$found) {
3074
+ // set first available font
3075
+ $fs = $this->available_unifonts[0];
3076
+ preg_match('/^([a-z_0-9\-]+)([BI]{0,2})$/',$fs,$fas); // Allow "-"
3077
+ // with requested style if possible
3078
+ $ws = $fas[1].$style;
3079
+ if (in_array($ws,$this->available_unifonts)) {
3080
+ $family = $fas[1]; // leave $style as is
3081
+ }
3082
+ else if (in_array($fas[1],$this->available_unifonts)) {
3083
+ // or without style
3084
+ $family = $fas[1];
3085
+ $style = '';
3086
+ }
3087
+ else {
3088
+ // or with the style specified
3089
+ $family = $fas[1];
3090
+ $style = $fas[2];
3091
+ }
3092
+ }
3093
+ }
3094
+ $fontkey = $family.$style;
3095
+ }
3096
+ }
3097
+ // try to add font (if not already added)
3098
+ $this->AddFont($family, $style);
3099
+
3100
+ //Test if font is already selected
3101
+ if($this->FontFamily == $family && $this->FontFamily == $this->currentfontfamily && $this->FontStyle == $style && $this->FontStyle == $this->currentfontstyle && $this->FontSizePt == $size && $this->FontSizePt == $this->currentfontsize && !$forcewrite) {
3102
+ return $family;
3103
+ }
3104
+
3105
+ $fontkey = $family.$style;
3106
+
3107
+ //Select it
3108
+ $this->FontFamily = $family;
3109
+ $this->FontStyle = $style;
3110
+ $this->FontSizePt = $size;
3111
+ $this->FontSize = $size / _MPDFK;
3112
+ $this->CurrentFont = &$this->fonts[$fontkey];
3113
+ if ($write) {
3114
+ $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
3115
+ if($this->page>0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']) || $this->keep_block_together)) { $this->_out($fontout); }
3116
+ $this->pageoutput[$this->page]['Font'] = $fontout;
3117
+ }
3118
+
3119
+
3120
+
3121
+ // Added - currentfont (lowercase) used in HTML2PDF
3122
+ $this->currentfontfamily=$family;
3123
+ $this->currentfontsize=$size;
3124
+ $this->currentfontstyle=$style.($this->U ? 'U' : '').($this->S ? 'S' : '');
3125
+ $this->setMBencoding('UTF-8');
3126
+ }
3127
+
3128
+ else { // if using core fonts
3129
+
3130
+
3131
+ if ($this->PDFA || $this->PDFX) {
3132
+ $this->Error('Core Adobe fonts cannot be embedded in mPDF (required for PDFA1-b or PDFX/1-a) - cannot use option to use core fonts.');
3133
+ }
3134
+ $this->setMBencoding('windows-1252');
3135
+
3136
+ //Test if font is already selected
3137
+ if(($this->FontFamily == $family) AND ($this->FontStyle == $style) AND ($this->FontSizePt == $size) && !$forcewrite) {
3138
+ return $family;
3139
+ }
3140
+
3141
+ if (!isset($this->CoreFonts[$fontkey])) {
3142
+ if (in_array($family,$this->serif_fonts)) { $family = 'ctimes'; }
3143
+ else if (in_array($family,$this->mono_fonts)) { $family = 'ccourier'; }
3144
+ else { $family = 'chelvetica'; }
3145
+ $this->usingCoreFont = true;
3146
+ $fontkey = $family.$style;
3147
+ }
3148
+
3149
+ if(!isset($this->fonts[$fontkey])) {
3150
+ // STANDARD CORE FONTS
3151
+ if (isset($this->CoreFonts[$fontkey])) {
3152
+ //Load metric file
3153
+ $file=$family;
3154
+ if($family=='ctimes' || $family=='chelvetica' || $family=='ccourier') { $file.=strtolower($style); }
3155
+ $file.='.php';
3156
+ include(_MPDF_PATH.'font/'.$file);
3157
+ if(!isset($cw)) { $this->Error('Could not include font metric file'); }
3158
+ $i=count($this->fonts)+$this->extraFontSubsets+1;
3159
+ $this->fonts[$fontkey]=array('i'=>$i,'type'=>'core','name'=>$this->CoreFonts[$fontkey],'desc'=>$desc,'up'=>$up,'ut'=>$ut,'cw'=>$cw);
3160
+ if ($this->useKerning) { $this->fonts[$fontkey]['kerninfo'] = $kerninfo; }
3161
+ }
3162
+ else {
3163
+ die('mPDF error - Font not defined');
3164
+ }
3165
+ }
3166
+ //Test if font is already selected
3167
+ if(($this->FontFamily == $family) AND ($this->FontStyle == $style) AND ($this->FontSizePt == $size) && !$forcewrite) {
3168
+ return $family;
3169
+ }
3170
+ //Select it
3171
+ $this->FontFamily=$family;
3172
+ $this->FontStyle=$style;
3173
+ $this->FontSizePt=$size;
3174
+ $this->FontSize=$size/_MPDFK;
3175
+ $this->CurrentFont=&$this->fonts[$fontkey];
3176
+ if ($write) {
3177
+ $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
3178
+ if($this->page>0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']) || $this->keep_block_together)) { $this->_out($fontout); }
3179
+ $this->pageoutput[$this->page]['Font'] = $fontout;
3180
+ }
3181
+ // Added - currentfont (lowercase) used in HTML2PDF
3182
+ $this->currentfontfamily=$family;
3183
+ $this->currentfontsize=$size;
3184
+ $this->currentfontstyle=$style.($this->U ? 'U' : '').($this->S ? 'S' : '');
3185
+
3186
+ }
3187
+
3188
+ return $family;
3189
+ }
3190
+
3191
+ function SetFontSize($size,$write=true) {
3192
+ //Set font size in points
3193
+ if($this->FontSizePt==$size) return;
3194
+ $this->FontSizePt=$size;
3195
+ $this->FontSize=$size/_MPDFK;
3196
+ $this->currentfontsize=$size;
3197
+ if ($write) {
3198
+ $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
3199
+ // Edited mPDF 3.0
3200
+ if($this->page>0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']) || $this->keep_block_together)) { $this->_out($fontout); }
3201
+ $this->pageoutput[$this->page]['Font'] = $fontout;
3202
+ }
3203
+ }
3204
+
3205
+ function AddLink() {
3206
+ //Create a new internal link
3207
+ $n=count($this->links)+1;
3208
+ $this->links[$n]=array(0,0);
3209
+ return $n;
3210
+ }
3211
+
3212
+ function SetLink($link,$y=0,$page=-1) {
3213
+ //Set destination of internal link
3214
+ if($y==-1) $y=$this->y;
3215
+ if($page==-1) $page=$this->page;
3216
+ $this->links[$link]=array($page,$y);
3217
+ }
3218
+
3219
+ function Link($x,$y,$w,$h,$link) {
3220
+ $l = array($x*_MPDFK,$this->hPt-$y*_MPDFK,$w*_MPDFK,$h*_MPDFK,$link);
3221
+ if ($this->keep_block_together) { // Save to array - don't write yet
3222
+ $this->ktLinks[$this->page][]= $l;
3223
+ return;
3224
+ }
3225
+ else if ($this->table_rotate) { // *TABLES*
3226
+ $this->tbrot_Links[$this->page][]= $l; // *TABLES*
3227
+ return; // *TABLES*
3228
+ } // *TABLES*
3229
+ else if ($this->kwt) {
3230
+ $this->kwt_Links[$this->page][]= $l;
3231
+ return;
3232
+ }
3233
+
3234
+ if ($this->writingHTMLheader || $this->writingHTMLfooter) {
3235
+ $this->HTMLheaderPageLinks[]= $l;
3236
+ return;
3237
+ }
3238
+ //Put a link on the page
3239
+ $this->PageLinks[$this->page][]= $l;
3240
+ // Save cross-reference to Column buffer
3241
+
3242
+ }
3243
+
3244
+ function Text($x,$y,$txt) {
3245
+ // Output a string
3246
+ // Called (internally) by Watermark and _tableWrite [rotated cells]
3247
+ // Expects input to be mb_encoded if necessary and RTL reversed
3248
+
3249
+ // ARTIFICIAL BOLD AND ITALIC
3250
+ $s = 'q ';
3251
+ if ($this->falseBoldWeight && strpos($this->ReqFontStyle,"B") !== false && strpos($this->FontStyle,"B") === false) {
3252
+ $s .= '2 Tr 1 J 1 j ';
3253
+ $s .= sprintf('%.3F w ',($this->FontSize/130)*_MPDFK*$this->falseBoldWeight);
3254
+ $tc = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
3255
+ if($this->FillColor!=$tc) { $s .= $tc.' '; } // stroke (outline) = same colour as text(fill)
3256
+ }
3257
+ if (strpos($this->ReqFontStyle,"I") !== false && strpos($this->FontStyle,"I") === false) {
3258
+ $aix = '1 0 0.261799 1 %.3F %.3F Tm';
3259
+ }
3260
+ else { $aix = '%.3F %.3F Td'; }
3261
+
3262
+ if($this->ColorFlag) $s.=$this->TextColor.' ';
3263
+
3264
+ $this->CurrentFont['used']= true;
3265
+ if ($this->CurrentFont['type']=='TTF' && ($this->CurrentFont['sip'] || $this->CurrentFont['smp'])) {
3266
+ $txt2 = str_replace(chr(194).chr(160),chr(32),$txt);
3267
+ $txt2 = $this->UTF8toSubset($txt2);
3268
+ $s.=sprintf('BT '.$aix.' %s Tj ET ',$x*_MPDFK,($this->h-$y)*_MPDFK,$txt2);
3269
+ }
3270
+ else if (!$this->usingCoreFont) {
3271
+ $txt2 = str_replace(chr(194).chr(160),chr(32),$txt);
3272
+ $this->UTF8StringToArray($txt2); // this is just to add chars to subset list
3273
+ if ($this->kerning && $this->useKerning) { $s .= $this->_kern($txt2, '', $aix, $x, $y); }
3274
+ else {
3275
+ //Convert string to UTF-16BE without BOM
3276
+ $txt2= $this->UTF8ToUTF16BE($txt2, false);
3277
+ $s.=sprintf('BT '.$aix.' (%s) Tj ET ',$x*_MPDFK,($this->h-$y)*_MPDFK,$this->_escape($txt2));
3278
+ }
3279
+ }
3280
+ else {
3281
+ $txt2 = str_replace(chr(160),chr(32),$txt);
3282
+ if ($this->kerning && $this->useKerning) { $s .= $this->_kern($txt2, '', $aix, $x, $y); }
3283
+ else {
3284
+ $s.=sprintf('BT '.$aix.' (%s) Tj ET ',$x*_MPDFK,($this->h-$y)*_MPDFK,$this->_escape($txt2));
3285
+ }
3286
+ }
3287
+ if($this->U && $txt!='') {
3288
+ $c = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
3289
+ if($this->FillColor!=$c) { $s.= ' '.$c.' '; }
3290
+ if (isset($this->CurrentFont['up'])) { $up=$this->CurrentFont['up']; }
3291
+ else { $up = -100; }
3292
+ $adjusty = (-$up/1000* $this->FontSize);
3293
+ if (isset($this->CurrentFont['ut'])) { $ut=$this->CurrentFont['ut']/1000* $this->FontSize; }
3294
+ else { $ut = 60/1000* $this->FontSize; }
3295
+ $olw = $this->LineWidth;
3296
+ $s.=' '.(sprintf(' %.3F w',$ut*_MPDFK));
3297
+ $s.=' '.$this->_dounderline($x,$y + $adjusty,$txt);
3298
+ $s.=' '.(sprintf(' %.3F w',$olw*_MPDFK));
3299
+ if($this->FillColor!=$c) { $s.= ' '.$this->FillColor.' '; }
3300
+ }
3301
+ // STRIKETHROUGH
3302
+ if($this->strike && $txt!='') {
3303
+ $c = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
3304
+ if($this->FillColor!=$c) { $s.= ' '.$c.' '; }
3305
+ //Superscript and Subscript Y coordinate adjustment (now for striked-through texts)
3306
+ if (isset($this->CurrentFont['desc']['CapHeight'])) { $ch=$this->CurrentFont['desc']['CapHeight']; }
3307
+ else { $ch = 700; }
3308
+ $adjusty = (-$ch/1000* $this->FontSize) * 0.35;
3309
+ if (isset($this->CurrentFont['ut'])) { $ut=$this->CurrentFont['ut']/1000* $this->FontSize; }
3310
+ else { $ut = 60/1000* $this->FontSize; }
3311
+ $olw = $this->LineWidth;
3312
+ $s.=' '.(sprintf(' %.3F w',$ut*_MPDFK));
3313
+ $s.=' '.$this->_dounderline($x,$y+$adjusty,$txt);
3314
+ $s.=' '.(sprintf(' %.3F w',$olw*_MPDFK));
3315
+ if($this->FillColor!=$c) { $s.= ' '.$this->FillColor.' '; }
3316
+ }
3317
+ $s .= 'Q';
3318
+ $this->_out($s);
3319
+ }
3320
+
3321
+ function WriteText($x,$y,$txt) {
3322
+ // Output a string using Text() but does encoding and text reversing of RTL
3323
+ $txt = $this->purify_utf8_text($txt);
3324
+ if ($this->text_input_as_HTML) {
3325
+ $txt = $this->all_entities_to_utf8($txt);
3326
+ }
3327
+ if ($this->usingCoreFont) { $txt = mb_convert_encoding($txt,$this->mb_enc,'UTF-8'); }
3328
+ // DIRECTIONALITY
3329
+ // Font-specific ligature substitution for Indic fonts
3330
+ $this->Text($x,$y,$txt);
3331
+ }
3332
+
3333
+ function WriteCell($w,$h=0,$txt='',$border=0,$ln=0,$align='',$fill=0,$link='', $currentx=0) {
3334
+ //Output a cell using Cell() but does encoding and text reversing of RTL
3335
+ $txt = $this->purify_utf8_text($txt);
3336
+ if ($this->text_input_as_HTML) {
3337
+ $txt = $this->all_entities_to_utf8($txt);
3338
+ }
3339
+ if ($this->usingCoreFont) { $txt = mb_convert_encoding($txt,$this->mb_enc,'UTF-8'); }
3340
+ // DIRECTIONALITY
3341
+ // Font-specific ligature substitution for Indic fonts
3342
+ $this->Cell($w,$h,$txt,$border,$ln,$align,$fill,$link, $currentx);
3343
+ }
3344
+
3345
+
3346
+ function ResetSpacing() {
3347
+ if ($this->ws != 0) { $this->_out('BT 0 Tw ET'); }
3348
+ $this->ws=0;
3349
+ if ($this->charspacing != 0) { $this->_out('BT 0 Tc ET'); }
3350
+ $this->charspacing=0;
3351
+ }
3352
+
3353
+
3354
+ function SetSpacing($cs,$ws) {
3355
+ if (intval($cs*1000)==0) { $cs = 0; }
3356
+ if ($cs) { $this->_out(sprintf('BT %.3F Tc ET',$cs)); }
3357
+ else if ($this->charspacing != 0) { $this->_out('BT 0 Tc ET'); }
3358
+ $this->charspacing=$cs;
3359
+ if (intval($ws*1000)==0) { $ws = 0; }
3360
+ if ($ws) { $this->_out(sprintf('BT %.3F Tw ET',$ws)); }
3361
+ else if ($this->ws != 0) { $this->_out('BT 0 Tw ET'); }
3362
+ $this->ws=$ws;
3363
+ }
3364
+
3365
+ // WORD SPACING
3366
+ function GetJspacing($nc,$ns,$w,$inclCursive) {
3367
+ $ws = 0;
3368
+ $charspacing = 0;
3369
+ $ww = $this->jSWord;
3370
+ $ncx = $nc-1;
3371
+ if ($nc == 0) { return array(0,0); }
3372
+ else if ($nc==1) { $charspacing = $w; }
3373
+ // Only word spacing allowed / possible
3374
+ else if ($this->fixedlSpacing !== false || $inclCursive) {
3375
+ if ($ns) { $ws = $w / $ns; }
3376
+ }
3377
+ else if (!$ns) {
3378
+ $charspacing = $w / ($ncx );
3379
+ if (($this->jSmaxChar > 0) && ($charspacing > $this->jSmaxChar)) {
3380
+ $charspacing = $this->jSmaxChar;
3381
+ }
3382
+ }
3383
+ else if ($ns == ($ncx )) {
3384
+ $charspacing = $w / $ns;
3385
+ }
3386
+ else {
3387
+ if ($this->usingCoreFont) {
3388
+ $cs = ($w * (1 - $this->jSWord)) / ($ncx );
3389
+ if (($this->jSmaxChar > 0) && ($cs > $this->jSmaxChar)) {
3390
+ $cs = $this->jSmaxChar;
3391
+ $ww = 1 - (($cs * ($ncx ))/$w);
3392
+ }
3393
+ $charspacing = $cs;
3394
+ $ws = ($w * ($ww) ) / $ns;
3395
+ }
3396
+ else {
3397
+ $cs = ($w * (1 - $this->jSWord)) / ($ncx -$ns);
3398
+ if (($this->jSmaxChar > 0) && ($cs > $this->jSmaxChar)) {
3399
+ $cs = $this->jSmaxChar;
3400
+ $ww = 1 - (($cs * ($ncx -$ns))/$w);
3401
+ }
3402
+ $charspacing = $cs;
3403
+ $ws = (($w * ($ww) ) / $ns) - $charspacing;
3404
+ }
3405
+ }
3406
+ return array($charspacing,$ws);
3407
+ }
3408
+
3409
+ function Cell($w,$h=0,$txt='',$border=0,$ln=0,$align='',$fill=0,$link='', $currentx=0, $lcpaddingL=0, $lcpaddingR=0, $valign='M', $spanfill=0, $abovefont=0, $belowfont=0, $exactWidth=false) {
3410
+ //Output a cell
3411
+ // Expects input to be mb_encoded if necessary and RTL reversed
3412
+ // NON_BREAKING SPACE
3413
+ if ($this->usingCoreFont) {
3414
+ $txt = str_replace(chr(160),chr(32),$txt);
3415
+ }
3416
+ else {
3417
+ $txt = str_replace(chr(194).chr(160),chr(32),$txt);
3418
+ }
3419
+
3420
+ $oldcolumn = $this->CurrCol;
3421
+ // Automatic page break
3422
+ // Allows PAGE-BREAK-AFTER = avoid to work
3423
+
3424
+ if (!$this->tableLevel && (($this->y+$this->divheight>$this->PageBreakTrigger) || ($this->y+$h>$this->PageBreakTrigger) ||
3425
+ ($this->y+($h*2)>$this->PageBreakTrigger && $this->blk[$this->blklvl]['page_break_after_avoid'])) and !$this->InFooter and $this->AcceptPageBreak()) {
3426
+ $x=$this->x;//Current X position
3427
+
3428
+
3429
+ // WORD SPACING
3430
+ $ws=$this->ws;//Word Spacing
3431
+ $charspacing=$this->charspacing;//Character Spacing
3432
+ $this->ResetSpacing();
3433
+
3434
+ $this->AddPage($this->CurOrientation);
3435
+ // Added to correct for OddEven Margins
3436
+ $x += $this->MarginCorrection;
3437
+ if ($currentx) {
3438
+ $currentx += $this->MarginCorrection;
3439
+ }
3440
+ $this->x=$x;
3441
+ // WORD SPACING
3442
+ $this->SetSpacing($charspacing,$ws);
3443
+ }
3444
+
3445
+ // Test: to put line through centre of cell: $this->Line($this->x,$this->y+($h/2),$this->x+50,$this->y+($h/2));
3446
+
3447
+
3448
+ // KEEP BLOCK TOGETHER Update/overwrite the lowest bottom of printing y value on first page
3449
+ if ($this->keep_block_together) {
3450
+ if ($h) { $this->ktBlock[$this->page]['bottom_margin'] = $this->y+$h; }
3451
+ // else { $this->ktBlock[$this->page]['bottom_margin'] = $this->y+$this->divheight; }
3452
+ }
3453
+
3454
+ if($w==0) $w = $this->w-$this->rMargin-$this->x;
3455
+ $s='';
3456
+ if($fill==1 && $this->FillColor) {
3457
+ if((isset($this->pageoutput[$this->page]['FillColor']) && $this->pageoutput[$this->page]['FillColor'] != $this->FillColor) || !isset($this->pageoutput[$this->page]['FillColor']) || $this->keep_block_together) { $s .= $this->FillColor.' '; }
3458
+ $this->pageoutput[$this->page]['FillColor'] = $this->FillColor;
3459
+ }
3460
+
3461
+
3462
+ $boxtop = $this->y;
3463
+ $boxheight = $h;
3464
+ $boxbottom = $this->y+$h;
3465
+
3466
+ if($txt!='') {
3467
+ // FONT SIZE - this determines the baseline caculation
3468
+ if ($this->linemaxfontsize && !$this->processingHeader) { $bfs = $this->linemaxfontsize; }
3469
+ else { $bfs = $this->FontSize; }
3470
+ //Calculate baseline Superscript and Subscript Y coordinate adjustment
3471
+ $bfx = $this->baselineC;
3472
+ $baseline = $bfx*$bfs;
3473
+ if($this->SUP) { $baseline += ($bfx-1.05)*$this->FontSize; }
3474
+ else if($this->SUB) { $baseline += ($bfx + 0.04)*$this->FontSize; }
3475
+ else if($this->bullet) { $baseline += ($bfx-0.7)*$this->FontSize; }
3476
+
3477
+ // Vertical align (for Images)
3478
+ if ($abovefont || $belowfont) { // from flowing block - valign always M
3479
+ $va = $abovefont + (0.5*$bfs);
3480
+ }
3481
+ else if ($this->lineheight_correction) {
3482
+ if ($valign == 'T') { $va = (0.5 * $bfs * $this->lineheight_correction); }
3483
+ else if ($valign == 'B') { $va = $h-(0.5 * $bfs * $this->lineheight_correction); }
3484
+ else { $va = 0.5*$h; } // Middle
3485
+ }
3486
+ else {
3487
+ if ($valign == 'T') { $va = (0.5 * $bfs * $this->default_lineheight_correction); }
3488
+ else if ($valign == 'B') { $va = $h-(0.5 * $bfs * $this->default_lineheight_correction); }
3489
+ else { $va = 0.5*$h; } // Middle
3490
+ }
3491
+
3492
+ // ONLY SET THESE IF WANT TO CONFINE BORDER +/- FILL TO FIT FONTSIZE - NOT FULL CELL AS IS ORIGINAL FUNCTION
3493
+ // spanfill or spanborder are set in FlowingBlock functions
3494
+ if ($spanfill || !empty($this->spanborddet) || $link!='') {
3495
+ $exth = 0.2; // Add to fontsize to increase height of background / link / border
3496
+ $boxtop = $this->y+$baseline+$va-($this->FontSize*(1+$exth/2)*(0.5+$bfx));
3497
+ $boxheight = $this->FontSize * (1+$exth);
3498
+ $boxbottom = $boxtop + $boxheight;
3499
+ }
3500
+ }
3501
+
3502
+ $bbw = $tbw = $lbw = $rbw = 0; // Border widths
3503
+ if (!empty($this->spanborddet)) {
3504
+ if (!isset($this->spanborddet['B'])) { $this->spanborddet['B'] = array('s' => 0, 'style' => '', 'w' => 0); }
3505
+ if (!isset($this->spanborddet['T'])) { $this->spanborddet['T'] = array('s' => 0, 'style' => '', 'w' => 0); }
3506
+ if (!isset($this->spanborddet['L'])) { $this->spanborddet['L'] = array('s' => 0, 'style' => '', 'w' => 0); }
3507
+ if (!isset($this->spanborddet['R'])) { $this->spanborddet['R'] = array('s' => 0, 'style' => '', 'w' => 0); }
3508
+ $bbw = $this->spanborddet['B']['w'];
3509
+ $tbw = $this->spanborddet['T']['w'];
3510
+ $lbw = $this->spanborddet['L']['w'];
3511
+ $rbw = $this->spanborddet['R']['w'];
3512
+ }
3513
+ if($fill==1 || $border==1 || !empty($this->spanborddet)) {
3514
+ if (!empty($this->spanborddet)) {
3515
+ if ($fill==1) {
3516
+ $s.=sprintf('%.3F %.3F %.3F %.3F re f ',($this->x-$lbw)*_MPDFK,($this->h-$boxtop+$tbw)*_MPDFK,($w+$lbw+$rbw)*_MPDFK,(-$boxheight-$tbw-$bbw)*_MPDFK);
3517
+ }
3518
+ $s.= ' q ';
3519
+ $dashon = 3;
3520
+ $dashoff = 3.5;
3521
+ $dot = 2.5;
3522
+ if($tbw) {
3523
+ $short = 0;
3524
+ if ($this->spanborddet['T']['style'] == 'dashed') {
3525
+ $s.=sprintf(' 0 j 0 J [%.3F %.3F] 0 d ',$tbw*$dashon*_MPDFK,$tbw*$dashoff*_MPDFK);
3526
+ }
3527
+ else if ($this->spanborddet['T']['style'] == 'dotted') {
3528
+ $s.=sprintf(' 1 j 1 J [%.3F %.3F] %.3F d ',0.001,$tbw*$dot*_MPDFK,-$tbw/2*_MPDFK);
3529
+ $short = $tbw/2;
3530
+ }
3531
+ else {
3532
+ $s.=' 0 j 0 J [] 0 d ';
3533
+ }
3534
+ $c = $this->SetDColor($this->spanborddet['T']['c'],true);
3535
+ if ($this->spanborddet['T']['style'] == 'double') {
3536
+ $s.=sprintf(' %s %.3F w ',$c,$tbw/3*_MPDFK);
3537
+ $xadj = $xadj2 = 0;
3538
+ if ($this->spanborddet['L']['style'] == 'double') { $xadj = $this->spanborddet['L']['w']*2/3; }
3539
+ if ($this->spanborddet['R']['style'] == 'double') { $xadj2 = $this->spanborddet['R']['w']*2/3; }
3540
+ $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$boxtop+$tbw*5/6)*_MPDFK,($this->x+$w+$rbw-$short)*_MPDFK,($this->h-$boxtop+$tbw*5/6)*_MPDFK);
3541
+ $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw+$xadj)*_MPDFK,($this->h-$boxtop+$tbw/6)*_MPDFK,($this->x+$w+$rbw-$short-$xadj2)*_MPDFK,($this->h-$boxtop+$tbw/6)*_MPDFK);
3542
+ }
3543
+ else {
3544
+ $s.=sprintf(' %s %.3F w ',$c,$tbw*_MPDFK);
3545
+ $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$boxtop+$tbw/2)*_MPDFK,($this->x+$w+$rbw-$short)*_MPDFK,($this->h-$boxtop+$tbw/2)*_MPDFK);
3546
+ }
3547
+ }
3548
+ if($bbw) {
3549
+ $short = 0;
3550
+ if ($this->spanborddet['B']['style'] == 'dashed') {
3551
+ $s.=sprintf(' 0 j 0 J [%.3F %.3F] 0 d ',$bbw*$dashon*_MPDFK,$bbw*$dashoff*_MPDFK);
3552
+ }
3553
+ else if ($this->spanborddet['B']['style'] == 'dotted') {
3554
+ $s.=sprintf(' 1 j 1 J [%.3F %.3F] %.3F d ',0.001,$bbw*$dot*_MPDFK,-$bbw/2*_MPDFK);
3555
+ $short = $bbw/2;
3556
+ }
3557
+ else {
3558
+ $s.=' 0 j 0 J [] 0 d ';
3559
+ }
3560
+ $c = $this->SetDColor($this->spanborddet['B']['c'],true);
3561
+ if ($this->spanborddet['B']['style'] == 'double') {
3562
+ $s.=sprintf(' %s %.3F w ',$c,$bbw/3*_MPDFK);
3563
+ $xadj = $xadj2 = 0;
3564
+ if ($this->spanborddet['L']['style'] == 'double') { $xadj = $this->spanborddet['L']['w']*2/3; }
3565
+ if ($this->spanborddet['R']['style'] == 'double') { $xadj2 = $this->spanborddet['R']['w']*2/3; }
3566
+ $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw+$xadj)*_MPDFK,($this->h-$boxbottom-$bbw/6)*_MPDFK,($this->x+$w+$rbw-$short-$xadj2)*_MPDFK,($this->h-$boxbottom-$bbw/6)*_MPDFK);
3567
+ $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$boxbottom-$bbw*5/6)*_MPDFK,($this->x+$w+$rbw-$short)*_MPDFK,($this->h-$boxbottom-$bbw*5/6)*_MPDFK);
3568
+ }
3569
+ else {
3570
+ $s.=sprintf(' %s %.3F w ',$c,$bbw*_MPDFK);
3571
+ $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$boxbottom-$bbw/2)*_MPDFK,($this->x+$w+$rbw-$short)*_MPDFK,($this->h-$boxbottom-$bbw/2)*_MPDFK);
3572
+ }
3573
+ }
3574
+ if($lbw) {
3575
+ $short = 0;
3576
+ if ($this->spanborddet['L']['style'] == 'dashed') {
3577
+ $s.=sprintf(' 0 j 0 J [%.3F %.3F] 0 d ',$lbw*$dashon*_MPDFK,$lbw*$dashoff*_MPDFK);
3578
+ }
3579
+ else if ($this->spanborddet['L']['style'] == 'dotted') {
3580
+ $s.=sprintf(' 1 j 1 J [%.3F %.3F] %.3F d ',0.001,$lbw*$dot*_MPDFK,-$lbw/2*_MPDFK);
3581
+ $short = $lbw/2;
3582
+ }
3583
+ else {
3584
+ $s.=' 0 j 0 J [] 0 d ';
3585
+ }
3586
+ $c = $this->SetDColor($this->spanborddet['L']['c'],true);
3587
+ if ($this->spanborddet['L']['style'] == 'double') {
3588
+ $s.=sprintf(' %s %.3F w ',$c,$lbw/3*_MPDFK);
3589
+ $yadj = $yadj2 = 0;
3590
+ if ($this->spanborddet['T']['style'] == 'double') { $yadj = $this->spanborddet['T']['w']*2/3; }
3591
+ if ($this->spanborddet['B']['style'] == 'double') { $yadj2 = $this->spanborddet['B']['w']*2/3; }
3592
+ $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw/6)*_MPDFK,($this->h-$boxtop+$tbw-$yadj)*_MPDFK,($this->x-$lbw/6)*_MPDFK,($this->h-$boxbottom-$bbw+$short+$yadj2)*_MPDFK);
3593
+ $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw*5/6)*_MPDFK,($this->h-$boxtop+$tbw)*_MPDFK,($this->x-$lbw*5/6)*_MPDFK,($this->h-$boxbottom-$bbw+$short)*_MPDFK);
3594
+ }
3595
+ else {
3596
+ $s.=sprintf(' %s %.3F w ',$c,$lbw*_MPDFK);
3597
+ $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw/2)*_MPDFK,($this->h-$boxtop+$tbw)*_MPDFK,($this->x-$lbw/2)*_MPDFK,($this->h-$boxbottom-$bbw+$short)*_MPDFK);
3598
+ }
3599
+ }
3600
+ if($rbw) {
3601
+ $short = 0;
3602
+ if ($this->spanborddet['R']['style'] == 'dashed') {
3603
+ $s.=sprintf(' 0 j 0 J [%.3F %.3F] 0 d ',$rbw*$dashon*_MPDFK,$rbw*$dashoff*_MPDFK);
3604
+ }
3605
+ else if ($this->spanborddet['R']['style'] == 'dotted') {
3606
+ $s.=sprintf(' 1 j 1 J [%.3F %.3F] %.3F d ',0.001,$rbw*$dot*_MPDFK,-$rbw/2*_MPDFK);
3607
+ $short = $rbw/2;
3608
+ }
3609
+ else {
3610
+ $s.=' 0 j 0 J [] 0 d ';
3611
+ }
3612
+ $c = $this->SetDColor($this->spanborddet['R']['c'],true);
3613
+ if ($this->spanborddet['R']['style'] == 'double') {
3614
+ $s.=sprintf(' %s %.3F w ',$c,$rbw/3*_MPDFK);
3615
+ $yadj = $yadj2 = 0;
3616
+ if ($this->spanborddet['T']['style'] == 'double') { $yadj = $this->spanborddet['T']['w']*2/3; }
3617
+ if ($this->spanborddet['B']['style'] == 'double') { $yadj2 = $this->spanborddet['B']['w']*2/3; }
3618
+ $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x+$w+$rbw/6)*_MPDFK,($this->h-$boxtop+$tbw-$yadj)*_MPDFK,($this->x+$w+$rbw/6)*_MPDFK,($this->h-$boxbottom-$bbw+$short+$yadj2)*_MPDFK);
3619
+ $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x+$w+$rbw*5/6)*_MPDFK,($this->h-$boxtop+$tbw)*_MPDFK,($this->x+$w+$rbw*5/6)*_MPDFK,($this->h-$boxbottom-$bbw+$short)*_MPDFK);
3620
+ }
3621
+ else {
3622
+ $s.=sprintf(' %s %.3F w ',$c,$rbw*_MPDFK);
3623
+ $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x+$w+$rbw/2)*_MPDFK,($this->h-$boxtop+$tbw)*_MPDFK,($this->x+$w+$rbw/2)*_MPDFK,($this->h-$boxbottom-$bbw+$short)*_MPDFK);
3624
+ }
3625
+ }
3626
+ $s.= ' Q ';
3627
+ }
3628
+ else {
3629
+ if ($fill==1) $op=($border==1) ? 'B' : 'f';
3630
+ else $op='S';
3631
+ $s.=sprintf('%.3F %.3F %.3F %.3F re %s ',$this->x*_MPDFK,($this->h-$boxtop)*_MPDFK,$w*_MPDFK,-$boxheight*_MPDFK,$op);
3632
+ }
3633
+ }
3634
+
3635
+ if(is_string($border)) {
3636
+ $x=$this->x;
3637
+ $y=$this->y;
3638
+ if(is_int(strpos($border,'L')))
3639
+ $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',$x*_MPDFK,($this->h-$boxtop)*_MPDFK,$x*_MPDFK,($this->h-($boxbottom))*_MPDFK);
3640
+ if(is_int(strpos($border,'T')))
3641
+ $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',$x*_MPDFK,($this->h-$boxtop)*_MPDFK,($x+$w)*_MPDFK,($this->h-$boxtop)*_MPDFK);
3642
+ if(is_int(strpos($border,'R')))
3643
+ $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($x+$w)*_MPDFK,($this->h-$boxtop)*_MPDFK,($x+$w)*_MPDFK,($this->h-($boxbottom))*_MPDFK);
3644
+ if(is_int(strpos($border,'B')))
3645
+ $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',$x*_MPDFK,($this->h-($boxbottom))*_MPDFK,($x+$w)*_MPDFK,($this->h-($boxbottom))*_MPDFK);
3646
+ }
3647
+
3648
+ if($txt!='') {
3649
+ if ($exactWidth)
3650
+ $stringWidth = $w;
3651
+ else
3652
+ $stringWidth = $this->GetStringWidth($txt) + ( $this->charspacing * mb_strlen( $txt, $this->mb_enc ) / _MPDFK )
3653
+ + ( $this->ws * mb_substr_count( $txt, ' ', $this->mb_enc ) / _MPDFK );
3654
+
3655
+ // Set x OFFSET FOR PRINTING
3656
+ if($align=='R') {
3657
+ $dx=$w-$this->cMarginR - $stringWidth - $lcpaddingR;
3658
+ }
3659
+ elseif($align=='C') {
3660
+ $dx=(($w - $stringWidth )/2);
3661
+ }
3662
+ elseif($align=='L' or $align=='J') $dx=$this->cMarginL + $lcpaddingL;
3663
+ else $dx = 0;
3664
+
3665
+ if($this->ColorFlag) $s .='q '.$this->TextColor.' ';
3666
+
3667
+ // OUTLINE
3668
+ if($this->textparam['outline-s'] && !$this->S) { // mPDF 5.6.07
3669
+ $s .=' '.sprintf('%.3F w',$this->LineWidth*_MPDFK).' ';
3670
+ $s .=" $this->DrawColor ";
3671
+ $s .=" 2 Tr ";
3672
+ }
3673
+ else if ($this->falseBoldWeight && strpos($this->ReqFontStyle,"B") !== false && strpos($this->FontStyle,"B") === false && !$this->S) { // can't use together with OUTLINE or Small Caps
3674
+ $s .= ' 2 Tr 1 J 1 j ';
3675
+ $s .= ' '.sprintf('%.3F w',($this->FontSize/130)*_MPDFK*$this->falseBoldWeight).' ';
3676
+ $tc = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
3677
+ if($this->FillColor!=$tc) { $s .= ' '.$tc.' '; } // stroke (outline) = same colour as text(fill)
3678
+ }
3679
+ else { $s .=" 0 Tr "; } // mPDF 5.6.07
3680
+
3681
+ if (strpos($this->ReqFontStyle,"I") !== false && strpos($this->FontStyle,"I") === false) { // Artificial italic
3682
+ $aix = '1 0 0.261799 1 %.3F %.3F Tm ';
3683
+ }
3684
+ else { $aix = '%.3F %.3F Td '; }
3685
+
3686
+ // THE TEXT
3687
+ $sub = '';
3688
+ $this->CurrentFont['used']= true;
3689
+
3690
+ // WORD SPACING
3691
+ // IF multibyte - Tw has no effect - need to use alternative method - do word spacing using an adjustment before each space
3692
+ if ($this->ws && !$this->usingCoreFont && !$this->CurrentFont['sip'] && !$this->CurrentFont['smp'] && !$this->S) {
3693
+ $sub .= ' BT 0 Tw ET ';
3694
+ if ($this->kerning && $this->useKerning) { $sub .= $this->_kern($txt, 'MBTw', $aix, ($this->x+$dx), ($this->y+$baseline+$va)); }
3695
+ else {
3696
+ $space = " ";
3697
+ //Convert string to UTF-16BE without BOM
3698
+ $space= $this->UTF8ToUTF16BE($space , false);
3699
+ $space=$this->_escape($space );
3700
+ $sub .=sprintf('BT '.$aix,($this->x+$dx)*_MPDFK,($this->h-($this->y+$baseline+$va))*_MPDFK);
3701
+ $t = explode(' ',$txt);
3702
+ $sub .=sprintf(' %.3F Tc [',$this->charspacing);
3703
+ $numt = count($t);
3704
+ for($i=0;$i<$numt;$i++) {
3705
+ $tx = $t[$i];
3706
+ //Convert string to UTF-16BE without BOM
3707
+ $tx = $this->UTF8ToUTF16BE($tx , false);
3708
+ $tx = $this->_escape($tx);
3709
+ $sub .=sprintf('(%s) ',$tx);
3710
+ if (($i+1)<$numt) {
3711
+ $adj = -($this->ws)*1000/$this->FontSizePt;
3712
+ $sub .=sprintf('%d(%s) ',$adj,$space);
3713
+ }
3714
+ }
3715
+ $sub .='] TJ ';
3716
+ $sub .=' ET';
3717
+ }
3718
+ }
3719
+ else {
3720
+ $txt2= $txt;
3721
+ if ($this->CurrentFont['type']=='TTF' && ($this->CurrentFont['sip'] || $this->CurrentFont['smp'])) {
3722
+ if ($this->S) { $sub .= $this->_smallCaps($txt2, 'SIPSMP', $aix, $dx, _MPDFK, $baseline, $va); }
3723
+ else {
3724
+ $txt2 = $this->UTF8toSubset($txt2);
3725
+ $sub .=sprintf('BT '.$aix.' %s Tj ET',($this->x+$dx)*_MPDFK,($this->h-($this->y+$baseline+$va))*_MPDFK,$txt2);
3726
+ }
3727
+ }
3728
+ else {
3729
+ if ($this->S) { $sub .= $this->_smallCaps($txt2, '', $aix, $dx, _MPDFK, $baseline, $va); }
3730
+ else if ($this->kerning && $this->useKerning) { $sub .= $this->_kern($txt2, '', $aix, ($this->x+$dx), ($this->y+$baseline+$va)); }
3731
+ else {
3732
+ if (!$this->usingCoreFont) {
3733
+ $txt2 = $this->UTF8ToUTF16BE($txt2, false);
3734
+ }
3735
+ $txt2=$this->_escape($txt2);
3736
+ $sub .=sprintf('BT '.$aix.' (%s) Tj ET',($this->x+$dx)*_MPDFK,($this->h-($this->y+$baseline+$va))*_MPDFK,$txt2);
3737
+ }
3738
+ }
3739
+ }
3740
+ // UNDERLINE
3741
+ if($this->U) {
3742
+ $c = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
3743
+ if($this->FillColor!=$c) { $sub .= ' '.$c.' '; }
3744
+ if (isset($this->CurrentFont['up'])) { $up=$this->CurrentFont['up']; }
3745
+ else { $up = -100; }
3746
+ $adjusty = (-$up/1000* $this->FontSize);
3747
+ if (isset($this->CurrentFont['ut'])) { $ut=$this->CurrentFont['ut']/1000* $this->FontSize; }
3748
+ else { $ut = 60/1000* $this->FontSize; }
3749
+ $olw = $this->LineWidth;
3750
+ $sub .=' '.(sprintf(' %.3F w 0 j 0 J ',$ut*_MPDFK));
3751
+ $sub .=' '.$this->_dounderline($this->x+$dx,$this->y+$baseline+$va+$adjusty,$txt);
3752
+ $sub .=' '.(sprintf(' %.3F w 2 j 2 J ',$olw*_MPDFK));
3753
+ if($this->FillColor!=$c) { $sub .= ' '.$this->FillColor.' '; }
3754
+ }
3755
+
3756
+ // STRIKETHROUGH
3757
+ if($this->strike) {
3758
+ $c = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
3759
+ if($this->FillColor!=$c) { $sub .= ' '.$c.' '; }
3760
+ //Superscript and Subscript Y coordinate adjustment (now for striked-through texts)
3761
+ if (isset($this->CurrentFont['desc']['CapHeight'])) { $ch=$this->CurrentFont['desc']['CapHeight']; }
3762
+ else { $ch = 700; }
3763
+ $adjusty = (-$ch/1000* $this->FontSize) * 0.35;
3764
+ if (isset($this->CurrentFont['ut'])) { $ut=$this->CurrentFont['ut']/1000* $this->FontSize; }
3765
+ else { $ut = 60/1000* $this->FontSize; }
3766
+ $olw = $this->LineWidth;
3767
+ $sub .=' '.(sprintf(' %.3F w 0 j 0 J ',$ut*_MPDFK));
3768
+ $sub .=' '.$this->_dounderline($this->x+$dx,$this->y+$baseline+$va+$adjusty,$txt);
3769
+ $sub .=' '.(sprintf(' %.3F w 2 j 2 J ',$olw*_MPDFK));
3770
+ if($this->FillColor!=$c) { $sub .= ' '.$this->FillColor.' '; }
3771
+ }
3772
+
3773
+ // TEXT SHADOW
3774
+ if ($this->textshadow) { // First to process is last in CSS comma separated shadows
3775
+ foreach($this->textshadow AS $ts) {
3776
+ $s .= ' q ';
3777
+ $s .= $this->SetTColor($ts['col'], true)."\n";
3778
+ if ($ts['col']{0}==5 && ord($ts['col']{4})<100) { // RGBa
3779
+ $s .= $this->SetAlpha(ord($ts['col']{4})/100, 'Normal', true, 'F')."\n";
3780
+ }
3781
+ else if ($ts['col']{0}==6 && ord($ts['col']{5})<100) { // CMYKa
3782
+ $s .= $this->SetAlpha(ord($ts['col']{5})/100, 'Normal', true, 'F')."\n";
3783
+ }
3784
+ else if ($ts['col']{0}==1 && $ts['col']{2}==1 && ord($ts['col']{3})<100) { // Gray
3785
+ $s .= $this->SetAlpha(ord($ts['col']{3})/100, 'Normal', true, 'F')."\n";
3786
+ }
3787
+ $s .= sprintf(' 1 0 0 1 %.4F %.4F cm', $ts['x']*_MPDFK, -$ts['y']*_MPDFK)."\n";
3788
+ $s .= $sub;
3789
+ $s .= ' Q ';
3790
+ }
3791
+ }
3792
+
3793
+ $s .= $sub;
3794
+
3795
+ // COLOR
3796
+ if($this->ColorFlag) $s .=' Q';
3797
+
3798
+ // LINK
3799
+ if($link!='') {
3800
+ $this->Link($this->x,$boxtop,$w,$boxheight,$link);
3801
+ }
3802
+ }
3803
+ if($s) $this->_out($s);
3804
+
3805
+ // WORD SPACING
3806
+ if ($this->ws && !$this->usingCoreFont) {
3807
+ $this->_out(sprintf('BT %.3F Tc ET',$this->charspacing));
3808
+ }
3809
+ $this->lasth=$h;
3810
+ if( strpos($txt,"\n") !== false) $ln=1; // cell recognizes \n from <BR> tag
3811
+ if($ln>0)
3812
+ {
3813
+ //Go to next line
3814
+ $this->y += $h;
3815
+ if($ln==1) {
3816
+ //Move to next line
3817
+ if ($currentx != 0) { $this->x=$currentx; }
3818
+ else { $this->x=$this->lMargin; }
3819
+ }
3820
+ }
3821
+ else $this->x+=$w;
3822
+
3823
+
3824
+ }
3825
+
3826
+
3827
+ function _kern($txt, $mode, $aix, $x, $y) {
3828
+ if ($mode == 'MBTw') { // Multibyte requiring word spacing
3829
+ $space = ' ';
3830
+ //Convert string to UTF-16BE without BOM
3831
+ $space= $this->UTF8ToUTF16BE($space , false);
3832
+ $space=$this->_escape($space );
3833
+ $s = sprintf(' BT '.$aix,$x*_MPDFK,($this->h-$y)*_MPDFK);
3834
+ $t = explode(' ',$txt);
3835
+ for($i=0;$i<count($t);$i++) {
3836
+ $tx = $t[$i];
3837
+
3838
+ $tj = '(';
3839
+ $unicode = $this->UTF8StringToArray($tx);
3840
+ for($ti=0;$ti<count($unicode);$ti++) {
3841
+ if ($ti > 0 && isset($this->CurrentFont['kerninfo'][$unicode[($ti-1)]][$unicode[$ti]])) {
3842
+ $kern = -$this->CurrentFont['kerninfo'][$unicode[($ti-1)]][$unicode[$ti]];
3843
+ $tj .= sprintf(')%d(',$kern);
3844
+ }
3845
+ $tc = code2utf($unicode[$ti]);
3846
+ $tc = $this->UTF8ToUTF16BE($tc, false);
3847
+ $tj .= $this->_escape($tc);
3848
+ }
3849
+ $tj .= ')';
3850
+ $s.=sprintf(' %.3F Tc [%s] TJ',$this->charspacing,$tj);
3851
+
3852
+
3853
+ if (($i+1)<count($t)) {
3854
+ $s.=sprintf(' %.3F Tc (%s) Tj',$this->ws+$this->charspacing,$space);
3855
+ }
3856
+ }
3857
+ $s.=' ET ';
3858
+ }
3859
+ else if (!$this->usingCoreFont) {
3860
+ $s = '';
3861
+ $tj = '(';
3862
+ $unicode = $this->UTF8StringToArray($txt);
3863
+ for($i=0;$i<count($unicode);$i++) {
3864
+ if ($i > 0 && isset($this->CurrentFont['kerninfo'][$unicode[($i-1)]][$unicode[$i]])) {
3865
+ $kern = -$this->CurrentFont['kerninfo'][$unicode[($i-1)]][$unicode[$i]];
3866
+ $tj .= sprintf(')%d(',$kern);
3867
+ }
3868
+ $tx = code2utf($unicode[$i]);
3869
+ $tx = $this->UTF8ToUTF16BE($tx, false);
3870
+ $tj .= $this->_escape($tx);
3871
+ }
3872
+ $tj .= ')';
3873
+ $s.=sprintf(' BT '.$aix.' [%s] TJ ET ',$x*_MPDFK,($this->h-$y)*_MPDFK,$tj);
3874
+ }
3875
+ else { // CORE Font
3876
+ $s = '';
3877
+ $tj = '(';
3878
+ $l = strlen($txt);
3879
+ for($i=0;$i<$l;$i++) {
3880
+ if ($i > 0 && isset($this->CurrentFont['kerninfo'][$txt[($i-1)]][$txt[$i]])) {
3881
+ $kern = -$this->CurrentFont['kerninfo'][$txt[($i-1)]][$txt[$i]];
3882
+ $tj .= sprintf(')%d(',$kern);
3883
+ }
3884
+ $tj .= $this->_escape($txt[$i]);
3885
+ }
3886
+ $tj .= ')';
3887
+ $s.=sprintf(' BT '.$aix.' [%s] TJ ET ',$x*_MPDFK,($this->h-$y)*_MPDFK,$tj);
3888
+ }
3889
+
3890
+ return $s;
3891
+ }
3892
+
3893
+
3894
+ function _smallCaps($txt, $mode, $aix, $dx, $k, $baseline, $va) {
3895
+ $upp = false;
3896
+ $str = array();
3897
+ $bits = array();
3898
+ if (!$this->usingCoreFont) {
3899
+ $unicode = $this->UTF8StringToArray($txt);
3900
+ foreach($unicode as $char) {
3901
+ if ($this->ws && $char == 32) { // space
3902
+ if (count($str)) { $bits[] = array($upp, $str, false); }
3903
+ $bits[] = array(false, array(32), true);
3904
+ $str = array();
3905
+ $upp = false;
3906
+ }
3907
+ else if (isset($this->upperCase[$char])) {
3908
+ if (!$upp) {
3909
+ if (count($str)) { $bits[] = array($upp, $str, false); }
3910
+ $str = array();
3911
+ }
3912
+ $str[] = $this->upperCase[$char];
3913
+ if ((!isset($this->CurrentFont['sip']) || !$this->CurrentFont['sip']) && (!isset($this->CurrentFont['smp']) || !$this->CurrentFont['smp'])) {
3914
+ $this->CurrentFont['subset'][$this->upperCase[$char]] = $this->upperCase[$char];
3915
+ }
3916
+ $upp = true;
3917
+ }
3918
+ else {
3919
+ if ($upp) {
3920
+ if (count($str)) { $bits[] = array($upp, $str, false); }
3921
+ $str = array();
3922
+ }
3923
+ $str[] = $char;
3924
+ $upp = false;
3925
+ }
3926
+ }
3927
+ }
3928
+ else {
3929
+ for($i=0;$i<strlen($txt);$i++) {
3930
+ if (isset($this->upperCase[ord($txt[$i])]) && $this->upperCase[ord($txt[$i])] < 256) {
3931
+ if (!$upp) {
3932
+ if (count($str)) { $bits[] = array($upp, $str, false); }
3933
+ $str = array();
3934
+ }
3935
+ $str[] = $this->upperCase[ord($txt[$i])];
3936
+ $upp = true;
3937
+ }
3938
+ else {
3939
+ if ($upp) {
3940
+ if (count($str)) { $bits[] = array($upp, $str, false); }
3941
+ $str = array();
3942
+ }
3943
+ $str[] = ord($txt[$i]);
3944
+ $upp = false;
3945
+ }
3946
+ }
3947
+ }
3948
+ if (count($str)) { $bits[] = array($upp, $str, false); }
3949
+
3950
+ $fid = $this->CurrentFont['i'];
3951
+
3952
+ $s=sprintf(' BT '.$aix,($this->x+$dx)*$k,($this->h-($this->y+$baseline+$va))*$k);
3953
+ foreach($bits AS $b) {
3954
+ if ($b[0]) { $upp = true; }
3955
+ else { $upp = false; }
3956
+
3957
+ $size = count ($b[1]);
3958
+ $txt = '';
3959
+ for ($i = 0; $i < $size; $i++) {
3960
+ $txt .= code2utf($b[1][$i]);
3961
+ }
3962
+ if ($this->usingCoreFont) {
3963
+ $txt = utf8_decode($txt);
3964
+ }
3965
+ if ($mode == 'SIPSMP') {
3966
+ $txt = $this->UTF8toSubset($txt);
3967
+ }
3968
+ else {
3969
+ if (!$this->usingCoreFont) {
3970
+ $txt = $this->UTF8ToUTF16BE($txt, false);
3971
+ }
3972
+ $txt=$this->_escape($txt);
3973
+ $txt = '('.$txt.')';
3974
+ }
3975
+ if ($b[2]) { // space
3976
+ $s.=sprintf(' /F%d %.3F Tf %d Tz', $fid, $this->FontSizePt, 100);
3977
+ $s.=sprintf(' %.3F Tc', ($this->charspacing+$this->ws));
3978
+ $s.=sprintf(' %s Tj', $txt);
3979
+ }
3980
+ else if ($upp) {
3981
+ $s.=sprintf(' /F%d %.3F Tf', $fid, $this->FontSizePt*$this->smCapsScale);
3982
+ $s.=sprintf(' %d Tz', $this->smCapsStretch);
3983
+ $s.=sprintf(' %.3F Tc', ($this->charspacing*100/$this->smCapsStretch));
3984
+ $s.=sprintf(' %s Tj', $txt);
3985
+ }
3986
+ else {
3987
+ $s.=sprintf(' /F%d %.3F Tf %d Tz', $fid, $this->FontSizePt, 100);
3988
+ $s.=sprintf(' %.3F Tc', ($this->charspacing));
3989
+ $s.=sprintf(' %s Tj', $txt);
3990
+ }
3991
+ }
3992
+ $s.=' ET ';
3993
+ return $s;
3994
+ }
3995
+
3996
+
3997
+ function MultiCell($w,$h,$txt,$border=0,$align='',$fill=0,$link='',$directionality='ltr',$encoded=false)
3998
+ {
3999
+ // Parameter (pre-)encoded - When called internally from ToC or textarea: mb_encoding already done - but not reverse RTL/Indic
4000
+ if (!$encoded) {
4001
+ $txt = $this->purify_utf8_text($txt);
4002
+ if ($this->text_input_as_HTML) {
4003
+ $txt = $this->all_entities_to_utf8($txt);
4004
+ }
4005
+ if ($this->usingCoreFont) { $txt = mb_convert_encoding($txt,$this->mb_enc,'UTF-8'); }
4006
+ // Font-specific ligature substitution for Indic fonts
4007
+ }
4008
+ if (!$align) { $align = $this->defaultAlign; }
4009
+
4010
+ //Output text with automatic or explicit line breaks
4011
+ $cw=&$this->CurrentFont['cw'];
4012
+ if($w==0) $w=$this->w-$this->rMargin-$this->x;
4013
+
4014
+ $wmax = ($w - ($this->cMarginL+$this->cMarginR));
4015
+ if ($this->usingCoreFont) {
4016
+ $s=str_replace("\r",'',$txt);
4017
+ $nb=strlen($s);
4018
+ while($nb>0 and $s[$nb-1]=="\n") $nb--;
4019
+ }
4020
+ else {
4021
+ $s=str_replace("\r",'',$txt);
4022
+ $nb=mb_strlen($s, $this->mb_enc );
4023
+ while($nb>0 and mb_substr($s,$nb-1,1,$this->mb_enc )=="\n") $nb--;
4024
+ }
4025
+ $b=0;
4026
+ if($border) {
4027
+ if($border==1) {
4028
+ $border='LTRB';
4029
+ $b='LRT';
4030
+ $b2='LR';
4031
+ }
4032
+ else {
4033
+ $b2='';
4034
+ if(is_int(strpos($border,'L'))) $b2.='L';
4035
+ if(is_int(strpos($border,'R'))) $b2.='R';
4036
+ $b=is_int(strpos($border,'T')) ? $b2.'T' : $b2;
4037
+ }
4038
+ }
4039
+ $sep=-1;
4040
+ $i=0;
4041
+ $j=0;
4042
+ $l=0;
4043
+ $ns=0;
4044
+ $nl=1;
4045
+
4046
+
4047
+
4048
+ if (!$this->usingCoreFont) {
4049
+ $checkCursive=false;
4050
+ if ($this->biDirectional) { $checkCursive=true; }
4051
+ while($i<$nb) {
4052
+ //Get next character
4053
+ $c = mb_substr($s,$i,1,$this->mb_enc );
4054
+ if($c == "\n") {
4055
+ //Explicit line break
4056
+ // WORD SPACING
4057
+ $this->ResetSpacing();
4058
+ $tmp = rtrim(mb_substr($s,$j,$i-$j,$this->mb_enc));
4059
+ // DIRECTIONALITY
4060
+
4061
+ $this->Cell($w,$h,$tmp,$b,2,$align,$fill,$link);
4062
+ $i++;
4063
+ $sep=-1;
4064
+ $j=$i;
4065
+ $l=0;
4066
+ $ns=0;
4067
+ $nl++;
4068
+ if($border and $nl==2) $b=$b2;
4069
+ continue;
4070
+ }
4071
+ if($c == " ") {
4072
+ $sep=$i;
4073
+ $ls=$l;
4074
+ $ns++;
4075
+ }
4076
+
4077
+ $l += $this->GetCharWidthNonCore($c);
4078
+
4079
+ if($l>$wmax) {
4080
+ //Automatic line break
4081
+ if($sep==-1) { // Only one word
4082
+ if($i==$j) $i++;
4083
+ // WORD SPACING
4084
+ $this->ResetSpacing();
4085
+ $tmp = rtrim(mb_substr($s,$j,$i-$j,$this->mb_enc));
4086
+ // DIRECTIONALITY
4087
+
4088
+ $this->Cell($w,$h,$tmp,$b,2,$align,$fill,$link);
4089
+ }
4090
+ else {
4091
+ $tmp = rtrim(mb_substr($s,$j,$sep-$j,$this->mb_enc));
4092
+ if($align=='J') {
4093
+ //////////////////////////////////////////
4094
+ // JUSTIFY J using Unicode fonts (Word spacing doesn't work)
4095
+ // WORD SPACING UNICODE
4096
+ // Change NON_BREAKING SPACE to spaces so they are 'spaced' properly
4097
+ $tmp = str_replace(chr(194).chr(160),chr(32),$tmp );
4098
+ $len_ligne = $this->GetStringWidth($tmp );
4099
+ $nb_carac = mb_strlen( $tmp , $this->mb_enc ) ;
4100
+ $nb_spaces = mb_substr_count( $tmp ,' ', $this->mb_enc ) ;
4101
+
4102
+ $inclCursive=false;
4103
+ if ($checkCursive) {
4104
+ }
4105
+ list($charspacing,$ws) = $this->GetJspacing($nb_carac,$nb_spaces,((($wmax) - $len_ligne) * _MPDFK),$inclCursive);
4106
+ $this->SetSpacing($charspacing,$ws);
4107
+ //////////////////////////////////////////
4108
+ }
4109
+
4110
+ // DIRECTIONALITY
4111
+
4112
+ $this->Cell($w,$h,$tmp,$b,2,$align,$fill,$link);
4113
+ $i=$sep+1;
4114
+ }
4115
+ $sep=-1;
4116
+ $j=$i;
4117
+ $l=0;
4118
+ $ns=0;
4119
+ $nl++;
4120
+ if($border and $nl==2) $b=$b2;
4121
+ }
4122
+ else $i++;
4123
+ }
4124
+ //Last chunk
4125
+ // WORD SPACING
4126
+
4127
+ $this->ResetSpacing();
4128
+
4129
+ }
4130
+
4131
+
4132
+ else {
4133
+
4134
+ while($i<$nb) {
4135
+ //Get next character
4136
+ $c=$s[$i];
4137
+ if($c == "\n") {
4138
+ //Explicit line break
4139
+ // WORD SPACING
4140
+ $this->ResetSpacing();
4141
+ $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill,$link);
4142
+ $i++;
4143
+ $sep=-1;
4144
+ $j=$i;
4145
+ $l=0;
4146
+ $ns=0;
4147
+ $nl++;
4148
+ if($border and $nl==2) $b=$b2;
4149
+ continue;
4150
+ }
4151
+ if($c == " ") {
4152
+ $sep=$i;
4153
+ $ls=$l;
4154
+ $ns++;
4155
+ }
4156
+
4157
+ $l += $this->GetCharWidthCore($c);
4158
+ if($l>$wmax) {
4159
+ //Automatic line break
4160
+ if($sep==-1) {
4161
+ if($i==$j) $i++;
4162
+ // WORD SPACING
4163
+ $this->ResetSpacing();
4164
+ $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill,$link);
4165
+ }
4166
+ else {
4167
+ if($align=='J') {
4168
+ $tmp = rtrim(substr($s,$j,$sep-$j));
4169
+ //////////////////////////////////////////
4170
+ // JUSTIFY J using Unicode fonts (Word spacing doesn't work)
4171
+ // WORD SPACING NON_UNICDOE/CJK
4172
+ // Change NON_BREAKING SPACE to spaces so they are 'spaced' properly
4173
+ $tmp = str_replace(chr(160),chr(32),$tmp);
4174
+ $len_ligne = $this->GetStringWidth($tmp );
4175
+ $nb_carac = strlen( $tmp ) ;
4176
+ $nb_spaces = substr_count( $tmp ,' ' ) ;
4177
+ list($charspacing,$ws) = $this->GetJspacing($nb_carac,$nb_spaces,((($wmax) - $len_ligne) * _MPDFK),false);
4178
+ $this->SetSpacing($charspacing,$ws);
4179
+ //////////////////////////////////////////
4180
+ }
4181
+ $this->Cell($w,$h,substr($s,$j,$sep-$j),$b,2,$align,$fill,$link);
4182
+ $i=$sep+1;
4183
+ }
4184
+ $sep=-1;
4185
+ $j=$i;
4186
+ $l=0;
4187
+ $ns=0;
4188
+ $nl++;
4189
+ if($border and $nl==2) $b=$b2;
4190
+ }
4191
+ else $i++;
4192
+ }
4193
+ //Last chunk
4194
+ // WORD SPACING
4195
+
4196
+ $this->ResetSpacing();
4197
+
4198
+ }
4199
+ //Last chunk
4200
+ if($border and is_int(strpos($border,'B'))) $b.='B';
4201
+ if (!$this->usingCoreFont) {
4202
+ $tmp = rtrim(mb_substr($s,$j,$i-$j,$this->mb_enc));
4203
+ // DIRECTIONALITY
4204
+ $this->Cell($w,$h,$tmp,$b,2,$align,$fill,$link);
4205
+ }
4206
+ else { $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill,$link); }
4207
+ $this->x=$this->lMargin;
4208
+ }
4209
+
4210
+
4211
+ function Write($h,$txt,$currentx=0,$link='',$directionality='ltr',$align='') {
4212
+ if (!class_exists('directw', false)) { include(_MPDF_PATH.'classes/directw.php'); }
4213
+ if (empty($this->directw)) { $this->directw = new directw($this); }
4214
+ $this->directw->Write($h,$txt,$currentx,$link,$directionality,$align);
4215
+ }
4216
+
4217
+
4218
+ function saveInlineProperties() {
4219
+ $saved = array();
4220
+ $saved[ 'family' ] = $this->FontFamily;
4221
+ $saved[ 'style' ] = $this->FontStyle;
4222
+ $saved[ 'sizePt' ] = $this->FontSizePt;
4223
+ $saved[ 'size' ] = $this->FontSize;
4224
+ $saved[ 'HREF' ] = $this->HREF;
4225
+ $saved[ 'underline' ] = $this->U;
4226
+ $saved[ 'smCaps' ] = $this->S;
4227
+ $saved[ 'strike' ] = $this->strike;
4228
+ $saved[ 'textshadow' ] = $this->textshadow;
4229
+ $saved[ 'SUP' ] = $this->SUP;
4230
+ $saved[ 'SUB' ] = $this->SUB;
4231
+ $saved[ 'linewidth' ] = $this->LineWidth;
4232
+ $saved[ 'drawcolor' ] = $this->DrawColor;
4233
+ $saved[ 'textparam' ] = $this->textparam;
4234
+ $saved[ 'toupper' ] = $this->toupper;
4235
+ $saved[ 'tolower' ] = $this->tolower;
4236
+ $saved[ 'capitalize' ] = $this->capitalize;
4237
+ $saved[ 'fontkerning' ] = $this->kerning;
4238
+ $saved[ 'lSpacingCSS' ] = $this->lSpacingCSS;
4239
+ $saved[ 'wSpacingCSS' ] = $this->wSpacingCSS;
4240
+ $saved[ 'I' ] = $this->I;
4241
+ $saved[ 'B' ] = $this->B;
4242
+ $saved[ 'colorarray' ] = $this->colorarray;
4243
+ $saved[ 'bgcolorarray' ] = $this->spanbgcolorarray;
4244
+ $saved[ 'border' ] = $this->spanborddet;
4245
+ $saved[ 'color' ] = $this->TextColor;
4246
+ $saved[ 'bgcolor' ] = $this->FillColor;
4247
+ $saved[ 'lang' ] = $this->currentLang;
4248
+ $saved[ 'display_off' ] = $this->inlineDisplayOff;
4249
+
4250
+ return $saved;
4251
+ }
4252
+
4253
+ function restoreInlineProperties( &$saved) {
4254
+ $FontFamily = $saved[ 'family' ];
4255
+ $this->FontStyle = $saved[ 'style' ];
4256
+ $this->FontSizePt = $saved[ 'sizePt' ];
4257
+ $this->FontSize = $saved[ 'size' ];
4258
+
4259
+ $this->currentLang = $saved['lang'];
4260
+ if ($this->useLang && !$this->usingCoreFont) {
4261
+ if ($this->currentLang != $this->default_lang && ((strlen($this->currentLang) == 5 && $this->currentLang != 'UTF-8') || strlen($this->currentLang ) == 2)) {
4262
+ list ($coreSuitable,$mpdf_pdf_unifonts) = GetLangOpts($this->currentLang, $this->useAdobeCJK);
4263
+ if ($mpdf_pdf_unifonts) { $this->RestrictUnicodeFonts($mpdf_pdf_unifonts); }
4264
+ else { $this->RestrictUnicodeFonts($this->default_available_fonts ); }
4265
+ }
4266
+ else {
4267
+ $this->RestrictUnicodeFonts($this->default_available_fonts );
4268
+ }
4269
+ }
4270
+
4271
+ $this->ColorFlag = ($this->FillColor != $this->TextColor); //Restore ColorFlag as well
4272
+
4273
+ $this->HREF = $saved[ 'HREF' ];
4274
+ $this->U = $saved[ 'underline' ];
4275
+ $this->S = $saved[ 'smCaps' ];
4276
+ $this->strike = $saved[ 'strike' ];
4277
+ $this->textshadow = $saved[ 'textshadow' ];
4278
+ $this->SUP = $saved[ 'SUP' ];
4279
+ $this->SUB = $saved[ 'SUB' ];
4280
+ $this->LineWidth = $saved[ 'linewidth' ];
4281
+ $this->DrawColor = $saved[ 'drawcolor' ];
4282
+ $this->textparam = $saved[ 'textparam' ];
4283
+ $this->inlineDisplayOff = $saved['display_off'];
4284
+
4285
+ $this->toupper = $saved[ 'toupper' ];
4286
+ $this->tolower = $saved[ 'tolower' ];
4287
+ $this->capitalize = $saved[ 'capitalize' ];
4288
+ $this->kerning = $saved[ 'fontkerning' ];
4289
+ $this->lSpacingCSS = $saved[ 'lSpacingCSS' ];
4290
+ if (($this->lSpacingCSS || $this->lSpacingCSS==='0') && strtoupper($this->lSpacingCSS) != 'NORMAL') {
4291
+ $this->fixedlSpacing = $this->ConvertSize($this->lSpacingCSS,$this->FontSize);
4292
+ }
4293
+ else { $this->fixedlSpacing = false; }
4294
+ $this->wSpacingCSS = $saved[ 'wSpacingCSS' ];
4295
+ if ($this->wSpacingCSS && strtoupper($this->wSpacingCSS) != 'NORMAL') {
4296
+ $this->minwSpacing = $this->ConvertSize($this->wSpacingCSS,$this->FontSize);
4297
+ }
4298
+ else { $this->minwSpacing = 0; }
4299
+
4300
+ $this->SetFont($FontFamily, $saved[ 'style' ].($this->U ? 'U' : '').($this->S ? 'S' : ''),$saved[ 'sizePt' ],false);
4301
+
4302
+ $this->currentfontstyle = $saved[ 'style' ].($this->U ? 'U' : '').($this->S ? 'S' : '');
4303
+ $this->currentfontsize = $saved[ 'sizePt' ];
4304
+ $this->SetStylesArray(array('S'=>$this->S, 'U'=>$this->U, 'B'=>$saved[ 'B' ], 'I'=>$saved[ 'I' ]));
4305
+
4306
+ $this->TextColor = $saved[ 'color' ];
4307
+ $this->FillColor = $saved[ 'bgcolor' ];
4308
+ $this->colorarray = $saved[ 'colorarray' ];
4309
+ $cor = $saved[ 'colorarray' ];
4310
+ if ($cor) $this->SetTColor($cor);
4311
+ $this->spanbgcolorarray = $saved[ 'bgcolorarray' ];
4312
+ $cor = $saved[ 'bgcolorarray' ];
4313
+ if ($cor) $this->SetFColor($cor);
4314
+ $this->spanborddet = $saved[ 'border' ];
4315
+ }
4316
+
4317
+
4318
+
4319
+ // Used when ColActive for tables - updated to return first block with background fill OR borders
4320
+ function GetFirstBlockFill() {
4321
+ // Returns the first blocklevel that uses a bgcolor fill
4322
+ $startfill = 0;
4323
+ for ($i=1;$i<=$this->blklvl;$i++) {
4324
+ if ($this->blk[$i]['bgcolor'] || $this->blk[$i]['border_left']['w'] || $this->blk[$i]['border_right']['w'] || $this->blk[$i]['border_top']['w'] || $this->blk[$i]['border_bottom']['w'] ) {
4325
+ $startfill = $i;
4326
+ break;
4327
+ }
4328
+ }
4329
+ return $startfill;
4330
+ }
4331
+
4332
+ function SetBlockFill($blvl) {
4333
+ if ($this->blk[$blvl]['bgcolor']) {
4334
+ $this->SetFColor($this->blk[$blvl]['bgcolorarray']);
4335
+ return 1;
4336
+ }
4337
+ else {
4338
+ $this->SetFColor($this->ConvertColor(255));
4339
+ return 0;
4340
+ }
4341
+ }
4342
+
4343
+
4344
+ //-------------------------FLOWING BLOCK------------------------------------//
4345
+ //The following functions were originally written by Damon Kohler //
4346
+ //--------------------------------------------------------------------------//
4347
+
4348
+ function saveFont() {
4349
+ $saved = array();
4350
+ $saved[ 'family' ] = $this->FontFamily;
4351
+ $saved[ 'style' ] = $this->FontStyle;
4352
+ $saved[ 'sizePt' ] = $this->FontSizePt;
4353
+ $saved[ 'size' ] = $this->FontSize;
4354
+ $saved[ 'curr' ] = &$this->CurrentFont;
4355
+ $saved[ 'color' ] = $this->TextColor;
4356
+ $saved[ 'spanbgcolor' ] = $this->spanbgcolor;
4357
+ $saved[ 'spanbgcolorarray' ] = $this->spanbgcolorarray;
4358
+ $saved[ 'bord' ] = $this->spanborder;
4359
+ $saved[ 'border' ] = $this->spanborddet;
4360
+ $saved[ 'HREF' ] = $this->HREF;
4361
+ $saved[ 'underline' ] = $this->U;
4362
+ $saved[ 'smCaps' ] = $this->S;
4363
+ $saved[ 'strike' ] = $this->strike;
4364
+ $saved[ 'textshadow' ] = $this->textshadow;
4365
+ $saved[ 'SUP' ] = $this->SUP;
4366
+ $saved[ 'SUB' ] = $this->SUB;
4367
+ $saved[ 'linewidth' ] = $this->LineWidth;
4368
+ $saved[ 'drawcolor' ] = $this->DrawColor;
4369
+ $saved[ 'textparam' ] = $this->textparam;
4370
+ $saved[ 'ReqFontStyle' ] = $this->ReqFontStyle;
4371
+ $saved[ 'fontkerning' ] = $this->kerning;
4372
+ $saved[ 'fixedlSpacing' ] = $this->fixedlSpacing;
4373
+ $saved[ 'minwSpacing' ] = $this->minwSpacing;
4374
+ return $saved;
4375
+ }
4376
+
4377
+ function restoreFont( &$saved, $write=true) {
4378
+ if (!isset($saved) || empty($saved)) return;
4379
+
4380
+ $this->FontFamily = $saved[ 'family' ];
4381
+ $this->FontStyle = $saved[ 'style' ];
4382
+ $this->FontSizePt = $saved[ 'sizePt' ];
4383
+ $this->FontSize = $saved[ 'size' ];
4384
+ $this->CurrentFont = &$saved[ 'curr' ];
4385
+ $this->TextColor = $saved[ 'color' ];
4386
+ $this->spanbgcolor = $saved[ 'spanbgcolor' ];
4387
+ $this->spanbgcolorarray = $saved[ 'spanbgcolorarray' ];
4388
+ $this->spanborder = $saved[ 'bord' ];
4389
+ $this->spanborddet = $saved[ 'border' ];
4390
+ $this->ColorFlag = ($this->FillColor != $this->TextColor); //Restore ColorFlag as well
4391
+ $this->HREF = $saved[ 'HREF' ];
4392
+ $this->U = $saved[ 'underline' ];
4393
+ $this->S = $saved[ 'smCaps' ];
4394
+ $this->kerning = $saved[ 'fontkerning' ];
4395
+ $this->fixedlSpacing = $saved[ 'fixedlSpacing' ];
4396
+ $this->minwSpacing = $saved[ 'minwSpacing' ];
4397
+ $this->strike = $saved[ 'strike' ];
4398
+ $this->textshadow = $saved[ 'textshadow' ];
4399
+ $this->SUP = $saved[ 'SUP' ];
4400
+ $this->SUB = $saved[ 'SUB' ];
4401
+ $this->LineWidth = $saved[ 'linewidth' ];
4402
+ $this->DrawColor = $saved[ 'drawcolor' ];
4403
+ $this->textparam = $saved[ 'textparam' ];
4404
+ if ($write) {
4405
+ $this->SetFont($saved[ 'family' ],$saved[ 'style' ].($this->U ? 'U' : '').($this->S ? 'S' : ''),$saved[ 'sizePt' ],true,true); // force output
4406
+ $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
4407
+ if($this->page>0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']) || $this->keep_block_together)) { $this->_out($fontout); }
4408
+ $this->pageoutput[$this->page]['Font'] = $fontout;
4409
+ }
4410
+ else
4411
+ $this->SetFont($saved[ 'family' ],$saved[ 'style' ].($this->U ? 'U' : '').($this->S ? 'S' : ''),$saved[ 'sizePt' ]);
4412
+ $this->ReqFontStyle = $saved[ 'ReqFontStyle' ];
4413
+ }
4414
+
4415
+ function newFlowingBlock( $w, $h, $a = '', $is_table = false, $is_list = false, $blockstate = 0, $newblock=true, $blockdir='ltr')
4416
+ {
4417
+ if (!$a) {
4418
+ if ($blockdir=='rtl') { $a = 'R'; }
4419
+ else { $a = 'L'; }
4420
+ }
4421
+ $this->flowingBlockAttr[ 'width' ] = ($w * _MPDFK);
4422
+ // line height in user units
4423
+ $this->flowingBlockAttr[ 'is_table' ] = $is_table;
4424
+ $this->flowingBlockAttr[ 'is_list' ] = $is_list;
4425
+ $this->flowingBlockAttr[ 'height' ] = $h;
4426
+ $this->flowingBlockAttr[ 'lineCount' ] = 0;
4427
+ $this->flowingBlockAttr[ 'align' ] = $a;
4428
+ $this->flowingBlockAttr[ 'font' ] = array();
4429
+ $this->flowingBlockAttr[ 'content' ] = array();
4430
+ $this->flowingBlockAttr[ 'contentB' ] = array();
4431
+ $this->flowingBlockAttr[ 'contentWidth' ] = 0;
4432
+ $this->flowingBlockAttr[ 'blockstate' ] = $blockstate;
4433
+
4434
+ $this->flowingBlockAttr[ 'newblock' ] = $newblock;
4435
+ $this->flowingBlockAttr[ 'valign' ] = 'M';
4436
+ $this->flowingBlockAttr['blockdir'] = $blockdir;
4437
+
4438
+ }
4439
+
4440
+ function finishFlowingBlock($endofblock=false, $next='') {
4441
+ $currentx = $this->x;
4442
+ //prints out the last chunk
4443
+ $is_table = $this->flowingBlockAttr[ 'is_table' ];
4444
+ $is_list = $this->flowingBlockAttr[ 'is_list' ];
4445
+ $maxWidth =& $this->flowingBlockAttr[ 'width' ];
4446
+ $lineHeight =& $this->flowingBlockAttr[ 'height' ];
4447
+ $align =& $this->flowingBlockAttr[ 'align' ];
4448
+ $content =& $this->flowingBlockAttr[ 'content' ];
4449
+ $contentB =& $this->flowingBlockAttr[ 'contentB' ];
4450
+ $font =& $this->flowingBlockAttr[ 'font' ];
4451
+ $contentWidth =& $this->flowingBlockAttr[ 'contentWidth' ];
4452
+ $lineCount =& $this->flowingBlockAttr[ 'lineCount' ];
4453
+ $valign =& $this->flowingBlockAttr[ 'valign' ];
4454
+ $blockstate = $this->flowingBlockAttr[ 'blockstate' ];
4455
+
4456
+ $newblock = $this->flowingBlockAttr[ 'newblock' ];
4457
+ $blockdir = $this->flowingBlockAttr['blockdir'];
4458
+
4459
+
4460
+ // *********** BLOCK BACKGROUND COLOR *****************//
4461
+ if ($this->blk[$this->blklvl]['bgcolor'] && !$is_table) {
4462
+ $fill = 0;
4463
+ }
4464
+ else {
4465
+ $this->SetFColor($this->ConvertColor(255));
4466
+ $fill = 0;
4467
+ }
4468
+
4469
+ $hanger = ''; // mPDF 5.6.40
4470
+
4471
+ // Always right trim!
4472
+ // Right trim content and adjust width if need to justify (later)
4473
+ if (isset($content[count($content)-1]) && preg_match('/[ ]+$/',$content[count($content)-1], $m)) {
4474
+ $strip = strlen($m[0]);
4475
+ $content[count($content)-1] = substr($content[count($content)-1],0,(strlen($content[count($content)-1])-$strip));
4476
+ $this->restoreFont( $font[ count($content)-1 ],false );
4477
+ $contentWidth -= $this->GetStringWidth($m[0]) * _MPDFK;
4478
+ }
4479
+
4480
+ // the amount of space taken up so far in user units
4481
+ $usedWidth = 0;
4482
+
4483
+ // COLS
4484
+ $oldcolumn = $this->CurrCol;
4485
+
4486
+
4487
+ // Print out each chunk
4488
+
4489
+ if ($is_table) {
4490
+ $ipaddingL = 0;
4491
+ $ipaddingR = 0;
4492
+ $paddingL = 0;
4493
+ $paddingR = 0;
4494
+ }
4495
+ else {
4496
+ $ipaddingL = $this->blk[$this->blklvl]['padding_left'];
4497
+ $ipaddingR = $this->blk[$this->blklvl]['padding_right'];
4498
+ $paddingL = ($ipaddingL * _MPDFK);
4499
+ $paddingR = ($ipaddingR * _MPDFK);
4500
+ $this->cMarginL = $this->blk[$this->blklvl]['border_left']['w'];
4501
+ $this->cMarginR = $this->blk[$this->blklvl]['border_right']['w'];
4502
+
4503
+ // Added mPDF 3.0 Float DIV
4504
+ $fpaddingR = 0;
4505
+ $fpaddingL = 0;
4506
+ if (count($this->floatDivs)) {
4507
+ list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl);
4508
+ if ($r_exists) { $fpaddingR = $r_width; }
4509
+ if ($l_exists) { $fpaddingL = $l_width; }
4510
+ }
4511
+
4512
+ $usey = $this->y + 0.002;
4513
+ if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 0) ) {
4514
+ $usey += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'];
4515
+ }
4516
+ // If float exists at this level
4517
+ if (isset($this->floatmargins['R']) && $usey <= $this->floatmargins['R']['y1'] && $usey >= $this->floatmargins['R']['y0'] && !$this->floatmargins['R']['skipline']) { $fpaddingR += $this->floatmargins['R']['w']; }
4518
+ if (isset($this->floatmargins['L']) && $usey <= $this->floatmargins['L']['y1'] && $usey >= $this->floatmargins['L']['y0'] && !$this->floatmargins['L']['skipline']) { $fpaddingL += $this->floatmargins['L']['w']; }
4519
+ } // *TABLES*
4520
+
4521
+ // Set Current lineheight (correction factor)
4522
+ $lhfixed = false;
4523
+ if ($is_list) {
4524
+ if (preg_match('/([0-9.,]+)mm/',$this->list_lineheight[$this->listlvl][$this->listOcc],$am)) {
4525
+ $lhfixed = true;
4526
+ $def_fontsize = $this->InlineProperties['LISTITEM'][$this->listlvl][$this->listOcc][$this->listnum]['size'];
4527
+ $this->lineheight_correction = $am[1] / $def_fontsize ;
4528
+ }
4529
+ else {
4530
+ $this->lineheight_correction = $this->list_lineheight[$this->listlvl][$this->listOcc];
4531
+ }
4532
+ }
4533
+ else
4534
+ if ($is_table) {
4535
+ if (preg_match('/([0-9.,]+)mm/',$this->table_lineheight,$am)) {
4536
+ $lhfixed = true;
4537
+ $def_fontsize = $this->FontSize; // needs to be default font-size for block ****
4538
+ $this->lineheight_correction = $lineHeight / $def_fontsize ;
4539
+ }
4540
+ else {
4541
+ $this->lineheight_correction = $this->table_lineheight;
4542
+ }
4543
+ }
4544
+ else
4545
+ if (isset($this->blk[$this->blklvl]['line_height']) && $this->blk[$this->blklvl]['line_height']) {
4546
+ if (preg_match('/([0-9.,]+)mm/',$this->blk[$this->blklvl]['line_height'],$am)) {
4547
+ $lhfixed = true;
4548
+ $def_fontsize = $this->blk[$this->blklvl]['InlineProperties']['size']; // needs to be default font-size for block ****
4549
+ $this->lineheight_correction = $am[1] / $def_fontsize ;
4550
+ }
4551
+ else {
4552
+ $this->lineheight_correction = $this->blk[$this->blklvl]['line_height'];
4553
+ }
4554
+ }
4555
+ else {
4556
+ $this->lineheight_correction = $this->normalLineheight;
4557
+ }
4558
+
4559
+ // correct lineheight to maximum fontsize
4560
+ if ($lhfixed) { $maxlineHeight = $this->lineheight; }
4561
+ else { $maxlineHeight = 0; }
4562
+ $this->forceExactLineheight = true;
4563
+ $maxfontsize = 0;
4564
+ // While we're at it, check if contains cursive text
4565
+ $checkCursive=false;
4566
+ foreach ( $content as $k => $chunk )
4567
+ {
4568
+ $this->restoreFont( $font[ $k ],false );
4569
+ if (!isset($this->objectbuffer[$k])) {
4570
+ // Soft Hyphens chr(173)
4571
+ if (!$this->usingCoreFont) {
4572
+ $content[$k] = $chunk = str_replace("\xc2\xad",'',$chunk );
4573
+ }
4574
+ else if ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
4575
+ $content[$k] = $chunk = str_replace(chr(173),'',$chunk );
4576
+ }
4577
+ // Special case of sub/sup carried over on its own to last line
4578
+ if (($this->SUB || $this->SUP) && count($content)==1) { $actfs = $this->FontSize*100/55; } // 55% is font change for sub/sup
4579
+ else { $actfs = $this->FontSize; }
4580
+ if (!$lhfixed) { $maxlineHeight = max($maxlineHeight,$actfs * $this->lineheight_correction ); }
4581
+ if ($lhfixed && ($actfs > $def_fontsize || ($actfs > ($lineHeight * $this->lineheight_correction) && $is_list))) {
4582
+ $this->forceExactLineheight = false;
4583
+ }
4584
+ $maxfontsize = max($maxfontsize,$actfs);
4585
+ }
4586
+ }
4587
+
4588
+ if(isset($font[count($font)-1])) {
4589
+ $lastfontreqstyle = $font[count($font)-1]['ReqFontStyle'];
4590
+ $lastfontstyle = $font[count($font)-1]['style'];
4591
+ }
4592
+ else {
4593
+ $lastfontreqstyle=null;
4594
+ $lastfontstyle=null;
4595
+ }
4596
+ if ($blockdir == 'ltr' && strpos($lastfontreqstyle,"I") !== false && strpos($lastfontstyle,"I") === false) { // Artificial italic
4597
+ $lastitalic = $this->FontSize*0.15*_MPDFK;
4598
+ }
4599
+ else { $lastitalic = 0; }
4600
+
4601
+
4602
+ if ($is_list && is_array($this->bulletarray) && count($this->bulletarray)) {
4603
+ $actfs = $this->bulletarray['fontsize'];
4604
+ if (!$lhfixed) { $maxlineHeight = max($maxlineHeight,$actfs * $this->lineheight_correction ); }
4605
+ if ($lhfixed && $actfs > $def_fontsize) { $this->forceExactLineheight = false; }
4606
+ $maxfontsize = max($maxfontsize,$actfs);
4607
+ }
4608
+
4609
+ // when every text item checked i.e. $maxfontsize is set properly
4610
+
4611
+ $af = 0; // Above font
4612
+ $bf = 0; // Below font
4613
+ $mta = 0; // Maximum top-aligned
4614
+ $mba = 0; // Maximum bottom-aligned
4615
+
4616
+ foreach ( $content as $k => $chunk )
4617
+ {
4618
+ if (isset($this->objectbuffer[$k])) {
4619
+ $oh = $this->objectbuffer[$k]['OUTER-HEIGHT'];
4620
+ $va = $this->objectbuffer[$k]['vertical-align']; // = $objattr['vertical-align'] = set as M,T,B,S
4621
+ if ($lhfixed && $oh > $def_fontsize) { $this->forceExactLineheight = false; }
4622
+
4623
+ if ($va == 'BS') { // (BASELINE default)
4624
+ $af = max($af, ($oh - ($maxfontsize * (0.5 + $this->baselineC))));
4625
+ }
4626
+ else if ($va == 'M') {
4627
+ $af = max($af, ($oh - $maxfontsize)/2);
4628
+ $bf = max($bf, ($oh - $maxfontsize)/2);
4629
+ }
4630
+ else if ($va == 'TT') {
4631
+ $bf = max($bf, ($oh - $maxfontsize));
4632
+ }
4633
+ else if ($va == 'TB') {
4634
+ $af = max($af, ($oh - $maxfontsize));
4635
+ }
4636
+ else if ($va == 'T') {
4637
+ $mta = max($mta, $oh);
4638
+ }
4639
+ else if ($va == 'B') {
4640
+ $mba = max($mba, $oh);
4641
+ }
4642
+ }
4643
+ }
4644
+ if ((!$lhfixed || !$this->forceExactLineheight) && ($af > (($maxlineHeight - $maxfontsize)/2) || $bf > (($maxlineHeight - $maxfontsize)/2))) {
4645
+ $maxlineHeight = $maxfontsize + $af + $bf;
4646
+ }
4647
+ else if (!$lhfixed) { $af = $bf = ($maxlineHeight - $maxfontsize)/2; }
4648
+ if ($mta > $maxlineHeight) {
4649
+ $bf += ($mta - $maxlineHeight);
4650
+ $maxlineHeight = $mta;
4651
+ }
4652
+ if ($mba > $maxlineHeight) {
4653
+ $af += ($mba - $maxlineHeight);
4654
+ $maxlineHeight = $mba;
4655
+ }
4656
+
4657
+ $lineHeight = $maxlineHeight;
4658
+ // If NOT images, and maxfontsize NOT > lineHeight - this value determines text baseline positioning
4659
+ if ($lhfixed && $af==0 && $bf==0 && $maxfontsize<=($def_fontsize * $this->lineheight_correction * 0.8 )) {
4660
+ $this->linemaxfontsize = $def_fontsize;
4661
+ }
4662
+ else { $this->linemaxfontsize = $maxfontsize; }
4663
+
4664
+ // Get PAGEBREAK TO TEST for height including the bottom border/padding
4665
+ $check_h = max($this->divheight,$lineHeight);
4666
+
4667
+ // This fixes a proven bug...
4668
+ if ($endofblock && $newblock && $blockstate==0 && !$content) { $check_h = 0; }
4669
+ // but ? needs to fix potentially more widespread...
4670
+ // if (!$content) { $check_h = 0; }
4671
+
4672
+ if ($this->blklvl > 0 && !$is_table) {
4673
+ if ($endofblock && $blockstate > 1) {
4674
+ if ($this->blk[$this->blklvl]['page_break_after_avoid']) { $check_h += $lineHeight; }
4675
+ $check_h += ($this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w']);
4676
+ }
4677
+ // mPDF 5.4.03
4678
+ if (($newblock && ($blockstate==1 || $blockstate==3) && $lineCount == 0) || ($endofblock && $blockstate ==3 && $lineCount == 0)) {
4679
+ $check_h += ($this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['border_top']['w']);
4680
+ }
4681
+ }
4682
+
4683
+ // Force PAGE break if column height cannot take check-height
4684
+ if ($this->ColActive && $check_h > ($this->PageBreakTrigger - $this->y0)) {
4685
+ $this->SetCol($this->NbCol-1);
4686
+ }
4687
+
4688
+ // mPDF 5.4.04
4689
+ // Avoid just border/background-color moved on to next page
4690
+ if ($endofblock && $blockstate > 1 && !$content) { $buff = $this->margBuffer; }
4691
+ else { $buff = 0; }
4692
+
4693
+
4694
+ // PAGEBREAK
4695
+ // mPDF 5.4.04
4696
+ if(!$is_table && ($this->y+$check_h) > ($this->PageBreakTrigger + $buff) and !$this->InFooter and $this->AcceptPageBreak()) {
4697
+ $bak_x=$this->x;//Current X position
4698
+ // WORD SPACING
4699
+ $ws=$this->ws;//Word Spacing
4700
+ $charspacing=$this->charspacing;//Character Spacing
4701
+ $this->ResetSpacing();
4702
+
4703
+ $this->AddPage($this->CurOrientation);
4704
+
4705
+ $this->x=$bak_x;
4706
+ // Added to correct for OddEven Margins
4707
+ $currentx += $this->MarginCorrection;
4708
+ $this->x += $this->MarginCorrection;
4709
+
4710
+ // WORD SPACING
4711
+ $this->SetSpacing($charspacing,$ws);
4712
+ }
4713
+
4714
+ if ($this->keep_block_together && !$is_table && $this->kt_p00 < $this->page && ($this->y+$check_h) > $this->kt_y00) {
4715
+ $this->printdivbuffer();
4716
+ $this->keep_block_together = 0;
4717
+ }
4718
+
4719
+
4720
+ // TOP MARGIN
4721
+ if ($newblock && ($blockstate==1 || $blockstate==3) && ($this->blk[$this->blklvl]['margin_top']) && $lineCount == 0 && !$is_table && !$is_list) {
4722
+ $this->DivLn($this->blk[$this->blklvl]['margin_top'],$this->blklvl-1,true,$this->blk[$this->blklvl]['margin_collapse']);
4723
+ }
4724
+
4725
+ if ($newblock && ($blockstate==1 || $blockstate==3) && $lineCount == 0 && !$is_table && !$is_list) {
4726
+ $this->blk[$this->blklvl]['y0'] = $this->y;
4727
+ $this->blk[$this->blklvl]['startpage'] = $this->page;
4728
+ if ($this->blk[$this->blklvl]['float']) { $this->blk[$this->blklvl]['float_start_y'] = $this->y; } // mPDF 5.6.63
4729
+ }
4730
+
4731
+ // ADDED for Paragraph_indent
4732
+ $WidthCorrection = 0;
4733
+ if (($newblock) && ($blockstate==1 || $blockstate==3) && isset($this->blk[$this->blklvl]['text_indent']) && ($lineCount == 0) && (!$is_table) && (!$is_list) && ($align != 'C')) {
4734
+ $ti = $this->ConvertSize($this->blk[$this->blklvl]['text_indent'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
4735
+ $WidthCorrection = ($ti*_MPDFK);
4736
+ }
4737
+
4738
+
4739
+ // PADDING and BORDER spacing/fill
4740
+ if (($newblock) && ($blockstate==1 || $blockstate==3) && (($this->blk[$this->blklvl]['padding_top']) || ($this->blk[$this->blklvl]['border_top'])) && ($lineCount == 0) && (!$is_table) && (!$is_list)) {
4741
+ // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
4742
+ $this->DivLn($this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'],-3,true,false,1);
4743
+ $this->x = $currentx;
4744
+ }
4745
+
4746
+
4747
+ // Added mPDF 3.0 Float DIV
4748
+ $fpaddingR = 0;
4749
+ $fpaddingL = 0;
4750
+ if (count($this->floatDivs)) {
4751
+ list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl);
4752
+ if ($r_exists) { $fpaddingR = $r_width; }
4753
+ if ($l_exists) { $fpaddingL = $l_width; }
4754
+ }
4755
+
4756
+ $usey = $this->y + 0.002;
4757
+ if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 0) ) {
4758
+ $usey += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'];
4759
+ }
4760
+ // If float exists at this level
4761
+ if (isset($this->floatmargins['R']) && $usey <= $this->floatmargins['R']['y1'] && $usey >= $this->floatmargins['R']['y0'] && !$this->floatmargins['R']['skipline']) { $fpaddingR += $this->floatmargins['R']['w']; }
4762
+ if (isset($this->floatmargins['L']) && $usey <= $this->floatmargins['L']['y1'] && $usey >= $this->floatmargins['L']['y0'] && !$this->floatmargins['L']['skipline']) { $fpaddingL += $this->floatmargins['L']['w']; }
4763
+
4764
+ if ($content) {
4765
+
4766
+ // In FinishFlowing Block no lines are justified as it is always last line
4767
+ // but if CJKorphan has allowed content width to go over max width, use J charspacing to compress line
4768
+ // JUSTIFICATION J - NOT!
4769
+ $nb_carac = 0;
4770
+ $nb_spaces = 0;
4771
+ $jcharspacing = 0;
4772
+ $jws = 0;
4773
+ $inclCursive=false;
4774
+ $dottab = false; // mPDF 5.6.19
4775
+ foreach ( $content as $k => $chunk ) {
4776
+ if (!isset($this->objectbuffer[$k]) || (isset($this->objectbuffer[$k]) && !$this->objectbuffer[$k])) {
4777
+ if ($this->usingCoreFont) {
4778
+ $chunk = str_replace(chr(160),chr(32),$chunk );
4779
+ }
4780
+ else {
4781
+ $chunk = str_replace(chr(194).chr(160),chr(32),$chunk );
4782
+ }
4783
+ $nb_carac += mb_strlen( $chunk, $this->mb_enc );
4784
+ $nb_spaces += mb_substr_count( $chunk,' ', $this->mb_enc );
4785
+ if ($checkCursive) {
4786
+ }
4787
+ }
4788
+ else if ($this->objectbuffer[$k]['type']=='dottab') { $dottab = $this->objectbuffer[$k]['outdent']; } // mPDF 5.6.19
4789
+ }
4790
+ // if it's justified, we need to find the char/word spacing (or if orphans have allowed length of line to go over the maxwidth)
4791
+ // If "orphans" in fact is just a final space - ignore this
4792
+ // mPDF 5.6.40
4793
+ $lastchar = mb_substr($content[(count($content)-1)],mb_strlen($content[(count($content)-1)], $this->mb_enc)-1, 1, $this->mb_enc);
4794
+ if (preg_match("/[".$this->CJKoverflow."]/u", $lastchar)) { $CJKoverflow = true; }
4795
+ else {$CJKoverflow = false; }
4796
+ if ((((($contentWidth + $lastitalic) > $maxWidth) && ($content[count($content)-1] != ' ') ) ||
4797
+ (!$endofblock && $align=='J' && ($next=='image' || $next=='select' || $next=='input' || $next=='textarea' || ($next=='br' && $this->justifyB4br)))) && !($CJKoverflow && $this->allowCJKoverflow) ) { // mPDF 5.6.40
4798
+ // WORD SPACING
4799
+ list($jcharspacing,$jws) = $this->GetJspacing($nb_carac,$nb_spaces,($maxWidth-$lastitalic-$contentWidth-$WidthCorrection-(($this->cMarginL+$this->cMarginR)*_MPDFK)-($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) )),$inclCursive);
4800
+ }
4801
+
4802
+ // Check if will fit at word/char spacing of previous line - if so continue it
4803
+ // but only allow a maximum of $this->jSmaxWordLast and $this->jSmaxCharLast
4804
+ else if ($contentWidth < ($maxWidth - $lastitalic-$WidthCorrection - (($this->cMarginL+$this->cMarginR)* _MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK))) && !$this->fixedlSpacing) {
4805
+ if ($this->ws > $this->jSmaxWordLast) {
4806
+ $jws = $this->jSmaxWordLast;
4807
+ }
4808
+ if ($this->charspacing > $this->jSmaxCharLast) {
4809
+ $jcharspacing = $this->jSmaxCharLast;
4810
+ }
4811
+ $check = $maxWidth - $lastitalic-$WidthCorrection - $contentWidth - (($this->cMarginL+$this->cMarginR)* _MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) ) - ( $jcharspacing * $nb_carac) - ( $jws * $nb_spaces);
4812
+ if ($check <= 0) {
4813
+ $jcharspacing = 0;
4814
+ $jws = 0;
4815
+ }
4816
+ }
4817
+
4818
+ $empty = $maxWidth - $lastitalic-$WidthCorrection - $contentWidth - (($this->cMarginL+$this->cMarginR)* _MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) );
4819
+
4820
+ $empty -= ($jcharspacing * $nb_carac);
4821
+ $empty -= ($jws * $nb_spaces);
4822
+
4823
+ $empty /= _MPDFK;
4824
+
4825
+ if (!$is_table) {
4826
+ $this->maxPosR = max($this->maxPosR , ($this->w - $this->rMargin - $this->blk[$this->blklvl]['outer_right_margin'] - $empty));
4827
+ $this->maxPosL = min($this->maxPosL , ($this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'] + $empty));
4828
+ }
4829
+
4830
+ $arraysize = count($content);
4831
+
4832
+ $margins = ($this->cMarginL+$this->cMarginR) + ($ipaddingL+$ipaddingR + $fpaddingR + $fpaddingR );
4833
+
4834
+ if (!$is_table) { $this->DivLn($lineHeight,$this->blklvl,false); } // false -> don't advance y
4835
+
4836
+ // DIRECTIONALITY RTL
4837
+ $all_rtl = false;
4838
+ $contains_rtl = false;
4839
+
4840
+ $this->x = $currentx + $this->cMarginL + $ipaddingL + $fpaddingL;
4841
+ if ($dottab !== false && $blockdir=='rtl') { $this->x -= $dottab; } // mPDF 5.6.19
4842
+ else if ($align == 'R') { $this->x += $empty; }
4843
+ else if ($align == 'J' && $blockdir == 'rtl') { $this->x += $empty; }
4844
+ else if ($align == 'C') { $this->x += ($empty / 2); }
4845
+
4846
+ // Paragraph INDENT
4847
+ $WidthCorrection = 0;
4848
+ if (($newblock) && ($blockstate==1 || $blockstate==3) && isset($this->blk[$this->blklvl]['text_indent']) && ($lineCount == 0) && (!$is_table) && (!$is_list) && ($align !='C')) {
4849
+ $ti = $this->ConvertSize($this->blk[$this->blklvl]['text_indent'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
4850
+ $this->x += $ti;
4851
+ }
4852
+
4853
+
4854
+ foreach ( $content as $k => $chunk )
4855
+ {
4856
+
4857
+ // FOR IMAGES
4858
+ if ((($blockdir == 'rtl') && ($contains_rtl )) || $all_rtl ) { $dirk = $arraysize-1 - $k; } else { $dirk = $k; }
4859
+
4860
+ $va = 'M'; // default for text
4861
+ if (isset($this->objectbuffer[$dirk]) && $this->objectbuffer[$dirk]) {
4862
+ $xadj = $this->x - $this->objectbuffer[$dirk]['OUTER-X'];
4863
+ $this->objectbuffer[$dirk]['OUTER-X'] += $xadj;
4864
+ $this->objectbuffer[$dirk]['BORDER-X'] += $xadj;
4865
+ $this->objectbuffer[$dirk]['INNER-X'] += $xadj;
4866
+ $va = $this->objectbuffer[$dirk]['vertical-align'];
4867
+ $yadj = $this->y - $this->objectbuffer[$dirk]['OUTER-Y'];
4868
+ if ($va == 'BS') {
4869
+ $yadj += $af + ($this->linemaxfontsize * (0.5 + $this->baselineC)) - $this->objectbuffer[$dirk]['OUTER-HEIGHT'];
4870
+ }
4871
+ else if ($va == 'M' || $va == '') {
4872
+ $yadj += $af + ($this->linemaxfontsize /2) - ($this->objectbuffer[$dirk]['OUTER-HEIGHT']/2);
4873
+ }
4874
+ else if ($va == 'TB') {
4875
+ $yadj += $af + $this->linemaxfontsize - $this->objectbuffer[$dirk]['OUTER-HEIGHT'];
4876
+ }
4877
+ else if ($va == 'TT') {
4878
+ $yadj += $af;
4879
+ }
4880
+ else if ($va == 'B') {
4881
+ $yadj += $af + $this->linemaxfontsize + $bf - $this->objectbuffer[$dirk]['OUTER-HEIGHT'];
4882
+ }
4883
+ else if ($va == 'T') {
4884
+ $yadj += 0;
4885
+ }
4886
+ $this->objectbuffer[$dirk]['OUTER-Y'] += $yadj;
4887
+ $this->objectbuffer[$dirk]['BORDER-Y'] += $yadj;
4888
+ $this->objectbuffer[$dirk]['INNER-Y'] += $yadj;
4889
+ }
4890
+
4891
+
4892
+ // DIRECTIONALITY RTL
4893
+ if ((($blockdir == 'rtl') && ($contains_rtl )) || $all_rtl ) { $this->restoreFont( $font[ $arraysize-1 - $k ] ); }
4894
+ else { $this->restoreFont( $font[ $k ] ); }
4895
+
4896
+ // mPDF 5.6.13 Decimal alignment - set in _tableWrite
4897
+ if ($is_table && substr($align,0,1)=='D' && $k==0 ) {
4898
+ $dp = $this->decimal_align[substr($align,0,2)];
4899
+ $s = preg_split('/'.preg_quote($dp,'/').'/', $content[0], 2); // ? needs to be /u if not core
4900
+ $s0 = $this->GetStringWidth($s[0], false);
4901
+ $this->x += ($this->decimal_offset - $s0);
4902
+ }
4903
+
4904
+ $this->SetSpacing(($this->fixedlSpacing*_MPDFK)+$jcharspacing,($this->fixedlSpacing+$this->minwSpacing)*_MPDFK+$jws);
4905
+ $this->fixedlSpacing = false;
4906
+ $this->minwSpacing = 0;
4907
+
4908
+ // mPDF 5.6.26
4909
+ $save_vis = $this->visibility;
4910
+ if (isset($this->textparam['visibility']) && $this->textparam['visibility'] && $this->textparam['visibility'] != $this->visibility) {
4911
+ $this->SetVisibility($this->textparam['visibility']);
4912
+ }
4913
+
4914
+ // *********** SPAN BACKGROUND COLOR ***************** //
4915
+ if (isset($this->spanbgcolor) && $this->spanbgcolor) {
4916
+ $cor = $this->spanbgcolorarray;
4917
+ $this->SetFColor($cor);
4918
+ $save_fill = $fill; $spanfill = 1; $fill = 1;
4919
+ }
4920
+ if (!empty($this->spanborddet)) {
4921
+ if (strpos($contentB[$k],'L')!==false && isset($this->spanborddet['L'])) $this->x += $this->spanborddet['L']['w'];
4922
+ if (strpos($contentB[$k],'L')===false) $this->spanborddet['L']['s'] = $this->spanborddet['L']['w'] = 0;
4923
+ if (strpos($contentB[$k],'R')===false) $this->spanborddet['R']['s'] = $this->spanborddet['R']['w'] = 0;
4924
+ }
4925
+ // WORD SPACING
4926
+ $stringWidth = $this->GetStringWidth($chunk ) + ( $this->charspacing * mb_strlen($chunk,$this->mb_enc ) / _MPDFK )
4927
+ + ( $this->ws * mb_substr_count($chunk,' ',$this->mb_enc ) / _MPDFK );
4928
+ if (isset($this->objectbuffer[$dirk])) {
4929
+ if ($this->objectbuffer[$dirk]['type']=='dottab') {
4930
+ $this->objectbuffer[$dirk]['OUTER-WIDTH'] +=$empty;
4931
+ $this->objectbuffer[$dirk]['OUTER-WIDTH'] +=$this->objectbuffer[$dirk]['outdent']; // mPDF 5.6.19
4932
+ }
4933
+ $stringWidth = $this->objectbuffer[$dirk]['OUTER-WIDTH'];
4934
+ }
4935
+
4936
+ if ($stringWidth==0) { $stringWidth = 0.000001; }
4937
+ if ($k == $arraysize-1) {
4938
+ // mPDF 5.6.40
4939
+ if ($this->checkCJK && $CJKoverflow && $align=='J' && $this->allowCJKoverflow && $hanger && $this->CJKforceend) {
4940
+ // force-end overhang
4941
+ $this->Cell( $stringWidth, $lineHeight, $chunk, '', 0, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, $af, $bf, true );
4942
+ $this->Cell( $this->GetStringWidth($hanger), $lineHeight, $hanger, '', 1, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, $af, $bf, true );
4943
+ }
4944
+ else {
4945
+ $this->Cell( $stringWidth, $lineHeight, $chunk, '', 1, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, $af, $bf, true );
4946
+ }
4947
+ }
4948
+ else $this->Cell( $stringWidth, $lineHeight, $chunk, '', 0, '', $fill, $this->HREF, 0, 0,0,'M', $fill, $af, $bf, true );//first or middle part
4949
+
4950
+
4951
+ if (!empty($this->spanborddet)) {
4952
+ if (strpos($contentB[$k],'R')!==false && $k != $arraysize-1) $this->x += $this->spanborddet['R']['w'];
4953
+ }
4954
+ // *********** SPAN BACKGROUND COLOR OFF - RESET BLOCK BGCOLOR ***************** //
4955
+ if (isset($spanfill) && $spanfill) {
4956
+ $fill = $save_fill; $spanfill = 0;
4957
+ if ($fill) { $this->SetFColor($bcor); }
4958
+ }
4959
+ // mPDF 5.6.26
4960
+ if (isset($this->textparam['visibility']) && $this->textparam['visibility'] && $this->visibility != $save_vis) {
4961
+ $this->SetVisibility($save_vis);
4962
+ }
4963
+
4964
+ }
4965
+
4966
+ $this->printobjectbuffer($is_table, $blockdir);
4967
+
4968
+ $this->objectbuffer = array();
4969
+
4970
+ $this->ResetSpacing();
4971
+
4972
+ // LIST BULLETS/NUMBERS
4973
+ if ($is_list && is_array($this->bulletarray) && ($lineCount == 0) ) {
4974
+
4975
+ $savedFont = $this->saveFont();
4976
+
4977
+ $bull = $this->bulletarray;
4978
+ if (isset($bull['level']) && isset($bull['occur']) && isset($this->InlineProperties['LIST'][$bull['level']][$bull['occur']])) {
4979
+ $this->restoreInlineProperties($this->InlineProperties['LIST'][$bull['level']][$bull['occur']]);
4980
+ }
4981
+ if (isset($bull['level']) && isset($bull['occur']) && isset($bull['num']) && isset($this->InlineProperties['LISTITEM'][$bull['level']][$bull['occur']][$bull['num']]) && $this->InlineProperties['LISTITEM'][$bull['level']][$bull['occur']][$bull['num']]) { $this->restoreInlineProperties($this->InlineProperties['LISTITEM'][$bull['level']][$bull['occur']][$bull['num']]); }
4982
+ if (isset($bull['font']) && $bull['font'] == 'czapfdingbats') {
4983
+ $this->bullet = true;
4984
+ $this->SetFont('czapfdingbats','',$this->FontSizePt/2.5);
4985
+ }
4986
+ else { $this->SetFont($this->FontFamily,$this->FontStyle,$this->FontSizePt,true,true); } // force output
4987
+ //Output bullet
4988
+ $this->x = $currentx;
4989
+ if (isset($bull['x'])) { $this->x += $bull['x']; }
4990
+ $this->y -= $lineHeight;
4991
+ if (isset($bull['col']) && $bull['col']) { $this->SetTColor($bull['col']); } // mPDF 5.6.67
4992
+
4993
+ if (isset($bull['txt'])) { $this->Cell($bull['w'], $lineHeight,$bull['txt'],'','',$bull['align'],0,'',0,-$this->cMarginL, -$this->cMarginR ); }
4994
+ if (isset($bull['font']) && $bull['font'] == 'czapfdingbats') {
4995
+ $this->bullet = false;
4996
+ }
4997
+ $this->x = $currentx; // Reset
4998
+ $this->y += $lineHeight;
4999
+
5000
+
5001
+ $this->restoreFont( $savedFont );
5002
+ // $font = array( $savedFont );
5003
+
5004
+ $this->bulletarray = array(); // prevents repeat of bullet/number if <li>....<br />.....</li>
5005
+ }
5006
+
5007
+
5008
+ } // END IF CONTENT
5009
+
5010
+ // Update values if set to skipline
5011
+ if ($this->floatmargins) { $this->_advanceFloatMargins(); }
5012
+
5013
+
5014
+ if ($endofblock && $blockstate>1) {
5015
+ // If float exists at this level
5016
+ if (isset($this->floatmargins['R']['y1'])) { $fry1 = $this->floatmargins['R']['y1']; }
5017
+ else { $fry1 = 0; }
5018
+ if (isset($this->floatmargins['L']['y1'])) { $fly1 = $this->floatmargins['L']['y1']; }
5019
+ else { $fly1 = 0; }
5020
+ if ($this->y < $fry1 || $this->y < $fly1) {
5021
+ $drop = max($fry1,$fly1) - $this->y;
5022
+ $this->DivLn($drop);
5023
+ $this->x = $currentx;
5024
+ }
5025
+ }
5026
+
5027
+
5028
+ // PADDING and BORDER spacing/fill
5029
+ if ($endofblock && ($blockstate > 1) && ($this->blk[$this->blklvl]['padding_bottom'] || $this->blk[$this->blklvl]['border_bottom'] || $this->blk[$this->blklvl]['css_set_height']) && (!$is_table) && (!$is_list)) {
5030
+ // If CSS height set, extend bottom - if on same page as block started, and CSS HEIGHT > actual height,
5031
+ // and does not force pagebreak
5032
+ $extra = 0;
5033
+ if ($this->blk[$this->blklvl]['css_set_height'] && $this->blk[$this->blklvl]['startpage']==$this->page) {
5034
+ // predicted height
5035
+ $h1 = ($this->y-$this->blk[$this->blklvl]['y0']) + $this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w'];
5036
+ if ($h1 < ($this->blk[$this->blklvl]['css_set_height']+$this->blk[$this->blklvl]['padding_bottom']+$this->blk[$this->blklvl]['padding_top'])) { $extra = ($this->blk[$this->blklvl]['css_set_height']+$this->blk[$this->blklvl]['padding_bottom']+$this->blk[$this->blklvl]['padding_top']) - $h1; }
5037
+ if($this->y + $this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w'] + $extra > $this->PageBreakTrigger) {
5038
+ $extra = $this->PageBreakTrigger - ($this->y + $this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w']);
5039
+ }
5040
+ }
5041
+
5042
+ // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
5043
+ $this->DivLn($this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w'] + $extra,-3,true,false,2);
5044
+ $this->x = $currentx;
5045
+
5046
+
5047
+ }
5048
+
5049
+ // SET Bottom y1 of block (used for painting borders)
5050
+ if (($endofblock) && ($blockstate > 1) && (!$is_table) && (!$is_list)) {
5051
+ $this->blk[$this->blklvl]['y1'] = $this->y;
5052
+ }
5053
+
5054
+ // BOTTOM MARGIN
5055
+ if (($endofblock) && ($blockstate > 1) && ($this->blk[$this->blklvl]['margin_bottom']) && (!$is_table) && (!$is_list)) {
5056
+ if($this->y+$this->blk[$this->blklvl]['margin_bottom'] < $this->PageBreakTrigger and !$this->InFooter) {
5057
+ $this->DivLn($this->blk[$this->blklvl]['margin_bottom'],$this->blklvl-1,true,$this->blk[$this->blklvl]['margin_collapse']);
5058
+ }
5059
+ }
5060
+
5061
+ // Reset lineheight
5062
+ $lineHeight = $this->divheight;
5063
+ }
5064
+
5065
+
5066
+
5067
+
5068
+
5069
+ function printobjectbuffer($is_table=false, $blockdir=false) {
5070
+ if (!$blockdir) { $blockdir = $this->directionality; }
5071
+ if ($is_table && $this->shrin_k > 1) { $k = $this->shrin_k; }
5072
+ else { $k = 1; }
5073
+ $save_y = $this->y;
5074
+ $save_x = $this->x;
5075
+ $save_currentfontfamily = $this->FontFamily;
5076
+ $save_currentfontsize = $this->FontSizePt;
5077
+ $save_currentfontstyle = $this->FontStyle.($this->U ? 'U' : '').($this->S ? 'S' : '');
5078
+ if ($blockdir == 'rtl') { $rtlalign = 'R'; } else { $rtlalign = 'L'; }
5079
+ foreach ($this->objectbuffer AS $ib => $objattr) {
5080
+ if ($objattr['type'] == 'bookmark' || $objattr['type'] == 'indexentry' || $objattr['type'] == 'toc') {
5081
+ $x = $objattr['OUTER-X'];
5082
+ $y = $objattr['OUTER-Y'];
5083
+ $this->y = $y - $this->FontSize/2;
5084
+ $this->x = $x;
5085
+ }
5086
+ else {
5087
+ $y = $objattr['OUTER-Y'];
5088
+ $x = $objattr['OUTER-X'];
5089
+ $w = $objattr['OUTER-WIDTH'];
5090
+ $h = $objattr['OUTER-HEIGHT'];
5091
+ if (isset($objattr['text'])) { $texto = $objattr['text']; }
5092
+ $this->y = $y;
5093
+ $this->x = $x;
5094
+ if (isset($objattr['fontfamily'])) { $this->SetFont($objattr['fontfamily'],'',$objattr['fontsize'] ); }
5095
+ }
5096
+
5097
+ // HR
5098
+ if ($objattr['type'] == 'hr') {
5099
+ $this->SetDColor($objattr['color']);
5100
+ switch($objattr['align']) {
5101
+ case 'C':
5102
+ $empty = $objattr['OUTER-WIDTH'] - $objattr['INNER-WIDTH'];
5103
+ $empty /= 2;
5104
+ $x += $empty;
5105
+ break;
5106
+ case 'R':
5107
+ $empty = $objattr['OUTER-WIDTH'] - $objattr['INNER-WIDTH'];
5108
+ $x += $empty;
5109
+ break;
5110
+ }
5111
+ $oldlinewidth = $this->LineWidth;
5112
+ $this->SetLineWidth($objattr['linewidth']/$k );
5113
+ $this->y += ($objattr['linewidth']/2) + $objattr['margin_top']/$k;
5114
+ $this->Line($x,$this->y,$x+$objattr['INNER-WIDTH'],$this->y);
5115
+ $this->SetLineWidth($oldlinewidth);
5116
+ $this->SetDColor($this->ConvertColor(0));
5117
+ }
5118
+ // IMAGE
5119
+ if ($objattr['type'] == 'image') {
5120
+ // mPDF 5.6.01 - LAYERS
5121
+ if (isset($objattr['z-index']) && $objattr['z-index'] > 0 && $this->currentlayer==0) {
5122
+ $this->BeginLayer($objattr['z-index']);
5123
+ }
5124
+ if(isset($objattr['visibility']) && $objattr['visibility']!='visible' && $objattr['visibility']) {
5125
+ $this->SetVisibility($objattr['visibility']);
5126
+ }
5127
+ if (isset($objattr['opacity'])) { $this->SetAlpha($objattr['opacity']); }
5128
+ $rotate = 0;
5129
+ $obiw = $objattr['INNER-WIDTH'];
5130
+ $obih = $objattr['INNER-HEIGHT'];
5131
+ $sx = $objattr['INNER-WIDTH']*_MPDFK / $objattr['orig_w'];
5132
+ $sy = abs($objattr['INNER-HEIGHT'])*_MPDFK / abs($objattr['orig_h']);
5133
+ $sx = ($objattr['INNER-WIDTH']*_MPDFK / $objattr['orig_w']);
5134
+ $sy = ($objattr['INNER-HEIGHT']*_MPDFK / $objattr['orig_h']);
5135
+
5136
+ if (isset($objattr['ROTATE'])) { $rotate = $objattr['ROTATE']; }
5137
+ if ($rotate==90) {
5138
+ // Clockwise
5139
+ $obiw = $objattr['INNER-HEIGHT'];
5140
+ $obih = $objattr['INNER-WIDTH'];
5141
+ $tr = $this->transformTranslate(0, -$objattr['INNER-WIDTH'], true) ;
5142
+ $tr .= ' '. $this->transformRotate(90, $objattr['INNER-X'],($objattr['INNER-Y'] +$objattr['INNER-WIDTH'] ),true) ;
5143
+ $sx = $obiw*_MPDFK / $objattr['orig_h'];
5144
+ $sy = $obih*_MPDFK / $objattr['orig_w'];
5145
+ }
5146
+ else if ($rotate==-90 || $rotate==270) {
5147
+ // AntiClockwise
5148
+ $obiw = $objattr['INNER-HEIGHT'];
5149
+ $obih = $objattr['INNER-WIDTH'];
5150
+ $tr = $this->transformTranslate($objattr['INNER-WIDTH'], ($objattr['INNER-HEIGHT']-$objattr['INNER-WIDTH']), true) ;
5151
+ $tr .= ' '. $this->transformRotate(-90, $objattr['INNER-X'],($objattr['INNER-Y'] +$objattr['INNER-WIDTH'] ),true) ;
5152
+ $sx = $obiw*_MPDFK / $objattr['orig_h'];
5153
+ $sy = $obih*_MPDFK / $objattr['orig_w'];
5154
+ }
5155
+ else if ($rotate==180) {
5156
+ // Mirror
5157
+ $tr = $this->transformTranslate($objattr['INNER-WIDTH'], -$objattr['INNER-HEIGHT'], true) ;
5158
+ $tr .= ' '. $this->transformRotate(180, $objattr['INNER-X'],($objattr['INNER-Y'] +$objattr['INNER-HEIGHT'] ),true) ;
5159
+ }
5160
+ else { $tr = ''; }
5161
+ $tr = trim($tr);
5162
+ if ($tr) { $tr .= ' '; }
5163
+ $gradmask = '';
5164
+
5165
+
5166
+ if (isset($objattr['GRADIENT-MASK'])) {
5167
+ $g = $this->grad->parseMozGradient( $objattr['GRADIENT-MASK'] );
5168
+ if ($g) {
5169
+ $dummy = $this->grad->Gradient($objattr['INNER-X'], $objattr['INNER-Y'], $obiw, $obih, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend'], true, true);
5170
+ $gradmask = '/TGS'.count($this->gradients).' gs ';
5171
+ // $this->_out("q ".$tr.$this->grad->Gradient($objattr['INNER-X'], $objattr['INNER-Y'], $obiw, $obih, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend'], true)." Q");
5172
+ }
5173
+ }
5174
+ if (isset($objattr['itype']) && $objattr['itype']=='svg') {
5175
+ $outstring = sprintf('q '.$tr.'%.3F 0 0 %.3F %.3F %.3F cm /FO%d Do Q', $sx, -$sy, $objattr['INNER-X']*_MPDFK-$sx*$objattr['wmf_x'], (($this->h-$objattr['INNER-Y'])*_MPDFK)+$sy*$objattr['wmf_y'], $objattr['ID']);
5176
+ }
5177
+ else {
5178
+ $outstring = sprintf("q ".$tr."%.3F 0 0 %.3F %.3F %.3F cm ".$gradmask."/I%d Do Q",$obiw*_MPDFK, $obih*_MPDFK, $objattr['INNER-X'] *_MPDFK, ($this->h-($objattr['INNER-Y'] +$obih ))*_MPDFK,$objattr['ID'] );
5179
+ }
5180
+ $this->_out($outstring);
5181
+ // LINK
5182
+ if (isset($objattr['link'])) $this->Link($objattr['INNER-X'],$objattr['INNER-Y'],$objattr['INNER-WIDTH'],$objattr['INNER-HEIGHT'],$objattr['link']);
5183
+ if (isset($objattr['opacity'])) { $this->SetAlpha(1); }
5184
+ if ((isset($objattr['border_top']) && $objattr['border_top']>0) || (isset($objattr['border_left']) && $objattr['border_left']>0) || (isset($objattr['border_right']) && $objattr['border_right']>0) || (isset($objattr['border_bottom']) && $objattr['border_bottom']>0)) { $this->PaintImgBorder($objattr,$is_table); }
5185
+ if(isset($objattr['visibility']) && $objattr['visibility']!='visible' && $objattr['visibility']) {
5186
+ $this->SetVisibility('visible');
5187
+ }
5188
+ // mPDF 5.6.01 - LAYERS
5189
+ if (isset($objattr['z-index']) && $objattr['z-index'] > 0 && $this->currentlayer==0) {
5190
+ $this->EndLayer();
5191
+ }
5192
+
5193
+ }
5194
+
5195
+
5196
+ // TEXT CIRCLE
5197
+ if ($objattr['type'] == 'textcircle') {
5198
+ $bgcol = ''; // mPDF 5.5.14
5199
+ if (isset($objattr['bgcolor']) && $objattr['bgcolor']) {
5200
+ $bgcol = $objattr['bgcolor'];
5201
+ }
5202
+ $col = $this->ConvertColor(0);
5203
+ if (isset($objattr['color']) && $objattr['color']) {
5204
+ $col = $objattr['color'];
5205
+ }
5206
+ $this->SetTColor($col);
5207
+ $this->SetFColor($bgcol);
5208
+ if ($bgcol) $this->Rect($objattr['BORDER-X'], $objattr['BORDER-Y'], $objattr['BORDER-WIDTH'], $objattr['BORDER-HEIGHT'], 'F'); // mPDF 5.5.14
5209
+ $this->SetFColor($this->ConvertColor(255));
5210
+ if (isset($objattr['BORDER-WIDTH'])) { $this->PaintImgBorder($objattr,$is_table); }
5211
+ if (!class_exists('directw', false)) { include(_MPDF_PATH.'classes/directw.php'); }
5212
+ if (empty($this->directw)) { $this->directw = new directw($this); }
5213
+ $save_lmfs = $this->linemaxfontsize;
5214
+ $this->linemaxfontsize = 0;
5215
+ if (isset($objattr['top-text'])) {
5216
+ $this->directw->CircularText($objattr['INNER-X']+$objattr['INNER-WIDTH']/2, $objattr['INNER-Y']+$objattr['INNER-HEIGHT']/2, $objattr['r']/$k, $objattr['top-text'], 'top', $objattr['fontfamily'], $objattr['fontsize']/$k, $objattr['fontstyle'], $objattr['space-width'], $objattr['char-width'], $objattr['divider']); // mPDF 5.5.23
5217
+ }
5218
+ if (isset($objattr['bottom-text'])) {
5219
+ $this->directw->CircularText($objattr['INNER-X']+$objattr['INNER-WIDTH']/2, $objattr['INNER-Y']+$objattr['INNER-HEIGHT']/2, $objattr['r']/$k, $objattr['bottom-text'], 'bottom', $objattr['fontfamily'], $objattr['fontsize']/$k, $objattr['fontstyle'], $objattr['space-width'], $objattr['char-width'], $objattr['divider']); // mPDF 5.5.23
5220
+ }
5221
+ $this->linemaxfontsize = $save_lmfs;
5222
+ }
5223
+
5224
+ $this->ResetSpacing();
5225
+
5226
+ // DOT-TAB
5227
+ if ($objattr['type'] == 'dottab') {
5228
+ // mPDF 5.6.19
5229
+ if (isset($objattr['fontfamily'])) { $this->SetFont($objattr['fontfamily'],'',$objattr['fontsize'] ); }
5230
+ $sp = $this->GetStringWidth(' ');
5231
+ $nb=floor(($w-2*$sp)/$this->GetStringWidth('.'));
5232
+ if ($nb>0) { $dots=' '.str_repeat('.',$nb).' '; }
5233
+ else { $dots=' '; }
5234
+ $col = $this->ConvertColor(0);
5235
+ if (isset($objattr['colorarray']) && ($objattr['colorarray'])) { // mPDF 5.6.19
5236
+ $col = $objattr['colorarray'];
5237
+ }
5238
+ $this->SetTColor($col);
5239
+ $save_dh = $this->divheight; // mPDF 5.6.19
5240
+ $save_sbd = $this->spanborddet;
5241
+ $save_u = $this->U;
5242
+ $save_s = $this->strike;
5243
+ $this->spanborddet = '';
5244
+ $this->divheight = 0; // mPDF 5.6.19
5245
+ $this->U = false;
5246
+ $this->strike = false;
5247
+ $this->Cell($w,$h,$dots,0,0,'C');
5248
+ $this->spanborddet = $save_sbd;
5249
+ $this->U = $save_u;
5250
+ $this->strike = $save_s;
5251
+ $this->divheight = $save_dh; // mPDF 5.6.19
5252
+ // mPDF 5.0
5253
+ $this->SetTColor($this->ConvertColor(0));
5254
+ }
5255
+
5256
+ }
5257
+ $this->SetFont($save_currentfontfamily,$save_currentfontstyle,$save_currentfontsize);
5258
+ $this->y = $save_y;
5259
+ $this->x = $save_x;
5260
+ unset($content);
5261
+ }
5262
+
5263
+
5264
+ function WriteFlowingBlock( $s)
5265
+ {
5266
+ $currentx = $this->x;
5267
+ $is_table = $this->flowingBlockAttr[ 'is_table' ];
5268
+ $is_list = $this->flowingBlockAttr[ 'is_list' ];
5269
+ // width of all the content so far in points
5270
+ $contentWidth =& $this->flowingBlockAttr[ 'contentWidth' ];
5271
+ // cell width in points
5272
+ $maxWidth =& $this->flowingBlockAttr[ 'width' ];
5273
+ $lineCount =& $this->flowingBlockAttr[ 'lineCount' ];
5274
+ // line height in user units
5275
+ $lineHeight =& $this->flowingBlockAttr[ 'height' ];
5276
+ $align =& $this->flowingBlockAttr[ 'align' ];
5277
+ $content =& $this->flowingBlockAttr[ 'content' ];
5278
+ $contentB =& $this->flowingBlockAttr[ 'contentB' ];
5279
+ $font =& $this->flowingBlockAttr[ 'font' ];
5280
+ $valign =& $this->flowingBlockAttr[ 'valign' ];
5281
+ $blockstate = $this->flowingBlockAttr[ 'blockstate' ];
5282
+
5283
+ $newblock = $this->flowingBlockAttr[ 'newblock' ];
5284
+ $blockdir = $this->flowingBlockAttr['blockdir'];
5285
+ // *********** BLOCK BACKGROUND COLOR ***************** //
5286
+ if ($this->blk[$this->blklvl]['bgcolor'] && !$is_table) {
5287
+ $fill = 0;
5288
+ }
5289
+ else {
5290
+ $this->SetFColor($this->ConvertColor(255));
5291
+ $fill = 0;
5292
+ }
5293
+ $font[] = $this->saveFont();
5294
+ $content[] = '';
5295
+ $contentB[] = '';
5296
+ $currContent =& $content[ count( $content ) - 1 ];
5297
+ // where the line should be cutoff if it is to be justified
5298
+ $cutoffWidth = $contentWidth;
5299
+
5300
+ $CJKoverflow = false;
5301
+ $hanger = ''; // mPDF 5.6.40
5302
+
5303
+ // COLS
5304
+ $oldcolumn = $this->CurrCol;
5305
+
5306
+
5307
+ if ($is_table) {
5308
+ $ipaddingL = 0;
5309
+ $ipaddingR = 0;
5310
+ $paddingL = 0;
5311
+ $paddingR = 0;
5312
+ $cpaddingadjustL = 0;
5313
+ $cpaddingadjustR = 0;
5314
+ // Added mPDF 3.0
5315
+ $fpaddingR = 0;
5316
+ $fpaddingL = 0;
5317
+ }
5318
+ else {
5319
+ $ipaddingL = $this->blk[$this->blklvl]['padding_left'];
5320
+ $ipaddingR = $this->blk[$this->blklvl]['padding_right'];
5321
+ $paddingL = ($ipaddingL * _MPDFK);
5322
+ $paddingR = ($ipaddingR * _MPDFK);
5323
+ $this->cMarginL = $this->blk[$this->blklvl]['border_left']['w'];
5324
+ $cpaddingadjustL = -$this->cMarginL;
5325
+ $this->cMarginR = $this->blk[$this->blklvl]['border_right']['w'];
5326
+ $cpaddingadjustR = -$this->cMarginR;
5327
+ // Added mPDF 3.0 Float DIV
5328
+ $fpaddingR = 0;
5329
+ $fpaddingL = 0;
5330
+ if (count($this->floatDivs)) {
5331
+ list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl);
5332
+ if ($r_exists) { $fpaddingR = $r_width; }
5333
+ if ($l_exists) { $fpaddingL = $l_width; }
5334
+ }
5335
+
5336
+ $usey = $this->y + 0.002;
5337
+ if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 0) ) {
5338
+ $usey += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'];
5339
+ }
5340
+ // If float exists at this level
5341
+ if (isset($this->floatmargins['R']) && $usey <= $this->floatmargins['R']['y1'] && $usey >= $this->floatmargins['R']['y0'] && !$this->floatmargins['R']['skipline']) { $fpaddingR += $this->floatmargins['R']['w']; }
5342
+ if (isset($this->floatmargins['L']) && $usey <= $this->floatmargins['L']['y1'] && $usey >= $this->floatmargins['L']['y0'] && !$this->floatmargins['L']['skipline']) { $fpaddingL += $this->floatmargins['L']['w']; }
5343
+ } // *TABLES*
5344
+
5345
+ //OBJECTS - IMAGES & FORM Elements (NB has already skipped line/page if required - in printbuffer)
5346
+ if (substr($s,0,3) == "\xbb\xa4\xac") { //identifier has been identified!
5347
+ $objattr = $this->_getObjAttr($s);
5348
+ $h_corr = 0;
5349
+ if ($is_table) { // *TABLES*
5350
+ $maximumW = ($maxWidth/_MPDFK) - ($this->cellPaddingL + $this->cMarginL + $this->cellPaddingR + $this->cMarginR); // *TABLES*
5351
+ } // *TABLES*
5352
+ else { // *TABLES*
5353
+ if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 0) && (!$is_table)) { $h_corr = $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w']; }
5354
+ $maximumW = ($maxWidth/_MPDFK) - ($this->blk[$this->blklvl]['padding_left'] + $this->blk[$this->blklvl]['border_left']['w'] + $this->blk[$this->blklvl]['padding_right'] + $this->blk[$this->blklvl]['border_right']['w'] + $fpaddingL + $fpaddingR );
5355
+ } // *TABLES*
5356
+ $objattr = $this->inlineObject($objattr['type'],$this->lMargin + $fpaddingL + ($contentWidth/_MPDFK),($this->y + $h_corr), $objattr, $this->lMargin,($contentWidth/_MPDFK),$maximumW,$lineHeight,true,$is_table);
5357
+
5358
+ // SET LINEHEIGHT for this line ================ RESET AT END
5359
+ $lineHeight = MAX($lineHeight,$objattr['OUTER-HEIGHT']);
5360
+ $this->objectbuffer[count($content)-1] = $objattr;
5361
+ // if (isset($objattr['vertical-align'])) { $valign = $objattr['vertical-align']; }
5362
+ // else { $valign = ''; }
5363
+ $contentWidth += ($objattr['OUTER-WIDTH'] * _MPDFK);
5364
+ return;
5365
+ }
5366
+
5367
+ $lbw = $rbw = 0; // Border widths
5368
+ if (!empty($this->spanborddet)) {
5369
+ if (isset($this->spanborddet['L'])) $lbw = $this->spanborddet['L']['w'];
5370
+ if (isset($this->spanborddet['R'])) $rbw = $this->spanborddet['R']['w'];
5371
+ }
5372
+
5373
+ if ($this->usingCoreFont) {
5374
+ $tmp = strlen( $s );
5375
+ }
5376
+ else {
5377
+ $tmp = mb_strlen( $s, $this->mb_enc );
5378
+ }
5379
+
5380
+ // for every character in the string
5381
+ for ( $i = 0; $i < $tmp; $i++ ) {
5382
+ // extract the current character
5383
+ // get the width of the character in points
5384
+ if ($this->usingCoreFont) {
5385
+ $c = $s[$i];
5386
+ // Soft Hyphens chr(173)
5387
+ $cw = ($this->GetCharWidthCore($c) * _MPDFK);
5388
+ if ($this->kerning && $this->useKerning && $i > 0) {
5389
+ if (isset($this->CurrentFont['kerninfo'][$s[($i-1)]][$c])) {
5390
+ $cw += ($this->CurrentFont['kerninfo'][$s[($i-1)]][$c] * $this->FontSizePt / 1000 );
5391
+ }
5392
+ }
5393
+ }
5394
+ else {
5395
+ $c = mb_substr($s,$i,1,$this->mb_enc );
5396
+ $cw = ($this->GetCharWidthNonCore($c, false) * _MPDFK);
5397
+ if ($this->kerning && $this->useKerning && $i > 0) {
5398
+ $lastc = mb_substr($s,($i-1),1,$this->mb_enc );
5399
+ $ulastc = $this->UTF8StringToArray($lastc, false);
5400
+ $uc = $this->UTF8StringToArray($c, false);
5401
+ if (isset($this->CurrentFont['kerninfo'][$ulastc[0]][$uc[0]])) {
5402
+ $cw += ($this->CurrentFont['kerninfo'][$ulastc[0]][$uc[0]] * $this->FontSizePt / 1000 );
5403
+ }
5404
+ }
5405
+ }
5406
+
5407
+ if ($i==0) {
5408
+ $cw += $lbw*_MPDFK;
5409
+ $contentB[(count($contentB)-1)] .= 'L';
5410
+ }
5411
+ if ($i==($tmp-1)) {
5412
+ $cw += $rbw*_MPDFK;
5413
+ $contentB[(count($contentB)-1)] .= 'R';
5414
+ }
5415
+ // mPDF 5.6.45
5416
+ if ($c==' ') {
5417
+ $currContent .= $c;
5418
+ $cutoffWidth = $contentWidth;
5419
+ $contentWidth += $cw;
5420
+ continue;
5421
+ }
5422
+
5423
+ // ADDED for Paragraph_indent
5424
+ $WidthCorrection = 0;
5425
+ if (($newblock) && ($blockstate==1 || $blockstate==3) && isset($this->blk[$this->blklvl]['text_indent']) && ($lineCount == 0) && (!$is_table) && (!$is_list) && ($align != 'C')) {
5426
+ $ti = $this->ConvertSize($this->blk[$this->blklvl]['text_indent'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
5427
+ $WidthCorrection = ($ti*_MPDFK);
5428
+ }
5429
+
5430
+ // Added mPDF 3.0 Float DIV
5431
+ $fpaddingR = 0;
5432
+ $fpaddingL = 0;
5433
+ if (count($this->floatDivs)) {
5434
+ list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl);
5435
+ if ($r_exists) { $fpaddingR = $r_width; }
5436
+ if ($l_exists) { $fpaddingL = $l_width; }
5437
+ }
5438
+
5439
+ $usey = $this->y + 0.002;
5440
+ if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 0) ) {
5441
+ $usey += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'];
5442
+ }
5443
+
5444
+ // If float exists at this level
5445
+ if (isset($this->floatmargins['R']) && $usey <= $this->floatmargins['R']['y1'] && $usey >= $this->floatmargins['R']['y0'] && !$this->floatmargins['R']['skipline']) { $fpaddingR += $this->floatmargins['R']['w']; }
5446
+ if (isset($this->floatmargins['L']) && $usey <= $this->floatmargins['L']['y1'] && $usey >= $this->floatmargins['L']['y0'] && !$this->floatmargins['L']['skipline']) { $fpaddingL += $this->floatmargins['L']['w']; }
5447
+
5448
+
5449
+
5450
+ // try adding another char
5451
+ if (( $contentWidth + $cw > $maxWidth - $WidthCorrection - (($this->cMarginL+$this->cMarginR)*_MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) ) + 0.001)) {// 0.001 is to correct for deviations converting mm=>pts
5452
+ // it won't fit, output what we already have
5453
+ $lineCount++;
5454
+
5455
+ // contains any content that didn't make it into this print
5456
+ $savedContent = '';
5457
+ $savedContentB = '';
5458
+ $savedFont = array();
5459
+ $savedObj = array();
5460
+ // mPDF 5.6.20
5461
+ $savedPreContent = array();
5462
+ $savedPreContentB = array();
5463
+ $savedPreFont = array();
5464
+
5465
+ // cut off and save any partial words at the end of the string
5466
+ $words = explode( ' ', $currContent );
5467
+ ///////////////////
5468
+ // HYPHENATION
5469
+ $currWord = $words[count($words)-1] ;
5470
+ $success = false;
5471
+
5472
+ // mPDF 5.6.21 Hard Hyphens -
5473
+ $hardsuccess = false;
5474
+ if ($this->textparam['hyphens'] != 2 && preg_match("/\-/",$currWord)) {
5475
+ $rem = $maxWidth - $WidthCorrection - (($this->cMarginL+$this->cMarginR)*_MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) );
5476
+ list($hardsuccess,$pre,$post,$prelength) = $this->hardHyphenate($currWord, (($rem-$cutoffWidth)/_MPDFK -$this->GetCharWidth("-", false)) );
5477
+ if ($hardsuccess) {
5478
+ $already = array_pop( $words );
5479
+ $forward = mb_substr($already,$prelength+1,mb_strlen($already, $this->mb_enc), $this->mb_enc);
5480
+ $words[] = $pre.'-';
5481
+ $words[] = $forward;
5482
+ $currContent = mb_substr($currContent,0,mb_strlen($currContent, $this->mb_enc)+1-mb_strlen($post, $this->mb_enc), $this->mb_enc) . '-';
5483
+ }
5484
+ }
5485
+
5486
+
5487
+ // mPDF 5.6.13 Decimal alignment (cancel if wraps to > 1 line)
5488
+ if ($is_table && substr($align,0,1)=='D' ) { $align=substr($align,2,1); }
5489
+
5490
+ // if it looks like we didn't finish any words for this chunk
5491
+ if ( count( $words ) == 1 ) {
5492
+ // TO correct for error when word too wide for page - but only when one long word from left to right margin
5493
+ if (count($content) == 1 && $currContent != ' ') {
5494
+ $lastchar = mb_substr($words[0],mb_strlen($words[0], $this->mb_enc)-1, 1, $this->mb_enc);
5495
+ $lastContent = $words[0];
5496
+ $savedFont = $this->saveFont();
5497
+ // replace the current content with the cropped version
5498
+ $currContent = rtrim( $lastContent );
5499
+ }
5500
+ // mPDF 5.6.20
5501
+ else if ( count($content)>1
5502
+ && (!isset($this->objectbuffer[(count($content)-1)]) && !isset($this->objectbuffer[(count($content)-2)]))
5503
+ && substr($content[count($content)-2],-1,1) != ' '
5504
+ && substr($currContent,0,1) != ' '
5505
+ ) {
5506
+ // Go back to find a space in a previous chunk of content
5507
+ $found = false;
5508
+ for ($ix=count($content)-1;$ix>=0;$ix--) {
5509
+ // mPDF 5.6.29
5510
+ if ($this->usingCoreFont && preg_match('/[ '.chr(173).']/',$content[$ix],$m)) { $match = $m[0]; $found = $ix; break; }
5511
+ else if (!$this->usingCoreFont) {
5512
+ if (preg_match('/[ ]/',$content[$ix])) { $match = ' '; $found = $ix; break; }
5513
+ else if (preg_match('/[\x{00AD}]/u',$content[$ix])) {
5514
+ // even though it is UTF-8 replace it temporarily with chr(173)
5515
+ $content[$ix] = preg_replace('/[\x{00AD}]/u',chr(173),$content[$ix]);
5516
+ $match = chr(173); $found = $ix; break;
5517
+ }
5518
+ }
5519
+ }
5520
+ if ($found !== false) {
5521
+ $charpos = strrpos($content[$found],$match); // mPDF 5.6.29
5522
+ for ($ix=count($content)-1;$ix>$found;$ix--) {
5523
+ // save and crop off any subsequent chunks
5524
+ $savedPreContent[] = array_pop($content);
5525
+ $savedPreContentB[] = array_pop($contentB);
5526
+ $savedPreFont[] = array_pop($font);
5527
+ }
5528
+ if (substr($content[count($content)-1],$charpos+1,strlen($content[count($content)-1])-1) != '') {
5529
+ $savedPreContent[] = substr($content[count($content)-1],$charpos+1,strlen($content[count($content)-1])-1);
5530
+ $savedPreContentB[] = preg_replace('/L/','',$contentB[count($content)-1]); // ???
5531
+ $savedPreFont[] = $font[count($content)-1];
5532
+ }
5533
+ $savedContent = '';
5534
+ $savedContentB = '';
5535
+ $savedFont = array();
5536
+
5537
+ $currContent =& $content[ count( $content ) - 1 ];
5538
+ $currContent = substr($currContent,0,$charpos);
5539
+ if ($match == chr(173)) { $currContent .= '-'; } // mPDF 5.6.29
5540
+ if (strpos($contentB[(count($contentB)-1)],'R')!==false) { // ???
5541
+ $contentB[count($content)-1] = preg_replace('/R/','',$contentB[count($content)-1]); // ???
5542
+ }
5543
+
5544
+ $currContent = rtrim( $currContent );
5545
+ }
5546
+ else {
5547
+ $savedContent = array_pop( $content );
5548
+ $savedContentB = array_pop($contentB);
5549
+ $savedFont = array_pop( $font );
5550
+ $currContent =& $content[ count( $content ) - 1 ];
5551
+ $currContent = rtrim( $currContent );
5552
+ }
5553
+ }
5554
+ else {
5555
+ // save and crop off the content currently on the stack
5556
+ $savedContent = array_pop( $content );
5557
+ $savedContentB = array_pop($contentB); // mPDF 5.6.20
5558
+ $savedFont = array_pop( $font );
5559
+ // trim any trailing spaces off the last bit of content
5560
+ $currContent =& $content[ count( $content ) - 1 ];
5561
+ $currContent = rtrim( $currContent );
5562
+ }
5563
+ }
5564
+ else { // otherwise, we need to find which bit to cut off
5565
+ $lastContent = '';
5566
+ for ( $w = 0; $w < count( $words ) - 1; $w++) { $lastContent .= $words[ $w ]." "; }
5567
+ $savedContent = $words[ count( $words ) - 1 ];
5568
+ $savedFont = $this->saveFont();
5569
+ // replace the current content with the cropped version
5570
+ $currContent = rtrim( $lastContent );
5571
+ }
5572
+ // CJK - strip CJK space at end of line
5573
+ // &#x3000; = \xe3\x80\x80 = CJK space
5574
+
5575
+
5576
+ if (isset($this->objectbuffer[(count($content)-1)]) && $this->objectbuffer[(count($content)-1)]['type']=='dottab') {
5577
+ $savedObj = array_pop( $this->objectbuffer );
5578
+ $contentWidth -= ($this->objectbuffer[(count($content)-1)]['OUTER-WIDTH'] * _MPDFK);
5579
+ }
5580
+
5581
+ // Set Current lineheight (correction factor)
5582
+ $lhfixed = false;
5583
+ if ($is_list) {
5584
+ if (preg_match('/([0-9.,]+)mm/',$this->list_lineheight[$this->listlvl][$this->listOcc],$am)) {
5585
+ $lhfixed = true;
5586
+ $def_fontsize = $this->InlineProperties['LISTITEM'][$this->listlvl][$this->listOcc][$this->listnum]['size'];
5587
+ $this->lineheight_correction = $am[1] / $def_fontsize ;
5588
+ }
5589
+ else {
5590
+ $this->lineheight_correction = $this->list_lineheight[$this->listlvl][$this->listOcc];
5591
+ }
5592
+ }
5593
+ else
5594
+ if ($is_table) {
5595
+ if (preg_match('/([0-9.,]+)mm/',$this->table_lineheight,$am)) {
5596
+ $lhfixed = true;
5597
+ $def_fontsize = $this->FontSize; // needs to be default font-size for block ****
5598
+ $this->lineheight_correction = $lineHeight / $def_fontsize ;
5599
+ }
5600
+ else {
5601
+ $this->lineheight_correction = $this->table_lineheight;
5602
+ }
5603
+ }
5604
+ else
5605
+ if (isset($this->blk[$this->blklvl]['line_height']) && $this->blk[$this->blklvl]['line_height']) {
5606
+ if (preg_match('/([0-9.,]+)mm/',$this->blk[$this->blklvl]['line_height'],$am)) {
5607
+ $lhfixed = true;
5608
+ $def_fontsize = $this->blk[$this->blklvl]['InlineProperties']['size']; // needs to be default font-size for block ****
5609
+ $this->lineheight_correction = $am[1] / $def_fontsize ;
5610
+ }
5611
+ else {
5612
+ $this->lineheight_correction = $this->blk[$this->blklvl]['line_height'];
5613
+ }
5614
+ }
5615
+ else {
5616
+ $this->lineheight_correction = $this->normalLineheight;
5617
+ }
5618
+ // update $contentWidth and $cutoffWidth since they changed with cropping
5619
+ // Also correct lineheight to maximum fontsize (not for tables)
5620
+ $contentWidth = 0;
5621
+ // correct lineheight to maximum fontsize
5622
+ if ($lhfixed) { $maxlineHeight = $this->lineheight; }
5623
+ else { $maxlineHeight = 0; }
5624
+ $this->forceExactLineheight = true;
5625
+ $maxfontsize = 0;
5626
+ // While we're at it, check for cursive text
5627
+ $checkCursive=false;
5628
+ foreach ( $content as $k => $chunk )
5629
+ {
5630
+ $this->restoreFont( $font[ $k ]);
5631
+ if (!isset($this->objectbuffer[$k])) {
5632
+ // mPDF 5.6.40
5633
+ if ($this->checkCJK && $k == count($content)-1 && $CJKoverflow && $align=='J' && $this->allowCJKoverflow && $this->CJKforceend) {
5634
+ // force-end overhang
5635
+ $hanger = mb_substr($chunk,mb_strlen($chunk,$this->mb_enc)-1,1,$this->mb_enc );
5636
+ $content[$k] = $chunk = mb_substr($chunk,0,mb_strlen($chunk,$this->mb_enc)-1,$this->mb_enc );
5637
+ }
5638
+ if (!$this->usingCoreFont) {
5639
+ $content[$k] = $chunk = str_replace("\xc2\xad",'',$chunk );
5640
+ }
5641
+ // Soft Hyphens chr(173)
5642
+ else if ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
5643
+ $content[$k] = $chunk = str_replace(chr(173),'',$chunk );
5644
+ }
5645
+ $contentWidth += $this->GetStringWidth( $chunk ) * _MPDFK;
5646
+ if (!empty($this->spanborddet)) {
5647
+ if (strpos($contentB[$k],'L')!==false) $contentWidth += $this->spanborddet['L']['w'] * _MPDFK;
5648
+ if (strpos($contentB[$k],'R')!==false) $contentWidth += $this->spanborddet['R']['w'] * _MPDFK;
5649
+ }
5650
+ if (!$lhfixed) { $maxlineHeight = max($maxlineHeight,$this->FontSize * $this->lineheight_correction ); }
5651
+ if ($lhfixed && ($this->FontSize > $def_fontsize || ($this->FontSize > ($lineHeight * $this->lineheight_correction) && $is_list))) {
5652
+ $this->forceExactLineheight = false;
5653
+ }
5654
+ $maxfontsize = max($maxfontsize,$this->FontSize);
5655
+ }
5656
+ }
5657
+
5658
+ $lastfontreqstyle = $font[count($font)-1]['ReqFontStyle'];
5659
+ $lastfontstyle = $font[count($font)-1]['style'];
5660
+ if ($blockdir == 'ltr' && strpos($lastfontreqstyle,"I") !== false && strpos($lastfontstyle,"I") === false) { // Artificial italic
5661
+ $lastitalic = $this->FontSize*0.15*_MPDFK;
5662
+ }
5663
+ else { $lastitalic = 0; }
5664
+
5665
+
5666
+ if ($is_list && is_array($this->bulletarray) && $this->bulletarray) {
5667
+ $actfs = $this->bulletarray['fontsize'];
5668
+ if (!$lhfixed) { $maxlineHeight = max($maxlineHeight,$actfs * $this->lineheight_correction ); }
5669
+ if ($lhfixed && $actfs > $def_fontsize) { $this->forceExactLineheight = false; }
5670
+ $maxfontsize = max($maxfontsize,$actfs);
5671
+ }
5672
+
5673
+ // when every text item checked i.e. $maxfontsize is set properly
5674
+
5675
+ $af = 0; // Above font
5676
+ $bf = 0; // Below font
5677
+ $mta = 0; // Maximum top-aligned
5678
+ $mba = 0; // Maximum bottom-aligned
5679
+
5680
+ foreach ( $content as $k => $chunk ) {
5681
+ if (isset($this->objectbuffer[$k]) && $this->objectbuffer[$k]) {
5682
+ $contentWidth += $this->objectbuffer[$k]['OUTER-WIDTH'] * _MPDFK;
5683
+ $oh = $this->objectbuffer[$k]['OUTER-HEIGHT'];
5684
+ $va = $this->objectbuffer[$k]['vertical-align']; // = $objattr['vertical-align'] = set as M,T,B,S
5685
+ if ($lhfixed && $oh > $def_fontsize) { $this->forceExactLineheight = false; }
5686
+
5687
+ if ($va == 'BS') { // (BASELINE default)
5688
+ $af = max($af, ($oh - ($maxfontsize * (0.5 + $this->baselineC))));
5689
+ }
5690
+ else if ($va == 'M') {
5691
+ $af = max($af, ($oh - $maxfontsize)/2);
5692
+ $bf = max($bf, ($oh - $maxfontsize)/2);
5693
+ }
5694
+ else if ($va == 'TT') {
5695
+ $bf = max($bf, ($oh - $maxfontsize));
5696
+ }
5697
+ else if ($va == 'TB') {
5698
+ $af = max($af, ($oh - $maxfontsize));
5699
+ }
5700
+ else if ($va == 'T') {
5701
+ $mta = max($mta, $oh);
5702
+ }
5703
+ else if ($va == 'B') {
5704
+ $mba = max($mba, $oh);
5705
+ }
5706
+ }
5707
+ }
5708
+ if ((!$lhfixed || !$this->forceExactLineheight) && ($af > (($maxlineHeight - $maxfontsize)/2) || $bf > (($maxlineHeight - $maxfontsize)/2))) {
5709
+ $maxlineHeight = $maxfontsize + $af + $bf;
5710
+ }
5711
+ else if (!$lhfixed) { $af = $bf = ($maxlineHeight - $maxfontsize)/2; }
5712
+
5713
+ if ($mta > $maxlineHeight) {
5714
+ $bf += ($mta - $maxlineHeight);
5715
+ $maxlineHeight = $mta;
5716
+ }
5717
+ if ($mba > $maxlineHeight) {
5718
+ $af += ($mba - $maxlineHeight);
5719
+ $maxlineHeight = $mba;
5720
+ }
5721
+
5722
+
5723
+ $lineHeight = $maxlineHeight;
5724
+ $cutoffWidth = $contentWidth;
5725
+ // If NOT images, and maxfontsize NOT > lineHeight - this value determines text baseline positioning
5726
+ if ($lhfixed && $af==0 && $bf==0 && $maxfontsize<=($def_fontsize * $this->lineheight_correction * 0.8 )) {
5727
+ $this->linemaxfontsize = $def_fontsize;
5728
+ }
5729
+ else { $this->linemaxfontsize = $maxfontsize; }
5730
+
5731
+
5732
+ $inclCursive=false;
5733
+ foreach ( $content as $k => $chunk ) {
5734
+ if (!isset($this->objectbuffer[$k]) || (isset($this->objectbuffer[$k]) && !$this->objectbuffer[$k])) {
5735
+ if ($this->usingCoreFont) {
5736
+ $content[$k] = str_replace(chr(160),chr(32),$chunk );
5737
+ }
5738
+ else {
5739
+ $content[$k] = str_replace(chr(194).chr(160),chr(32),$chunk );
5740
+ if ($checkCursive) {
5741
+ }
5742
+ }
5743
+ }
5744
+ }
5745
+
5746
+ // JUSTIFICATION J
5747
+ $jcharspacing = 0;
5748
+ $jws = 0;
5749
+ $nb_carac = 0;
5750
+ $nb_spaces = 0;
5751
+ // if it's justified, we need to find the char/word spacing (or if orphans have allowed length of line to go over the maxwidth)
5752
+ if ( ($align == 'J' && !$CJKoverflow) || (($cutoffWidth + $lastitalic > $maxWidth - $WidthCorrection - (($this->cMarginL+$this->cMarginR)*_MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) ) + 0.001) && (!$CJKoverflow || ($CJKoverflow && !$this->allowCJKoverflow))) || $CJKoverflow && $align=='J' && $this->allowCJKoverflow && $hanger && $this->CJKforceend) { // 0.001 is to correct for deviations converting mm=>pts // mPDF 5.6.40
5753
+ // JUSTIFY J (Use character spacing)
5754
+ // WORD SPACING
5755
+ foreach ( $content as $k => $chunk ) {
5756
+ if (!isset($this->objectbuffer[$k]) || (isset($this->objectbuffer[$k]) && !$this->objectbuffer[$k])) {
5757
+ $nb_carac += mb_strlen( $chunk, $this->mb_enc ) ;
5758
+ $nb_spaces += mb_substr_count( $chunk,' ', $this->mb_enc ) ;
5759
+ }
5760
+ }
5761
+ list($jcharspacing,$jws) = $this->GetJspacing($nb_carac,$nb_spaces,($maxWidth-$lastitalic-$cutoffWidth-$WidthCorrection-(($this->cMarginL+$this->cMarginR)*_MPDFK)-($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) )),$inclCursive);
5762
+ }
5763
+
5764
+
5765
+ // WORD SPACING
5766
+ $empty = $maxWidth - $lastitalic-$WidthCorrection - $contentWidth - (($this->cMarginL+$this->cMarginR)* _MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) );
5767
+
5768
+ $empty -= ($jcharspacing * $nb_carac);
5769
+ $empty -= ($jws * $nb_spaces);
5770
+
5771
+ $empty /= _MPDFK;
5772
+ $b = ''; //do not use borders
5773
+ // Get PAGEBREAK TO TEST for height including the top border/padding
5774
+ $check_h = max($this->divheight,$lineHeight);
5775
+ if (($newblock) && ($blockstate==1 || $blockstate==3) && ($this->blklvl > 0) && ($lineCount == 1) && (!$is_table) && (!$is_list)) {
5776
+ $check_h += ($this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['border_top']['w']);
5777
+ }
5778
+
5779
+ if ($this->ColActive && $check_h > ($this->PageBreakTrigger - $this->y0)) {
5780
+ $this->SetCol($this->NbCol-1);
5781
+ }
5782
+
5783
+ // PAGEBREAK
5784
+ // 'If' below used in order to fix "first-line of other page with justify on" bug
5785
+ if(!$is_table && ($this->y+$check_h) > $this->PageBreakTrigger and !$this->InFooter and $this->AcceptPageBreak()) {
5786
+ $bak_x=$this->x;//Current X position
5787
+
5788
+ // WORD SPACING
5789
+ $ws=$this->ws;//Word Spacing
5790
+ $charspacing=$this->charspacing;//Character Spacing
5791
+ $this->ResetSpacing();
5792
+
5793
+ $this->AddPage($this->CurOrientation);
5794
+
5795
+ $this->x = $bak_x;
5796
+ // Added to correct for OddEven Margins
5797
+ $currentx += $this->MarginCorrection;
5798
+ $this->x += $this->MarginCorrection;
5799
+
5800
+ // WORD SPACING
5801
+ $this->SetSpacing($charspacing,$ws);
5802
+ }
5803
+
5804
+ if ($this->keep_block_together && !$is_table && $this->kt_p00 < $this->page && ($this->y+$check_h) > $this->kt_y00) {
5805
+ $this->printdivbuffer();
5806
+ $this->keep_block_together = 0;
5807
+ }
5808
+
5809
+
5810
+
5811
+ // TOP MARGIN
5812
+ if (($newblock) && ($blockstate==1 || $blockstate==3) && ($this->blk[$this->blklvl]['margin_top']) && ($lineCount == 1) && (!$is_table) && (!$is_list)) {
5813
+ $this->DivLn($this->blk[$this->blklvl]['margin_top'],$this->blklvl-1,true,$this->blk[$this->blklvl]['margin_collapse']);
5814
+ }
5815
+
5816
+
5817
+ // Update y0 for top of block (used to paint border)
5818
+ if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 1) && (!$is_table) && (!$is_list)) {
5819
+ $this->blk[$this->blklvl]['y0'] = $this->y;
5820
+ $this->blk[$this->blklvl]['startpage'] = $this->page;
5821
+ if ($this->blk[$this->blklvl]['float']) { $this->blk[$this->blklvl]['float_start_y'] = $this->y; } // mPDF 5.6.63
5822
+ }
5823
+
5824
+ // TOP PADDING and BORDER spacing/fill
5825
+ if (($newblock) && ($blockstate==1 || $blockstate==3) && (($this->blk[$this->blklvl]['padding_top']) || ($this->blk[$this->blklvl]['border_top'])) && ($lineCount == 1) && (!$is_table) && (!$is_list)) {
5826
+ // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
5827
+ $this->DivLn($this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'],-3,true,false,1);
5828
+ }
5829
+
5830
+ $arraysize = count($content);
5831
+
5832
+ $margins = ($this->cMarginL+$this->cMarginR) + ($ipaddingL+$ipaddingR + $fpaddingR + $fpaddingR );
5833
+
5834
+ // PAINT BACKGROUND FOR THIS LINE
5835
+ if (!$is_table) { $this->DivLn($lineHeight,$this->blklvl,false); } // false -> don't advance y
5836
+
5837
+ $this->x = $currentx + $this->cMarginL + $ipaddingL + $fpaddingL ;
5838
+ if ($align == 'R') { $this->x += $empty; }
5839
+ else if ($align == 'C') { $this->x += ($empty / 2); }
5840
+
5841
+ // Paragraph INDENT
5842
+ if (isset($this->blk[$this->blklvl]['text_indent']) && ($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 1) && (!$is_table) && ($blockdir !='rtl') && ($align !='C')) {
5843
+ $ti = $this->ConvertSize($this->blk[$this->blklvl]['text_indent'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
5844
+ $this->x += $ti;
5845
+ }
5846
+
5847
+ // DIRECTIONALITY RTL
5848
+ $all_rtl = false;
5849
+ $contains_rtl = false;
5850
+
5851
+ foreach ( $content as $k => $chunk ) {
5852
+
5853
+ // FOR IMAGES - UPDATE POSITION
5854
+ if (($blockdir =='rtl' && $contains_rtl) || $all_rtl) { $dirk = $arraysize-1 - $k ; } else { $dirk = $k; }
5855
+
5856
+ $va = 'M'; // default for text
5857
+ if (isset($this->objectbuffer[$dirk]) && $this->objectbuffer[$dirk]) {
5858
+ $xadj = $this->x - $this->objectbuffer[$dirk]['OUTER-X'] ;
5859
+ $this->objectbuffer[$dirk]['OUTER-X'] += $xadj;
5860
+ $this->objectbuffer[$dirk]['BORDER-X'] += $xadj;
5861
+ $this->objectbuffer[$dirk]['INNER-X'] += $xadj;
5862
+ $va = $this->objectbuffer[$dirk]['vertical-align'];
5863
+ $yadj = $this->y - $this->objectbuffer[$dirk]['OUTER-Y'];
5864
+ if ($va == 'BS') {
5865
+ $yadj += $af + ($this->linemaxfontsize * (0.5 + $this->baselineC)) - $this->objectbuffer[$dirk]['OUTER-HEIGHT'];
5866
+ }
5867
+ else if ($va == 'M' || $va == '') {
5868
+ $yadj += $af + ($this->linemaxfontsize /2) - ($this->objectbuffer[$dirk]['OUTER-HEIGHT']/2);
5869
+ }
5870
+ else if ($va == 'TB') {
5871
+ $yadj += $af + $this->linemaxfontsize - $this->objectbuffer[$dirk]['OUTER-HEIGHT'];
5872
+ }
5873
+ else if ($va == 'TT') {
5874
+ $yadj += $af;
5875
+ }
5876
+ else if ($va == 'B') {
5877
+ $yadj += $af + $this->linemaxfontsize + $bf - $this->objectbuffer[$dirk]['OUTER-HEIGHT'];
5878
+ }
5879
+ else if ($va == 'T') {
5880
+ $yadj += 0;
5881
+ }
5882
+ $this->objectbuffer[$dirk]['OUTER-Y'] += $yadj;
5883
+ $this->objectbuffer[$dirk]['BORDER-Y'] += $yadj;
5884
+ $this->objectbuffer[$dirk]['INNER-Y'] += $yadj;
5885
+ }
5886
+
5887
+ // DIRECTIONALITY RTL
5888
+ if ((($blockdir == 'rtl') && ($contains_rtl )) || ($all_rtl )) { $this->restoreFont($font[$arraysize-1 - $k]); }
5889
+ else { $this->restoreFont( $font[ $k ] ); }
5890
+
5891
+ $this->SetSpacing(($this->fixedlSpacing*_MPDFK)+$jcharspacing,($this->fixedlSpacing+$this->minwSpacing)*_MPDFK+$jws);
5892
+ // Now unset these values so they don't influence GetStringwidth below or in fn. Cell
5893
+ $this->fixedlSpacing = false;
5894
+ $this->minwSpacing = 0;
5895
+
5896
+ // mPDF 5.6.26
5897
+ $save_vis = $this->visibility;
5898
+ if (isset($this->textparam['visibility']) && $this->textparam['visibility'] && $this->textparam['visibility'] != $this->visibility) {
5899
+ $this->SetVisibility($this->textparam['visibility']);
5900
+ }
5901
+ // *********** SPAN BACKGROUND COLOR ***************** //
5902
+ if ($this->spanbgcolor) {
5903
+ $cor = $this->spanbgcolorarray;
5904
+ $this->SetFColor($cor);
5905
+ $save_fill = $fill; $spanfill = 1; $fill = 1;
5906
+ }
5907
+ if (!empty($this->spanborddet)) {
5908
+ if (strpos($contentB[$k],'L')!==false) $this->x += $this->spanborddet['L']['w'];
5909
+ if (strpos($contentB[$k],'L')===false) $this->spanborddet['L']['s'] = $this->spanborddet['L']['w'] = 0;
5910
+ if (strpos($contentB[$k],'R')===false) $this->spanborddet['R']['s'] = $this->spanborddet['R']['w'] = 0;
5911
+ }
5912
+
5913
+ // WORD SPACING
5914
+ $stringWidth = $this->GetStringWidth($chunk );
5915
+ $stringWidth += ( $this->charspacing * mb_strlen($chunk,$this->mb_enc ) / _MPDFK );
5916
+ $stringWidth += ( $this->ws * mb_substr_count($chunk,' ',$this->mb_enc ) / _MPDFK );
5917
+ if (isset($this->objectbuffer[$dirk])) { $stringWidth = $this->objectbuffer[$dirk]['OUTER-WIDTH']; }
5918
+
5919
+ if ($stringWidth==0) { $stringWidth = 0.000001; }
5920
+ if ($k == $arraysize-1) {
5921
+ $stringWidth -= ( $this->charspacing / _MPDFK );
5922
+ // mPDF 5.6.40
5923
+ if ($this->checkCJK && $CJKoverflow && $align=='J' && $this->allowCJKoverflow && $hanger && $this->CJKforceend) {
5924
+ // force-end overhang
5925
+ $this->Cell( $stringWidth, $lineHeight, $chunk, '', 0, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, $af, $bf, true );
5926
+ $this->Cell( $this->GetStringWidth($hanger), $lineHeight, $hanger, '', 1, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, $af, $bf, true );
5927
+ }
5928
+ else {
5929
+ $this->Cell( $stringWidth, $lineHeight, $chunk, '', 1, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, $af, $bf, true ); //mono-style line or last part (skips line)
5930
+ }
5931
+
5932
+ }
5933
+ else $this->Cell( $stringWidth, $lineHeight, $chunk, '', 0, '', $fill, $this->HREF, 0, 0,0,'M', $fill, $af, $bf, true );//first or middle part
5934
+
5935
+ if (!empty($this->spanborddet)) {
5936
+ if (strpos($contentB[$k],'R')!==false && $k != $arraysize-1) $this->x += $this->spanborddet['R']['w'];
5937
+ }
5938
+ // *********** SPAN BACKGROUND COLOR OFF - RESET BLOCK BGCOLOR ***************** //
5939
+ if (isset($spanfill) && $spanfill) {
5940
+ $fill = $save_fill; $spanfill = 0;
5941
+ if ($fill) { $this->SetFColor($bcor); }
5942
+ }
5943
+ // mPDF 5.6.26
5944
+ if (isset($this->textparam['visibility']) && $this->textparam['visibility'] && $this->visibility != $save_vis) {
5945
+ $this->SetVisibility($save_vis);
5946
+ }
5947
+
5948
+ }
5949
+ if (!$is_table) {
5950
+ $this->maxPosR = max($this->maxPosR , ($this->w - $this->rMargin - $this->blk[$this->blklvl]['outer_right_margin']));
5951
+ $this->maxPosL = min($this->maxPosL , ($this->lMargin + $this->blk[$this->blklvl]['outer_left_margin']));
5952
+ }
5953
+
5954
+ // move on to the next line, reset variables, tack on saved content and current char
5955
+
5956
+ $this->printobjectbuffer($is_table, $blockdir);
5957
+ $this->objectbuffer = array();
5958
+
5959
+ // LIST BULLETS/NUMBERS
5960
+ if ($is_list && is_array($this->bulletarray) && ($lineCount == 1) ) {
5961
+
5962
+ $this->ResetSpacing();
5963
+
5964
+ $bull = $this->bulletarray;
5965
+ if (isset($bull['level']) && isset($bull['occur']) && isset($this->InlineProperties['LIST'][$bull['level']][$bull['occur']])) {
5966
+ $this->restoreInlineProperties($this->InlineProperties['LIST'][$bull['level']][$bull['occur']]);
5967
+ }
5968
+ if (isset($bull['level']) && isset($bull['occur']) && isset($bull['num']) && isset($this->InlineProperties['LISTITEM'][$bull['level']][$bull['occur']][$bull['num']]) && $this->InlineProperties['LISTITEM'][$bull['level']][$bull['occur']][$bull['num']]) { $this->restoreInlineProperties($this->InlineProperties['LISTITEM'][$bull['level']][$bull['occur']][$bull['num']]); }
5969
+ if (isset($bull['font']) && $bull['font'] == 'czapfdingbats') {
5970
+ $this->bullet = true;
5971
+ $this->SetFont('czapfdingbats','',$this->FontSizePt/2.5);
5972
+ }
5973
+ else { $this->SetFont($this->FontFamily,$this->FontStyle,$this->FontSizePt,true,true); } // force output
5974
+ //Output bullet
5975
+ $this->x = $currentx;
5976
+ if (isset($bull['x'])) { $this->x += $bull['x']; }
5977
+ $this->y -= $lineHeight;
5978
+ if (isset($bull['col']) && $bull['col']) { $this->SetTColor($bull['col']); } // mPDF 5.6.67
5979
+ if (isset($bull['txt'])) { $this->Cell($bull['w'], $lineHeight,$bull['txt'],'','',$bull['align'],0,'',0,-$this->cMarginL, -$this->cMarginR ); }
5980
+ if (isset($bull['font']) && $bull['font'] == 'czapfdingbats') {
5981
+ $this->bullet = false;
5982
+ }
5983
+ $this->x = $currentx; // Reset
5984
+ $this->y += $lineHeight;
5985
+
5986
+
5987
+ $this->bulletarray = array(); // prevents repeat of bullet/number if <li>....<br />.....</li>
5988
+ }
5989
+
5990
+
5991
+ // Update values if set to skipline
5992
+ if ($this->floatmargins) { $this->_advanceFloatMargins(); }
5993
+
5994
+ // Reset lineheight
5995
+ $lineHeight = $this->divheight;
5996
+ $valign = 'M';
5997
+
5998
+ $font = array();
5999
+ $content = array();
6000
+ $contentB = array();
6001
+ $contentWidth = 0;
6002
+ if (!empty($savedObj)) {
6003
+ $this->objectbuffer[] = $savedObj;
6004
+ $font[] = $savedFont;
6005
+ $content[] = '';
6006
+ $contentB[] = '';
6007
+ $contentWidth += $savedObj['OUTER-WIDTH'] * _MPDFK;
6008
+ }
6009
+ // mPDF 5.6.20
6010
+ if (count($savedPreContent) > 0) {
6011
+ for($ix=count($savedPreContent)-1;$ix>=0;$ix--) {
6012
+ $font[] = $savedPreFont[$ix];
6013
+ $content[] = $savedPreContent[$ix];
6014
+ $contentB[] = $savedPreContentB[$ix];
6015
+ $this->restoreFont( $savedPreFont[$ix] );
6016
+ $lbw = $rbw = 0; // Border widths
6017
+ if (!empty($this->spanborddet)) {
6018
+ $lbw = $this->spanborddet['L']['w'];
6019
+ $rbw = $this->spanborddet['R']['w'];
6020
+ }
6021
+ if ($ix>0) {
6022
+ $contentWidth += $this->GetStringWidth( $savedPreContent[$ix] ) * _MPDFK;
6023
+ if (strpos($savedPreContentB[$ix],'L')!==false) $contentWidth += $lbw;
6024
+ if (strpos($savedPreContentB[$ix],'R')!==false) $contentWidth += $rbw;
6025
+ }
6026
+ }
6027
+ $savedPreContent = array();
6028
+ $savedPreContentB = array();
6029
+ $savedPreFont = array();
6030
+ $content[ (count($content)-1) ] .= $c;
6031
+ }
6032
+ else {
6033
+ $font[] = $savedFont;
6034
+ $content[] = $savedContent . $c;
6035
+ $contentB[] = $savedContentB ;
6036
+ }
6037
+
6038
+ $currContent =& $content[ (count($content)-1) ];
6039
+
6040
+ // CJK - strip CJK space at end of line
6041
+ // &#x3000; = \xe3\x80\x80 = CJK space
6042
+
6043
+ $this->restoreFont( $savedFont );
6044
+ $lbw = $rbw = 0; // Border widths
6045
+ if (!empty($this->spanborddet)) {
6046
+ $lbw = $this->spanborddet['L']['w'];
6047
+ $rbw = $this->spanborddet['R']['w'];
6048
+ }
6049
+ $contentWidth += $this->GetStringWidth( $currContent ) * _MPDFK;
6050
+ if (strpos($savedContentB,'L')!==false) $contentWidth += $lbw;
6051
+ $cutoffWidth = $contentWidth;
6052
+ $CJKoverflow = false;
6053
+ $hanger = ''; // mPDF 5.6.40
6054
+ }
6055
+ // another character will fit, so add it on
6056
+ else {
6057
+ $contentWidth += $cw;
6058
+ $currContent .= $c;
6059
+ }
6060
+ }
6061
+ unset($content);
6062
+ unset($contentB);
6063
+ }
6064
+ //----------------------END OF FLOWING BLOCK------------------------------------//
6065
+
6066
+
6067
+ // Update values if set to skipline
6068
+ function _advanceFloatMargins() {
6069
+ // Update floatmargins - L
6070
+ if (isset($this->floatmargins['L']) && $this->floatmargins['L']['skipline'] && $this->floatmargins['L']['y0'] != $this->y) {
6071
+ $yadj = $this->y - $this->floatmargins['L']['y0'];
6072
+ $this->floatmargins['L']['y0'] = $this->y;
6073
+ $this->floatmargins['L']['y1'] += $yadj;
6074
+
6075
+ // Update objattr in floatbuffer
6076
+ if ($this->floatbuffer[$this->floatmargins['L']['id']]['border_left']['w']) {
6077
+ $this->floatbuffer[$this->floatmargins['L']['id']]['BORDER-Y'] += $yadj;
6078
+ }
6079
+ $this->floatbuffer[$this->floatmargins['L']['id']]['INNER-Y'] += $yadj;
6080
+ $this->floatbuffer[$this->floatmargins['L']['id']]['OUTER-Y'] += $yadj;
6081
+
6082
+ // Unset values
6083
+ $this->floatbuffer[$this->floatmargins['L']['id']]['skipline'] = false;
6084
+ $this->floatmargins['L']['skipline'] = false;
6085
+ $this->floatmargins['L']['id'] = '';
6086
+ }
6087
+ // Update floatmargins - R
6088
+ if (isset($this->floatmargins['R']) && $this->floatmargins['R']['skipline'] && $this->floatmargins['R']['y0'] != $this->y) {
6089
+ $yadj = $this->y - $this->floatmargins['R']['y0'];
6090
+ $this->floatmargins['R']['y0'] = $this->y;
6091
+ $this->floatmargins['R']['y1'] += $yadj;
6092
+
6093
+ // Update objattr in floatbuffer
6094
+ if ($this->floatbuffer[$this->floatmargins['R']['id']]['border_left']['w']) {
6095
+ $this->floatbuffer[$this->floatmargins['R']['id']]['BORDER-Y'] += $yadj;
6096
+ }
6097
+ $this->floatbuffer[$this->floatmargins['R']['id']]['INNER-Y'] += $yadj;
6098
+ $this->floatbuffer[$this->floatmargins['R']['id']]['OUTER-Y'] += $yadj;
6099
+
6100
+ // Unset values
6101
+ $this->floatbuffer[$this->floatmargins['R']['id']]['skipline'] = false;
6102
+ $this->floatmargins['R']['skipline'] = false;
6103
+ $this->floatmargins['R']['id'] = '';
6104
+ }
6105
+ }
6106
+
6107
+
6108
+
6109
+ ////////////////////////////////////////////////////////////////////////////////
6110
+ // ADDED forcewrap - to call from inline OBJECT functions to breakwords if necessary in cell
6111
+ ////////////////////////////////////////////////////////////////////////////////
6112
+ function WordWrap(&$text, $maxwidth, $forcewrap = 0) {
6113
+ $biggestword=0;
6114
+ $toonarrow=false;
6115
+
6116
+ $text = trim($text);
6117
+
6118
+ if ($text==='') return 0;
6119
+ $space = $this->GetCharWidth(' ',false);
6120
+ $lines = explode("\n", $text);
6121
+ $text = '';
6122
+ $count = 0;
6123
+ foreach ($lines as $line) {
6124
+ $words = explode(' ', $line);
6125
+ $width = 0;
6126
+ foreach ($words as $word) {
6127
+ $word = trim($word);
6128
+ $wordwidth = $this->GetStringWidth($word);
6129
+ //Warn user that maxwidth is insufficient
6130
+ if ($wordwidth > $maxwidth + 0.0001) {
6131
+ if ($wordwidth > $biggestword) { $biggestword = $wordwidth; }
6132
+ $toonarrow=true;
6133
+ // ADDED
6134
+ if ($forcewrap) {
6135
+ while($wordwidth > $maxwidth) {
6136
+ $chw = 0; // check width
6137
+ for ( $i = 0; $i < mb_strlen($word, $this->mb_enc ); $i++ ) {
6138
+ $chw = $this->GetStringWidth(mb_substr($word,0,$i+1,$this->mb_enc ));
6139
+ if ($chw > $maxwidth ) {
6140
+ if ($text) {
6141
+ $text = rtrim($text)."\n".mb_substr($word,0,$i,$this->mb_enc );
6142
+ $count++;
6143
+ }
6144
+ else {
6145
+ $text = mb_substr($word,0,$i,$this->mb_enc );
6146
+ }
6147
+ $word = mb_substr($word,$i,mb_strlen($word, $this->mb_enc )-$i,$this->mb_enc );
6148
+ $wordwidth = $this->GetStringWidth($word);
6149
+ $width = $maxwidth;
6150
+ break;
6151
+ }
6152
+ }
6153
+ }
6154
+ }
6155
+ }
6156
+
6157
+ if ($width + $wordwidth < $maxwidth - 0.0001) {
6158
+ $width += $wordwidth + $space;
6159
+ $text .= $word.' ';
6160
+ }
6161
+ else {
6162
+ $width = $wordwidth + $space;
6163
+ $text = rtrim($text)."\n".$word.' ';
6164
+ $count++;
6165
+ }
6166
+ }
6167
+ $text .= "\n";
6168
+ $count++;
6169
+ }
6170
+ $text = rtrim($text);
6171
+
6172
+ //Return -(wordsize) if word is bigger than maxwidth
6173
+
6174
+ // ADDED
6175
+ if ($forcewrap) { return $count; }
6176
+ if (($toonarrow) && ($this->table_error_report)) {
6177
+ $this->Error("Word is too long to fit in table - ".$this->table_error_report_param);
6178
+ }
6179
+ if ($toonarrow) return -$biggestword;
6180
+ else return $count;
6181
+ }
6182
+
6183
+
6184
+ function _SetTextRendering($mode) {
6185
+ if (!(($mode == 0) || ($mode == 1) || ($mode == 2)))
6186
+ $this->Error("Text rendering mode should be 0, 1 or 2 (value : $mode)");
6187
+ $tr = ($mode.' Tr');
6188
+ if($this->page>0 && ((isset($this->pageoutput[$this->page]['TextRendering']) && $this->pageoutput[$this->page]['TextRendering'] != $tr) || !isset($this->pageoutput[$this->page]['TextRendering']) || $this->keep_block_together)) { $this->_out($tr); }
6189
+ $this->pageoutput[$this->page]['TextRendering'] = $tr;
6190
+
6191
+ }
6192
+
6193
+ function SetTextOutline($params=array()) { // mPDF 5.6.07
6194
+ if (isset($params['outline-s']) && $params['outline-s'])
6195
+ {
6196
+ $this->SetLineWidth($params['outline-WIDTH']);
6197
+ $this->SetDColor($params['outline-COLOR']);
6198
+ $tr = ('2 Tr');
6199
+ if($this->page>0 && ((isset($this->pageoutput[$this->page]['TextRendering']) && $this->pageoutput[$this->page]['TextRendering'] != $tr) || !isset($this->pageoutput[$this->page]['TextRendering']) || $this->keep_block_together)) { $this->_out($tr); }
6200
+ $this->pageoutput[$this->page]['TextRendering'] = $tr;
6201
+ }
6202
+ else //Now resets all values
6203
+ {
6204
+ $this->SetLineWidth(0.2);
6205
+ $this->SetDColor($this->ConvertColor(0));
6206
+ $this->_SetTextRendering(0);
6207
+ $tr = ('0 Tr');
6208
+ if($this->page>0 && ((isset($this->pageoutput[$this->page]['TextRendering']) && $this->pageoutput[$this->page]['TextRendering'] != $tr) || !isset($this->pageoutput[$this->page]['TextRendering']) || $this->keep_block_together)) { $this->_out($tr); }
6209
+ $this->pageoutput[$this->page]['TextRendering'] = $tr;
6210
+ }
6211
+ }
6212
+
6213
+ function Image($file,$x,$y,$w=0,$h=0,$type='',$link='',$paint=true, $constrain=true, $watermark=false, $shownoimg=true, $allowvector=true) {
6214
+ $orig_srcpath = $file;
6215
+ $this->GetFullPath($file);
6216
+
6217
+ $info=$this->_getImage($file, true, $allowvector, $orig_srcpath );
6218
+ if(!$info && $paint) {
6219
+ $info = $this->_getImage($this->noImageFile);
6220
+ if ($info) {
6221
+ $file = $this->noImageFile;
6222
+ $w = ($info['w'] * (25.4/$this->dpi)); // 14 x 16px
6223
+ $h = ($info['h'] * (25.4/$this->dpi)); // 14 x 16px
6224
+ }
6225
+ }
6226
+ if(!$info) return false;
6227
+ //Automatic width and height calculation if needed
6228
+ if($w==0 and $h==0) {
6229
+ if ($info['type']=='svg') {
6230
+ // returned SVG units are pts
6231
+ // divide by k to get user units (mm)
6232
+ $w = abs($info['w'])/_MPDFK;
6233
+ $h = abs($info['h']) /_MPDFK;
6234
+ }
6235
+ else {
6236
+ //Put image at default image dpi
6237
+ $w=($info['w']/_MPDFK) * (72/$this->img_dpi);
6238
+ $h=($info['h']/_MPDFK) * (72/$this->img_dpi);
6239
+ }
6240
+ }
6241
+ if($w==0) $w=abs($h*$info['w']/$info['h']);
6242
+ if($h==0) $h=abs($w*$info['h']/$info['w']);
6243
+
6244
+
6245
+ if ($constrain) {
6246
+ // Automatically resize to maximum dimensions of page if too large
6247
+ if (isset($this->blk[$this->blklvl]['inner_width']) && $this->blk[$this->blklvl]['inner_width']) { $maxw = $this->blk[$this->blklvl]['inner_width']; }
6248
+ else { $maxw = $this->pgwidth; }
6249
+ if ($w > $maxw) {
6250
+ $w = $maxw;
6251
+ $h=abs($w*$info['h']/$info['w']);
6252
+ }
6253
+ if ($h > $this->h - ($this->tMargin + $this->bMargin + 1)) { // see below - +10 to avoid drawing too close to border of page
6254
+ $h = $this->h - ($this->tMargin + $this->bMargin + 1) ;
6255
+ if ($this->fullImageHeight) { $h = $this->fullImageHeight; }
6256
+ $w=abs($h*$info['w']/$info['h']);
6257
+ }
6258
+
6259
+
6260
+ //Avoid drawing out of the paper(exceeding width limits).
6261
+ //if ( ($x + $w) > $this->fw ) {
6262
+ if ( ($x + $w) > $this->w ) {
6263
+ $x = $this->lMargin;
6264
+ $y += 5;
6265
+ }
6266
+
6267
+ $changedpage = false;
6268
+ $oldcolumn = $this->CurrCol;
6269
+ //Avoid drawing out of the page.
6270
+ if($y+$h>$this->PageBreakTrigger and !$this->InFooter and $this->AcceptPageBreak()) {
6271
+ $this->AddPage($this->CurOrientation);
6272
+ // Added to correct for OddEven Margins
6273
+ $x=$x +$this->MarginCorrection;
6274
+ $y = $tMargin + $this->margin_header;
6275
+ $changedpage = true;
6276
+ }
6277
+ } // end of IF constrain
6278
+
6279
+ if ($info['type']=='svg') {
6280
+ $sx = $w*_MPDFK / $info['w'];
6281
+ $sy = -$h*_MPDFK / $info['h'];
6282
+ $outstring = sprintf('q %.3F 0 0 %.3F %.3F %.3F cm /FO%d Do Q', $sx, $sy, $x*_MPDFK-$sx*$info['x'], (($this->h-$y)*_MPDFK)-$sy*$info['y'], $info['i']);
6283
+ }
6284
+ else {
6285
+ $outstring = sprintf("q %.3F 0 0 %.3F %.3F %.3F cm /I%d Do Q",$w*_MPDFK,$h*_MPDFK,$x*_MPDFK,($this->h-($y+$h))*_MPDFK,$info['i']);
6286
+ }
6287
+
6288
+ if($paint) {
6289
+ $this->_out($outstring);
6290
+ if($link) $this->Link($x,$y,$w,$h,$link);
6291
+
6292
+ // Avoid writing text on top of the image. // THIS WAS OUTSIDE THE if ($paint) bit!!!!!!!!!!!!!!!!
6293
+ $this->y = $y + $h;
6294
+ }
6295
+
6296
+ //Return width-height array
6297
+ $sizesarray['WIDTH'] = $w;
6298
+ $sizesarray['HEIGHT'] = $h;
6299
+ $sizesarray['X'] = $x; //Position before painting image
6300
+ $sizesarray['Y'] = $y; //Position before painting image
6301
+ $sizesarray['OUTPUT'] = $outstring;
6302
+
6303
+ $sizesarray['IMAGE_ID'] = $info['i'];
6304
+ $sizesarray['itype'] = $info['type'];
6305
+ $sizesarray['set-dpi'] = $info['set-dpi'];
6306
+ return $sizesarray;
6307
+ }
6308
+
6309
+
6310
+
6311
+ //=============================================================
6312
+ //=============================================================
6313
+ //=============================================================
6314
+ //=============================================================
6315
+ //=============================================================
6316
+
6317
+ function _getObjAttr($t) {
6318
+ $c = explode("\xbb\xa4\xac",$t,2);
6319
+ $c = explode(",",$c[1],2);
6320
+ foreach($c as $v) {
6321
+ $v = explode("=",$v,2);
6322
+ $sp[$v[0]] = $v[1];
6323
+ }
6324
+ return (unserialize($sp['objattr']));
6325
+ }
6326
+
6327
+
6328
+ function inlineObject($type,$x,$y,$objattr,$Lmargin,$widthUsed,$maxWidth,$lineHeight,$paint=false,$is_table=false)
6329
+ {
6330
+ if ($is_table) { $k = $this->shrin_k; } else { $k = 1; }
6331
+
6332
+ // NB $x is only used when paint=true
6333
+ // Lmargin not used
6334
+ $w = 0;
6335
+ if (isset($objattr['width'])) { $w = $objattr['width']/$k; }
6336
+ $h = 0;
6337
+ if (isset($objattr['height'])) { $h = abs($objattr['height']/$k); }
6338
+ $widthLeft = $maxWidth - $widthUsed;
6339
+ $maxHeight = $this->h - ($this->tMargin + $this->bMargin + 10) ;
6340
+ if ($this->fullImageHeight) { $maxHeight = $this->fullImageHeight; }
6341
+ // For Images
6342
+ if (isset($objattr['border_left'])) {
6343
+ $extraWidth = ($objattr['border_left']['w'] + $objattr['border_right']['w'] + $objattr['margin_left']+ $objattr['margin_right'])/$k;
6344
+ $extraHeight = ($objattr['border_top']['w'] + $objattr['border_bottom']['w'] + $objattr['margin_top']+ $objattr['margin_bottom'])/$k;
6345
+
6346
+ if ($type == 'image' || $type == 'barcode' || $type == 'textcircle') {
6347
+ $extraWidth += ($objattr['padding_left'] + $objattr['padding_right'])/$k;
6348
+ $extraHeight += ($objattr['padding_top'] + $objattr['padding_bottom'])/$k;
6349
+ }
6350
+ }
6351
+
6352
+ if (!isset($objattr['vertical-align'])) { $objattr['vertical-align'] = 'M'; }
6353
+
6354
+ if ($type == 'image' || (isset($objattr['subtype']) && $objattr['subtype'] == 'IMAGE')) {
6355
+ if (isset($objattr['itype']) && ($objattr['itype'] == 'wmf' || $objattr['itype'] == 'svg')) {
6356
+ $file = $objattr['file'];
6357
+ $info=$this->formobjects[$file];
6358
+ }
6359
+ else if (isset($objattr['file'])) {
6360
+ $file = $objattr['file'];
6361
+ $info=$this->images[$file];
6362
+ }
6363
+ }
6364
+ if ($type == 'annot' || $type == 'bookmark' || $type == 'indexentry' || $type == 'toc') {
6365
+ $w = 0.00001;
6366
+ $h = 0.00001;
6367
+ }
6368
+
6369
+ // TEST whether need to skipline
6370
+ if (!$paint) {
6371
+ if ($type == 'hr') { // always force new line
6372
+ if (($y + $h + $lineHeight > $this->PageBreakTrigger) && !$this->InFooter && !$is_table) { return array(-2, $w ,$h ); } // New page + new line
6373
+ else { return array(1, $w ,$h ); } // new line
6374
+ }
6375
+ else {
6376
+ if ($widthUsed > 0 && $w > $widthLeft && (!$is_table || $type != 'image')) { // New line needed
6377
+ if (($y + $h + $lineHeight > $this->PageBreakTrigger) && !$this->InFooter) { return array(-2,$w ,$h ); } // New page + new line
6378
+ return array(1,$w ,$h ); // new line
6379
+ }
6380
+ else if ($widthUsed > 0 && $w > $widthLeft && $is_table) { // New line needed in TABLE
6381
+ return array(1,$w ,$h ); // new line
6382
+ }
6383
+ // Will fit on line but NEW PAGE REQUIRED
6384
+ else if (($y + $h > $this->PageBreakTrigger) && !$this->InFooter && !$is_table) { return array(-1,$w ,$h ); }
6385
+ else { return array(0,$w ,$h ); }
6386
+ }
6387
+ }
6388
+
6389
+ if ($type == 'annot' || $type == 'bookmark' || $type == 'indexentry' || $type == 'toc') {
6390
+ $w = 0.00001;
6391
+ $h = 0.00001;
6392
+ $objattr['BORDER-WIDTH'] = 0;
6393
+ $objattr['BORDER-HEIGHT'] = 0;
6394
+ $objattr['BORDER-X'] = $x;
6395
+ $objattr['BORDER-Y'] = $y;
6396
+ $objattr['INNER-WIDTH'] = 0;
6397
+ $objattr['INNER-HEIGHT'] = 0;
6398
+ $objattr['INNER-X'] = $x;
6399
+ $objattr['INNER-Y'] = $y;
6400
+ }
6401
+
6402
+ if ($type == 'image') {
6403
+ // Automatically resize to width remaining
6404
+ if ($w > $widthLeft && !$is_table) {
6405
+ $w = $widthLeft ;
6406
+ $h=abs($w*$info['h']/$info['w']);
6407
+ }
6408
+ $img_w = $w - $extraWidth ;
6409
+ $img_h = $h - $extraHeight ;
6410
+
6411
+ $objattr['BORDER-WIDTH'] = $img_w + $objattr['padding_left']/$k + $objattr['padding_right']/$k + (($objattr['border_left']['w']/$k + $objattr['border_right']['w']/$k)/2) ;
6412
+ $objattr['BORDER-HEIGHT'] = $img_h + $objattr['padding_top']/$k + $objattr['padding_bottom']/$k + (($objattr['border_top']['w']/$k + $objattr['border_bottom']['w']/$k)/2) ;
6413
+ $objattr['BORDER-X'] = $x + $objattr['margin_left']/$k + (($objattr['border_left']['w']/$k)/2) ;
6414
+ $objattr['BORDER-Y'] = $y + $objattr['margin_top']/$k + (($objattr['border_top']['w']/$k)/2) ;
6415
+ $objattr['INNER-WIDTH'] = $img_w;
6416
+ $objattr['INNER-HEIGHT'] = $img_h;
6417
+ $objattr['INNER-X'] = $x + $objattr['padding_left']/$k + $objattr['margin_left']/$k + ($objattr['border_left']['w']/$k);
6418
+ $objattr['INNER-Y'] = $y + $objattr['padding_top']/$k + $objattr['margin_top']/$k + ($objattr['border_top']['w']/$k) ;
6419
+ $objattr['ID'] = $info['i'];
6420
+ }
6421
+
6422
+ if ($type == 'input' && $objattr['subtype'] == 'IMAGE') {
6423
+ $img_w = $w - $extraWidth ;
6424
+ $img_h = $h - $extraHeight ;
6425
+ $objattr['BORDER-WIDTH'] = $img_w + (($objattr['border_left']['w']/$k + $objattr['border_right']['w']/$k)/2) ;
6426
+ $objattr['BORDER-HEIGHT'] = $img_h + (($objattr['border_top']['w']/$k + $objattr['border_bottom']['w']/$k)/2) ;
6427
+ $objattr['BORDER-X'] = $x + $objattr['margin_left']/$k + (($objattr['border_left']['w']/$k)/2) ;
6428
+ $objattr['BORDER-Y'] = $y + $objattr['margin_top']/$k + (($objattr['border_top']['w']/$k)/2) ;
6429
+ $objattr['INNER-WIDTH'] = $img_w;
6430
+ $objattr['INNER-HEIGHT'] = $img_h;
6431
+ $objattr['INNER-X'] = $x + $objattr['margin_left']/$k + ($objattr['border_left']['w']/$k);
6432
+ $objattr['INNER-Y'] = $y + $objattr['margin_top']/$k + ($objattr['border_top']['w']/$k) ;
6433
+ $objattr['ID'] = $info['i'];
6434
+ }
6435
+
6436
+ if ($type == 'barcode' || $type == 'textcircle') {
6437
+ $b_w = $w - $extraWidth ;
6438
+ $b_h = $h - $extraHeight ;
6439
+ $objattr['BORDER-WIDTH'] = $b_w + $objattr['padding_left']/$k + $objattr['padding_right']/$k + (($objattr['border_left']['w']/$k + $objattr['border_right']['w']/$k)/2) ;
6440
+ $objattr['BORDER-HEIGHT'] = $b_h + $objattr['padding_top']/$k + $objattr['padding_bottom']/$k + (($objattr['border_top']['w']/$k + $objattr['border_bottom']['w']/$k)/2) ;
6441
+ $objattr['BORDER-X'] = $x + $objattr['margin_left']/$k + (($objattr['border_left']['w']/$k)/2) ;
6442
+ $objattr['BORDER-Y'] = $y + $objattr['margin_top']/$k + (($objattr['border_top']['w']/$k)/2) ;
6443
+ $objattr['INNER-X'] = $x + $objattr['padding_left']/$k + $objattr['margin_left']/$k + ($objattr['border_left']['w']/$k);
6444
+ $objattr['INNER-Y'] = $y + $objattr['padding_top']/$k + $objattr['margin_top']/$k + ($objattr['border_top']['w']/$k) ;
6445
+ $objattr['INNER-WIDTH'] = $b_w;
6446
+ $objattr['INNER-HEIGHT'] = $b_h;
6447
+ }
6448
+
6449
+
6450
+ if ($type == 'textarea') {
6451
+ // Automatically resize to width remaining
6452
+ if ($w > $widthLeft && !$is_table) {
6453
+ $w = $widthLeft ;
6454
+ }
6455
+ if (($y + $h > $this->PageBreakTrigger) && !$this->InFooter) {
6456
+ $h=$this->h - $y - $this->bMargin;
6457
+ }
6458
+ }
6459
+
6460
+ if ($type == 'hr') {
6461
+ if ($is_table) {
6462
+ $objattr['INNER-WIDTH'] = $maxWidth * $objattr['W-PERCENT']/100;
6463
+ $objattr['width'] = $objattr['INNER-WIDTH'];
6464
+ $w = $maxWidth;
6465
+ }
6466
+ else {
6467
+ if ($w>$maxWidth) { $w = $maxWidth; }
6468
+ $objattr['INNER-WIDTH'] = $w;
6469
+ $w = $maxWidth;
6470
+ }
6471
+ }
6472
+
6473
+
6474
+
6475
+ if (($type == 'select') || ($type == 'input' && ($objattr['subtype'] == 'TEXT' || $objattr['subtype'] == 'PASSWORD'))) {
6476
+ // Automatically resize to width remaining
6477
+ if ($w > $widthLeft && !$is_table) {
6478
+ $w = $widthLeft;
6479
+ }
6480
+ }
6481
+
6482
+ if ($type == 'textarea' || $type == 'select' || $type == 'input') {
6483
+ if (isset($objattr['fontsize'])) $objattr['fontsize'] /= $k;
6484
+ if (isset($objattr['linewidth'])) $objattr['linewidth'] /= $k;
6485
+ }
6486
+
6487
+ if (!isset($objattr['BORDER-Y'])) { $objattr['BORDER-Y'] = 0; }
6488
+ if (!isset($objattr['BORDER-X'])) { $objattr['BORDER-X'] = 0; }
6489
+ if (!isset($objattr['INNER-Y'])) { $objattr['INNER-Y'] = 0; }
6490
+ if (!isset($objattr['INNER-X'])) { $objattr['INNER-X'] = 0; }
6491
+
6492
+ //Return width-height array
6493
+ $objattr['OUTER-WIDTH'] = $w;
6494
+ $objattr['OUTER-HEIGHT'] = $h;
6495
+ $objattr['OUTER-X'] = $x;
6496
+ $objattr['OUTER-Y'] = $y;
6497
+ return $objattr;
6498
+ }
6499
+
6500
+
6501
+ //=============================================================
6502
+ //=============================================================
6503
+ //=============================================================
6504
+ //=============================================================
6505
+ //=============================================================
6506
+
6507
+ function SetLineJoin($mode=0)
6508
+ {
6509
+ $s=sprintf('%d j',$mode);
6510
+ if($this->page>0 && ((isset($this->pageoutput[$this->page]['LineJoin']) && $this->pageoutput[$this->page]['LineJoin'] != $s) || !isset($this->pageoutput[$this->page]['LineJoin']) || $this->keep_block_together)) { $this->_out($s); }
6511
+ $this->pageoutput[$this->page]['LineJoin'] = $s;
6512
+
6513
+ }
6514
+ function SetLineCap($mode=2) {
6515
+ $s=sprintf('%d J',$mode);
6516
+ if($this->page>0 && ((isset($this->pageoutput[$this->page]['LineCap']) && $this->pageoutput[$this->page]['LineCap'] != $s) || !isset($this->pageoutput[$this->page]['LineCap']) || $this->keep_block_together)) { $this->_out($s); }
6517
+ $this->pageoutput[$this->page]['LineCap'] = $s;
6518
+
6519
+ }
6520
+
6521
+ function SetDash($black=false,$white=false)
6522
+ {
6523
+ if($black and $white) $s=sprintf('[%.3F %.3F] 0 d',$black*_MPDFK,$white*_MPDFK);
6524
+ else $s='[] 0 d';
6525
+ if($this->page>0 && ((isset($this->pageoutput[$this->page]['Dash']) && $this->pageoutput[$this->page]['Dash'] != $s) || !isset($this->pageoutput[$this->page]['Dash']) || $this->keep_block_together)) { $this->_out($s); }
6526
+ $this->pageoutput[$this->page]['Dash'] = $s;
6527
+
6528
+ }
6529
+
6530
+ function SetDisplayPreferences($preferences) {
6531
+ // String containing any or none of /HideMenubar/HideToolbar/HideWindowUI/DisplayDocTitle/CenterWindow/FitWindow
6532
+ $this->DisplayPreferences .= $preferences;
6533
+ }
6534
+
6535
+
6536
+ function Ln($h='',$collapsible=0)
6537
+ {
6538
+ // Added collapsible to allow collapsible top-margin on new page
6539
+ //Line feed; default value is last cell height
6540
+ $this->x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'];
6541
+ if ($collapsible && ($this->y==$this->tMargin) && (!$this->ColActive)) { $h = 0; }
6542
+ if(is_string($h)) $this->y+=$this->lasth;
6543
+ else $this->y+=$h;
6544
+ }
6545
+
6546
+ // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
6547
+ function DivLn($h,$level=-3,$move_y=true,$collapsible=false,$state=0) {
6548
+ // this->x is returned as it was
6549
+ // adds lines (y) where DIV bgcolors are filled in
6550
+ // allows .00001 as nominal height used for bookmarks/annotations etc.
6551
+ if ($collapsible && (sprintf("%0.4f", $this->y)==sprintf("%0.4f", $this->tMargin)) && (!$this->ColActive)) { return; }
6552
+
6553
+ // Still use this method if columns or page-break-inside: avoid, as it allows repositioning later
6554
+ // otherwise, now uses PaintDivBB()
6555
+ if (!$this->ColActive && !$this->keep_block_together && !$this->kwt) {
6556
+ if ($move_y && !$this->ColActive) { $this->y += $h; }
6557
+ return;
6558
+ }
6559
+
6560
+ if ($level == -3) { $level = $this->blklvl; }
6561
+ $firstblockfill = $this->GetFirstBlockFill();
6562
+ if ($firstblockfill && $this->blklvl > 0 && $this->blklvl >= $firstblockfill) {
6563
+ $last_x = 0;
6564
+ $last_w = 0;
6565
+ $last_fc = $this->FillColor;
6566
+ $bak_x = $this->x;
6567
+ $bak_h = $this->divheight;
6568
+ $this->divheight = 0; // Temporarily turn off divheight - as Cell() uses it to check for PageBreak
6569
+ for ($blvl=$firstblockfill;$blvl<=$level;$blvl++) {
6570
+ $this->SetBlockFill($blvl);
6571
+ $this->x = $this->lMargin + $this->blk[$blvl]['outer_left_margin'];
6572
+ if ($last_x != $this->lMargin + $this->blk[$blvl]['outer_left_margin'] || $last_w != $this->blk[$blvl]['width'] || $last_fc != $this->FillColor || $this->blk[$blvl]['border_top']['s'] || $this->blk[$blvl]['border_bottom']['s'] || $this->blk[$blvl]['border_left']['s'] || $this->blk[$blvl]['border_right']['s']) { // mPDF 5.6.55
6573
+ $x = $this->x;
6574
+ $this->Cell( ($this->blk[$blvl]['width']), $h, '', '', 0, '', 1);
6575
+ if (!$this->keep_block_together && !$this->writingHTMLheader && !$this->writingHTMLfooter) {
6576
+ $this->x = $x;
6577
+ // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
6578
+ if ($blvl == $this->blklvl) { $this->PaintDivLnBorder($state,$blvl,$h); }
6579
+ else { $this->PaintDivLnBorder(0,$blvl,$h); }
6580
+ }
6581
+ }
6582
+ $last_x = $this->lMargin + $this->blk[$blvl]['outer_left_margin'];
6583
+ $last_w = $this->blk[$blvl]['width'];
6584
+ $last_fc = $this->FillColor;
6585
+ }
6586
+ // Reset current block fill
6587
+ if (isset($this->blk[$this->blklvl]['bgcolorarray'])) {
6588
+ $bcor = $this->blk[$this->blklvl]['bgcolorarray'];
6589
+ $this->SetFColor($bcor);
6590
+ }
6591
+ $this->x = $bak_x;
6592
+ $this->divheight = $bak_h;
6593
+ }
6594
+ if ($move_y) { $this->y += $h; }
6595
+ }
6596
+
6597
+
6598
+ function SetX($x)
6599
+ {
6600
+ //Set x position
6601
+ if($x >= 0) $this->x=$x;
6602
+ else $this->x = $this->w + $x;
6603
+ }
6604
+
6605
+ function SetY($y)
6606
+ {
6607
+ //Set y position and reset x
6608
+ $this->x=$this->lMargin;
6609
+ if($y>=0)
6610
+ $this->y=$y;
6611
+ else
6612
+ $this->y=$this->h+$y;
6613
+ }
6614
+
6615
+ function SetXY($x,$y)
6616
+ {
6617
+ //Set x and y positions
6618
+ $this->SetY($y);
6619
+ $this->SetX($x);
6620
+ }
6621
+
6622
+
6623
+ function Output($name='',$dest='')
6624
+ {
6625
+ //Output PDF to some destination
6626
+ if ($this->showStats) {
6627
+ echo '<div>Generated in '.sprintf('%.2F',(microtime(true) - $this->time0)).' seconds</div>';
6628
+ }
6629
+ //Finish document if necessary
6630
+ if($this->state < 3) $this->Close();
6631
+ // fn. error_get_last is only in PHP>=5.2
6632
+ if ($this->debug && function_exists('error_get_last') && error_get_last()) {
6633
+ $e = error_get_last();
6634
+ if (($e['type'] < 2048 && $e['type'] != 8) || (intval($e['type']) & intval(ini_get("error_reporting")))) {
6635
+ echo "<p>Error message detected - PDF file generation aborted.</p>";
6636
+ echo $e['message'].'<br />';
6637
+ echo 'File: '.$e['file'].'<br />';
6638
+ echo 'Line: '.$e['line'].'<br />';
6639
+ exit;
6640
+ }
6641
+ }
6642
+
6643
+
6644
+ if (($this->PDFA || $this->PDFX) && $this->encrypted) { $this->Error("PDFA1-b or PDFX/1-a does not permit encryption of documents."); }
6645
+ if (count($this->PDFAXwarnings) && (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto))) {
6646
+ if ($this->PDFA) {
6647
+ echo '<div>WARNING - This file could not be generated as it stands as a PDFA1-b compliant file.</div>';
6648
+ echo '<div>These issues can be automatically fixed by mPDF using <i>$mpdf-&gt;PDFAauto=true;</i></div>';
6649
+ echo '<div>Action that mPDF will take to automatically force PDFA1-b compliance are shown in brackets.</div>';
6650
+ }
6651
+ else {
6652
+ echo '<div>WARNING - This file could not be generated as it stands as a PDFX/1-a compliant file.</div>';
6653
+ echo '<div>These issues can be automatically fixed by mPDF using <i>$mpdf-&gt;PDFXauto=true;</i></div>';
6654
+ echo '<div>Action that mPDF will take to automatically force PDFX/1-a compliance are shown in brackets.</div>';
6655
+ }
6656
+ echo '<div>Warning(s) generated:</div><ul>';
6657
+ $this->PDFAXwarnings = array_unique($this->PDFAXwarnings);
6658
+ foreach($this->PDFAXwarnings AS $w) {
6659
+ echo '<li>'.$w.'</li>';
6660
+ }
6661
+ echo '</ul>';
6662
+ exit;
6663
+ }
6664
+
6665
+ if ($this->showStats) {
6666
+ echo '<div>Compiled in '.sprintf('%.2F',(microtime(true) - $this->time0)).' seconds (total)</div>';
6667
+ echo '<div>Peak Memory usage '.number_format((memory_get_peak_usage(true)/(1024*1024)),2).' MB</div>';
6668
+ echo '<div>PDF file size '.number_format((strlen($this->buffer)/1024)).' kB</div>';
6669
+ echo '<div>Number of fonts '.count($this->fonts).'</div>';
6670
+ exit;
6671
+ }
6672
+
6673
+
6674
+ if(is_bool($dest)) $dest=$dest ? 'D' : 'F';
6675
+ $dest=strtoupper($dest);
6676
+ if($dest=='') {
6677
+ if($name=='') {
6678
+ $name='mpdf.pdf';
6679
+ $dest='I';
6680
+ }
6681
+ else { $dest='F'; }
6682
+ }
6683
+
6684
+
6685
+ switch($dest) {
6686
+ case 'I':
6687
+ if ($this->debug && !$this->allow_output_buffering && ob_get_contents()) { echo "<p>Output has already been sent from the script - PDF file generation aborted.</p>"; exit; }
6688
+ //Send to standard output
6689
+ if(PHP_SAPI!='cli') {
6690
+ //We send to a browser
6691
+ header('Content-Type: application/pdf');
6692
+ if(headers_sent())
6693
+ $this->Error('Some data has already been output to browser, can\'t send PDF file');
6694
+ if (!isset($_SERVER['HTTP_ACCEPT_ENCODING']) OR empty($_SERVER['HTTP_ACCEPT_ENCODING'])) {
6695
+ // don't use length if server using compression
6696
+ header('Content-Length: '.strlen($this->buffer));
6697
+ }
6698
+ header('Content-disposition: inline; filename="'.$name.'"');
6699
+ header('Cache-Control: public, must-revalidate, max-age=0');
6700
+ header('Pragma: public');
6701
+ header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
6702
+ header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
6703
+ }
6704
+ echo $this->buffer;
6705
+ break;
6706
+ case 'D':
6707
+ //Download file
6708
+ header('Content-Description: File Transfer');
6709
+ if (headers_sent())
6710
+ $this->Error('Some data has already been output to browser, can\'t send PDF file');
6711
+ header('Content-Transfer-Encoding: binary');
6712
+ header('Cache-Control: public, must-revalidate, max-age=0');
6713
+ header('Pragma: public');
6714
+ header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
6715
+ header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
6716
+ header('Content-Type: application/force-download');
6717
+ header('Content-Type: application/octet-stream', false);
6718
+ header('Content-Type: application/download', false);
6719
+ header('Content-Type: application/pdf', false);
6720
+ if (!isset($_SERVER['HTTP_ACCEPT_ENCODING']) OR empty($_SERVER['HTTP_ACCEPT_ENCODING'])) {
6721
+ // don't use length if server using compression
6722
+ header('Content-Length: '.strlen($this->buffer));
6723
+ }
6724
+ header('Content-disposition: attachment; filename="'.$name.'"');
6725
+ echo $this->buffer;
6726
+ break;
6727
+ case 'F':
6728
+ //Save to local file
6729
+ $f=fopen($name,'wb');
6730
+ if(!$f) $this->Error('Unable to create output file: '.$name);
6731
+ fwrite($f,$this->buffer,strlen($this->buffer));
6732
+ fclose($f);
6733
+ break;
6734
+ case 'S':
6735
+ //Return as a string
6736
+ return $this->buffer;
6737
+ default:
6738
+ $this->Error('Incorrect output destination: '.$dest);
6739
+ }
6740
+
6741
+ //======================================================================================================
6742
+ // DELETE OLD TMP FILES - Housekeeping
6743
+ // Delete any files in tmp/ directory that are >1 hrs old
6744
+ $interval = 3600;
6745
+ if ($handle = opendir(preg_replace('/\/$/','',_MPDF_TEMP_PATH))) {
6746
+ while (false !== ($file = readdir($handle))) {
6747
+ if (!is_dir($file) && ((filemtime(_MPDF_TEMP_PATH.$file)+$interval) < time()) && ($file != "..") && ($file != ".")) { // mPDF 5.4.19
6748
+ unlink(_MPDF_TEMP_PATH.$file);
6749
+ }
6750
+ }
6751
+ closedir($handle);
6752
+ }
6753
+ //==============================================================================================================
6754
+
6755
+ return '';
6756
+ }
6757
+
6758
+
6759
+ // *****************************************************************************
6760
+ // *
6761
+ // Protected methods *
6762
+ // *
6763
+ // *****************************************************************************
6764
+ function _dochecks()
6765
+ {
6766
+ //Check for locale-related bug
6767
+ if(1.1==1)
6768
+ $this->Error('Don\'t alter the locale before including mPDF');
6769
+ //Check for decimal separator
6770
+ if(sprintf('%.1f',1.0)!='1.0')
6771
+ setlocale(LC_NUMERIC,'C');
6772
+ // mPDF 5.4.11
6773
+ $mqr=ini_get("magic_quotes_runtime");
6774
+ if ($mqr) { $this->Error('mPDF requires magic_quotes_runtime to be turned off e.g. by using ini_set("magic_quotes_runtime", 0);'); }
6775
+ }
6776
+
6777
+ function _begindoc()
6778
+ {
6779
+ //Start document
6780
+ $this->state=1;
6781
+ $this->_out('%PDF-'.$this->pdf_version);
6782
+ $this->_out('%'.chr(226).chr(227).chr(207).chr(211)); // 4 chars > 128 to show binary file
6783
+ }
6784
+
6785
+
6786
+ function _puthtmlheaders() {
6787
+ $this->state=2;
6788
+ $nb=$this->page;
6789
+ for($n=1;$n<=$nb;$n++) {
6790
+ if ($this->mirrorMargins && $n%2==0) { $OE = 'E'; } // EVEN
6791
+ else { $OE = 'O'; }
6792
+ $this->page = $n;
6793
+ if (isset($this->saveHTMLHeader[$n][$OE])) {
6794
+ $html = $this->saveHTMLHeader[$n][$OE]['html'];
6795
+ $this->lMargin = $this->saveHTMLHeader[$n][$OE]['ml'];
6796
+ $this->rMargin = $this->saveHTMLHeader[$n][$OE]['mr'];
6797
+ $this->tMargin = $this->saveHTMLHeader[$n][$OE]['mh'];
6798
+ $this->bMargin = $this->saveHTMLHeader[$n][$OE]['mf'];
6799
+ $this->margin_header = $this->saveHTMLHeader[$n][$OE]['mh'];
6800
+ $this->margin_footer = $this->saveHTMLHeader[$n][$OE]['mf'];
6801
+ $this->w = $this->saveHTMLHeader[$n][$OE]['pw'];
6802
+ $this->h = $this->saveHTMLHeader[$n][$OE]['ph'];
6803
+ $rotate = (isset($this->saveHTMLHeader[$n][$OE]['rotate']) ? $this->saveHTMLHeader[$n][$OE]['rotate'] : null);
6804
+ $this->Reset();
6805
+ $this->pageoutput[$n] = array();
6806
+ $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
6807
+ $this->x = $this->lMargin;
6808
+ $this->y = $this->margin_header;
6809
+ // mPDF 5.6.47
6810
+ $pn = $this->docPageNum($n);
6811
+ if ($pn)
6812
+ $pnstr = $this->pagenumPrefix.$pn.$this->pagenumSuffix;
6813
+ else { $pnstr = ''; }
6814
+ $html = str_replace('{PAGENO}',$pnstr,$html);
6815
+ $pnt = $this->docPageNumTotal($n);
6816
+ if ($pnt)
6817
+ $pntstr = $this->nbpgPrefix.$pnt.$this->nbpgSuffix;
6818
+ else { $pntstr = ''; }
6819
+ $html = str_replace($this->aliasNbPgGp,$pntstr,$html ); // {nbpg}
6820
+ $html = str_replace($this->aliasNbPg,$nb,$html ); // {nb}
6821
+ $html = preg_replace('/\{DATE\s+(.*?)\}/e',"date('\\1')",$html );
6822
+
6823
+ $this->HTMLheaderPageLinks = array();
6824
+ $this->HTMLheaderPageAnnots = array();
6825
+ $this->HTMLheaderPageForms = array();
6826
+ $this->pageBackgrounds = array();
6827
+
6828
+ $this->writingHTMLheader = true;
6829
+ $this->WriteHTML($html , 4); // parameter 4 saves output to $this->headerbuffer
6830
+ $this->writingHTMLheader = false;
6831
+ $this->Reset();
6832
+ $this->pageoutput[$n] = array();
6833
+
6834
+ $s = $this->PrintPageBackgrounds();
6835
+ $this->headerbuffer = $s . $this->headerbuffer;
6836
+ $os = '';
6837
+ if ($rotate) {
6838
+ $os .= sprintf('q 0 -1 1 0 0 %.3F cm ',($this->w*_MPDFK));
6839
+ }
6840
+ $os .= $this->headerbuffer ;
6841
+ if ($rotate) {
6842
+ $os .= ' Q' . "\n";
6843
+ }
6844
+
6845
+ // Writes over the page background but behind any other output on page
6846
+ $os = preg_replace('/\\\\/','\\\\\\\\',$os);
6847
+ $this->pages[$n] = preg_replace('/(___HEADER___MARKER'.date('jY').')/', "\n".$os."\n".'\\1', $this->pages[$n]);
6848
+
6849
+ $lks = $this->HTMLheaderPageLinks;
6850
+ foreach($lks AS $lk) {
6851
+ if ($rotate) {
6852
+ $lw = $lk[2];
6853
+ $lh = $lk[3];
6854
+ $lk[2] = $lh;
6855
+ $lk[3] = $lw; // swap width and height
6856
+ $ax = $lk[0]/_MPDFK;
6857
+ $ay = $lk[1]/_MPDFK;
6858
+ $bx = $ay-($lh/_MPDFK);
6859
+ $by = $this->w-$ax;
6860
+ $lk[0] = $bx*_MPDFK;
6861
+ $lk[1] = ($this->h-$by)*_MPDFK - $lw;
6862
+ }
6863
+ $this->PageLinks[$n][]=$lk;
6864
+ }
6865
+
6866
+
6867
+ }
6868
+ if (isset($this->saveHTMLFooter[$n][$OE])) {
6869
+ $html = $this->saveHTMLFooter[$this->page][$OE]['html'];
6870
+ $this->lMargin = $this->saveHTMLFooter[$n][$OE]['ml'];
6871
+ $this->rMargin = $this->saveHTMLFooter[$n][$OE]['mr'];
6872
+ $this->tMargin = $this->saveHTMLFooter[$n][$OE]['mh'];
6873
+ $this->bMargin = $this->saveHTMLFooter[$n][$OE]['mf'];
6874
+ $this->margin_header = $this->saveHTMLFooter[$n][$OE]['mh'];
6875
+ $this->margin_footer = $this->saveHTMLFooter[$n][$OE]['mf'];
6876
+ $this->w = $this->saveHTMLFooter[$n][$OE]['pw'];
6877
+ $this->h = $this->saveHTMLFooter[$n][$OE]['ph'];
6878
+ $rotate = (isset($this->saveHTMLFooter[$n][$OE]['rotate']) ? $this->saveHTMLFooter[$n][$OE]['rotate'] : null);
6879
+ $this->Reset();
6880
+ $this->pageoutput[$n] = array();
6881
+ $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
6882
+ $this->x = $this->lMargin;
6883
+ $top_y = $this->y = $this->h - $this->margin_footer;
6884
+
6885
+ // if bottom-margin==0, corrects to avoid division by zero
6886
+ if ($this->y == $this->h) { $top_y = $this->y = ($this->h - 0.1); }
6887
+ // mPDF 5.6.47
6888
+ $pn = $this->docPageNum($n);
6889
+ if ($pn)
6890
+ $pnstr = $this->pagenumPrefix.$pn.$this->pagenumSuffix;
6891
+ else { $pnstr = ''; }
6892
+ $html = str_replace('{PAGENO}',$pnstr,$html);
6893
+ $pnt = $this->docPageNumTotal($n);
6894
+ if ($pnt)
6895
+ $pntstr = $this->nbpgPrefix.$pnt.$this->nbpgSuffix;
6896
+ else { $pntstr = ''; }
6897
+ $html = str_replace($this->aliasNbPgGp,$pntstr,$html ); // {nbpg}
6898
+ $html = str_replace($this->aliasNbPg,$nb,$html ); // {nb}
6899
+ $html = preg_replace('/\{DATE\s+(.*?)\}/e',"date('\\1')",$html );
6900
+
6901
+
6902
+ $this->HTMLheaderPageLinks = array();
6903
+ $this->HTMLheaderPageAnnots = array();
6904
+ $this->HTMLheaderPageForms = array();
6905
+ $this->pageBackgrounds = array();
6906
+
6907
+ $this->writingHTMLfooter = true;
6908
+ $this->InFooter = true;
6909
+ $this->WriteHTML($html , 4); // parameter 4 saves output to $this->headerbuffer
6910
+ $this->writingHTMLfooter = false;
6911
+ $this->InFooter = false;
6912
+ $this->Reset();
6913
+ $this->pageoutput[$n] = array();
6914
+
6915
+ $fheight = $this->y - $top_y;
6916
+ $adj = -$fheight;
6917
+
6918
+ $s = $this->PrintPageBackgrounds(-$adj);
6919
+ $this->headerbuffer = $s . $this->headerbuffer;
6920
+
6921
+ $os = '';
6922
+ $os .= $this->StartTransform(true)."\n";
6923
+ if ($rotate) {
6924
+ $os .= sprintf('q 0 -1 1 0 0 %.3F cm ',($this->w*_MPDFK));
6925
+ }
6926
+ $os .= $this->transformTranslate(0, $adj, true)."\n";
6927
+ $os .= $this->headerbuffer ;
6928
+ if ($rotate) {
6929
+ $os .= ' Q' . "\n";
6930
+ }
6931
+ $os .= $this->StopTransform(true)."\n";
6932
+ // Writes over the page background but behind any other output on page
6933
+ $os = preg_replace('/\\\\/','\\\\\\\\',$os);
6934
+ $this->pages[$n] = preg_replace('/(___HEADER___MARKER'.date('jY').')/', "\n".$os."\n".'\\1', $this->pages[$n]);
6935
+
6936
+ $lks = $this->HTMLheaderPageLinks;
6937
+ foreach($lks AS $lk) {
6938
+ $lk[1] -= $adj*_MPDFK;
6939
+ if ($rotate) {
6940
+ $lw = $lk[2];
6941
+ $lh = $lk[3];
6942
+ $lk[2] = $lh;
6943
+ $lk[3] = $lw; // swap width and height
6944
+
6945
+ $ax = $lk[0]/_MPDFK;
6946
+ $ay = $lk[1]/_MPDFK;
6947
+ $bx = $ay-($lh/_MPDFK);
6948
+ $by = $this->w-$ax;
6949
+ $lk[0] = $bx*_MPDFK;
6950
+ $lk[1] = ($this->h-$by)*_MPDFK - $lw;
6951
+ }
6952
+ $this->PageLinks[$n][]=$lk;
6953
+ }
6954
+ }
6955
+ }
6956
+ $this->page=$nb;
6957
+ $this->state=1;
6958
+ }
6959
+
6960
+
6961
+ function _putpages()
6962
+ {
6963
+ $nb=$this->page;
6964
+ $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
6965
+
6966
+ if($this->DefOrientation=='P') {
6967
+ $defwPt=$this->fwPt;
6968
+ $defhPt=$this->fhPt;
6969
+ }
6970
+ else {
6971
+ $defwPt=$this->fhPt;
6972
+ $defhPt=$this->fwPt;
6973
+ }
6974
+ $annotid=(3+2*$nb);
6975
+
6976
+ // Active Forms
6977
+ $totaladdnum = 0;
6978
+ for($n=1;$n<=$nb;$n++) {
6979
+ if (isset($this->PageLinks[$n])) { $totaladdnum += count($this->PageLinks[$n]); }
6980
+
6981
+ }
6982
+
6983
+ // Select unused fonts (usually default font)
6984
+ $unused = array();
6985
+ foreach($this->fonts as $fk=>$font) {
6986
+ if (!$font['used'] && ($font['type']=='TTF')) {
6987
+ $unused[] = $fk;
6988
+ }
6989
+ }
6990
+
6991
+
6992
+ for($n=1;$n<=$nb;$n++)
6993
+ {
6994
+ $thispage = $this->pages[$n];
6995
+ // unset($this->pages[$n]); // mPDF 5.6.47
6996
+ if(isset($this->OrientationChanges[$n])) {
6997
+ $hPt=$this->pageDim[$n]['w']*_MPDFK;
6998
+ $wPt=$this->pageDim[$n]['h']*_MPDFK;
6999
+ $owidthPt_LR = $this->pageDim[$n]['outer_width_TB']*_MPDFK;
7000
+ $owidthPt_TB = $this->pageDim[$n]['outer_width_LR']*_MPDFK;
7001
+ }
7002
+ else {
7003
+ $wPt=$this->pageDim[$n]['w']*_MPDFK;
7004
+ $hPt=$this->pageDim[$n]['h']*_MPDFK;
7005
+ $owidthPt_LR = $this->pageDim[$n]['outer_width_LR']*_MPDFK;
7006
+ $owidthPt_TB = $this->pageDim[$n]['outer_width_TB']*_MPDFK;
7007
+ }
7008
+ // Remove references to unused fonts (usually default font)
7009
+ foreach($unused as $fk) {
7010
+ if ($this->fonts[$fk]['sip'] || $this->fonts[$fk]['smp']) {
7011
+ foreach($this->fonts[$fk]['subsetfontids'] AS $k => $fid) {
7012
+ $thispage = preg_replace('/\s\/F'.$fid.' \d[\d.]* Tf\s/is',' ',$thispage);
7013
+ }
7014
+ }
7015
+ else {
7016
+ $thispage = preg_replace('/\s\/F'.$this->fonts[$fk]['i'].' \d[\d.]* Tf\s/is',' ',$thispage);
7017
+ }
7018
+ }
7019
+ //Replace number of pages
7020
+ if(!empty($this->aliasNbPg)) {
7021
+ if (!$this->onlyCoreFonts) { $s1 = $this->UTF8ToUTF16BE($this->aliasNbPg, false); }
7022
+ $s2 = $this->aliasNbPg;
7023
+ if (!$this->onlyCoreFonts) { $r1 = $this->UTF8ToUTF16BE($nb, false); }
7024
+ $r2 = $nb;
7025
+ if (preg_match_all('/{mpdfheadernbpg (C|R) ff=(\S*) fs=(\S*) fz=(.*?)}/',$thispage,$m)) {
7026
+ for($hi=0;$hi<count($m[0]);$hi++) {
7027
+ $pos = $m[1][$hi];
7028
+ $hff = $m[2][$hi];
7029
+ $hfst = $m[3][$hi];
7030
+ $hfsz = $m[4][$hi];
7031
+ $this->SetFont($hff,$hfst,$hfsz, false);
7032
+ $x1 = $this->GetStringWidth($this->aliasNbPg);
7033
+ $x2 = $this->GetStringWidth($nb);
7034
+ $xadj = $x1 - $x2;
7035
+ if ($pos=='C') { $xadj /= 2; }
7036
+ $rep = sprintf(' q 1 0 0 1 %.3F 0 cm ', $xadj*_MPDFK);
7037
+ $thispage = str_replace($m[0][$hi], $rep, $thispage);
7038
+ }
7039
+ }
7040
+ if (!$this->onlyCoreFonts) { $thispage=str_replace($s1,$r1,$thispage); }
7041
+ $thispage=str_replace($s2,$r2,$thispage);
7042
+
7043
+ // And now for any SMP/SIP fonts subset using <HH> format
7044
+ $r = '';
7045
+ $nstr = "$nb";
7046
+ for($i=0;$i<strlen($nstr);$i++) {
7047
+ $r .= sprintf("%02s", strtoupper(dechex(intval($nstr[$i])+48)));
7048
+ }
7049
+ $thispage=str_replace($this->aliasNbPgHex,$r,$thispage);
7050
+
7051
+ }
7052
+ //Replace number of pages in group
7053
+ if(!empty($this->aliasNbPgGp)) {
7054
+ if (!$this->onlyCoreFonts) { $s1 = $this->UTF8ToUTF16BE($this->aliasNbPgGp, false); }
7055
+ $s2 = $this->aliasNbPgGp;
7056
+ $nbt = $this->docPageNumTotal($n);
7057
+ if (!$this->onlyCoreFonts) { $r1 = $this->UTF8ToUTF16BE($nbt, false); }
7058
+ $r2 = $nbt;
7059
+ if (preg_match_all('/{mpdfheadernbpggp (C|R) ff=(\S*) fs=(\S*) fz=(.*?)}/',$thispage,$m)) {
7060
+ for($hi=0;$hi<count($m[0]);$hi++) {
7061
+ $pos = $m[1][$hi];
7062
+ $hff = $m[2][$hi];
7063
+ $hfst = $m[3][$hi];
7064
+ $hfsz = $m[4][$hi];
7065
+ $this->SetFont($hff,$hfst,$hfsz, false);
7066
+ $x1 = $this->GetStringWidth($this->aliasNbPgGp);
7067
+ $x2 = $this->GetStringWidth($nbt);
7068
+ $xadj = $x1 - $x2;
7069
+ if ($pos=='C') { $xadj /= 2; }
7070
+ $rep = sprintf(' q 1 0 0 1 %.3F 0 cm ', $xadj*_MPDFK);
7071
+ $thispage = str_replace($m[0][$hi], $rep, $thispage);
7072
+ }
7073
+ }
7074
+ if (!$this->onlyCoreFonts) { $thispage=str_replace($s1,$r1,$thispage); }
7075
+ $thispage=str_replace($s2,$r2,$thispage);
7076
+
7077
+ // And now for any SMP/SIP fonts subset using <HH> format
7078
+ $r = '';
7079
+ $nstr = "$nbt";
7080
+ for($i=0;$i<strlen($nstr);$i++) {
7081
+ $r .= sprintf("%02s", strtoupper(dechex(intval($nstr[$i])+48)));
7082
+ }
7083
+ $thispage=str_replace($this->aliasNbPgGpHex,$r,$thispage);
7084
+
7085
+ }
7086
+ $thispage = preg_replace('/(\s*___BACKGROUND___PATTERNS'.date('jY').'\s*)/', " ", $thispage);
7087
+ $thispage = preg_replace('/(\s*___HEADER___MARKER'.date('jY').'\s*)/', " ", $thispage);
7088
+ $thispage = preg_replace('/(\s*___PAGE___START'.date('jY').'\s*)/', " ", $thispage);
7089
+ $thispage = preg_replace('/(\s*___TABLE___BACKGROUNDS'.date('jY').'\s*)/', " ", $thispage);
7090
+
7091
+ //Page
7092
+ $this->_newobj();
7093
+ $this->_out('<</Type /Page');
7094
+ $this->_out('/Parent 1 0 R');
7095
+ if(isset($this->OrientationChanges[$n])) {
7096
+ $this->_out(sprintf('/MediaBox [0 0 %.3F %.3F]',$hPt,$wPt));
7097
+ //If BleedBox is defined, it must be larger than the TrimBox, but smaller than the MediaBox
7098
+ $bleedMargin = $this->pageDim[$n]['bleedMargin']*_MPDFK;
7099
+ if ($bleedMargin && ($owidthPt_TB || $owidthPt_LR)) {
7100
+ $x0 = $owidthPt_TB-$bleedMargin;
7101
+ $y0 = $owidthPt_LR-$bleedMargin;
7102
+ $x1 = $hPt-$owidthPt_TB+$bleedMargin;
7103
+ $y1 = $wPt-$owidthPt_LR+$bleedMargin;
7104
+ $this->_out(sprintf('/BleedBox [%.3F %.3F %.3F %.3F]', $x0, $y0, $x1, $y1));
7105
+ }
7106
+ $this->_out(sprintf('/TrimBox [%.3F %.3F %.3F %.3F]', $owidthPt_TB, $owidthPt_LR, ($hPt-$owidthPt_TB), ($wPt-$owidthPt_LR)));
7107
+ if (isset($this->OrientationChanges[$n]) && $this->displayDefaultOrientation) {
7108
+ if ($this->DefOrientation=='P') { $this->_out('/Rotate 270'); }
7109
+ else { $this->_out('/Rotate 90'); }
7110
+ }
7111
+ }
7112
+ //else if($wPt != $defwPt || $hPt != $defhPt) {
7113
+ else {
7114
+ $this->_out(sprintf('/MediaBox [0 0 %.3F %.3F]',$wPt,$hPt));
7115
+ $bleedMargin = $this->pageDim[$n]['bleedMargin']*_MPDFK;
7116
+ if ($bleedMargin && ($owidthPt_TB || $owidthPt_LR)) {
7117
+ $x0 = $owidthPt_LR-$bleedMargin;
7118
+ $y0 = $owidthPt_TB-$bleedMargin;
7119
+ $x1 = $wPt-$owidthPt_LR+$bleedMargin;
7120
+ $y1 = $hPt-$owidthPt_TB+$bleedMargin;
7121
+ $this->_out(sprintf('/BleedBox [%.3F %.3F %.3F %.3F]', $x0, $y0, $x1, $y1));
7122
+ }
7123
+ $this->_out(sprintf('/TrimBox [%.3F %.3F %.3F %.3F]', $owidthPt_LR, $owidthPt_TB, ($wPt-$owidthPt_LR), ($hPt-$owidthPt_TB)));
7124
+ }
7125
+ $this->_out('/Resources 2 0 R');
7126
+
7127
+ // Important to keep in RGB colorSpace when using transparency
7128
+ if (!$this->PDFA && !$this->PDFX) {
7129
+ if ($this->restrictColorSpace == 3)
7130
+ $this->_out('/Group << /Type /Group /S /Transparency /CS /DeviceCMYK >> ');
7131
+ else if ($this->restrictColorSpace == 1)
7132
+ $this->_out('/Group << /Type /Group /S /Transparency /CS /DeviceGray >> ');
7133
+ else
7134
+ $this->_out('/Group << /Type /Group /S /Transparency /CS /DeviceRGB >> ');
7135
+ }
7136
+
7137
+ $annotsnum = 0;
7138
+ if (isset($this->PageLinks[$n])) { $annotsnum += count($this->PageLinks[$n]); }
7139
+
7140
+ if ($annotsnum || $formsnum) {
7141
+ $s = '/Annots [ ';
7142
+ for($i=0;$i<$annotsnum;$i++) {
7143
+ $s .= ($annotid + $i) . ' 0 R ';
7144
+ }
7145
+ $annotid += $annotsnum;
7146
+ $s .= '] ';
7147
+ $this->_out($s);
7148
+ }
7149
+
7150
+ $this->_out('/Contents '.($this->n+1).' 0 R>>');
7151
+ $this->_out('endobj');
7152
+
7153
+ //Page content
7154
+ $this->_newobj();
7155
+ $p=($this->compress) ? gzcompress($thispage) : $thispage;
7156
+ $this->_out('<<'.$filter.'/Length '.strlen($p).'>>');
7157
+ $this->_putstream($p);
7158
+ $this->_out('endobj');
7159
+ }
7160
+ $this->_putannots($n);
7161
+
7162
+ //Pages root
7163
+ $this->offsets[1]=strlen($this->buffer);
7164
+ $this->_out('1 0 obj');
7165
+ $this->_out('<</Type /Pages');
7166
+ $kids='/Kids [';
7167
+ for($i=0;$i<$nb;$i++)
7168
+ $kids.=(3+2*$i).' 0 R ';
7169
+ $this->_out($kids.']');
7170
+ $this->_out('/Count '.$nb);
7171
+ $this->_out(sprintf('/MediaBox [0 0 %.3F %.3F]',$defwPt,$defhPt));
7172
+ $this->_out('>>');
7173
+ $this->_out('endobj');
7174
+ }
7175
+
7176
+
7177
+ function _putannots($n) {
7178
+ $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
7179
+ $nb=$this->page;
7180
+ for($n=1;$n<=$nb;$n++)
7181
+ {
7182
+ $annotobjs = array();
7183
+ if(isset($this->PageLinks[$n]) || isset($this->PageAnnots[$n]) || count($this->form->forms) > 0 ) {
7184
+ $wPt=$this->pageDim[$n]['w']*_MPDFK;
7185
+ $hPt=$this->pageDim[$n]['h']*_MPDFK;
7186
+
7187
+ //Links
7188
+ if(isset($this->PageLinks[$n])) {
7189
+ foreach($this->PageLinks[$n] as $key => $pl) {
7190
+ $this->_newobj();
7191
+ $annot='';
7192
+ $rect=sprintf('%.3F %.3F %.3F %.3F',$pl[0],$pl[1],$pl[0]+$pl[2],$pl[1]-$pl[3]);
7193
+ $annot .= '<</Type /Annot /Subtype /Link /Rect ['.$rect.']';
7194
+ $annot .= ' /Contents '.$this->_UTF16BEtextstring($pl[4]);
7195
+ $annot .= ' /NM '.$this->_textstring(sprintf('%04u-%04u', $n, $key));
7196
+ $annot .= ' /M '.$this->_textstring('D:'.date('YmdHis'));
7197
+ $annot .= ' /Border [0 0 0]';
7198
+ // Use this (instead of /Border) to specify border around link
7199
+ // $annot .= ' /BS <</W 1'; // Width on points; 0 = no line
7200
+ // $annot .= ' /S /D'; // style - [S]olid, [D]ashed, [B]eveled, [I]nset, [U]nderline
7201
+ // $annot .= ' /D [3 2]'; // Dash array - if dashed
7202
+ // $annot .= ' >>';
7203
+ // $annot .= ' /C [1 0 0]'; // Color RGB
7204
+
7205
+ if ($this->PDFA || $this->PDFX) { $annot .= ' /F 28'; }
7206
+ if (strpos($pl[4],'@')===0) {
7207
+ $p=substr($pl[4],1);
7208
+ // $h=isset($this->OrientationChanges[$p]) ? $wPt : $hPt;
7209
+ $htarg=$this->pageDim[$p]['h']*_MPDFK;
7210
+ $annot.=sprintf(' /Dest [%d 0 R /XYZ 0 %.3F null]>>',1+2*$p,$htarg);
7211
+ }
7212
+ else if(is_string($pl[4])) {
7213
+ $annot .= ' /A <</S /URI /URI '.$this->_textstring($pl[4]).'>> >>';
7214
+ }
7215
+ else {
7216
+ $l=$this->links[$pl[4]];
7217
+ // may not be set if #link points to non-existent target
7218
+ if (isset($this->pageDim[$l[0]]['h'])) { $htarg=$this->pageDim[$l[0]]['h']*_MPDFK; }
7219
+ else { $htarg=$this->h*_MPDFK; } // doesn't really matter
7220
+ $annot.=sprintf(' /Dest [%d 0 R /XYZ 0 %.3F null]>>',1+2*$l[0],$htarg-$l[1]*_MPDFK);
7221
+ }
7222
+ $this->_out($annot);
7223
+ $this->_out('endobj');
7224
+ }
7225
+ }
7226
+
7227
+
7228
+
7229
+ }
7230
+ }
7231
+ }
7232
+
7233
+
7234
+
7235
+
7236
+ function _putfonts() {
7237
+ $nf=$this->n;
7238
+ foreach($this->FontFiles as $fontkey=>$info) {
7239
+ // TrueType embedded
7240
+ if (isset($info['type']) && $info['type']=='TTF' && !$info['sip'] && !$info['smp']) {
7241
+ $used = true;
7242
+ $asSubset = false;
7243
+ foreach($this->fonts AS $k=>$f) {
7244
+ if ($f['fontkey'] == $fontkey && $f['type']=='TTF') {
7245
+ $used = $f['used'];
7246
+ if ($used) {
7247
+ $nChars = (ord($f['cw'][0]) << 8) + ord($f['cw'][1]);
7248
+ $usage = intval(count($f['subset'])*100 / $nChars);
7249
+ $fsize = $info['length1'];
7250
+ // Always subset the very large TTF files
7251
+ if ($fsize > ($this->maxTTFFilesize *1024)) { $asSubset = true; }
7252
+ else if ($usage < $this->percentSubset) { $asSubset = true; }
7253
+ }
7254
+ if ($f['unAGlyphs']) $aaSubset = true; // mPDF 5.4.05
7255
+ if ($this->PDFA || $this->PDFX) $asSubset = false;
7256
+ $this->fonts[$k]['asSubset'] = $asSubset;
7257
+ break;
7258
+ }
7259
+ }
7260
+ if ($used && !$asSubset) {
7261
+ //Font file embedding
7262
+ $this->_newobj();
7263
+ $this->FontFiles[$fontkey]['n']=$this->n;
7264
+ $font='';
7265
+ $originalsize = $info['length1'];
7266
+ if ($this->repackageTTF || $this->fonts[$fontkey]['TTCfontID']>0) {
7267
+ // First see if there is a cached compressed file
7268
+ if (file_exists(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.z')) {
7269
+ $f=fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.z','rb');
7270
+ if(!$f) { $this->Error('Font file .ps.z not found'); }
7271
+ while(!feof($f)) { $font .= fread($f, 2048); }
7272
+ fclose($f);
7273
+ include(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.php'); // sets $originalsize (of repackaged font)
7274
+ }
7275
+ else {
7276
+ if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
7277
+ $ttf = new TTFontFile();
7278
+ $font = $ttf->repackageTTF($this->FontFiles[$fontkey]['ttffile'], $this->fonts[$fontkey]['TTCfontID'], $this->debugfonts, $this->fonts[$fontkey]['unAGlyphs']); // mPDF 5.4.05
7279
+
7280
+ $originalsize = strlen($font);
7281
+ $font = gzcompress($font);
7282
+ unset($ttf);
7283
+ if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
7284
+ $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.z',"wb");
7285
+ fwrite($fh,$font,strlen($font));
7286
+ fclose($fh);
7287
+ $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.php',"wb");
7288
+ $len = "<?php \n";
7289
+ $len.='$originalsize='.$originalsize.";\n";
7290
+ $len.="?>";
7291
+ fwrite($fh,$len,strlen($len));
7292
+ fclose($fh);
7293
+ }
7294
+ }
7295
+ }
7296
+ else {
7297
+ // First see if there is a cached compressed file
7298
+ if (file_exists(_MPDF_TTFONTDATAPATH.$fontkey.'.z')) {
7299
+ $f=fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.z','rb');
7300
+ if(!$f) { $this->Error('Font file not found'); }
7301
+ while(!feof($f)) { $font .= fread($f, 2048); }
7302
+ fclose($f);
7303
+ }
7304
+ else {
7305
+ $f=fopen($this->FontFiles[$fontkey]['ttffile'],'rb');
7306
+ if(!$f) { $this->Error('Font file not found'); }
7307
+ while(!feof($f)) { $font .= fread($f, 2048); }
7308
+ fclose($f);
7309
+ $font = gzcompress($font);
7310
+ if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
7311
+ $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.z',"wb");
7312
+ fwrite($fh,$font,strlen($font));
7313
+ fclose($fh);
7314
+ }
7315
+ }
7316
+ }
7317
+
7318
+ $this->_out('<</Length '.strlen($font));
7319
+ $this->_out('/Filter /FlateDecode');
7320
+ $this->_out('/Length1 '.$originalsize);
7321
+ $this->_out('>>');
7322
+ $this->_putstream($font);
7323
+ $this->_out('endobj');
7324
+ }
7325
+ }
7326
+ }
7327
+
7328
+ $nfonts = count($this->fonts);
7329
+ $fctr = 1;
7330
+ foreach($this->fonts as $k=>$font) {
7331
+ //Font objects
7332
+ $type=$font['type'];
7333
+ $name=$font['name'];
7334
+ if ((!isset($font['used']) || !$font['used']) && $type=='TTF') { continue; }
7335
+ if (isset($font['asSubset'])) { $asSubset = $font['asSubset']; }
7336
+ else { $asSubset = ''; }
7337
+ if($type=='core') {
7338
+ //Standard font
7339
+ $this->fonts[$k]['n']=$this->n+1;
7340
+ if ($this->PDFA || $this->PDFX) { $this->Error('Core fonts are not allowed in PDF/A1-b or PDFX/1-a files (Times, Helvetica, Courier etc.)'); }
7341
+ $this->_newobj();
7342
+ $this->_out('<</Type /Font');
7343
+ $this->_out('/BaseFont /'.$name);
7344
+ $this->_out('/Subtype /Type1');
7345
+ if($name!='Symbol' && $name!='ZapfDingbats') {
7346
+ $this->_out('/Encoding /WinAnsiEncoding');
7347
+ }
7348
+ $this->_out('>>');
7349
+ $this->_out('endobj');
7350
+ }
7351
+ // TrueType embedded SUBSETS for SIP (CJK extB containing Supplementary Ideographic Plane 2)
7352
+ // Or Unicode Plane 1 - Supplementary Multilingual Plane
7353
+ else if ($type=='TTF' && ($font['sip'] || $font['smp'])) {
7354
+ if (!$font['used']) { continue; }
7355
+ $ssfaid="AA";
7356
+ if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
7357
+ $ttf = new TTFontFile();
7358
+ for($sfid=0;$sfid<count($font['subsetfontids']);$sfid++) {
7359
+ $this->fonts[$k]['n'][$sfid]=$this->n+1; // NB an array for subset
7360
+ $subsetname = 'MPDF'.$ssfaid.'+'.$font['name'];
7361
+ $ssfaid++;
7362
+ $subset = $font['subsets'][$sfid];
7363
+ unset($subset[0]);
7364
+ $ttfontstream = $ttf->makeSubsetSIP($font['ttffile'], $subset, $font['TTCfontID'], $this->debugfonts);
7365
+ $ttfontsize = strlen($ttfontstream);
7366
+ $fontstream = gzcompress($ttfontstream);
7367
+ $widthstring = '';
7368
+ $toUnistring = '';
7369
+ foreach($font['subsets'][$sfid] AS $cp=>$u) {
7370
+ $w = $this->_getCharWidth($font['cw'], $u);
7371
+ if ($w !== false) {
7372
+ $widthstring .= $w.' ';
7373
+ }
7374
+ else {
7375
+ $widthstring .= round($ttf->defaultWidth).' ';
7376
+ }
7377
+ if ($u > 65535) {
7378
+ $utf8 = chr(($u>>18)+240).chr((($u>>12)&63)+128).chr((($u>>6)&63)+128) .chr(($u&63)+128);
7379
+ $utf16 = mb_convert_encoding($utf8, 'UTF-16BE', 'UTF-8');
7380
+ $l1 = ord($utf16[0]);
7381
+ $h1 = ord($utf16[1]);
7382
+ $l2 = ord($utf16[2]);
7383
+ $h2 = ord($utf16[3]);
7384
+ $toUnistring .= sprintf("<%02s> <%02s%02s%02s%02s>\n", strtoupper(dechex($cp)), strtoupper(dechex($l1)), strtoupper(dechex($h1)), strtoupper(dechex($l2)), strtoupper(dechex($h2)));
7385
+ }
7386
+ else {
7387
+ $toUnistring .= sprintf("<%02s> <%04s>\n", strtoupper(dechex($cp)), strtoupper(dechex($u)));
7388
+ }
7389
+ }
7390
+
7391
+ //Additional Type1 or TrueType font
7392
+ $this->_newobj();
7393
+ $this->_out('<</Type /Font');
7394
+ $this->_out('/BaseFont /'.$subsetname);
7395
+ $this->_out('/Subtype /TrueType');
7396
+ $this->_out('/FirstChar 0 /LastChar '.(count($font['subsets'][$sfid])-1));
7397
+ $this->_out('/Widths '.($this->n+1).' 0 R');
7398
+ $this->_out('/FontDescriptor '.($this->n+2).' 0 R');
7399
+ $this->_out('/ToUnicode '.($this->n + 3).' 0 R');
7400
+ $this->_out('>>');
7401
+ $this->_out('endobj');
7402
+
7403
+ //Widths
7404
+ $this->_newobj();
7405
+ $this->_out('['.$widthstring.']');
7406
+ $this->_out('endobj');
7407
+
7408
+ //Descriptor
7409
+ $this->_newobj();
7410
+ $s='<</Type /FontDescriptor /FontName /'.$subsetname."\n";
7411
+ foreach($font['desc'] as $kd=>$v) {
7412
+ if ($kd == 'Flags') { $v = $v | 4; $v = $v & ~32; } // SYMBOLIC font flag
7413
+ $s.=' /'.$kd.' '.$v."\n";
7414
+ }
7415
+ $s.='/FontFile2 '.($this->n + 2).' 0 R';
7416
+ $this->_out($s.'>>');
7417
+ $this->_out('endobj');
7418
+
7419
+ // ToUnicode
7420
+ $this->_newobj();
7421
+ $toUni = "/CIDInit /ProcSet findresource begin\n";
7422
+ $toUni .= "12 dict begin\n";
7423
+ $toUni .= "begincmap\n";
7424
+ $toUni .= "/CIDSystemInfo\n";
7425
+ $toUni .= "<</Registry (Adobe)\n";
7426
+ $toUni .= "/Ordering (UCS)\n";
7427
+ $toUni .= "/Supplement 0\n";
7428
+ $toUni .= ">> def\n";
7429
+ $toUni .= "/CMapName /Adobe-Identity-UCS def\n";
7430
+ $toUni .= "/CMapType 2 def\n";
7431
+ $toUni .= "1 begincodespacerange\n";
7432
+ $toUni .= "<00> <FF>\n";
7433
+ $toUni .= "endcodespacerange\n";
7434
+ $toUni .= count($font['subsets'][$sfid])." beginbfchar\n";
7435
+ $toUni .= $toUnistring;
7436
+ $toUni .= "endbfchar\n";
7437
+ $toUni .= "endcmap\n";
7438
+ $toUni .= "CMapName currentdict /CMap defineresource pop\n";
7439
+ $toUni .= "end\n";
7440
+ $toUni .= "end\n";
7441
+
7442
+ $this->_out('<</Length '.(strlen($toUni)).'>>');
7443
+ $this->_putstream($toUni);
7444
+ $this->_out('endobj');
7445
+
7446
+ //Font file
7447
+ $this->_newobj();
7448
+ $this->_out('<</Length '.strlen($fontstream));
7449
+ $this->_out('/Filter /FlateDecode');
7450
+ $this->_out('/Length1 '.$ttfontsize);
7451
+ $this->_out('>>');
7452
+ $this->_putstream($fontstream);
7453
+ $this->_out('endobj');
7454
+ } // foreach subset
7455
+ unset($ttf);
7456
+ }
7457
+ // TrueType embedded SUBSETS or FULL
7458
+ else if ($type=='TTF') {
7459
+ $this->fonts[$k]['n']=$this->n+1;
7460
+ if ($asSubset ) {
7461
+ $ssfaid="A";
7462
+ if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
7463
+ $ttf = new TTFontFile();
7464
+ $fontname = 'MPDFA'.$ssfaid.'+'.$font['name'];
7465
+ $subset = $font['subset'];
7466
+ unset($subset[0]);
7467
+ $ttfontstream = $ttf->makeSubset($font['ttffile'], $subset, $font['TTCfontID'], $this->debugfonts, $font['unAGlyphs']); // mPDF 5.4.05
7468
+ $ttfontsize = strlen($ttfontstream);
7469
+ $fontstream = gzcompress($ttfontstream);
7470
+ $codeToGlyph = $ttf->codeToGlyph;
7471
+ unset($codeToGlyph[0]);
7472
+ }
7473
+ else { $fontname = $font['name']; }
7474
+ // Type0 Font
7475
+ // A composite font - a font composed of other fonts, organized hierarchically
7476
+ $this->_newobj();
7477
+ $this->_out('<</Type /Font');
7478
+ $this->_out('/Subtype /Type0');
7479
+ $this->_out('/BaseFont /'.$fontname.'');
7480
+ $this->_out('/Encoding /Identity-H');
7481
+ $this->_out('/DescendantFonts ['.($this->n + 1).' 0 R]');
7482
+ $this->_out('/ToUnicode '.($this->n + 2).' 0 R');
7483
+ $this->_out('>>');
7484
+ $this->_out('endobj');
7485
+
7486
+ // CIDFontType2
7487
+ // A CIDFont whose glyph descriptions are based on TrueType font technology
7488
+ $this->_newobj();
7489
+ $this->_out('<</Type /Font');
7490
+ $this->_out('/Subtype /CIDFontType2');
7491
+ $this->_out('/BaseFont /'.$fontname.'');
7492
+ $this->_out('/CIDSystemInfo '.($this->n + 2).' 0 R');
7493
+ $this->_out('/FontDescriptor '.($this->n + 3).' 0 R');
7494
+ if (isset($font['desc']['MissingWidth'])){
7495
+ $this->_out('/DW '.$font['desc']['MissingWidth'].'');
7496
+ }
7497
+
7498
+ if (!$asSubset && file_exists(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw')) {
7499
+ $w = '';
7500
+ $w=file_get_contents(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw');
7501
+ $this->_out($w);
7502
+ }
7503
+ else {
7504
+ $this->_putTTfontwidths($font, $asSubset, $ttf->maxUni);
7505
+ }
7506
+
7507
+ $this->_out('/CIDToGIDMap '.($this->n + 4).' 0 R');
7508
+ $this->_out('>>');
7509
+ $this->_out('endobj');
7510
+
7511
+ // ToUnicode
7512
+ $this->_newobj();
7513
+ $toUni = "/CIDInit /ProcSet findresource begin\n";
7514
+ $toUni .= "12 dict begin\n";
7515
+ $toUni .= "begincmap\n";
7516
+ $toUni .= "/CIDSystemInfo\n";
7517
+ $toUni .= "<</Registry (Adobe)\n";
7518
+ $toUni .= "/Ordering (UCS)\n";
7519
+ $toUni .= "/Supplement 0\n";
7520
+ $toUni .= ">> def\n";
7521
+ $toUni .= "/CMapName /Adobe-Identity-UCS def\n";
7522
+ $toUni .= "/CMapType 2 def\n";
7523
+ $toUni .= "1 begincodespacerange\n";
7524
+ $toUni .= "<0000> <FFFF>\n";
7525
+ $toUni .= "endcodespacerange\n";
7526
+ $toUni .= "1 beginbfrange\n";
7527
+ $toUni .= "<0000> <FFFF> <0000>\n";
7528
+ $toUni .= "endbfrange\n";
7529
+ $toUni .= "endcmap\n";
7530
+ $toUni .= "CMapName currentdict /CMap defineresource pop\n";
7531
+ $toUni .= "end\n";
7532
+ $toUni .= "end\n";
7533
+ $this->_out('<</Length '.(strlen($toUni)).'>>');
7534
+ $this->_putstream($toUni);
7535
+ $this->_out('endobj');
7536
+
7537
+
7538
+ // CIDSystemInfo dictionary
7539
+ $this->_newobj();
7540
+ $this->_out('<</Registry (Adobe)');
7541
+ $this->_out('/Ordering (UCS)');
7542
+ $this->_out('/Supplement 0');
7543
+ $this->_out('>>');
7544
+ $this->_out('endobj');
7545
+
7546
+ // Font descriptor
7547
+ $this->_newobj();
7548
+ $this->_out('<</Type /FontDescriptor');
7549
+ $this->_out('/FontName /'.$fontname);
7550
+ foreach($font['desc'] as $kd=>$v) {
7551
+ if ($asSubset && $kd == 'Flags') { $v = $v | 4; $v = $v & ~32; } // SYMBOLIC font flag
7552
+ $this->_out(' /'.$kd.' '.$v);
7553
+ }
7554
+ if ($font['panose']) {
7555
+ $this->_out(' /Style << /Panose <'.$font['panose'].'> >>');
7556
+ }
7557
+ if ($asSubset ) {
7558
+ $this->_out('/FontFile2 '.($this->n + 2).' 0 R');
7559
+ }
7560
+ else if ($font['fontkey']) {
7561
+ // obj ID of a stream containing a TrueType font program
7562
+ $this->_out('/FontFile2 '.$this->FontFiles[$font['fontkey']]['n'].' 0 R');
7563
+ }
7564
+ $this->_out('>>');
7565
+ $this->_out('endobj');
7566
+
7567
+ // Embed CIDToGIDMap
7568
+ // A specification of the mapping from CIDs to glyph indices
7569
+ if ($asSubset ) {
7570
+ $cidtogidmap = '';
7571
+ $cidtogidmap = str_pad('', 256*256*2, "\x00");
7572
+ foreach($codeToGlyph as $cc=>$glyph) {
7573
+ $cidtogidmap[$cc*2] = chr($glyph >> 8);
7574
+ $cidtogidmap[$cc*2 + 1] = chr($glyph & 0xFF);
7575
+ }
7576
+ $cidtogidmap = gzcompress($cidtogidmap);
7577
+ }
7578
+ else {
7579
+ // First see if there is a cached CIDToGIDMapfile
7580
+ $cidtogidmap = '';
7581
+ if (file_exists(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cgm')) {
7582
+ $f=fopen(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cgm','rb');
7583
+ while(!feof($f)) { $cidtogidmap .= fread($f, 2048); }
7584
+ fclose($f);
7585
+ }
7586
+ else {
7587
+ if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
7588
+ $ttf = new TTFontFile();
7589
+ $charToGlyph = $ttf->getCTG($font['ttffile'], $font['TTCfontID'], $this->debugfonts, $font['unAGlyphs']); // mPDF 5.4.05
7590
+ $cidtogidmap = str_pad('', 256*256*2, "\x00");
7591
+ foreach($charToGlyph as $cc=>$glyph) {
7592
+ $cidtogidmap[$cc*2] = chr($glyph >> 8);
7593
+ $cidtogidmap[$cc*2 + 1] = chr($glyph & 0xFF);
7594
+ }
7595
+ unset($ttf);
7596
+ $cidtogidmap = gzcompress($cidtogidmap);
7597
+ if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
7598
+ $fh = fopen(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cgm',"wb");
7599
+ fwrite($fh,$cidtogidmap,strlen($cidtogidmap));
7600
+ fclose($fh);
7601
+ }
7602
+ }
7603
+ }
7604
+ $this->_newobj();
7605
+ $this->_out('<</Length '.strlen($cidtogidmap).'');
7606
+ $this->_out('/Filter /FlateDecode');
7607
+ $this->_out('>>');
7608
+ $this->_putstream($cidtogidmap);
7609
+ $this->_out('endobj');
7610
+
7611
+ //Font file
7612
+ if ($asSubset ) {
7613
+ $this->_newobj();
7614
+ $this->_out('<</Length '.strlen($fontstream));
7615
+ $this->_out('/Filter /FlateDecode');
7616
+ $this->_out('/Length1 '.$ttfontsize);
7617
+ $this->_out('>>');
7618
+ $this->_putstream($fontstream);
7619
+ $this->_out('endobj');
7620
+ unset($ttf);
7621
+ }
7622
+ }
7623
+ else { $this->Error('Unsupported font type: '.$type.' ('.$name.')'); }
7624
+ }
7625
+ }
7626
+
7627
+
7628
+
7629
+ function _putTTfontwidths(&$font, $asSubset, $maxUni) {
7630
+ if ($asSubset && file_exists(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw127.php')) {
7631
+ include(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw127.php') ;
7632
+ $startcid = 128;
7633
+ }
7634
+ else {
7635
+ $rangeid = 0;
7636
+ $range = array();
7637
+ $prevcid = -2;
7638
+ $prevwidth = -1;
7639
+ $interval = false;
7640
+ $startcid = 1;
7641
+ }
7642
+ if ($asSubset) { $cwlen = $maxUni + 1; }
7643
+ else { $cwlen = (strlen($font['cw'])/2); }
7644
+
7645
+ // for each character
7646
+ for ($cid=$startcid; $cid<$cwlen; $cid++) {
7647
+ if ($cid==128 && $asSubset && (!file_exists(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw127.php'))) {
7648
+ if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
7649
+ $fh = fopen(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw127.php',"wb");
7650
+ $cw127='<?php'."\n";
7651
+ $cw127.='$rangeid='.$rangeid.";\n";
7652
+ $cw127.='$prevcid='.$prevcid.";\n";
7653
+ $cw127.='$prevwidth='.$prevwidth.";\n";
7654
+ if ($interval) { $cw127.='$interval=true'.";\n"; }
7655
+ else { $cw127.='$interval=false'.";\n"; }
7656
+ $cw127.='$range='.var_export($range,true).";\n";
7657
+ $cw127.="?>";
7658
+ fwrite($fh,$cw127,strlen($cw127));
7659
+ fclose($fh);
7660
+ }
7661
+ }
7662
+ if ($font['cw'][$cid*2] == "\00" && $font['cw'][$cid*2+1] == "\00") { continue; }
7663
+ $width = (ord($font['cw'][$cid*2]) << 8) + ord($font['cw'][$cid*2+1]);
7664
+ if ($width == 65535) { $width = 0; }
7665
+ if ($asSubset && $cid > 255 && (!isset($font['subset'][$cid]) || !$font['subset'][$cid])) {
7666
+ continue;
7667
+ }
7668
+ if (!isset($font['dw']) || (isset($font['dw']) && $width != $font['dw'])) {
7669
+ if ($cid == ($prevcid + 1)) {
7670
+ // consecutive CID
7671
+ if ($width == $prevwidth) {
7672
+ if ($width == $range[$rangeid][0]) {
7673
+ $range[$rangeid][] = $width;
7674
+ } else {
7675
+ array_pop($range[$rangeid]);
7676
+ // new range
7677
+ $rangeid = $prevcid;
7678
+ $range[$rangeid] = array();
7679
+ $range[$rangeid][] = $prevwidth;
7680
+ $range[$rangeid][] = $width;
7681
+ }
7682
+ $interval = true;
7683
+ $range[$rangeid]['interval'] = true;
7684
+ } else {
7685
+ if ($interval) {
7686
+ // new range
7687
+ $rangeid = $cid;
7688
+ $range[$rangeid] = array();
7689
+ $range[$rangeid][] = $width;
7690
+ } else {
7691
+ $range[$rangeid][] = $width;
7692
+ }
7693
+ $interval = false;
7694
+ }
7695
+ } else {
7696
+ // new range
7697
+ $rangeid = $cid;
7698
+ $range[$rangeid] = array();
7699
+ $range[$rangeid][] = $width;
7700
+ $interval = false;
7701
+ }
7702
+ $prevcid = $cid;
7703
+ $prevwidth = $width;
7704
+ }
7705
+ }
7706
+ $w = $this->_putfontranges($range);
7707
+ $this->_out($w);
7708
+ if (!$asSubset) {
7709
+ if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
7710
+ $fh = fopen(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw',"wb");
7711
+ fwrite($fh,$w,strlen($w));
7712
+ fclose($fh);
7713
+ }
7714
+ }
7715
+ }
7716
+
7717
+ function _putfontranges(&$range) {
7718
+ // optimize ranges
7719
+ $prevk = -1;
7720
+ $nextk = -1;
7721
+ $prevint = false;
7722
+ foreach ($range as $k => $ws) {
7723
+ $cws = count($ws);
7724
+ if (($k == $nextk) AND (!$prevint) AND ((!isset($ws['interval'])) OR ($cws < 4))) {
7725
+ if (isset($range[$k]['interval'])) {
7726
+ unset($range[$k]['interval']);
7727
+ }
7728
+ $range[$prevk] = array_merge($range[$prevk], $range[$k]);
7729
+ unset($range[$k]);
7730
+ } else {
7731
+ $prevk = $k;
7732
+ }
7733
+ $nextk = $k + $cws;
7734
+ if (isset($ws['interval'])) {
7735
+ if ($cws > 3) {
7736
+ $prevint = true;
7737
+ } else {
7738
+ $prevint = false;
7739
+ }
7740
+ unset($range[$k]['interval']);
7741
+ --$nextk;
7742
+ } else {
7743
+ $prevint = false;
7744
+ }
7745
+ }
7746
+ // output data
7747
+ $w = '';
7748
+ foreach ($range as $k => $ws) {
7749
+ if (count(array_count_values($ws)) == 1) {
7750
+ // interval mode is more compact
7751
+ $w .= ' '.$k.' '.($k + count($ws) - 1).' '.$ws[0];
7752
+ } else {
7753
+ // range mode
7754
+ $w .= ' '.$k.' [ '.implode(' ', $ws).' ]' . "\n";
7755
+ }
7756
+ }
7757
+ return '/W ['.$w.' ]';
7758
+ }
7759
+
7760
+
7761
+ function _putfontwidths(&$font, $cidoffset=0) {
7762
+ ksort($font['cw']);
7763
+ unset($font['cw'][65535]);
7764
+ $rangeid = 0;
7765
+ $range = array();
7766
+ $prevcid = -2;
7767
+ $prevwidth = -1;
7768
+ $interval = false;
7769
+ // for each character
7770
+ foreach ($font['cw'] as $cid => $width) {
7771
+ $cid -= $cidoffset;
7772
+ if (!isset($font['dw']) || (isset($font['dw']) && $width != $font['dw'])) {
7773
+ if ($cid == ($prevcid + 1)) {
7774
+ // consecutive CID
7775
+ if ($width == $prevwidth) {
7776
+ if ($width == $range[$rangeid][0]) {
7777
+ $range[$rangeid][] = $width;
7778
+ } else {
7779
+ array_pop($range[$rangeid]);
7780
+ // new range
7781
+ $rangeid = $prevcid;
7782
+ $range[$rangeid] = array();
7783
+ $range[$rangeid][] = $prevwidth;
7784
+ $range[$rangeid][] = $width;
7785
+ }
7786
+ $interval = true;
7787
+ $range[$rangeid]['interval'] = true;
7788
+ } else {
7789
+ if ($interval) {
7790
+ // new range
7791
+ $rangeid = $cid;
7792
+ $range[$rangeid] = array();
7793
+ $range[$rangeid][] = $width;
7794
+ } else {
7795
+ $range[$rangeid][] = $width;
7796
+ }
7797
+ $interval = false;
7798
+ }
7799
+ } else {
7800
+ // new range
7801
+ $rangeid = $cid;
7802
+ $range[$rangeid] = array();
7803
+ $range[$rangeid][] = $width;
7804
+ $interval = false;
7805
+ }
7806
+ $prevcid = $cid;
7807
+ $prevwidth = $width;
7808
+ }
7809
+ }
7810
+ $this->_out($this->_putfontranges($range));
7811
+ }
7812
+
7813
+
7814
+
7815
+
7816
+
7817
+ function _putimages()
7818
+ {
7819
+ $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
7820
+ reset($this->images);
7821
+ while(list($file,$info)=each($this->images)) {
7822
+ $this->_newobj();
7823
+ $this->images[$file]['n']=$this->n;
7824
+ $this->_out('<</Type /XObject');
7825
+ $this->_out('/Subtype /Image');
7826
+ $this->_out('/Width '.$info['w']);
7827
+ $this->_out('/Height '.$info['h']);
7828
+ if (isset($info['masked'])) {
7829
+ $this->_out('/SMask '.($this->n - 1).' 0 R');
7830
+ }
7831
+ if($info['cs']=='Indexed') {
7832
+ if ($this->PDFX || ($this->PDFA && $this->restrictColorSpace==3)) { $this->Error("PDFA1-b and PDFX/1-a files do not permit using mixed colour space (".$file.")."); }
7833
+ $this->_out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
7834
+ }
7835
+ else {
7836
+ $this->_out('/ColorSpace /'.$info['cs']);
7837
+ if($info['cs']=='DeviceCMYK') {
7838
+ if ($this->PDFA && $this->restrictColorSpace!=3) { $this->Error("PDFA1-b does not permit Images using mixed colour space (".$file.")."); }
7839
+ if($info['type']=='jpg') { $this->_out('/Decode [1 0 1 0 1 0 1 0]'); }
7840
+ }
7841
+ else if ($info['cs']=='DeviceRGB' && ($this->PDFX || ($this->PDFA && $this->restrictColorSpace==3))) { $this->Error("PDFA1-b and PDFX/1-a files do not permit using mixed colour space (".$file.")."); }
7842
+ }
7843
+ $this->_out('/BitsPerComponent '.$info['bpc']);
7844
+ if (isset($info['f']) && $info['f']) { $this->_out('/Filter /'.$info['f']); }
7845
+ if(isset($info['parms'])) { $this->_out($info['parms']); }
7846
+ if(isset($info['trns']) and is_array($info['trns'])) {
7847
+ $trns='';
7848
+ for($i=0;$i<count($info['trns']);$i++)
7849
+ $trns.=$info['trns'][$i].' '.$info['trns'][$i].' ';
7850
+ $this->_out('/Mask ['.$trns.']');
7851
+ }
7852
+ $this->_out('/Length '.strlen($info['data']).'>>');
7853
+ $this->_putstream($info['data']);
7854
+
7855
+ unset($this->images[$file]['data']);
7856
+ $this->_out('endobj');
7857
+ //Palette
7858
+ if($info['cs']=='Indexed') {
7859
+ $this->_newobj();
7860
+ $pal=($this->compress) ? gzcompress($info['pal']) : $info['pal'];
7861
+ $this->_out('<<'.$filter.'/Length '.strlen($pal).'>>');
7862
+ $this->_putstream($pal);
7863
+ $this->_out('endobj');
7864
+ }
7865
+ }
7866
+ }
7867
+
7868
+ function _putinfo()
7869
+ {
7870
+ $this->_out('/Producer '.$this->_UTF16BEtextstring('mPDF '.mPDF_VERSION));
7871
+ if(!empty($this->title))
7872
+ $this->_out('/Title '.$this->_UTF16BEtextstring($this->title));
7873
+ if(!empty($this->subject))
7874
+ $this->_out('/Subject '.$this->_UTF16BEtextstring($this->subject));
7875
+ if(!empty($this->author))
7876
+ $this->_out('/Author '.$this->_UTF16BEtextstring($this->author));
7877
+ if(!empty($this->keywords))
7878
+ $this->_out('/Keywords '.$this->_UTF16BEtextstring($this->keywords));
7879
+ if(!empty($this->creator))
7880
+ $this->_out('/Creator '.$this->_UTF16BEtextstring($this->creator));
7881
+
7882
+ $z = date('O'); // +0200
7883
+ $offset = substr($z,0,3)."'".substr($z,3,2)."'";
7884
+ $this->_out('/CreationDate '.$this->_textstring(date('YmdHis').$offset));
7885
+ $this->_out('/ModDate '.$this->_textstring(date('YmdHis').$offset));
7886
+ if ($this->PDFX) {
7887
+ $this->_out('/Trapped/False');
7888
+ $this->_out('/GTS_PDFXVersion(PDF/X-1a:2003)');
7889
+ }
7890
+ }
7891
+
7892
+ function _putmetadata() {
7893
+ $this->_newobj();
7894
+ $this->MetadataRoot = $this->n;
7895
+ $Producer = 'mPDF '.mPDF_VERSION;
7896
+ $z = date('O'); // +0200
7897
+ $offset = substr($z,0,3).':'.substr($z,3,2);
7898
+ $CreationDate = date('Y-m-d\TH:i:s').$offset; // 2006-03-10T10:47:26-05:00 2006-06-19T09:05:17Z
7899
+ $uuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff),
7900
+ mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000,
7901
+ mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff) );
7902
+
7903
+
7904
+ $m = '<?xpacket begin="'.chr(239).chr(187).chr(191).'" id="W5M0MpCehiHzreSzNTczkc9d"?>'."\n"; // begin = FEFF BOM
7905
+ $m .= ' <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="3.1-701">'."\n";
7906
+ $m .= ' <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">'."\n";
7907
+ $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">'."\n";
7908
+ $m .= ' <pdf:Producer>'.$Producer.'</pdf:Producer>'."\n";
7909
+ if(!empty($this->keywords)) { $m .= ' <pdf:Keywords>'.$this->keywords.'</pdf:Keywords>'."\n"; }
7910
+ $m .= ' </rdf:Description>'."\n";
7911
+
7912
+ $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:xmp="http://ns.adobe.com/xap/1.0/">'."\n";
7913
+ $m .= ' <xmp:CreateDate>'.$CreationDate.'</xmp:CreateDate>'."\n";
7914
+ $m .= ' <xmp:ModifyDate>'.$CreationDate.'</xmp:ModifyDate>'."\n";
7915
+ $m .= ' <xmp:MetadataDate>'.$CreationDate.'</xmp:MetadataDate>'."\n";
7916
+ if(!empty($this->creator)) { $m .= ' <xmp:CreatorTool>'.$this->creator.'</xmp:CreatorTool>'."\n"; }
7917
+ $m .= ' </rdf:Description>'."\n";
7918
+
7919
+ // DC elements
7920
+ $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:dc="http://purl.org/dc/elements/1.1/">'."\n";
7921
+ $m .= ' <dc:format>application/pdf</dc:format>'."\n";
7922
+ if(!empty($this->title)) {
7923
+ $m .= ' <dc:title>
7924
+ <rdf:Alt>
7925
+ <rdf:li xml:lang="x-default">'.$this->title.'</rdf:li>
7926
+ </rdf:Alt>
7927
+ </dc:title>'."\n";
7928
+ }
7929
+ if(!empty($this->keywords)) {
7930
+ $m .= ' <dc:subject>
7931
+ <rdf:Bag>
7932
+ <rdf:li>'.$this->keywords.'</rdf:li>
7933
+ </rdf:Bag>
7934
+ </dc:subject>'."\n";
7935
+ }
7936
+ if(!empty($this->subject)) {
7937
+ $m .= ' <dc:description>
7938
+ <rdf:Alt>
7939
+ <rdf:li xml:lang="x-default">'.$this->subject.'</rdf:li>
7940
+ </rdf:Alt>
7941
+ </dc:description>'."\n";
7942
+ }
7943
+ if(!empty($this->author)) {
7944
+ $m .= ' <dc:creator>
7945
+ <rdf:Seq>
7946
+ <rdf:li>'.$this->author.'</rdf:li>
7947
+ </rdf:Seq>
7948
+ </dc:creator>'."\n";
7949
+ }
7950
+ $m .= ' </rdf:Description>'."\n";
7951
+
7952
+
7953
+ // This bit is specific to PDFX-1a
7954
+ if ($this->PDFX) {
7955
+ $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:pdfx="http://ns.adobe.com/pdfx/1.3/" pdfx:Apag_PDFX_Checkup="1.3" pdfx:GTS_PDFXConformance="PDF/X-1a:2003" pdfx:GTS_PDFXVersion="PDF/X-1:2003"/>'."\n";
7956
+ }
7957
+
7958
+ // This bit is specific to PDFA-1b
7959
+ else if ($this->PDFA) {
7960
+ $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/" >'."\n";
7961
+ $m .= ' <pdfaid:part>1</pdfaid:part>'."\n";
7962
+ $m .= ' <pdfaid:conformance>B</pdfaid:conformance>'."\n";
7963
+ $m .= ' <pdfaid:amd>2005</pdfaid:amd>'."\n";
7964
+ $m .= ' </rdf:Description>'."\n";
7965
+ }
7966
+
7967
+ $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/">'."\n";
7968
+ $m .= ' <xmpMM:DocumentID>uuid:'.$uuid.'</xmpMM:DocumentID>'."\n";
7969
+ $m .= ' </rdf:Description>'."\n";
7970
+ $m .= ' </rdf:RDF>'."\n";
7971
+ $m .= ' </x:xmpmeta>'."\n";
7972
+ $m .= str_repeat(str_repeat(' ',100)."\n",20); // 2-4kB whitespace padding required
7973
+ $m .= '<?xpacket end="w"?>'; // "r" read only
7974
+ $this->_out('<</Type/Metadata/Subtype/XML/Length '.strlen($m).'>>');
7975
+ $this->_putstream($m);
7976
+ $this->_out('endobj');
7977
+ }
7978
+
7979
+ function _putoutputintent() {
7980
+ $this->_newobj();
7981
+ $this->OutputIntentRoot = $this->n;
7982
+ $this->_out('<</Type /OutputIntent');
7983
+
7984
+ if ($this->PDFA) {
7985
+ $this->_out('/S /GTS_PDFA1');
7986
+ if ($this->ICCProfile) {
7987
+ $this->_out('/Info ('.preg_replace('/_/',' ',$this->ICCProfile).')');
7988
+ $this->_out('/OutputConditionIdentifier (Custom)');
7989
+ $this->_out('/OutputCondition ()');
7990
+ }
7991
+ else {
7992
+ $this->_out('/Info (sRGB IEC61966-2.1)');
7993
+ $this->_out('/OutputConditionIdentifier (sRGB IEC61966-2.1)');
7994
+ $this->_out('/OutputCondition ()');
7995
+ }
7996
+ $this->_out('/DestOutputProfile '.($this->n+1).' 0 R');
7997
+ }
7998
+ else if ($this->PDFX) { // always a CMYK profile
7999
+ $this->_out('/S /GTS_PDFX');
8000
+ if ($this->ICCProfile) {
8001
+ $this->_out('/Info ('.preg_replace('/_/',' ',$this->ICCProfile).')');
8002
+ $this->_out('/OutputConditionIdentifier (Custom)');
8003
+ $this->_out('/OutputCondition ()');
8004
+ $this->_out('/DestOutputProfile '.($this->n+1).' 0 R');
8005
+ }
8006
+ else {
8007
+ $this->_out('/Info (CGATS TR 001)');
8008
+ $this->_out('/OutputConditionIdentifier (CGATS TR 001)');
8009
+ $this->_out('/OutputCondition (CGATS TR 001 (SWOP))');
8010
+ $this->_out('/RegistryName (http://www.color.org)');
8011
+ }
8012
+ }
8013
+ $this->_out('>>');
8014
+ $this->_out('endobj');
8015
+
8016
+ if ($this->PDFX && !$this->ICCProfile) { return; } // no ICCProfile embedded
8017
+
8018
+ $this->_newobj();
8019
+ if ($this->ICCProfile)
8020
+ $s = file_get_contents(_MPDF_PATH.'iccprofiles/'.$this->ICCProfile.'.icc');
8021
+ else
8022
+ $s = file_get_contents(_MPDF_PATH.'iccprofiles/sRGB_IEC61966-2-1.icc');
8023
+ if ($this->compress) { $s = gzcompress($s); }
8024
+ $this->_out('<<');
8025
+ if ($this->PDFX || ($this->PDFA && $this->restrictColorSpace == 3)) { $this->_out('/N 4'); }
8026
+ else { $this->_out('/N 3'); }
8027
+ if ($this->compress)
8028
+ $this->_out('/Filter /FlateDecode ');
8029
+ $this->_out('/Length '.strlen($s).'>>');
8030
+ $this->_putstream($s);
8031
+ $this->_out('endobj');
8032
+ }
8033
+
8034
+
8035
+ function _putcatalog() {
8036
+ $this->_out('/Type /Catalog');
8037
+ $this->_out('/Pages 1 0 R');
8038
+ if($this->ZoomMode=='fullpage') $this->_out('/OpenAction [3 0 R /Fit]');
8039
+ elseif($this->ZoomMode=='fullwidth') $this->_out('/OpenAction [3 0 R /FitH null]');
8040
+ elseif($this->ZoomMode=='real') $this->_out('/OpenAction [3 0 R /XYZ null null 1]');
8041
+ elseif(!is_string($this->ZoomMode)) $this->_out('/OpenAction [3 0 R /XYZ null null '.($this->ZoomMode/100).']');
8042
+ else $this->_out('/OpenAction [3 0 R /XYZ null null null]');
8043
+ if($this->LayoutMode=='single') $this->_out('/PageLayout /SinglePage');
8044
+ elseif($this->LayoutMode=='continuous') $this->_out('/PageLayout /OneColumn');
8045
+ elseif($this->LayoutMode=='twoleft') $this->_out('/PageLayout /TwoColumnLeft');
8046
+ elseif($this->LayoutMode=='tworight') $this->_out('/PageLayout /TwoColumnRight');
8047
+ elseif($this->LayoutMode=='two') {
8048
+ if ($this->mirrorMargins) { $this->_out('/PageLayout /TwoColumnRight'); }
8049
+ else { $this->_out('/PageLayout /TwoColumnLeft'); }
8050
+ }
8051
+
8052
+ if(is_int(strpos($this->DisplayPreferences,'FullScreen'))) $this->_out('/PageMode /FullScreen');
8053
+
8054
+ // Metadata
8055
+ if ($this->PDFA || $this->PDFX) {
8056
+ $this->_out('/Metadata '.$this->MetadataRoot.' 0 R');
8057
+ }
8058
+ // OutputIntents
8059
+ if ($this->PDFA || $this->PDFX || $this->ICCProfile) {
8060
+ $this->_out('/OutputIntents ['.$this->OutputIntentRoot.' 0 R]');
8061
+ }
8062
+
8063
+ if ( isset($this->js) ) {
8064
+ $this->_out('/Names << /JavaScript '.($this->n_js).' 0 R >> ');
8065
+ }
8066
+
8067
+ if($this->DisplayPreferences || $this->directionality == 'rtl' || $this->mirrorMargins) {
8068
+ $this->_out('/ViewerPreferences<<');
8069
+ if(is_int(strpos($this->DisplayPreferences,'HideMenubar'))) $this->_out('/HideMenubar true');
8070
+ if(is_int(strpos($this->DisplayPreferences,'HideToolbar'))) $this->_out('/HideToolbar true');
8071
+ if(is_int(strpos($this->DisplayPreferences,'HideWindowUI'))) $this->_out('/HideWindowUI true');
8072
+ if(is_int(strpos($this->DisplayPreferences,'DisplayDocTitle'))) $this->_out('/DisplayDocTitle true');
8073
+ if(is_int(strpos($this->DisplayPreferences,'CenterWindow'))) $this->_out('/CenterWindow true');
8074
+ if(is_int(strpos($this->DisplayPreferences,'FitWindow'))) $this->_out('/FitWindow true');
8075
+ // /PrintScaling is PDF 1.6 spec.
8076
+ if(is_int(strpos($this->DisplayPreferences,'NoPrintScaling')) && !$this->PDFA && !$this->PDFX)
8077
+ $this->_out('/PrintScaling /None');
8078
+ if($this->directionality == 'rtl') $this->_out('/Direction /R2L');
8079
+ // /Duplex is PDF 1.7 spec.
8080
+ if($this->mirrorMargins && !$this->PDFA && !$this->PDFX) {
8081
+ // if ($this->DefOrientation=='P') $this->_out('/Duplex /DuplexFlipShortEdge');
8082
+ $this->_out('/Duplex /DuplexFlipLongEdge'); // PDF v1.7+
8083
+ }
8084
+ $this->_out('>>');
8085
+ }
8086
+ // mPDF 5.6.01
8087
+ if($this->open_layer_pane && ($this->hasOC || count($this->layers)))
8088
+ $this->_out('/PageMode /UseOC');
8089
+
8090
+ // mPDF 5.6.01
8091
+ if ($this->hasOC || count($this->layers)) {
8092
+ $p = $v = $h = $l = $loff = $lall = $as = ''; // mPDF 5.6.28
8093
+ if ($this->hasOC) {
8094
+ if (($this->hasOC & 1) == 1) $p=$this->n_ocg_print.' 0 R';
8095
+ if (($this->hasOC & 2) == 2) $v=$this->n_ocg_view.' 0 R';
8096
+ if (($this->hasOC & 4) == 4) $h=$this->n_ocg_hidden.' 0 R';
8097
+ $as="<</Event /Print /OCGs [$p $v $h] /Category [/Print]>> <</Event /View /OCGs [$p $v $h] /Category [/View]>>";
8098
+ }
8099
+
8100
+ if(count($this->layers)) {
8101
+ foreach($this->layers as $k=>$layer) { // mPDF 5.6.28
8102
+ if (strtolower($this->layerDetails[$k]['state'])=='hidden') { $loff .= $layer['n'].' 0 R '; }
8103
+ else { $l .= $layer['n'].' 0 R '; }
8104
+ $lall .= $layer['n'].' 0 R ';
8105
+ }
8106
+ }
8107
+ $this->_out("/OCProperties <</OCGs [$p $v $h $lall] /D <</ON [$p $l] /OFF [$v $h $loff] "); // mPDF 5.6.28
8108
+ $this->_out("/Order [$v $p $h $lall] "); // mPDF 5.6.28
8109
+ if ($as) $this->_out("/AS [$as] ");
8110
+ $this->_out(">>>>");
8111
+
8112
+ }
8113
+
8114
+ }
8115
+
8116
+ // Inactive function left for backwards compatability
8117
+ function SetUserRights($enable=true, $annots="", $form="", $signature="") {
8118
+ // Does nothing
8119
+ }
8120
+
8121
+ function _enddoc() {
8122
+ $this->_puthtmlheaders(); // *HTMLHEADERS-FOOTERS*
8123
+ // Remove references to unused fonts (usually default font)
8124
+ foreach($this->fonts as $fk=>$font) {
8125
+ if (!$font['used'] && ($font['type']=='TTF')) {
8126
+ if ($font['sip'] || $font['smp']) {
8127
+ foreach($font['subsetfontids'] AS $k => $fid) {
8128
+ foreach($this->pages AS $pn=>$page) {
8129
+ $this->pages[$pn] = preg_replace('/\s\/F'.$fid.' \d[\d.]* Tf\s/is',' ',$this->pages[$pn]);
8130
+ }
8131
+ }
8132
+ }
8133
+ else {
8134
+ foreach($this->pages AS $pn=>$page) {
8135
+ $this->pages[$pn] = preg_replace('/\s\/F'.$font['i'].' \d[\d.]* Tf\s/is',' ',$this->pages[$pn]);
8136
+ }
8137
+ }
8138
+ }
8139
+ }
8140
+
8141
+ // mPDF 5.6.01 - LAYERS
8142
+ if (count($this->layers)) {
8143
+ foreach($this->pages AS $pn=>$page) {
8144
+ preg_match_all('/\/OCZ-index \/ZI(\d+) BDC(.*?)(EMCZ)-index/is',$this->pages[$pn],$m1);
8145
+ preg_match_all('/\/OCBZ-index \/ZI(\d+) BDC(.*?)(EMCBZ)-index/is',$this->pages[$pn],$m2);
8146
+ preg_match_all('/\/OCGZ-index \/ZI(\d+) BDC(.*?)(EMCGZ)-index/is',$this->pages[$pn],$m3);
8147
+ $m = array();
8148
+ for ($i=0;$i<4;$i++) {
8149
+ $m[$i] = array_merge($m1[$i],$m2[$i],$m3[$i]);
8150
+ }
8151
+ if (count($m[0])) {
8152
+ $sortarr = array();
8153
+ for($i=0;$i<count($m[0]);$i++) {
8154
+ $key = $m[1][$i]*2;
8155
+ if ($m[3][$i]=='EMCZ') $key +=2; // background first then gradient then normal
8156
+ else if ($m[3][$i]=='EMCGZ') $key +=1;
8157
+ $sortarr[$i] = $key;
8158
+ }
8159
+ asort($sortarr);
8160
+ foreach($sortarr AS $i=>$k) {
8161
+ $this->pages[$pn] = str_replace($m[0][$i],'',$this->pages[$pn] );
8162
+ $this->pages[$pn] .= "\n".$m[0][$i]."\n";
8163
+ }
8164
+ $this->pages[$pn] = preg_replace('/\/OC[BG]{0,1}Z-index \/ZI(\d+) BDC/is','/OC /ZI\\1 BDC ',$this->pages[$pn]);
8165
+ $this->pages[$pn] = preg_replace('/EMC[BG]{0,1}Z-index/is','EMC',$this->pages[$pn]);
8166
+ }
8167
+ }
8168
+ }
8169
+
8170
+ $this->_putpages();
8171
+
8172
+ $this->_putresources();
8173
+ //Info
8174
+ $this->_newobj();
8175
+ $this->InfoRoot = $this->n;
8176
+ $this->_out('<<');
8177
+ $this->_putinfo();
8178
+ $this->_out('>>');
8179
+ $this->_out('endobj');
8180
+
8181
+ // METADATA
8182
+ if ($this->PDFA || $this->PDFX) { $this->_putmetadata(); }
8183
+ // OUTPUTINTENT
8184
+ if ($this->PDFA || $this->PDFX || $this->ICCProfile) { $this->_putoutputintent(); }
8185
+
8186
+ //Catalog
8187
+ $this->_newobj();
8188
+ $this->_out('<<');
8189
+ $this->_putcatalog();
8190
+ $this->_out('>>');
8191
+ $this->_out('endobj');
8192
+ //Cross-ref
8193
+ $o=strlen($this->buffer);
8194
+ $this->_out('xref');
8195
+ $this->_out('0 '.($this->n+1));
8196
+ $this->_out('0000000000 65535 f ');
8197
+ for($i=1; $i <= $this->n ; $i++)
8198
+ $this->_out(sprintf('%010d 00000 n ',$this->offsets[$i]));
8199
+ //Trailer
8200
+ $this->_out('trailer');
8201
+ $this->_out('<<');
8202
+ $this->_puttrailer();
8203
+ $this->_out('>>');
8204
+ $this->_out('startxref');
8205
+ $this->_out($o);
8206
+
8207
+ $this->buffer .= '%%EOF';
8208
+ $this->state=3;
8209
+ }
8210
+
8211
+ function _beginpage($orientation,$mgl='',$mgr='',$mgt='',$mgb='',$mgh='',$mgf='',$ohname='',$ehname='',$ofname='',$efname='',$ohvalue=0,$ehvalue=0,$ofvalue=0,$efvalue=0,$pagesel='',$newformat='') {
8212
+ if (!($pagesel && $this->page==1 && (sprintf("%0.4f", $this->y)==sprintf("%0.4f", $this->tMargin)))) {
8213
+ $this->page++;
8214
+ $this->pages[$this->page]='';
8215
+ }
8216
+ $this->state=2;
8217
+ $resetHTMLHeadersrequired = false;
8218
+
8219
+ if ($newformat) { $this->_setPageSize($newformat, $orientation); }
8220
+ // Paged media (page-box)
8221
+
8222
+ if ($pagesel || (isset($this->page_box['using']) && $this->page_box['using'])) {
8223
+ if ($pagesel || $this->page==1) { $first = true; }
8224
+ else { $first = false; }
8225
+ if ($this->mirrorMargins && ($this->page % 2==0)) { $oddEven = 'E'; }
8226
+ else { $oddEven = 'O'; }
8227
+ if ($pagesel) { $psel = $pagesel; }
8228
+ else if ($this->page_box['current']) { $psel = $this->page_box['current']; }
8229
+ else { $psel = ''; }
8230
+ list($orientation,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$hname,$fname,$bg,$resetpagenum,$pagenumstyle,$suppress,$marks,$newformat) = $this->SetPagedMediaCSS($psel, $first, $oddEven);
8231
+ if ($this->mirrorMargins && ($this->page % 2==0)) {
8232
+ if ($hname) { $ehvalue = 1; $ehname = $hname; } else { $ehvalue = -1; }
8233
+ if ($fname) { $efvalue = 1; $efname = $fname; } else { $efvalue = -1; }
8234
+ }
8235
+ else {
8236
+ if ($hname) { $ohvalue = 1; $ohname = $hname; } else { $ohvalue = -1; }
8237
+ if ($fname) { $ofvalue = 1; $ofname = $fname; } else { $ofvalue = -1; }
8238
+ }
8239
+ if ($resetpagenum || $pagenumstyle || $suppress) {
8240
+ $this->PageNumSubstitutions[] = array('from'=>($this->page), 'reset'=> $resetpagenum, 'type'=>$pagenumstyle, 'suppress'=>$suppress);
8241
+ }
8242
+ // PAGED MEDIA - CROP / CROSS MARKS from @PAGE
8243
+ $this->show_marks = $marks;
8244
+
8245
+ // Background color
8246
+ if (isset($bg['BACKGROUND-COLOR'])) {
8247
+ $cor = $this->ConvertColor($bg['BACKGROUND-COLOR']);
8248
+ if ($cor) {
8249
+ $this->bodyBackgroundColor = $cor;
8250
+ }
8251
+ }
8252
+ else { $this->bodyBackgroundColor = false; }
8253
+
8254
+ if (isset($bg['BACKGROUND-GRADIENT'])) {
8255
+ $this->bodyBackgroundGradient = $bg['BACKGROUND-GRADIENT'];
8256
+ }
8257
+ else { $this->bodyBackgroundGradient = false; }
8258
+
8259
+ // Tiling Patterns
8260
+ if (isset($bg['BACKGROUND-IMAGE']) && $bg['BACKGROUND-IMAGE']) {
8261
+ $ret = $this->SetBackground($bg, $this->pgwidth);
8262
+ if ($ret) { $this->bodyBackgroundImage = $ret; }
8263
+ }
8264
+ else { $this->bodyBackgroundImage = false; }
8265
+
8266
+ $this->page_box['current'] = $psel;
8267
+ $this->page_box['using'] = true;
8268
+ }
8269
+
8270
+ //Page orientation
8271
+ if(!$orientation)
8272
+ $orientation=$this->DefOrientation;
8273
+ else {
8274
+ $orientation=strtoupper(substr($orientation,0,1));
8275
+ if($orientation!=$this->DefOrientation)
8276
+ $this->OrientationChanges[$this->page]=true;
8277
+ }
8278
+ if($orientation!=$this->CurOrientation || $newformat) {
8279
+
8280
+ //Change orientation
8281
+ if($orientation=='P') {
8282
+ $this->wPt=$this->fwPt;
8283
+ $this->hPt=$this->fhPt;
8284
+ $this->w=$this->fw;
8285
+ $this->h=$this->fh;
8286
+ if (($this->forcePortraitHeaders || $this->forcePortraitMargins) && $this->DefOrientation=='P') {
8287
+ $this->tMargin = $this->orig_tMargin;
8288
+ $this->bMargin = $this->orig_bMargin;
8289
+ $this->DeflMargin = $this->orig_lMargin;
8290
+ $this->DefrMargin = $this->orig_rMargin;
8291
+ $this->margin_header = $this->orig_hMargin;
8292
+ $this->margin_footer = $this->orig_fMargin;
8293
+ }
8294
+ else { $resetHTMLHeadersrequired = true; } // *HTMLHEADERS-FOOTERS*
8295
+ }
8296
+ else {
8297
+ $this->wPt=$this->fhPt;
8298
+ $this->hPt=$this->fwPt;
8299
+ $this->w=$this->fh;
8300
+ $this->h=$this->fw;
8301
+ if (($this->forcePortraitHeaders || $this->forcePortraitMargins) && $this->DefOrientation=='P') {
8302
+ $this->tMargin = $this->orig_lMargin;
8303
+ $this->bMargin = $this->orig_rMargin;
8304
+ $this->DeflMargin = $this->orig_bMargin;
8305
+ $this->DefrMargin = $this->orig_tMargin;
8306
+ $this->margin_header = $this->orig_hMargin;
8307
+ $this->margin_footer = $this->orig_fMargin;
8308
+ }
8309
+ else { $resetHTMLHeadersrequired = true; } // *HTMLHEADERS-FOOTERS*
8310
+
8311
+ }
8312
+ $this->CurOrientation=$orientation;
8313
+ $this->ResetMargins();
8314
+ $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
8315
+ $this->PageBreakTrigger=$this->h-$this->bMargin;
8316
+ }
8317
+
8318
+ $this->pageDim[$this->page]['w']=$this->w ;
8319
+ $this->pageDim[$this->page]['h']=$this->h ;
8320
+
8321
+ $this->pageDim[$this->page]['outer_width_LR'] = isset($this->page_box['outer_width_LR']) ? $this->page_box['outer_width_LR'] : 0;
8322
+ $this->pageDim[$this->page]['outer_width_TB'] = isset($this->page_box['outer_width_TB']) ? $this->page_box['outer_width_TB'] : 0;
8323
+ if (!isset($this->page_box['outer_width_LR']) && !isset($this->page_box['outer_width_TB'])) {
8324
+ $this->pageDim[$this->page]['bleedMargin'] = 0;
8325
+ }
8326
+ else if ($this->bleedMargin <= $this->page_box['outer_width_LR'] && $this->bleedMargin <= $this->page_box['outer_width_TB']) {
8327
+ $this->pageDim[$this->page]['bleedMargin'] = $this->bleedMargin;
8328
+ }
8329
+ else {
8330
+ $this->pageDim[$this->page]['bleedMargin'] = min($this->page_box['outer_width_LR'], $this->page_box['outer_width_TB'])-0.01;
8331
+ }
8332
+
8333
+ // If Page Margins are re-defined
8334
+ // strlen()>0 is used to pick up (integer) 0, (string) '0', or set value
8335
+ if ((strlen($mgl)>0 && $this->DeflMargin != $mgl) || (strlen($mgr)>0 && $this->DefrMargin != $mgr) || (strlen($mgt)>0 && $this->tMargin != $mgt) || (strlen($mgb)>0 && $this->bMargin != $mgb) || (strlen($mgh)>0 && $this->margin_header!=$mgh) || (strlen($mgf)>0 && $this->margin_footer!=$mgf)) {
8336
+ if (strlen($mgl)>0) $this->DeflMargin = $mgl;
8337
+ if (strlen($mgr)>0) $this->DefrMargin = $mgr;
8338
+ if (strlen($mgt)>0) $this->tMargin = $mgt;
8339
+ if (strlen($mgb)>0) $this->bMargin = $mgb;
8340
+ if (strlen($mgh)>0) $this->margin_header=$mgh;
8341
+ if (strlen($mgf)>0) $this->margin_footer=$mgf;
8342
+ $this->ResetMargins();
8343
+ $this->SetAutoPageBreak($this->autoPageBreak,$this->bMargin);
8344
+ $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
8345
+ $resetHTMLHeadersrequired = true; // *HTMLHEADERS-FOOTERS*
8346
+ }
8347
+
8348
+ $this->ResetMargins();
8349
+ $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
8350
+ $this->SetAutoPageBreak($this->autoPageBreak,$this->bMargin);
8351
+
8352
+ // Reset column top margin
8353
+ $this->y0 = $this->tMargin;
8354
+
8355
+ $this->x=$this->lMargin;
8356
+ $this->y=$this->tMargin;
8357
+ $this->FontFamily='';
8358
+
8359
+ // HEADERS AND FOOTERS
8360
+ if ($ohvalue<0 || strtoupper($ohvalue)=='OFF') {
8361
+ $this->HTMLHeader = '';
8362
+ $this->headerDetails['odd'] = array();
8363
+ $resetHTMLHeadersrequired = true; // *HTMLHEADERS-FOOTERS*
8364
+ }
8365
+ else if ($ohname && $ohvalue>0) {
8366
+ if (preg_match('/^html_(.*)$/i',$ohname,$n)) {
8367
+ if (isset($this->pageHTMLheaders[$n[1]])) { $this->HTMLHeader = $this->pageHTMLheaders[$n[1]]; }
8368
+ else { $this->HTMLHeader = ''; }
8369
+ $this->headerDetails['odd'] = array();
8370
+ $resetHTMLHeadersrequired = true;
8371
+ }
8372
+ else {
8373
+ if (isset($this->pageheaders[$ohname])) { $this->headerDetails['odd'] = $this->pageheaders[$ohname]; }
8374
+ else if ($ohname!='_default') { $this->headerDetails['odd'] = array(); }
8375
+ $this->HTMLHeader = '';
8376
+ $resetHTMLHeadersrequired = false;
8377
+ }
8378
+ }
8379
+
8380
+ if ($ehvalue<0 || strtoupper($ehvalue)=='OFF') {
8381
+ $this->HTMLHeaderE = '';
8382
+ $this->headerDetails['even'] = array();
8383
+ $resetHTMLHeadersrequired = true; // *HTMLHEADERS-FOOTERS*
8384
+ }
8385
+ else if ($ehname && $ehvalue>0) {
8386
+ if (preg_match('/^html_(.*)$/i',$ehname,$n)) {
8387
+ if (isset($this->pageHTMLheaders[$n[1]])) { $this->HTMLHeaderE = $this->pageHTMLheaders[$n[1]]; }
8388
+ else { $this->HTMLHeaderE = ''; }
8389
+ $this->headerDetails['even'] = array();
8390
+ $resetHTMLHeadersrequired = true;
8391
+ }
8392
+ else {
8393
+ if (isset($this->pageheaders[$ehname])) { $this->headerDetails['even'] = $this->pageheaders[$ehname]; }
8394
+ else if ($ehname!='_default') { $this->headerDetails['even'] = array(); }
8395
+ $this->HTMLHeaderE = '';
8396
+ $resetHTMLHeadersrequired = false;
8397
+ }
8398
+ }
8399
+
8400
+ if ($ofvalue<0 || strtoupper($ofvalue)=='OFF') {
8401
+ $this->HTMLFooter = '';
8402
+ $this->footerDetails['odd'] = array();
8403
+ $resetHTMLHeadersrequired = true; // *HTMLHEADERS-FOOTERS*
8404
+ }
8405
+ else if ($ofname && $ofvalue>0) {
8406
+ if (preg_match('/^html_(.*)$/i',$ofname,$n)) {
8407
+ if (isset($this->pageHTMLfooters[$n[1]])) { $this->HTMLFooter = $this->pageHTMLfooters[$n[1]]; }
8408
+ else { $this->HTMLFooter = ''; }
8409
+ $this->footerDetails['odd'] = array();
8410
+ $resetHTMLHeadersrequired = true;
8411
+ }
8412
+ else {
8413
+ if (isset($this->pagefooters[$ofname])) { $this->footerDetails['odd'] = $this->pagefooters[$ofname]; }
8414
+ else if ($ofname!='_default') { $this->footerDetails['odd'] = array(); }
8415
+ $this->HTMLFooter = '';
8416
+ $resetHTMLHeadersrequired = true;
8417
+ }
8418
+ }
8419
+
8420
+ if ($efvalue<0 || strtoupper($efvalue)=='OFF') {
8421
+ $this->HTMLFooterE = '';
8422
+ $this->footerDetails['even'] = array();
8423
+ $resetHTMLHeadersrequired = true; // *HTMLHEADERS-FOOTERS*
8424
+ }
8425
+ else if ($efname && $efvalue>0) {
8426
+ if (preg_match('/^html_(.*)$/i',$efname,$n)) {
8427
+ if (isset($this->pageHTMLfooters[$n[1]])) { $this->HTMLFooterE = $this->pageHTMLfooters[$n[1]]; }
8428
+ else { $this->HTMLFooterE = ''; }
8429
+ $this->footerDetails['even'] = array();
8430
+ $resetHTMLHeadersrequired = true;
8431
+ }
8432
+ else {
8433
+ if (isset($this->pagefooters[$efname])) { $this->footerDetails['even'] = $this->pagefooters[$efname]; }
8434
+ else if ($efname!='_default') { $this->footerDetails['even'] = array(); }
8435
+ $this->HTMLFooterE = '';
8436
+ $resetHTMLHeadersrequired = true;
8437
+ }
8438
+ }
8439
+ if ($resetHTMLHeadersrequired) {
8440
+ $this->SetHTMLHeader($this->HTMLHeader );
8441
+ $this->SetHTMLHeader($this->HTMLHeaderE ,'E');
8442
+ $this->SetHTMLFooter($this->HTMLFooter );
8443
+ $this->SetHTMLFooter($this->HTMLFooterE ,'E');
8444
+ }
8445
+
8446
+
8447
+ if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
8448
+ $this->_setAutoHeaderHeight($this->headerDetails['even'], $this->HTMLHeaderE);
8449
+ $this->_setAutoFooterHeight($this->footerDetails['even'], $this->HTMLFooterE);
8450
+ }
8451
+ else { // ODD or DEFAULT
8452
+ $this->_setAutoHeaderHeight($this->headerDetails['odd'], $this->HTMLHeader);
8453
+ $this->_setAutoFooterHeight($this->footerDetails['odd'], $this->HTMLFooter);
8454
+ }
8455
+ // Reset column top margin
8456
+ $this->y0 = $this->tMargin;
8457
+
8458
+ $this->x=$this->lMargin;
8459
+ $this->y=$this->tMargin;
8460
+ }
8461
+
8462
+
8463
+
8464
+ function _setAutoHeaderHeight(&$det, &$htmlh) {
8465
+ if ($this->setAutoTopMargin=='pad') {
8466
+ if ($htmlh['h']) { $h = $htmlh['h']; }
8467
+ else if ($det) { $h = $this->_getHFHeight($det,'H'); }
8468
+ else { $h = 0; }
8469
+ $this->tMargin = $this->margin_header + $h + $this->orig_tMargin;
8470
+ }
8471
+ else if ($this->setAutoTopMargin=='stretch') {
8472
+ if ($htmlh['h']) { $h = $htmlh['h']; }
8473
+ else if ($det) { $h = $this->_getHFHeight($det,'H'); }
8474
+ else { $h = 0; }
8475
+ $this->tMargin = max($this->orig_tMargin, $this->margin_header + $h + $this->autoMarginPadding);
8476
+ }
8477
+ }
8478
+
8479
+
8480
+ function _setAutoFooterHeight(&$det, &$htmlf) {
8481
+ if ($this->setAutoBottomMargin=='pad') {
8482
+ if ($htmlf['h']) { $h = $htmlf['h']; }
8483
+ else if ($det) { $h = $this->_getHFHeight($det,'F'); }
8484
+ else { $h = 0; }
8485
+ $this->bMargin = $this->margin_footer + $h + $this->orig_bMargin;
8486
+ $this->PageBreakTrigger=$this->h-$this->bMargin ;
8487
+ }
8488
+ else if ($this->setAutoBottomMargin=='stretch') {
8489
+ if ($htmlf['h']) { $h = $htmlf['h']; }
8490
+ else if ($det) { $h = $this->_getHFHeight($det,'F'); }
8491
+ else { $h = 0; }
8492
+ $this->bMargin = max($this->orig_bMargin, $this->margin_footer + $h + $this->autoMarginPadding);
8493
+ $this->PageBreakTrigger=$this->h-$this->bMargin ;
8494
+ }
8495
+ }
8496
+
8497
+ function _getHFHeight(&$det,$end) {
8498
+ $h = 0;
8499
+ if(count($det)) {
8500
+ foreach(array('L','C','R') AS $pos) {
8501
+ if (isset($det[$pos]['content']) && $det[$pos]['content']) {
8502
+ if (isset($det[$pos]['font-size']) && $det[$pos]['font-size']) { $hfsz = $det[$pos]['font-size']; }
8503
+ else { $hfsz = $this->default_font_size; }
8504
+ $h = max($h,$hfsz/_MPDFK);
8505
+ }
8506
+ }
8507
+ if ($det['line'] && $end=='H') { $h += $h/_MPDFK*$this->header_line_spacing; }
8508
+ else if ($det['line'] && $end=='F') { $h += $h/_MPDFK*$this->footer_line_spacing; }
8509
+ }
8510
+ return $h;
8511
+ }
8512
+
8513
+
8514
+ function _endpage() {
8515
+ $this->printfloatbuffer();
8516
+
8517
+ if($this->visibility!='visible')
8518
+ $this->SetVisibility('visible');
8519
+ $this->EndLayer(); // mPDF 5.6.01
8520
+ //End of page contents
8521
+ $this->state=1;
8522
+ }
8523
+
8524
+ function _newobj($obj_id=false,$onlynewobj=false) {
8525
+ if (!$obj_id) {
8526
+ $obj_id = ++$this->n;
8527
+ }
8528
+ //Begin a new object
8529
+ if (!$onlynewobj) {
8530
+ $this->offsets[$obj_id] = strlen($this->buffer);
8531
+ $this->_out($obj_id.' 0 obj');
8532
+ $this->_current_obj_id = $obj_id; // for later use with encryption
8533
+ }
8534
+ }
8535
+
8536
+ function _dounderline($x,$y,$txt) {
8537
+ // Now print line exactly where $y secifies - called from Text() and Cell() - adjust position there
8538
+ // WORD SPACING
8539
+ $w =($this->GetStringWidth($txt)*_MPDFK) + ($this->charspacing * mb_strlen( $txt, $this->mb_enc ))
8540
+ + ( $this->ws * mb_substr_count( $txt, ' ', $this->mb_enc ));
8541
+ //Draw a line
8542
+ return sprintf('%.3F %.3F m %.3F %.3F l S',$x*_MPDFK,($this->h-$y)*_MPDFK,($x*_MPDFK)+$w,($this->h-$y)*_MPDFK);
8543
+ }
8544
+
8545
+
8546
+ function _imageError($file, $firsttime, $msg) {
8547
+ // Save re-trying image URL's which have already failed
8548
+ $this->failedimages[$file] = true;
8549
+ if ($firsttime && ($this->showImageErrors || $this->debug)) {
8550
+ $this->Error("IMAGE Error (".$file."): ".$msg);
8551
+ }
8552
+ return false;
8553
+ }
8554
+
8555
+
8556
+ function _getImage(&$file, $firsttime=true, $allowvector=true, $orig_srcpath=false) {
8557
+ // firsttime i.e. whether to add to this->images - use false when calling iteratively
8558
+ // Image Data passed directly as var:varname
8559
+ if (preg_match('/var:\s*(.*)/',$file, $v)) {
8560
+ $data = $this->$v[1];
8561
+ $file = md5($data);
8562
+ }
8563
+ // mPDF 5.5.13
8564
+ if (preg_match('/data:image\/(gif|jpeg|png);base64,(.*)/',$file, $v)) {
8565
+ $type = $v[1];
8566
+ $data = base64_decode($v[2]);
8567
+ $file = md5($data);
8568
+ }
8569
+
8570
+ // mPDF 5.6.02
8571
+ if ($firsttime && $file && substr($file,0,5)!='data:') { $file = urlencode_part($file); }
8572
+ if ($firsttime && $orig_srcpath && substr($orig_srcpath,0,5)!='data:') { $orig_srcpath = urlencode_part($orig_srcpath); }
8573
+
8574
+ $ppUx = 0;
8575
+ if ($orig_srcpath && isset($this->images[$orig_srcpath])) { $file=$orig_srcpath; return $this->images[$orig_srcpath]; }
8576
+ if (isset($this->images[$file])) { return $this->images[$file]; }
8577
+ else if ($orig_srcpath && isset($this->formobjects[$orig_srcpath])) { $file=$orig_srcpath; return $this->formobjects[$file]; }
8578
+ else if (isset($this->formobjects[$file])) { return $this->formobjects[$file]; }
8579
+ // Save re-trying image URL's which have already failed
8580
+ else if ($firsttime && isset($this->failedimages[$file])) { return $this->_imageError($file, $firsttime, ''); }
8581
+ if (empty($data)) {
8582
+ $type = '';
8583
+ $data = '';
8584
+
8585
+ if ($orig_srcpath && $this->basepathIsLocal && $check = @fopen($orig_srcpath,"rb")) {
8586
+ fclose($check);
8587
+ $file=$orig_srcpath;
8588
+ $data = file_get_contents($file);
8589
+ $type = $this->_imageTypeFromString($data);
8590
+ }
8591
+ if (!$data && $check = @fopen($file,"rb")) {
8592
+ fclose($check);
8593
+ $data = file_get_contents($file);
8594
+ $type = $this->_imageTypeFromString($data);
8595
+ }
8596
+ if ((!$data || !$type) && !ini_get('allow_url_fopen') ) { // only worth trying if remote file and !ini_get('allow_url_fopen')
8597
+ $this->file_get_contents_by_socket($file, $data); // needs full url?? even on local (never needed for local)
8598
+ if ($data) { $type = $this->_imageTypeFromString($data); }
8599
+ }
8600
+ if ((!$data || !$type) && !ini_get('allow_url_fopen') && function_exists("curl_init")) {
8601
+ $this->file_get_contents_by_curl($file, $data); // needs full url?? even on local (never needed for local)
8602
+ if ($data) { $type = $this->_imageTypeFromString($data); }
8603
+ }
8604
+
8605
+ }
8606
+ if (!$data) { return $this->_imageError($file, $firsttime, 'Could not find image file'); }
8607
+ if (empty($type)) { $type = $this->_imageTypeFromString($data); }
8608
+ if (($type == 'wmf' || $type == 'svg') && !$allowvector) { return $this->_imageError($file, $firsttime, 'WMF or SVG image file not supported in this context'); }
8609
+
8610
+ // SVG
8611
+ if ($type == 'svg') {
8612
+ if (!class_exists('SVG', false)) { include(_MPDF_PATH .'classes/svg.php'); }
8613
+ $svg = new SVG($this);
8614
+ $family=$this->FontFamily;
8615
+ $style=$this->FontStyle;
8616
+ $size=$this->FontSizePt;
8617
+ $info = $svg->ImageSVG($data);
8618
+ //Restore font
8619
+ if($family) $this->SetFont($family,$style,$size,false);
8620
+ if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing SVG file'); }
8621
+ $info['type']='svg';
8622
+ $info['i']=count($this->formobjects)+1;
8623
+ $this->formobjects[$file]=$info;
8624
+ return $info;
8625
+ }
8626
+
8627
+ // JPEG
8628
+ if ($type == 'jpeg' || $type == 'jpg') {
8629
+ $hdr = $this->_jpgHeaderFromString($data);
8630
+ if (!$hdr) { return $this->_imageError($file, $firsttime, 'Error parsing JPG header'); }
8631
+ $a = $this->_jpgDataFromHeader($hdr);
8632
+ $j = strpos($data,'JFIF');
8633
+ if ($j) {
8634
+ //Read resolution
8635
+ $unitSp=ord(substr($data,($j+7),1));
8636
+ if ($unitSp > 0) {
8637
+ $ppUx=$this->_twobytes2int(substr($data,($j+8),2)); // horizontal pixels per meter, usually set to zero
8638
+ if ($unitSp == 2) { // = dots per cm (if == 1 set as dpi)
8639
+ $ppUx=round($ppUx/10 *25.4);
8640
+ }
8641
+ }
8642
+ }
8643
+ if ($a[2] == 'DeviceCMYK' && (($this->PDFA && $this->restrictColorSpace!=3) || $this->restrictColorSpace==2)) {
8644
+ // convert to RGB image
8645
+ if (!function_exists("gd_info")) { $this->Error("JPG image may not use CMYK color space (".$file.")."); }
8646
+ if ($this->PDFA && !$this->PDFAauto) { $this->PDFAXwarnings[] = "JPG image may not use CMYK color space - ".$file." - (Image converted to RGB. NB This will alter the colour profile of the image.)"; }
8647
+ $im = @imagecreatefromstring($data);
8648
+ if ($im) {
8649
+ $tempfile = _MPDF_TEMP_PATH.'_tempImgPNG'.RAND(1,10000).'.png';
8650
+ imageinterlace($im, false);
8651
+ $check = @imagepng($im, $tempfile);
8652
+ if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary file ('.$tempfile.') whilst using GD library to parse JPG(CMYK) image'); }
8653
+ $info = $this->_getImage($tempfile, false);
8654
+ if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse JPG(CMYK) image'); }
8655
+ imagedestroy($im);
8656
+ unlink($tempfile);
8657
+ $info['type']='jpg';
8658
+ if ($firsttime) {
8659
+ $info['i']=count($this->images)+1;
8660
+ $this->images[$file]=$info;
8661
+ }
8662
+ return $info;
8663
+ }
8664
+ else { return $this->_imageError($file, $firsttime, 'Error creating GD image file from JPG(CMYK) image'); }
8665
+ }
8666
+ else if ($a[2] == 'DeviceRGB' && ($this->PDFX || $this->restrictColorSpace==3)) {
8667
+ // Convert to CMYK image stream - nominally returned as type='png'
8668
+ $info = $this->_convImage($data, $a[2], 'DeviceCMYK', $a[0], $a[1], $ppUx, false);
8669
+ if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "JPG image may not use RGB color space - ".$file." - (Image converted to CMYK. NB This will alter the colour profile of the image.)"; }
8670
+ }
8671
+ else if (($a[2] == 'DeviceRGB' || $a[2] == 'DeviceCMYK') && $this->restrictColorSpace==1) {
8672
+ // Convert to Grayscale image stream - nominally returned as type='png'
8673
+ $info = $this->_convImage($data, $a[2], 'DeviceGray', $a[0], $a[1], $ppUx, false);
8674
+ }
8675
+ else {
8676
+ $info = array('w'=>$a[0],'h'=>$a[1],'cs'=>$a[2],'bpc'=>$a[3],'f'=>'DCTDecode','data'=>$data, 'type'=>'jpg');
8677
+ if ($ppUx) { $info['set-dpi'] = $ppUx; }
8678
+ }
8679
+ if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing or converting JPG image'); }
8680
+
8681
+ if ($firsttime) {
8682
+ $info['i']=count($this->images)+1;
8683
+ $this->images[$file]=$info;
8684
+ }
8685
+ return $info;
8686
+ }
8687
+
8688
+ // PNG
8689
+ else if ($type == 'png') {
8690
+ //Check signature
8691
+ if(substr($data,0,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) {
8692
+ return $this->_imageError($file, $firsttime, 'Error parsing PNG identifier');
8693
+ }
8694
+ //Read header chunk
8695
+ if(substr($data,12,4)!='IHDR') {
8696
+ return $this->_imageError($file, $firsttime, 'Incorrect PNG file (no IHDR block found)');
8697
+ }
8698
+
8699
+ $w=$this->_fourbytes2int(substr($data,16,4));
8700
+ $h=$this->_fourbytes2int(substr($data,20,4));
8701
+ $bpc=ord(substr($data,24,1));
8702
+ $errpng = false;
8703
+ $pngalpha = false;
8704
+ if($bpc>8) { $errpng = 'not 8-bit depth'; }
8705
+ $ct=ord(substr($data,25,1));
8706
+ if($ct==0) { $colspace='DeviceGray'; }
8707
+ elseif($ct==2) { $colspace='DeviceRGB'; }
8708
+ elseif($ct==3) { $colspace='Indexed'; }
8709
+ elseif($ct==4) { $colspace='DeviceGray'; $errpng = 'alpha channel'; $pngalpha = true; }
8710
+ else { $colspace='DeviceRGB'; $errpng = 'alpha channel'; $pngalpha = true; }
8711
+ if(ord(substr($data,26,1))!=0) { $errpng = 'compression method'; }
8712
+ if(ord(substr($data,27,1))!=0) { $errpng = 'filter method'; }
8713
+ if(ord(substr($data,28,1))!=0) { $errpng = 'interlaced file'; }
8714
+ $j = strpos($data,'pHYs');
8715
+ if ($j) {
8716
+ //Read resolution
8717
+ $unitSp=ord(substr($data,($j+12),1));
8718
+ if ($unitSp == 1) {
8719
+ $ppUx=$this->_fourbytes2int(substr($data,($j+4),4)); // horizontal pixels per meter, usually set to zero
8720
+ $ppUx=round($ppUx/1000 *25.4);
8721
+ }
8722
+ }
8723
+ if (($colspace == 'DeviceRGB' || $colspace == 'Indexed') && ($this->PDFX || $this->restrictColorSpace==3)) {
8724
+ // Convert to CMYK image stream - nominally returned as type='png'
8725
+ $info = $this->_convImage($data, $colspace, 'DeviceCMYK', $w, $h, $ppUx, $pngalpha);
8726
+ if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "PNG image may not use RGB color space - ".$file." - (Image converted to CMYK. NB This will alter the colour profile of the image.)"; }
8727
+ }
8728
+ else if (($colspace == 'DeviceRGB' || $colspace == 'Indexed') && $this->restrictColorSpace==1) {
8729
+ // Convert to Grayscale image stream - nominally returned as type='png'
8730
+ $info = $this->_convImage($data, $colspace, 'DeviceGray', $w, $h, $ppUx, $pngalpha);
8731
+ }
8732
+ else if (($this->PDFA || $this->PDFX) && $pngalpha) {
8733
+ // Remove alpha channel
8734
+ if ($this->restrictColorSpace==1) { // Grayscale
8735
+ $info = $this->_convImage($data, $colspace, 'DeviceGray', $w, $h, $ppUx, $pngalpha);
8736
+ }
8737
+ else if ($this->restrictColorSpace==3) { // CMYK
8738
+ $info = $this->_convImage($data, $colspace, 'DeviceCMYK', $w, $h, $ppUx, $pngalpha);
8739
+ }
8740
+ else if ($this->PDFA ) { // RGB
8741
+ $info = $this->_convImage($data, $colspace, 'DeviceRGB', $w, $h, $ppUx, $pngalpha);
8742
+ }
8743
+ if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "Transparency (alpha channel) not permitted in PDFA or PDFX files - ".$file." - (Image converted to one without transparency.)"; }
8744
+ }
8745
+ else if ($errpng || $pngalpha) {
8746
+ if (function_exists('gd_info')) { $gd = gd_info(); }
8747
+ else {$gd = array(); }
8748
+ if (!isset($gd['PNG Support'])) { return $this->_imageError($file, $firsttime, 'GD library required for PNG image ('.$errpng.')'); }
8749
+ $im = imagecreatefromstring($data);
8750
+ if (!$im) { return $this->_imageError($file, $firsttime, 'Error creating GD image from PNG file ('.$errpng.')'); }
8751
+ $w = imagesx($im);
8752
+ $h = imagesy($im);
8753
+ if ($im) {
8754
+ $tempfile = _MPDF_TEMP_PATH.'_tempImgPNG'.RAND(1,10000).'.png';
8755
+ // Alpha channel set
8756
+ if ($pngalpha) {
8757
+ if ($this->PDFA) { $this->Error("PDFA1-b does not permit images with alpha channel transparency (".$file.")."); }
8758
+ $imgalpha = imagecreate($w, $h);
8759
+ // generate gray scale pallete
8760
+ for ($c = 0; $c < 256; ++$c) { ImageColorAllocate($imgalpha, $c, $c, $c); }
8761
+ // extract alpha channel
8762
+ $gammacorr = 2.2; // gamma correction
8763
+ for ($xpx = 0; $xpx < $w; ++$xpx) {
8764
+ for ($ypx = 0; $ypx < $h; ++$ypx) {
8765
+ //$colorindex = imagecolorat($im, $xpx, $ypx);
8766
+ //$col = imagecolorsforindex($im, $colorindex);
8767
+ //$gamma2 = (pow((((127 - $col['alpha']) * 255 / 127) / 255), $gammacorr) * 255);
8768
+ $alpha = (imagecolorat($im, $xpx, $ypx) & 0x7F000000) >> 24;
8769
+ if ($alpha < 127) {
8770
+ if ($alpha==0) { $gamma = 255; }
8771
+ else
8772
+ $gamma = (pow((((127 - $alpha) * 255 / 127) / 255), $gammacorr) * 255);
8773
+ imagesetpixel($imgalpha, $xpx, $ypx, $gamma);
8774
+ }
8775
+ }
8776
+ }
8777
+ // create temp alpha file
8778
+ $tempfile_alpha = _MPDF_TEMP_PATH.'_tempMskPNG'.RAND(1,10000).'.png';
8779
+ if (!is_writable($tempfile_alpha)) {
8780
+ ob_start();
8781
+ $check = @imagepng($imgalpha);
8782
+ if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary image object whilst using GD library to parse PNG image'); }
8783
+ imagedestroy($imgalpha);
8784
+ $this->_tempimg = ob_get_contents();
8785
+ $this->_tempimglnk = 'var:_tempimg';
8786
+ ob_end_clean();
8787
+ // extract image without alpha channel
8788
+ $imgplain = imagecreatetruecolor($w, $h);
8789
+ imagecopy($imgplain, $im, 0, 0, 0, 0, $w, $h);
8790
+ // create temp image file
8791
+ $minfo = $this->_getImage($this->_tempimglnk, false);
8792
+ if (!$minfo) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file image object created with GD library to parse PNG image'); }
8793
+ ob_start();
8794
+ $check = @imagepng($imgplain);
8795
+ if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary image object whilst using GD library to parse PNG image'); }
8796
+ $this->_tempimg = ob_get_contents();
8797
+ $this->_tempimglnk = 'var:_tempimg';
8798
+ ob_end_clean();
8799
+ $info = $this->_getImage($this->_tempimglnk, false);
8800
+ if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file image object created with GD library to parse PNG image'); }
8801
+ imagedestroy($imgplain);
8802
+ $imgmask = count($this->images)+1;
8803
+ $minfo['cs'] = 'DeviceGray';
8804
+ $minfo['i']=$imgmask ;
8805
+ $this->images[$tempfile_alpha] = $minfo;
8806
+
8807
+ }
8808
+ else {
8809
+ $check = @imagepng($imgalpha, $tempfile_alpha);
8810
+ if (!$check) { return $this->_imageError($file, $firsttime, 'Failed to create temporary image file ('.$tempfile_alpha.') parsing PNG image with alpha channel ('.$errpng.')'); }
8811
+ imagedestroy($imgalpha);
8812
+
8813
+ // extract image without alpha channel
8814
+ $imgplain = imagecreatetruecolor($w, $h);
8815
+ imagecopy($imgplain, $im, 0, 0, 0, 0, $w, $h);
8816
+
8817
+ // create temp image file
8818
+ $check = @imagepng($imgplain, $tempfile);
8819
+ if (!$check) { return $this->_imageError($file, $firsttime, 'Failed to create temporary image file ('.$tempfile.') parsing PNG image with alpha channel ('.$errpng.')'); }
8820
+ imagedestroy($imgplain);
8821
+ // embed mask image
8822
+ $minfo = $this->_getImage($tempfile_alpha, false);
8823
+ unlink($tempfile_alpha);
8824
+ if (!$minfo) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile_alpha.') created with GD library to parse PNG image'); }
8825
+ $imgmask = count($this->images)+1;
8826
+ $minfo['cs'] = 'DeviceGray';
8827
+ $minfo['i']=$imgmask ;
8828
+ $this->images[$tempfile_alpha] = $minfo;
8829
+ // embed image, masked with previously embedded mask
8830
+ $info = $this->_getImage($tempfile, false);
8831
+ unlink($tempfile);
8832
+ if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse PNG image'); }
8833
+
8834
+ }
8835
+ $info['masked'] = $imgmask;
8836
+ if ($ppUx) { $info['set-dpi'] = $ppUx; }
8837
+ $info['type']='png';
8838
+ if ($firsttime) {
8839
+ $info['i']=count($this->images)+1;
8840
+ $this->images[$file]=$info;
8841
+ }
8842
+ return $info;
8843
+ }
8844
+ else { // No alpha/transparency set
8845
+ imagealphablending($im, false);
8846
+ imagesavealpha($im, false);
8847
+ imageinterlace($im, false);
8848
+ if (!is_writable($tempfile)) {
8849
+ ob_start();
8850
+ $check = @imagepng($im);
8851
+ if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary image object whilst using GD library to parse PNG image'); }
8852
+ $this->_tempimg = ob_get_contents();
8853
+ $this->_tempimglnk = 'var:_tempimg';
8854
+ ob_end_clean();
8855
+ $info = $this->_getImage($this->_tempimglnk, false);
8856
+ if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file image object created with GD library to parse PNG image'); }
8857
+ imagedestroy($im);
8858
+ }
8859
+ else {
8860
+ $check = @imagepng($im, $tempfile );
8861
+ if (!$check) { return $this->_imageError($file, $firsttime, 'Failed to create temporary image file ('.$tempfile.') parsing PNG image ('.$errpng.')'); }
8862
+ imagedestroy($im);
8863
+ $info = $this->_getImage($tempfile, false) ;
8864
+ unlink($tempfile );
8865
+ if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse PNG image'); }
8866
+ }
8867
+ if ($ppUx) { $info['set-dpi'] = $ppUx; }
8868
+ $info['type']='png';
8869
+ if ($firsttime) {
8870
+ $info['i']=count($this->images)+1;
8871
+ $this->images[$file]=$info;
8872
+ }
8873
+ return $info;
8874
+ }
8875
+ }
8876
+ }
8877
+
8878
+ else {
8879
+ $parms='/DecodeParms <</Predictor 15 /Colors '.($ct==2 ? 3 : 1).' /BitsPerComponent '.$bpc.' /Columns '.$w.'>>';
8880
+ //Scan chunks looking for palette, transparency and image data
8881
+ $pal='';
8882
+ $trns='';
8883
+ $pngdata='';
8884
+ $p = 33;
8885
+ do {
8886
+ $n=$this->_fourbytes2int(substr($data,$p,4)); $p += 4;
8887
+ $type=substr($data,$p,4); $p += 4;
8888
+ if($type=='PLTE') {
8889
+ //Read palette
8890
+ $pal=substr($data,$p,$n); $p += $n;
8891
+ $p += 4;
8892
+ }
8893
+ elseif($type=='tRNS') {
8894
+ //Read transparency info
8895
+ $t=substr($data,$p,$n); $p += $n;
8896
+ if($ct==0) $trns=array(ord(substr($t,1,1)));
8897
+ elseif($ct==2) $trns=array(ord(substr($t,1,1)),ord(substr($t,3,1)),ord(substr($t,5,1)));
8898
+ else
8899
+ {
8900
+ $pos=strpos($t,chr(0));
8901
+ if(is_int($pos)) $trns=array($pos);
8902
+ }
8903
+ $p += 4;
8904
+ }
8905
+ elseif($type=='IDAT') {
8906
+ $pngdata.=substr($data,$p,$n); $p += $n;
8907
+ $p += 4;
8908
+ }
8909
+ elseif($type=='IEND') { break; }
8910
+ else if (preg_match('/[a-zA-Z]{4}/',$type)) { $p += $n+4; }
8911
+ else { return $this->_imageError($file, $firsttime, 'Error parsing PNG image data'); }
8912
+ }
8913
+ while($n);
8914
+ if (!$pngdata) { return $this->_imageError($file, $firsttime, 'Error parsing PNG image data - no IDAT data found'); }
8915
+ if($colspace=='Indexed' and empty($pal)) { return $this->_imageError($file, $firsttime, 'Error parsing PNG image data - missing colour palette'); }
8916
+ $info = array('w'=>$w,'h'=>$h,'cs'=>$colspace,'bpc'=>$bpc,'f'=>'FlateDecode','parms'=>$parms,'pal'=>$pal,'trns'=>$trns,'data'=>$pngdata);
8917
+ $info['type']='png';
8918
+ if ($ppUx) { $info['set-dpi'] = $ppUx; }
8919
+ }
8920
+
8921
+ if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing or converting PNG image'); }
8922
+
8923
+ if ($firsttime) {
8924
+ $info['i']=count($this->images)+1;
8925
+ $this->images[$file]=$info;
8926
+ }
8927
+ return $info;
8928
+ }
8929
+
8930
+ // GIF
8931
+ else if ($type == 'gif') {
8932
+ if (function_exists('gd_info')) { $gd = gd_info(); }
8933
+ else {$gd = array(); }
8934
+ if (isset($gd['GIF Read Support']) && $gd['GIF Read Support']) {
8935
+ $im = @imagecreatefromstring($data);
8936
+ if ($im) {
8937
+ $tempfile = _MPDF_TEMP_PATH.'_tempImgPNG'.RAND(1,10000).'.png';
8938
+ imagealphablending($im, false);
8939
+ imagesavealpha($im, false);
8940
+ imageinterlace($im, false);
8941
+ if (!is_writable($tempfile)) {
8942
+ ob_start();
8943
+ $check = @imagepng($im);
8944
+ if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary image object whilst using GD library to parse GIF image'); }
8945
+ $this->_tempimg = ob_get_contents();
8946
+ $this->_tempimglnk = 'var:_tempimg';
8947
+ ob_end_clean();
8948
+ $info = $this->_getImage($this->_tempimglnk, false);
8949
+ if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file image object created with GD library to parse GIF image'); }
8950
+ imagedestroy($im);
8951
+ }
8952
+ else {
8953
+ $check = @imagepng($im, $tempfile);
8954
+ if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary file ('.$tempfile.') whilst using GD library to parse GIF image'); }
8955
+ $info = $this->_getImage($tempfile, false);
8956
+ if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse GIF image'); }
8957
+ imagedestroy($im);
8958
+ unlink($tempfile);
8959
+ }
8960
+ $info['type']='gif';
8961
+ if ($firsttime) {
8962
+ $info['i']=count($this->images)+1;
8963
+ $this->images[$file]=$info;
8964
+ }
8965
+ return $info;
8966
+ }
8967
+ else { return $this->_imageError($file, $firsttime, 'Error creating GD image file from GIF image'); }
8968
+ }
8969
+
8970
+ if (!class_exists('gif', false)) {
8971
+ include_once(_MPDF_PATH.'classes/gif.php');
8972
+ }
8973
+ $gif=new CGIF();
8974
+
8975
+ $h=0;
8976
+ $w=0;
8977
+ $gif->loadFile($data, 0);
8978
+
8979
+ if(isset($gif->m_img->m_gih->m_bLocalClr) && $gif->m_img->m_gih->m_bLocalClr) {
8980
+ $nColors = $gif->m_img->m_gih->m_nTableSize;
8981
+ $pal = $gif->m_img->m_gih->m_colorTable->toString();
8982
+ if($bgColor != -1) {
8983
+ $bgColor = $gif->m_img->m_gih->m_colorTable->colorIndex($bgColor);
8984
+ }
8985
+ $colspace='Indexed';
8986
+ } elseif(isset($gif->m_gfh->m_bGlobalClr) && $gif->m_gfh->m_bGlobalClr) {
8987
+ $nColors = $gif->m_gfh->m_nTableSize;
8988
+ $pal = $gif->m_gfh->m_colorTable->toString();
8989
+ if((isset($bgColor)) and $bgColor != -1) {
8990
+ $bgColor = $gif->m_gfh->m_colorTable->colorIndex($bgColor);
8991
+ }
8992
+ $colspace='Indexed';
8993
+ } else {
8994
+ $nColors = 0;
8995
+ $bgColor = -1;
8996
+ $colspace='DeviceGray';
8997
+ $pal='';
8998
+ }
8999
+
9000
+ $trns='';
9001
+ if(isset($gif->m_img->m_bTrans) && $gif->m_img->m_bTrans && ($nColors > 0)) {
9002
+ $trns=array($gif->m_img->m_nTrans);
9003
+ }
9004
+ $gifdata=$gif->m_img->m_data;
9005
+ $w=$gif->m_gfh->m_nWidth;
9006
+ $h=$gif->m_gfh->m_nHeight;
9007
+ $gif->ClearData();
9008
+
9009
+ if($colspace=='Indexed' and empty($pal)) {
9010
+ return $this->_imageError($file, $firsttime, 'Error parsing GIF image - missing colour palette');
9011
+ }
9012
+ if ($this->compress) {
9013
+ $gifdata=gzcompress($gifdata);
9014
+ $info = array( 'w'=>$w, 'h'=>$h, 'cs'=>$colspace, 'bpc'=>8, 'f'=>'FlateDecode', 'pal'=>$pal, 'trns'=>$trns, 'data'=>$gifdata);
9015
+ }
9016
+ else {
9017
+ $info = array( 'w'=>$w, 'h'=>$h, 'cs'=>$colspace, 'bpc'=>8, 'pal'=>$pal, 'trns'=>$trns, 'data'=>$gifdata);
9018
+ }
9019
+ $info['type']='gif';
9020
+ if ($firsttime) {
9021
+ $info['i']=count($this->images)+1;
9022
+ $this->images[$file]=$info;
9023
+ }
9024
+ return $info;
9025
+ }
9026
+
9027
+
9028
+ // UNKNOWN TYPE - try GD imagecreatefromstring
9029
+ else {
9030
+ if (function_exists('gd_info')) { $gd = gd_info(); }
9031
+ else {$gd = array(); }
9032
+ if (isset($gd['PNG Support']) && $gd['PNG Support']) {
9033
+ $im = @imagecreatefromstring($data);
9034
+ if (!$im) { return $this->_imageError($file, $firsttime, 'Error parsing image file - image type not recognised, and not supported by GD imagecreate'); }
9035
+ $tempfile = _MPDF_TEMP_PATH.'_tempImgPNG'.RAND(1,10000).'.png';
9036
+ imagealphablending($im, false);
9037
+ imagesavealpha($im, false);
9038
+ imageinterlace($im, false);
9039
+ $check = @imagepng($im, $tempfile);
9040
+ if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary file ('.$tempfile.') whilst using GD library to parse unknown image type'); }
9041
+ $info = $this->_getImage($tempfile, false);
9042
+ imagedestroy($im);
9043
+ unlink($tempfile);
9044
+ if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse unknown image type'); }
9045
+ $info['type']='png';
9046
+ if ($firsttime) {
9047
+ $info['i']=count($this->images)+1;
9048
+ $this->images[$file]=$info;
9049
+ }
9050
+ return $info;
9051
+ }
9052
+ }
9053
+
9054
+ return $this->_imageError($file, $firsttime, 'Error parsing image file - image type not recognised');
9055
+ }
9056
+ //==============================================================
9057
+ function _convImage(&$data, $colspace, $targetcs, $w, $h, $dpi, $mask) {
9058
+ if ($this->PDFA || $this->PDFX) { $mask=false; }
9059
+ $im = @imagecreatefromstring($data);
9060
+ $info = array();
9061
+ if ($im) {
9062
+ $imgdata = '';
9063
+ $mimgdata = '';
9064
+ $minfo = array();
9065
+ //Read transparency info
9066
+ $trns=array();
9067
+ $trnsrgb = false;
9068
+ if (!$this->PDFA && !$this->PDFX) {
9069
+ $p = strpos($data,'tRNS');
9070
+ if ($p) {
9071
+ $n=$this->_fourbytes2int(substr($data,($p-4),4));
9072
+ $t = substr($data,($p+4),$n);
9073
+ if ($colspace=='DeviceGray') {
9074
+ $trns=array(ord(substr($t,1,1)));
9075
+ $trnsrgb = array($trns[0],$trns[0],$trns[0]);
9076
+ }
9077
+ else if ($colspace=='DeviceRGB') {
9078
+ $trns=array(ord(substr($t,1,1)),ord(substr($t,3,1)),ord(substr($t,5,1)));
9079
+ $trnsrgb = $trns;
9080
+ if ($targetcs=='DeviceCMYK') {
9081
+ $col = $this->rgb2cmyk(array(3,$trns[0],$trns[1],$trns[2]));
9082
+ $c1 = intval($col[1]*2.55);
9083
+ $c2 = intval($col[2]*2.55);
9084
+ $c3 = intval($col[3]*2.55);
9085
+ $c4 = intval($col[4]*2.55);
9086
+ $trns = array($c1,$c2,$c3,$c4);
9087
+ }
9088
+ else if ($targetcs=='DeviceGray') {
9089
+ $c = intval(($trns[0] * .21) + ($trns[1] * .71) + ($trns[2] * .07));
9090
+ $trns = array($c);
9091
+ }
9092
+ }
9093
+ else { // Indexed
9094
+ $pos = strpos($t,chr(0));
9095
+ if (is_int($pos)) {
9096
+ $pal = imagecolorsforindex($im, $pos);
9097
+ $r = $pal['red'];
9098
+ $g = $pal['green'];
9099
+ $b = $pal['blue'];
9100
+ $trns=array($r,$g,$b); // ****
9101
+ $trnsrgb = $trns;
9102
+ if ($targetcs=='DeviceCMYK') {
9103
+ $col = $this->rgb2cmyk(array(3,$r,$g,$b));
9104
+ $c1 = intval($col[1]*2.55);
9105
+ $c2 = intval($col[2]*2.55);
9106
+ $c3 = intval($col[3]*2.55);
9107
+ $c4 = intval($col[4]*2.55);
9108
+ $trns = array($c1,$c2,$c3,$c4);
9109
+ }
9110
+ else if ($targetcs=='DeviceGray') {
9111
+ $c = intval(($r * .21) + ($g * .71) + ($b * .07));
9112
+ $trns = array($c);
9113
+ }
9114
+ }
9115
+ }
9116
+ }
9117
+ }
9118
+ for ($i = 0; $i < $h; $i++) {
9119
+ for ($j = 0; $j < $w; $j++) {
9120
+ $rgb = imagecolorat($im, $j, $i);
9121
+ $r = ($rgb >> 16) & 0xFF;
9122
+ $g = ($rgb >> 8) & 0xFF;
9123
+ $b = $rgb & 0xFF;
9124
+ if ($colspace=='Indexed') {
9125
+ $pal = imagecolorsforindex($im, $rgb);
9126
+ $r = $pal['red'];
9127
+ $g = $pal['green'];
9128
+ $b = $pal['blue'];
9129
+ }
9130
+
9131
+ if ($targetcs=='DeviceCMYK') {
9132
+ $col = $this->rgb2cmyk(array(3,$r,$g,$b));
9133
+ $c1 = intval($col[1]*2.55);
9134
+ $c2 = intval($col[2]*2.55);
9135
+ $c3 = intval($col[3]*2.55);
9136
+ $c4 = intval($col[4]*2.55);
9137
+ if ($trnsrgb) {
9138
+ // original pixel was not set as transparent but processed color does match
9139
+ if ($trnsrgb!=array($r,$g,$b) && $trns==array($c1,$c2,$c3,$c4)) {
9140
+ if ($c4==0) { $c4=1; } else { $c4--; }
9141
+ }
9142
+ }
9143
+ $imgdata .= chr($c1).chr($c2).chr($c3).chr($c4);
9144
+ }
9145
+ else if ($targetcs=='DeviceGray') {
9146
+ $c = intval(($r * .21) + ($g * .71) + ($b * .07));
9147
+ if ($trnsrgb) {
9148
+ // original pixel was not set as transparent but processed color does match
9149
+ if ($trnsrgb!=array($r,$g,$b) && $trns==array($c)) {
9150
+ if ($c==0) { $c=1; } else { $c--; }
9151
+ }
9152
+ }
9153
+ $imgdata .= chr($c);
9154
+ }
9155
+ else if ($targetcs=='DeviceRGB') {
9156
+ $imgdata .= chr($r).chr($g).chr($b);
9157
+ }
9158
+ if ($mask) {
9159
+ $col = imagecolorsforindex($im, $rgb);
9160
+ $gammacorr = 2.2; // gamma correction
9161
+ $gamma = intval((pow((((127 - $col['alpha']) * 255 / 127) / 255), $gammacorr) * 255));
9162
+ $mimgdata .= chr($gamma);
9163
+ }
9164
+ }
9165
+ }
9166
+
9167
+ if ($targetcs=='DeviceGray') { $ncols = 1; }
9168
+ else if ($targetcs=='DeviceRGB') { $ncols = 3; }
9169
+ else if ($targetcs=='DeviceCMYK') { $ncols = 4; }
9170
+
9171
+ $imgdata = gzcompress($imgdata);
9172
+ $info = array('w'=>$w,'h'=>$h,'cs'=>$targetcs,'bpc'=>8,'f'=>'FlateDecode','data'=>$imgdata, 'type'=>'png',
9173
+ 'parms'=>'/DecodeParms <</Colors '.$ncols.' /BitsPerComponent 8 /Columns '.$w.'>>');
9174
+ if ($dpi) { $info['set-dpi'] = $dpi; }
9175
+ if ($mask) {
9176
+ $mimgdata = gzcompress($mimgdata);
9177
+ $minfo = array('w'=>$w,'h'=>$h,'cs'=>'DeviceGray','bpc'=>8,'f'=>'FlateDecode','data'=>$mimgdata, 'type'=>'png',
9178
+ 'parms'=>'/DecodeParms <</Colors '.$ncols.' /BitsPerComponent 8 /Columns '.$w.'>>');
9179
+ if ($dpi) { $minfo['set-dpi'] = $dpi; }
9180
+ $tempfile = '_tempImgPNG'.RAND(1,10000).'.png';
9181
+ $imgmask = count($this->images)+1;
9182
+ $minfo['i']=$imgmask ;
9183
+ $this->images[$tempfile] = $minfo;
9184
+ $info['masked'] = $imgmask;
9185
+ }
9186
+ else if ($trns) { $info['trns'] = $trns; }
9187
+ imagedestroy($im);
9188
+ }
9189
+ return $info;
9190
+ }
9191
+
9192
+
9193
+
9194
+
9195
+ function _fourbytes2int($s) {
9196
+ //Read a 4-byte integer from string
9197
+ return (ord($s[0])<<24) + (ord($s[1])<<16) + (ord($s[2])<<8) + ord($s[3]);
9198
+ }
9199
+
9200
+ function _twobytes2int($s) {
9201
+ //Read a 2-byte integer from string
9202
+ return (ord(substr($s, 0, 1))<<8) + ord(substr($s, 1, 1));
9203
+ }
9204
+
9205
+ function _jpgHeaderFromString(&$data) {
9206
+ $p = 4;
9207
+ $p += $this->_twobytes2int(substr($data, $p, 2)); // Length of initial marker block
9208
+ $marker = substr($data, $p, 2);
9209
+ while($marker != chr(255).chr(192) && $marker != chr(255).chr(194) && $p<strlen($data)) {
9210
+ // Start of frame marker (FFC0) or (FFC2) mPDF 4.4.004
9211
+ $p += ($this->_twobytes2int(substr($data, $p+2, 2))) + 2; // Length of marker block
9212
+ $marker = substr($data, $p, 2);
9213
+ }
9214
+ if ($marker != chr(255).chr(192) && $marker != chr(255).chr(194)) { return false; }
9215
+ return substr($data, $p+2, 10);
9216
+ }
9217
+
9218
+ function _jpgDataFromHeader($hdr) {
9219
+ $bpc = ord(substr($hdr, 2, 1));
9220
+ if (!$bpc) { $bpc = 8; }
9221
+ $h = $this->_twobytes2int(substr($hdr, 3, 2));
9222
+ $w = $this->_twobytes2int(substr($hdr, 5, 2));
9223
+ $channels = ord(substr($hdr, 7, 1));
9224
+ if ($channels==3) { $colspace='DeviceRGB'; }
9225
+ elseif($channels==4) { $colspace='DeviceCMYK'; }
9226
+ else { $colspace='DeviceGray'; }
9227
+ return array($w, $h, $colspace, $bpc);
9228
+ }
9229
+
9230
+ function file_get_contents_by_curl($url, &$data) {
9231
+ $timeout = 5;
9232
+ $ch = curl_init($url);
9233
+ curl_setopt($ch, CURLOPT_HEADER, 0);
9234
+ curl_setopt($ch, CURLOPT_NOBODY, 0);
9235
+ curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , 1 );
9236
+ curl_setopt ( $ch , CURLOPT_CONNECTTIMEOUT , $timeout );
9237
+ $data = curl_exec($ch);
9238
+ curl_close($ch);
9239
+ }
9240
+
9241
+
9242
+ function file_get_contents_by_socket($url, &$data) {
9243
+ $timeout = 1;
9244
+ $p = parse_url($url);
9245
+ $file = $p['path'];
9246
+ if ($p['query']) { $file .= '?'.$p['query']; }
9247
+ if(!($fh = @fsockopen($p['host'], 80, $errno, $errstr, $timeout))) { return false; }
9248
+ $getstring =
9249
+ "GET ".$file." HTTP/1.0 \r\n" .
9250
+ "Host: ".$p['host']." \r\n" .
9251
+ "Connection: close\r\n\r\n";
9252
+ fwrite($fh, $getstring);
9253
+ // Get rid of HTTP header
9254
+ $s = fgets($fh, 1024);
9255
+ if (!$s) { return false; }
9256
+ $httpheader .= $s;
9257
+ while (!feof($fh)) {
9258
+ $s = fgets($fh, 1024);
9259
+ if ( $s == "\r\n" ) { break; }
9260
+ }
9261
+ $data = '';
9262
+ while (!feof($fh)) {
9263
+ $data .= fgets($fh, 1024);
9264
+ }
9265
+ fclose($fh);
9266
+ }
9267
+
9268
+ //==============================================================
9269
+
9270
+ function _imageTypeFromString(&$data) {
9271
+ $type = '';
9272
+ if (substr($data, 6, 4)== 'JFIF' || substr($data, 6, 4)== 'Exif') {
9273
+ $type = 'jpeg';
9274
+ }
9275
+ else if (substr($data, 0, 6)== "GIF87a" || substr($data, 0, 6)== "GIF89a") {
9276
+ $type = 'gif';
9277
+ }
9278
+ else if (substr($data, 0, 8)== chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) {
9279
+ $type = 'png';
9280
+ }
9281
+ else if (preg_match('/<svg.*<\/svg>/is',$data)) {
9282
+ $type = 'svg';
9283
+ }
9284
+ // BMP images
9285
+ else if (substr($data, 0, 2)== "BM") {
9286
+ $type = 'bmp';
9287
+ }
9288
+ return $type;
9289
+ }
9290
+ //==============================================================
9291
+
9292
+ // Moved outside WMF as also needed for SVG
9293
+ function _putformobjects() {
9294
+ reset($this->formobjects);
9295
+ while(list($file,$info)=each($this->formobjects)) {
9296
+ $this->_newobj();
9297
+ $this->formobjects[$file]['n']=$this->n;
9298
+ $this->_out('<</Type /XObject');
9299
+ $this->_out('/Subtype /Form');
9300
+ $this->_out('/Group '.($this->n+1).' 0 R');
9301
+ $this->_out('/BBox ['.$info['x'].' '.$info['y'].' '.($info['w']+$info['x']).' '.($info['h']+$info['y']).']');
9302
+ if ($this->compress)
9303
+ $this->_out('/Filter /FlateDecode');
9304
+ $data=($this->compress) ? gzcompress($info['data']) : $info['data'];
9305
+ $this->_out('/Length '.strlen($data).'>>');
9306
+ $this->_putstream($data);
9307
+ unset($this->formobjects[$file]['data']);
9308
+ $this->_out('endobj');
9309
+ // Required for SVG transparency (opacity) to work
9310
+ $this->_newobj();
9311
+ $this->_out('<</Type /Group');
9312
+ $this->_out('/S /Transparency');
9313
+ $this->_out('>>');
9314
+ $this->_out('endobj');
9315
+ }
9316
+ }
9317
+
9318
+ function _freadint($f)
9319
+ {
9320
+ //Read a 4-byte integer from file
9321
+ $i=ord(fread($f,1))<<24;
9322
+ $i+=ord(fread($f,1))<<16;
9323
+ $i+=ord(fread($f,1))<<8;
9324
+ $i+=ord(fread($f,1));
9325
+ return $i;
9326
+ }
9327
+
9328
+ function _UTF16BEtextstring($s) {
9329
+ $s = $this->UTF8ToUTF16BE($s, true);
9330
+ if ($this->encrypted) {
9331
+ $s = $this->_RC4($this->_objectkey($this->_current_obj_id), $s);
9332
+ }
9333
+ return '('. $this->_escape($s).')';
9334
+ }
9335
+
9336
+ function _textstring($s) {
9337
+ if ($this->encrypted) {
9338
+ $s = $this->_RC4($this->_objectkey($this->_current_obj_id), $s);
9339
+ }
9340
+ return '('. $this->_escape($s).')';
9341
+ }
9342
+
9343
+
9344
+ function _escape($s)
9345
+ {
9346
+ // the chr(13) substitution fixes the Bugs item #1421290.
9347
+ return strtr($s, array(')' => '\\)', '(' => '\\(', '\\' => '\\\\', chr(13) => '\r'));
9348
+ }
9349
+
9350
+ function _putstream($s) {
9351
+ if ($this->encrypted) {
9352
+ $s = $this->_RC4($this->_objectkey($this->_current_obj_id), $s);
9353
+ }
9354
+ $this->_out('stream');
9355
+ $this->_out($s);
9356
+ $this->_out('endstream');
9357
+ }
9358
+
9359
+
9360
+ function _out($s,$ln=true) {
9361
+ if($this->state==2) {
9362
+ if ($this->bufferoutput) {
9363
+ $this->headerbuffer.= $s."\n";
9364
+ }
9365
+ else if ($this->table_rotate && !$this->processingHeader && !$this->processingFooter) {
9366
+ // Captures eveything in buffer for rotated tables;
9367
+ $this->tablebuffer .= $s . "\n";
9368
+ }
9369
+ else if ($this->kwt && !$this->processingHeader && !$this->processingFooter) {
9370
+ // Captures eveything in buffer for keep-with-table (h1-6);
9371
+ $this->kwt_buffer[] = array(
9372
+ 's' => $s, // Text string to output
9373
+ 'x' => $this->x, // x when printed
9374
+ 'y' => $this->y, // y when printed
9375
+ );
9376
+ }
9377
+ else if (($this->keep_block_together) && !$this->processingHeader && !$this->processingFooter) {
9378
+ if (!isset($this->ktBlock[$this->page]['bottom_margin'])) {
9379
+ $this->ktBlock[$this->page]['bottom_margin'] = $this->y;
9380
+ }
9381
+
9382
+ // Captures eveything in buffer;
9383
+ if (preg_match('/q \d+\.\d\d+ 0 0 (\d+\.\d\d+) \d+\.\d\d+ \d+\.\d\d+ cm \/(I|FO)\d+ Do Q/',$s,$m)) { // Image data
9384
+ $h = ($m[1]/_MPDFK);
9385
+ // Update/overwrite the lowest bottom of printing y value for Keep together block
9386
+ $this->ktBlock[$this->page]['bottom_margin'] = $this->y+$h;
9387
+ }
9388
+ else { // Td Text Set in Cell()
9389
+ if (isset($this->ktBlock[$this->page]['bottom_margin'])) { $h = $this->ktBlock[$this->page]['bottom_margin'] - $this->y; }
9390
+ else { $h = 0; }
9391
+ }
9392
+ if ($h < 0) { $h = -$h; }
9393
+ $this->divbuffer[] = array(
9394
+ 'page' => $this->page,
9395
+ 's' => $s, // Text string to output
9396
+ 'x' => $this->x, // x when printed
9397
+ 'y' => $this->y, // y when printed (after column break)
9398
+ 'h' => $h // actual y at bottom when printed = y+h
9399
+ );
9400
+ }
9401
+ else {
9402
+ $this->pages[$this->page] .= $s.($ln == true ? "\n" : '');
9403
+ }
9404
+
9405
+ }
9406
+ else {
9407
+ $this->buffer .= $s.($ln == true ? "\n" : '');
9408
+ }
9409
+ }
9410
+
9411
+
9412
+
9413
+ function Rotate($angle,$x=-1,$y=-1)
9414
+ {
9415
+ if($x==-1)
9416
+ $x=$this->x;
9417
+ if($y==-1)
9418
+ $y=$this->y;
9419
+ if($this->angle!=0)
9420
+ $this->_out('Q');
9421
+ $this->angle=$angle;
9422
+ if($angle!=0)
9423
+ {
9424
+ $angle*=M_PI/180;
9425
+ $c=cos($angle);
9426
+ $s=sin($angle);
9427
+ $cx=$x*_MPDFK;
9428
+ $cy=($this->h-$y)*_MPDFK;
9429
+ $this->_out(sprintf('q %.5F %.5F %.5F %.5F %.3F %.3F cm 1 0 0 1 %.3F %.3F cm',$c,$s,-$s,$c,$cx,$cy,-$cx,-$cy));
9430
+ }
9431
+ }
9432
+
9433
+
9434
+
9435
+ function CircularText($x, $y, $r, $text, $align='top', $fontfamily='', $fontsize=0, $fontstyle='', $kerning=120, $fontwidth=100, $divider) { // mPDF 5.5.23
9436
+ if (!class_exists('directw', false)) { include(_MPDF_PATH.'classes/directw.php'); }
9437
+ if (empty($this->directw)) { $this->directw = new directw($this); }
9438
+ $this->directw->CircularText($x, $y, $r, $text, $align, $fontfamily, $fontsize, $fontstyle, $kerning, $fontwidth, $divider); // mPDF 5.5.23
9439
+ }
9440
+
9441
+
9442
+ // From Invoice
9443
+ function RoundedRect($x, $y, $w, $h, $r, $style = '')
9444
+ {
9445
+ $hp = $this->h;
9446
+ if($style=='F')
9447
+ $op='f';
9448
+ elseif($style=='FD' or $style=='DF')
9449
+ $op='B';
9450
+ else
9451
+ $op='S';
9452
+ $MyArc = 4/3 * (sqrt(2) - 1);
9453
+ $this->_out(sprintf('%.3F %.3F m',($x+$r)*_MPDFK,($hp-$y)*_MPDFK ));
9454
+ $xc = $x+$w-$r ;
9455
+ $yc = $y+$r;
9456
+ $this->_out(sprintf('%.3F %.3F l', $xc*_MPDFK,($hp-$y)*_MPDFK ));
9457
+
9458
+ $this->_Arc($xc + $r*$MyArc, $yc - $r, $xc + $r, $yc - $r*$MyArc, $xc + $r, $yc);
9459
+ $xc = $x+$w-$r ;
9460
+ $yc = $y+$h-$r;
9461
+ $this->_out(sprintf('%.3F %.3F l',($x+$w)*_MPDFK,($hp-$yc)*_MPDFK));
9462
+ $this->_Arc($xc + $r, $yc + $r*$MyArc, $xc + $r*$MyArc, $yc + $r, $xc, $yc + $r);
9463
+ $xc = $x+$r ;
9464
+ $yc = $y+$h-$r;
9465
+ $this->_out(sprintf('%.3F %.3F l',$xc*_MPDFK,($hp-($y+$h))*_MPDFK));
9466
+ $this->_Arc($xc - $r*$MyArc, $yc + $r, $xc - $r, $yc + $r*$MyArc, $xc - $r, $yc);
9467
+ $xc = $x+$r ;
9468
+ $yc = $y+$r;
9469
+ $this->_out(sprintf('%.3F %.3F l',($x)*_MPDFK,($hp-$yc)*_MPDFK ));
9470
+ $this->_Arc($xc - $r, $yc - $r*$MyArc, $xc - $r*$MyArc, $yc - $r, $xc, $yc - $r);
9471
+ $this->_out($op);
9472
+ }
9473
+
9474
+ function _Arc($x1, $y1, $x2, $y2, $x3, $y3)
9475
+ {
9476
+ $h = $this->h;
9477
+ $this->_out(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $x1*_MPDFK, ($h-$y1)*_MPDFK,
9478
+ $x2*_MPDFK, ($h-$y2)*_MPDFK, $x3*_MPDFK, ($h-$y3)*_MPDFK));
9479
+ }
9480
+
9481
+
9482
+
9483
+
9484
+ //====================================================
9485
+
9486
+
9487
+
9488
+ function Shaded_box( $text,$font='',$fontstyle='B',$szfont='',$width='70%',$style='DF',$radius=2.5,$fill='#FFFFFF',$color='#000000',$pad=2 ) {
9489
+ // F (shading - no line),S (line, no shading),DF (both)
9490
+ if (!class_exists('directw', false)) { include(_MPDF_PATH.'classes/directw.php'); }
9491
+ if (empty($this->directw)) { $this->directw = new directw($this); }
9492
+ $this->directw->Shaded_box( $text,$font,$fontstyle,$szfont,$width,$style,$radius,$fill,$color,$pad);
9493
+ }
9494
+
9495
+
9496
+ function UTF8StringToArray($str, $addSubset=true) {
9497
+ $out = array();
9498
+ $len = strlen($str);
9499
+ for ($i = 0; $i < $len; $i++) {
9500
+ $uni = -1;
9501
+ $h = ord($str[$i]);
9502
+ if ( $h <= 0x7F )
9503
+ $uni = $h;
9504
+ elseif ( $h >= 0xC2 ) {
9505
+ if ( ($h <= 0xDF) && ($i < $len -1) )
9506
+ $uni = ($h & 0x1F) << 6 | (ord($str[++$i]) & 0x3F);
9507
+ elseif ( ($h <= 0xEF) && ($i < $len -2) )
9508
+ $uni = ($h & 0x0F) << 12 | (ord($str[++$i]) & 0x3F) << 6 | (ord($str[++$i]) & 0x3F);
9509
+ elseif ( ($h <= 0xF4) && ($i < $len -3) )
9510
+ $uni = ($h & 0x0F) << 18 | (ord($str[++$i]) & 0x3F) << 12 | (ord($str[++$i]) & 0x3F) << 6 | (ord($str[++$i]) & 0x3F);
9511
+ }
9512
+ if ($uni >= 0) {
9513
+ $out[] = $uni;
9514
+ if ($addSubset && isset($this->CurrentFont['subset'])) {
9515
+ $this->CurrentFont['subset'][$uni] = $uni;
9516
+ }
9517
+ }
9518
+ }
9519
+ return $out;
9520
+ }
9521
+
9522
+
9523
+ //Convert utf-8 string to <HHHHHH> for Font Subsets
9524
+ function UTF8toSubset($str) {
9525
+ $ret = '<';
9526
+ $str = preg_replace('/'.preg_quote($this->aliasNbPg,'/').'/', chr(7), $str );
9527
+ $str = preg_replace('/'.preg_quote($this->aliasNbPgGp,'/').'/', chr(8), $str );
9528
+ $unicode = $this->UTF8StringToArray($str);
9529
+ $orig_fid = $this->CurrentFont['subsetfontids'][0];
9530
+ $last_fid = $this->CurrentFont['subsetfontids'][0];
9531
+ foreach($unicode as $c) {
9532
+ if ($c == 7 || $c == 8) {
9533
+ if ($orig_fid != $last_fid) {
9534
+ $ret .= '> Tj /F'.$orig_fid.' '.$this->FontSizePt.' Tf <';
9535
+ $last_fid = $orig_fid;
9536
+ }
9537
+ if ($c == 7) { $ret .= $this->aliasNbPgHex; }
9538
+ else { $ret .= $this->aliasNbPgGpHex; }
9539
+ continue;
9540
+ }
9541
+ for ($i=0; $i<99; $i++) {
9542
+ // return c as decimal char
9543
+ $init = array_search($c, $this->CurrentFont['subsets'][$i]);
9544
+ if ($init!==false) {
9545
+ if ($this->CurrentFont['subsetfontids'][$i] != $last_fid) {
9546
+ $ret .= '> Tj /F'.$this->CurrentFont['subsetfontids'][$i].' '.$this->FontSizePt.' Tf <';
9547
+ $last_fid = $this->CurrentFont['subsetfontids'][$i];
9548
+ }
9549
+ $ret .= sprintf("%02s", strtoupper(dechex($init)));
9550
+ break;
9551
+ }
9552
+ // TrueType embedded SUBSETS
9553
+ else if (count($this->CurrentFont['subsets'][$i]) < 255) {
9554
+ $n = count($this->CurrentFont['subsets'][$i]);
9555
+ $this->CurrentFont['subsets'][$i][$n] = $c;
9556
+ if ($this->CurrentFont['subsetfontids'][$i] != $last_fid) {
9557
+ $ret .= '> Tj /F'.$this->CurrentFont['subsetfontids'][$i].' '.$this->FontSizePt.' Tf <';
9558
+ $last_fid = $this->CurrentFont['subsetfontids'][$i];
9559
+ }
9560
+ $ret .= sprintf("%02s", strtoupper(dechex($n)));
9561
+ break;
9562
+ }
9563
+ else if (!isset($this->CurrentFont['subsets'][($i+1)])) {
9564
+ // TrueType embedded SUBSETS
9565
+ $this->CurrentFont['subsets'][($i+1)] = array(0=>0);
9566
+ $new_fid = count($this->fonts)+$this->extraFontSubsets+1;
9567
+ $this->CurrentFont['subsetfontids'][($i+1)] = $new_fid;
9568
+ $this->extraFontSubsets++;
9569
+ }
9570
+ }
9571
+ }
9572
+ $ret .= '>';
9573
+ if ($last_fid != $orig_fid) {
9574
+ $ret .= ' Tj /F'.$orig_fid.' '.$this->FontSizePt.' Tf <> ';
9575
+ }
9576
+ return $ret;
9577
+ }
9578
+
9579
+
9580
+ // Converts UTF-8 strings to UTF16-BE.
9581
+ function UTF8ToUTF16BE($str, $setbom=true) {
9582
+ if ($this->checkSIP && preg_match("/([\x{20000}-\x{2FFFF}])/u", $str)) {
9583
+ if (!in_array($this->currentfontfamily, array('gb','big5','sjis','uhc','gbB','big5B','sjisB','uhcB','gbI','big5I','sjisI','uhcI',
9584
+ 'gbBI','big5BI','sjisBI','uhcBI'))) {
9585
+ $str = preg_replace("/[\x{20000}-\x{2FFFF}]/u", chr(0), $str);
9586
+ }
9587
+ }
9588
+ if ($this->checkSMP && preg_match("/([\x{10000}-\x{1FFFF}])/u", $str )) {
9589
+ $str = preg_replace("/[\x{10000}-\x{1FFFF}]/u", chr(0), $str );
9590
+ }
9591
+ $outstr = ""; // string to be returned
9592
+ if ($setbom) {
9593
+ $outstr .= "\xFE\xFF"; // Byte Order Mark (BOM)
9594
+ }
9595
+ $outstr .= mb_convert_encoding($str, 'UTF-16BE', 'UTF-8');
9596
+ return $outstr;
9597
+ }
9598
+
9599
+
9600
+
9601
+
9602
+
9603
+ // ====================================================
9604
+ // ====================================================
9605
+
9606
+ //////////////////////////////////////////////////////////////////////////////
9607
+ //////////////////////////////////////////////////////////////////////////////
9608
+ //////////////////////////////////////////////////////////////////////////////
9609
+ //////////////////////////////////////////////////////////////////////////////
9610
+ //////////////////////////////////////////////////////////////////////////////
9611
+ //////////////////////////////////////////////////////////////////////////////
9612
+ //////////////////////////////////////////////////////////////////////////////
9613
+ function SetAutoFont($af = AUTOFONT_ALL) {
9614
+ if ($this->onlyCoreFonts) { return false; }
9615
+ if (!$af && $af !== 0) { $af = AUTOFONT_ALL; }
9616
+ $this->autoFontGroups = $af;
9617
+ if ($this->autoFontGroups ) {
9618
+ $this->useLang = true;
9619
+ }
9620
+ }
9621
+
9622
+
9623
+ function SetDefaultFont($font) {
9624
+ // Disallow embedded fonts to be used as defaults in PDFA
9625
+ if ($this->PDFA || $this->PDFX) {
9626
+ if (strtolower($font) == 'ctimes') { $font = 'serif'; }
9627
+ if (strtolower($font) == 'ccourier') { $font = 'monospace'; }
9628
+ if (strtolower($font) == 'chelvetica') { $font = 'sans-serif'; }
9629
+ }
9630
+ $font = $this->SetFont($font); // returns substituted font if necessary
9631
+ $this->default_font = $font;
9632
+ $this->original_default_font = $font;
9633
+ $this->defaultCSS['BODY']['FONT-FAMILY'] = $font;
9634
+ $this->cssmgr->CSS['BODY']['FONT-FAMILY'] = $font;
9635
+ }
9636
+
9637
+ function SetDefaultFontSize($fontsize) {
9638
+ $this->default_font_size = $fontsize;
9639
+ $this->original_default_font_size = $fontsize;
9640
+ $this->SetFontSize($fontsize);
9641
+ $this->defaultCSS['BODY']['FONT-SIZE'] = $fontsize . 'pt';
9642
+ $this->cssmgr->CSS['BODY']['FONT-SIZE'] = $fontsize . 'pt';
9643
+ }
9644
+
9645
+ function SetDefaultBodyCSS($prop, $val) {
9646
+ if ($prop) {
9647
+ $this->defaultCSS['BODY'][strtoupper($prop)] = $val;
9648
+ $this->cssmgr->CSS['BODY'][strtoupper($prop)] = $val;
9649
+ }
9650
+ }
9651
+
9652
+
9653
+ function SetDirectionality($dir='ltr') {
9654
+ $this->directionality = 'ltr';
9655
+ $this->defaultAlign = 'L';
9656
+ $this->defaultTableAlign = 'L';
9657
+ $this->cssmgr->CSS['BODY']['DIRECTION'] = $this->directionality;
9658
+ }
9659
+
9660
+
9661
+
9662
+ // Added to set line-height-correction
9663
+ function SetLineHeightCorrection($val) {
9664
+ if ($val > 0) { $this->default_lineheight_correction = $val; }
9665
+ else { $this->default_lineheight_correction = 1.2; }
9666
+ }
9667
+
9668
+ // Set a (fixed) lineheight to an actual value - either to named fontsize(pts) or default
9669
+ function SetLineHeight($FontPt='',$spacing = '') {
9670
+ if ($this->shrin_k > 1) { $k = $this->shrin_k; }
9671
+ else { $k = 1; }
9672
+ if ($spacing > 0) {
9673
+ if (preg_match('/mm/',$spacing)) {
9674
+ $this->lineheight = ($spacing + 0.0) / $k; // convert to number
9675
+ }
9676
+ else {
9677
+ if ($FontPt) { $this->lineheight = (($FontPt/_MPDFK) *$spacing); }
9678
+ else { $this->lineheight = (($this->FontSizePt/_MPDFK) *$spacing); }
9679
+ }
9680
+ }
9681
+ else {
9682
+ if ($FontPt) { $this->lineheight = (($FontPt/_MPDFK) *$this->normalLineheight); }
9683
+ else { $this->lineheight = (($this->FontSizePt/_MPDFK) *$this->normalLineheight); }
9684
+ }
9685
+ }
9686
+
9687
+ function _computeLineheight($lh, $fs='') {
9688
+ if ($this->shrin_k > 1) { $k = $this->shrin_k; }
9689
+ else { $k = 1; }
9690
+ if (!$fs) { $fs = $this->FontSize; }
9691
+ if (preg_match('/mm/',$lh)) {
9692
+ return (($lh + 0.0) / $k); // convert to number
9693
+ }
9694
+ else if ($lh > 0) {
9695
+ return ($fs * $lh);
9696
+ }
9697
+ else if (isset($this->normalLineheight)) { return ($fs * $this->normalLineheight); }
9698
+ else return ($fs * $this->default_lineheight_correction);
9699
+ }
9700
+
9701
+
9702
+ function SetBasePath($str='') {
9703
+ if ( isset($_SERVER['HTTP_HOST']) ) { $host = $_SERVER['HTTP_HOST']; }
9704
+ else if ( isset($_SERVER['SERVER_NAME']) ) { $host = $_SERVER['SERVER_NAME']; }
9705
+ else { $host = ''; }
9706
+ if (!$str) {
9707
+ if ($_SERVER['SCRIPT_NAME']) { $currentPath = dirname($_SERVER['SCRIPT_NAME']); }
9708
+ else { $currentPath = dirname($_SERVER['PHP_SELF']); }
9709
+ $currentPath = str_replace("\\","/",$currentPath);
9710
+ if ($currentPath == '/') { $currentPath = ''; }
9711
+ if ($host) { $currpath = 'http://' . $host . $currentPath .'/'; }
9712
+ else { $currpath = ''; }
9713
+ $this->basepath = $currpath;
9714
+ $this->basepathIsLocal = true;
9715
+ return;
9716
+ }
9717
+ $str = preg_replace('/\?.*/','',$str);
9718
+ if (!preg_match('/(http|https|ftp):\/\/.*\//i',$str)) { $str .= '/'; }
9719
+ $str .= 'xxx'; // in case $str ends in / e.g. http://www.bbc.co.uk/
9720
+ $this->basepath = dirname($str) . "/"; // returns e.g. e.g. http://www.google.com/dir1/dir2/dir3/
9721
+ $this->basepath = str_replace("\\","/",$this->basepath); //If on Windows
9722
+ $tr = parse_url($this->basepath);
9723
+ if (isset($tr['host']) && ($tr['host'] == $host)) { $this->basepathIsLocal = true; }
9724
+ else { $this->basepathIsLocal = false; }
9725
+ }
9726
+
9727
+
9728
+ function GetFullPath(&$path,$basepath='') {
9729
+ // When parsing CSS need to pass temporary basepath - so links are relative to current stylesheet
9730
+ if (!$basepath) { $basepath = $this->basepath; }
9731
+ //Fix path value
9732
+ $path = str_replace("\\","/",$path); //If on Windows
9733
+ $path = preg_replace('/^\/\//','http://',$path); // mPDF 5.6.27
9734
+ $regexp = '|^./|'; // Inadvertently corrects "./path/etc" and "//www.domain.com/etc"
9735
+ $path = preg_replace($regexp,'',$path);
9736
+
9737
+
9738
+ if(substr($path,0,1) == '#') { return; }
9739
+ if (stristr($path,"mailto:") !== false) { return; }
9740
+ if (strpos($path,"../") !== false ) { //It is a Relative Link
9741
+ $backtrackamount = substr_count($path,"../");
9742
+ $maxbacktrack = substr_count($basepath,"/") - 3; // mPDF 5.6.18
9743
+ $filepath = str_replace("../",'',$path);
9744
+ $path = $basepath;
9745
+ //If it is an invalid relative link, then make it go to directory root
9746
+ if ($backtrackamount > $maxbacktrack) $backtrackamount = $maxbacktrack;
9747
+ //Backtrack some directories
9748
+ for( $i = 0 ; $i < $backtrackamount + 1 ; $i++ ) $path = substr( $path, 0 , strrpos($path,"/") );
9749
+ $path = $path . "/" . $filepath; //Make it an absolute path
9750
+ }
9751
+ else if( strpos($path,":/") === false || strpos($path,":/") > 10) { //It is a Local Link
9752
+ if (substr($path,0,1) == "/") {
9753
+ $tr = parse_url($basepath);
9754
+ $root = $tr['scheme'].'://'.$tr['host'];
9755
+ $path = $root . $path;
9756
+ }
9757
+ else { $path = $basepath . $path; }
9758
+ }
9759
+ //Do nothing if it is an Absolute Link
9760
+ }
9761
+
9762
+
9763
+ // Used for external CSS files
9764
+ function _get_file($path) {
9765
+ // If local file try using local path (? quicker, but also allowed even if allow_url_fopen false)
9766
+ $contents = '';
9767
+ $contents = @file_get_contents($path);
9768
+ if ($contents) { return $contents; }
9769
+ if ($this->basepathIsLocal) {
9770
+ $tr = parse_url($path);
9771
+ $lp=getenv("SCRIPT_NAME");
9772
+ $ap=realpath($lp);
9773
+ $ap=str_replace("\\","/",$ap);
9774
+ $docroot=substr($ap,0,strpos($ap,$lp));
9775
+ // WriteHTML parses all paths to full URLs; may be local file name
9776
+ if ($tr['scheme'] && $tr['host'] && $_SERVER["DOCUMENT_ROOT"] ) {
9777
+ $localpath = $_SERVER["DOCUMENT_ROOT"] . $tr['path'];
9778
+ }
9779
+ // DOCUMENT_ROOT is not returned on IIS
9780
+ else if ($docroot) {
9781
+ $localpath = $docroot . $tr['path'];
9782
+ }
9783
+ else { $localpath = $path; }
9784
+ $contents = @file_get_contents($localpath);
9785
+ }
9786
+ // if not use full URL
9787
+ else if (!$contents && !ini_get('allow_url_fopen') && function_exists("curl_init")) {
9788
+ $ch = curl_init($path);
9789
+ curl_setopt($ch, CURLOPT_HEADER, 0);
9790
+ curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , 1 );
9791
+ $contents = curl_exec($ch);
9792
+ curl_close($ch);
9793
+ }
9794
+ return $contents;
9795
+ }
9796
+
9797
+
9798
+ function docPageNum($num = 0, $extras = false) {
9799
+ if ($num < 1) { $num = $this->page; }
9800
+ $type = '1'; // set default decimal
9801
+ $ppgno = $num;
9802
+ $suppress = 0;
9803
+ $offset = 0;
9804
+ $lastreset = 0;
9805
+ foreach($this->PageNumSubstitutions AS $psarr) {
9806
+ if ($num >= $psarr['from']) {
9807
+ if ($psarr['reset']) {
9808
+ if ($psarr['reset']>1) { $offset = $psarr['reset']-1; }
9809
+ $ppgno = $num - $psarr['from'] + 1 + $offset;
9810
+ $lastreset = $psarr['from'];
9811
+ }
9812
+ if ($psarr['type']) { $type = $psarr['type']; }
9813
+ if (strtoupper($psarr['suppress'])=='ON' || $psarr['suppress']==1) { $suppress = 1; }
9814
+ else if (strtoupper($psarr['suppress'])=='OFF') { $suppress = 0; }
9815
+ }
9816
+ }
9817
+ if ($suppress) { return ''; }
9818
+
9819
+ foreach($this->pgsIns AS $k=>$v) {
9820
+ if ($k>$lastreset && $k<$num) {
9821
+ $ppgno -= $v;
9822
+ }
9823
+ }
9824
+ if ($type=='A') { $ppgno = $this->dec2alpha($ppgno,true); }
9825
+ else if ($type=='a') { $ppgno = $this->dec2alpha($ppgno,false);}
9826
+ else if ($type=='I') { $ppgno = $this->dec2roman($ppgno,true); }
9827
+ else if ($type=='i') { $ppgno = $this->dec2roman($ppgno,false); }
9828
+ if ($extras) { $ppgno = $this->pagenumPrefix . $ppgno . $this->pagenumSuffix; }
9829
+ return $ppgno;
9830
+ }
9831
+
9832
+
9833
+ function docPageSettings($num = 0) {
9834
+ // Returns current type (numberstyle), suppression state for this page number;
9835
+ // reset is only returned if set for this page number
9836
+ if ($num < 1) { $num = $this->page; }
9837
+ $type = '1'; // set default decimal
9838
+ $ppgno = $num;
9839
+ $suppress = 0;
9840
+ $offset = 0;
9841
+ $reset = '';
9842
+ foreach($this->PageNumSubstitutions AS $psarr) {
9843
+ if ($num >= $psarr['from']) {
9844
+ if ($psarr['reset']) {
9845
+ if ($psarr['reset']>1) { $offset = $psarr['reset']-1; }
9846
+ $ppgno = $num - $psarr['from'] + 1 + $offset;
9847
+ }
9848
+ if ($psarr['type']) { $type = $psarr['type']; }
9849
+ if (strtoupper($psarr['suppress'])=='ON' || $psarr['suppress']==1) { $suppress = 1; }
9850
+ else if (strtoupper($psarr['suppress'])=='OFF') { $suppress = 0; }
9851
+ }
9852
+ if ($num == $psarr['from']) { $reset = $psarr['reset']; }
9853
+ }
9854
+ if ($suppress) { $suppress = 'on'; }
9855
+ else { $suppress = 'off'; }
9856
+ return array($type, $suppress, $reset);
9857
+ }
9858
+
9859
+ function docPageNumTotal($num = 0, $extras = false) {
9860
+ if ($num < 1) { $num = $this->page; }
9861
+ $type = '1'; // set default decimal
9862
+ $ppgstart = 1;
9863
+ $ppgend = count($this->pages)+1;
9864
+ $suppress = 0;
9865
+ $offset = 0;
9866
+ foreach($this->PageNumSubstitutions AS $psarr) {
9867
+ if ($num >= $psarr['from']) {
9868
+ if ($psarr['reset']) {
9869
+ if ($psarr['reset']>1) { $offset = $psarr['reset']-1; }
9870
+ $ppgstart = $psarr['from'] + $offset;
9871
+ $ppgend = count($this->pages)+1 + $offset;
9872
+ }
9873
+ if ($psarr['type']) { $type = $psarr['type']; }
9874
+ if (strtoupper($psarr['suppress'])=='ON' || $psarr['suppress']==1) { $suppress = 1; }
9875
+ else if (strtoupper($psarr['suppress'])=='OFF') { $suppress = 0; }
9876
+ }
9877
+ if ($num < $psarr['from']) {
9878
+ if ($psarr['reset']) {
9879
+ $ppgend = $psarr['from'] + $offset;
9880
+ break;
9881
+ }
9882
+ }
9883
+ }
9884
+ if ($suppress) { return ''; }
9885
+ $ppgno = $ppgend-$ppgstart+$offset;
9886
+
9887
+ // mPDF 5.6.47
9888
+ foreach($this->pgsIns AS $k => $v) {
9889
+ if ($k>$ppgstart && $k<$ppgend) {
9890
+ $ppgno -= $v;
9891
+ }
9892
+ }
9893
+
9894
+ if ($extras) { $ppgno = $this->nbpgPrefix . $ppgno . $this->nbpgSuffix; }
9895
+ return $ppgno;
9896
+ }
9897
+
9898
+ function RestartDocTemplate() {
9899
+ $this->docTemplateStart = $this->page;
9900
+ }
9901
+
9902
+
9903
+
9904
+ //Page header
9905
+ function Header($content='') {
9906
+
9907
+ $this->cMarginL = 0;
9908
+ $this->cMarginR = 0;
9909
+
9910
+
9911
+ if (($this->mirrorMargins && ($this->page%2==0) && $this->HTMLHeaderE) || ($this->mirrorMargins && ($this->page%2==1) && $this->HTMLHeader) || (!$this->mirrorMargins && $this->HTMLHeader)) {
9912
+ $this->writeHTMLHeaders();
9913
+ return;
9914
+ }
9915
+ $this->processingHeader=true;
9916
+ $h = $this->headerDetails;
9917
+ if(count($h)) {
9918
+
9919
+ if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
9920
+ $this->_out(sprintf('q 0 -1 1 0 0 %.3F cm ',($this->h*_MPDFK)));
9921
+ $yadj = $this->w - $this->h;
9922
+ $headerpgwidth = $this->h - $this->orig_lMargin - $this->orig_rMargin;
9923
+ if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
9924
+ $headerlmargin = $this->orig_rMargin;
9925
+ }
9926
+ else {
9927
+ $headerlmargin = $this->orig_lMargin;
9928
+ }
9929
+ }
9930
+ else {
9931
+ $yadj = 0;
9932
+ $headerpgwidth = $this->pgwidth;
9933
+ $headerlmargin = $this->lMargin;
9934
+ }
9935
+
9936
+ $this->y = $this->margin_header - $yadj ;
9937
+ $this->SetTColor($this->ConvertColor(0));
9938
+ $this->SUP = false;
9939
+ $this->SUB = false;
9940
+ $this->bullet = false;
9941
+
9942
+ // only show pagenumber if numbering on
9943
+ $pgno = $this->docPageNum($this->page, true);
9944
+
9945
+ if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
9946
+ $side = 'even';
9947
+ }
9948
+ else { // ODD // OR NOT MIRRORING MARGINS/FOOTERS = DEFAULT
9949
+ $side = 'odd';
9950
+ }
9951
+ $maxfontheight = 0;
9952
+ foreach(array('L','C','R') AS $pos) {
9953
+ if (isset($h[$side][$pos]['content']) && $h[$side][$pos]['content']) {
9954
+ if (isset($h[$side][$pos]['font-size']) && $h[$side][$pos]['font-size']) { $hfsz = $h[$side][$pos]['font-size']; }
9955
+ else { $hfsz = $this->default_font_size; }
9956
+ $maxfontheight = max($maxfontheight,$hfsz);
9957
+ }
9958
+ }
9959
+ // LEFT-CENTER-RIGHT
9960
+ foreach(array('L','C','R') AS $pos) {
9961
+ if (isset($h[$side][$pos]['content']) && $h[$side][$pos]['content']) {
9962
+ $hd = str_replace('{PAGENO}',$pgno,$h[$side][$pos]['content']);
9963
+ $hd = str_replace($this->aliasNbPgGp,$this->nbpgPrefix.$this->aliasNbPgGp.$this->nbpgSuffix,$hd);
9964
+ $hd = preg_replace('/\{DATE\s+(.*?)\}/e',"date('\\1')",$hd);
9965
+ if (isset($h[$side][$pos]['font-family']) && $h[$side][$pos]['font-family']) { $hff = $h[$side][$pos]['font-family']; }
9966
+ else { $hff = $this->original_default_font; }
9967
+ if (isset($h[$side][$pos]['font-size']) && $h[$side][$pos]['font-size']) { $hfsz = $h[$side][$pos]['font-size']; }
9968
+ else { $hfsz = $this->original_default_font_size; } // pts
9969
+ $maxfontheight = max($maxfontheight,$hfsz);
9970
+ $hfst = '';
9971
+ if (isset($h[$side][$pos]['font-style']) && $h[$side][$pos]['font-style']) {
9972
+ $hfst = $h[$side][$pos]['font-style'];
9973
+ }
9974
+ if (isset($h[$side][$pos]['color']) && $h[$side][$pos]['color']) {
9975
+ $hfcol = $h[$side][$pos]['color'];
9976
+ $cor = $this->ConvertColor($hfcol);
9977
+ if ($cor) { $this->SetTColor($cor); }
9978
+ }
9979
+ else { $hfcol = ''; }
9980
+ $this->SetFont($hff,$hfst,$hfsz,true,true);
9981
+ $this->x = $headerlmargin ;
9982
+ $this->y = $this->margin_header - $yadj ;
9983
+
9984
+ $hd = $this->purify_utf8_text($hd);
9985
+ if ($this->text_input_as_HTML) {
9986
+ $hd = $this->all_entities_to_utf8($hd);
9987
+ }
9988
+ // CONVERT CODEPAGE
9989
+ if ($this->usingCoreFont) { $hd = mb_convert_encoding($hd,$this->mb_enc,'UTF-8'); }
9990
+ // DIRECTIONALITY RTL
9991
+ // Font-specific ligature substitution for Indic fonts
9992
+ $align = $pos;
9993
+ if ($pos!='L' && (strpos($hd,$this->aliasNbPg)!==false || strpos($hd,$this->aliasNbPgGp)!==false)) {
9994
+ if (strpos($hd,$this->aliasNbPgGp)!==false) { $type= 'nbpggp'; } else { $type= 'nbpg'; }
9995
+ $this->_out('{mpdfheader'.$type.' '.$pos.' ff='.$hff.' fs='.$hfst.' fz='.$hfsz.'}');
9996
+ $this->Cell($headerpgwidth ,$maxfontheight/_MPDFK ,$hd,0,0,$align,0,'',0,0,0,'M');
9997
+ $this->_out('Q');
9998
+ }
9999
+ else {
10000
+ $this->Cell($headerpgwidth ,$maxfontheight/_MPDFK ,$hd,0,0,$align,0,'',0,0,0,'M');
10001
+ }
10002
+ if ($hfcol) { $this->SetTColor($this->ConvertColor(0)); }
10003
+ }
10004
+ }
10005
+ //Return Font to normal
10006
+ $this->SetFont($this->default_font,'',$this->original_default_font_size);
10007
+ // LINE
10008
+ if (isset($h[$side]['line']) && $h[$side]['line']) {
10009
+ $this->SetLineWidth(0.1);
10010
+ $this->SetDColor($this->ConvertColor(0));
10011
+ $this->Line($headerlmargin , $this->margin_header + ($maxfontheight*(1+$this->header_line_spacing)/_MPDFK) - $yadj , $headerlmargin + $headerpgwidth, $this->margin_header + ($maxfontheight*(1+$this->header_line_spacing)/_MPDFK) - $yadj );
10012
+ }
10013
+ if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
10014
+ $this->_out('Q');
10015
+ }
10016
+ }
10017
+ $this->SetY($this->tMargin);
10018
+
10019
+ $this->processingHeader=false;
10020
+ }
10021
+
10022
+
10023
+
10024
+ function TableHeaderFooter($content='',$tablestartpage='',$tablestartcolumn ='',$horf = 'H',$level, $firstSpread=true, $finalSpread=true) {
10025
+ if(($horf=='H' || $horf=='F') && !empty($content) && !empty($content[0])) { // mPDF 5.6.61
10026
+ $table = &$this->table[1][1];
10027
+ // Advance down page by half width of top border
10028
+
10029
+ if ($horf=='H') { // Only if header
10030
+ if ($table['borders_separate']) { $adv = $table['border_spacing_V']/2 + $table['border_details']['T']['w'] + $table['padding']['T']; }
10031
+ else { $adv = $table['max_cell_border_width']['T'] /2 ; }
10032
+ if ($adv) {
10033
+ if ($this->table_rotate) {
10034
+ $this->y += ($adv);
10035
+ }
10036
+ else {
10037
+ $this->DivLn($adv,$this->blklvl,true);
10038
+ }
10039
+ }
10040
+ }
10041
+
10042
+ if ($horf=='F') { // Table Footer
10043
+ $firstrow = count($table['cells']) - $table['footernrows'];
10044
+ $lastrow = count($table['cells']) - 1;
10045
+ }
10046
+ else { // Table Header
10047
+ $firstrow = 0;
10048
+ $lastrow = $table['headernrows'] - 1;
10049
+ }
10050
+
10051
+ $topy = $content[$firstrow][0]['y']-$this->y;
10052
+
10053
+ for ($i=$firstrow ; $i<=$lastrow; $i++) {
10054
+
10055
+ $y = $this->y;
10056
+
10057
+
10058
+ $colctr = 0;
10059
+ foreach($content[$i] as $tablehf) {
10060
+ $colctr++;
10061
+ $y = $tablehf['y'] - $topy;
10062
+ $this->y = $y;
10063
+ //Set some cell values
10064
+ $x = $tablehf['x'];
10065
+ if (($this->mirrorMargins) && ($tablestartpage == 'ODD') && (($this->page)%2==0)) { // EVEN
10066
+ $x = $x +$this->MarginCorrection;
10067
+ }
10068
+ else if (($this->mirrorMargins) && ($tablestartpage == 'EVEN') && (($this->page)%2==1)) { // ODD
10069
+ $x = $x +$this->MarginCorrection;
10070
+ }
10071
+
10072
+ if ($colctr==1) { $x0 = $x; }
10073
+
10074
+ // mPDF ITERATION
10075
+ if ($this->iterationCounter) {
10076
+ foreach($tablehf['textbuffer'] AS $k=>$t) {
10077
+ if (!is_array($t[0]) && preg_match('/{iteration ([a-zA-Z0-9_]+)}/',$t[0], $m)) { // mPDF 5.5.06
10078
+ $vname = '__'.$m[1].'_';
10079
+ if (!isset($this->$vname)) { $this->$vname = 1; }
10080
+ else { $this->$vname++; }
10081
+ $tablehf['textbuffer'][$k][0] = preg_replace('/{iteration '.$m[1].'}/', $this->$vname, $tablehf['textbuffer'][$k][0]);
10082
+ }
10083
+ }
10084
+ }
10085
+
10086
+
10087
+ $w = $tablehf['w'];
10088
+ $h = $tablehf['h'];
10089
+ $va = $tablehf['va'];
10090
+ $R = $tablehf['R'];
10091
+ $mih = $tablehf['mih'];
10092
+ $border = $tablehf['border'];
10093
+ $border_details = $tablehf['border_details'];
10094
+ $padding = $tablehf['padding'];
10095
+ $this->tabletheadjustfinished = true;
10096
+
10097
+ $textbuffer = $tablehf['textbuffer'];
10098
+
10099
+ $align = $tablehf['a'];
10100
+ //Align
10101
+ $this->divalign=$align;
10102
+ $this->x = $x;
10103
+
10104
+ if ($this->ColActive) {
10105
+ if ($table['borders_separate']) {
10106
+ $tablefill = isset($table['bgcolor'][-1]) ? $table['bgcolor'][-1] : 0;
10107
+ if ($tablefill) {
10108
+ $color = $this->ConvertColor($tablefill);
10109
+ if ($color) {
10110
+ $xadj = ($table['border_spacing_H']/2);
10111
+ $yadj = ($table['border_spacing_V']/2);
10112
+ $wadj = $table['border_spacing_H'];
10113
+ $hadj = $table['border_spacing_V'];
10114
+ if ($i == $firstrow && $horf=='H') { // Top
10115
+ $yadj += $table['padding']['T'] + $table['border_details']['T']['w'] ;
10116
+ $hadj += $table['padding']['T'] + $table['border_details']['T']['w'] ;
10117
+ }
10118
+ if (($i == ($lastrow) || (isset($tablehf['rowspan']) && ($i+$tablehf['rowspan']) == ($lastrow+1)) || (!isset($tablehf['rowspan']) && ($i+1) == ($lastrow+1))) && $horf=='F') { // Bottom
10119
+ $hadj += $table['padding']['B'] + $table['border_details']['B']['w'] ;
10120
+ }
10121
+ if ($colctr == 1) { // Left
10122
+ $xadj += $table['padding']['L'] + $table['border_details']['L']['w'] ;
10123
+ $wadj += $table['padding']['L'] + $table['border_details']['L']['w'] ;
10124
+ }
10125
+ if ($colctr == count($content[$i]) ) { // Right
10126
+ $wadj += $table['padding']['R'] + $table['border_details']['R']['w'] ;
10127
+ }
10128
+ $this->SetFColor($color);
10129
+ $this->Rect($x - $xadj, $y - $yadj, $w + $wadj, $h + $hadj, 'F');
10130
+ }
10131
+ }
10132
+ }
10133
+ }
10134
+
10135
+ if ($table['empty_cells']!='hide' || !empty($textbuffer) || !$table['borders_separate']) { $paintcell = true; }
10136
+ else { $paintcell = false; }
10137
+
10138
+ //Vertical align
10139
+ if ($R && INTVAL($R) > 0 && isset($va) && $va!='B') { $va='B';}
10140
+
10141
+ if (!isset($va) || empty($va) || $va=='M') $this->y += ($h-$mih)/2;
10142
+ elseif (isset($va) && $va=='B') $this->y += $h-$mih;
10143
+
10144
+
10145
+ //TABLE ROW OR CELL FILL BGCOLOR
10146
+ $fill = 0;
10147
+ if (isset($tablehf['bgcolor']) && $tablehf['bgcolor'] && $tablehf['bgcolor']!='transparent') {
10148
+ $fill = $tablehf['bgcolor'];
10149
+ $leveladj = 6;
10150
+ }
10151
+ else if (isset($content[$i][0]['trbgcolor']) && $content[$i][0]['trbgcolor'] && $content[$i][0]['trbgcolor']!='transparent') { // Row color
10152
+ $fill = $content[$i][0]['trbgcolor'];
10153
+ $leveladj = 3;
10154
+ }
10155
+ if ($fill && $paintcell) {
10156
+ $color = $this->ConvertColor($fill);
10157
+ if ($color) {
10158
+ if ($table['borders_separate']) {
10159
+ if ($this->ColActive) {
10160
+ $this->SetFColor($color);
10161
+ $this->Rect($x+ ($table['border_spacing_H']/2), $y+ ($table['border_spacing_V']/2), $w- $table['border_spacing_H'], $h- $table['border_spacing_V'], 'F');
10162
+ }
10163
+ else {
10164
+ $this->tableBackgrounds[$level*9+$leveladj][] = array('gradient'=>false, 'x'=>($x + ($table['border_spacing_H']/2)), 'y'=>($y + ($table['border_spacing_V']/2)), 'w'=>($w - $table['border_spacing_H']), 'h'=>($h - $table['border_spacing_V']), 'col'=>$color);
10165
+ }
10166
+ }
10167
+ else {
10168
+ if ($this->ColActive) {
10169
+ $this->SetFColor($color);
10170
+ $this->Rect($x, $y, $w, $h, 'F');
10171
+ }
10172
+ else {
10173
+ $this->tableBackgrounds[$level*9+$leveladj][] = array('gradient'=>false, 'x'=>$x, 'y'=>$y, 'w'=>$w, 'h'=>$h, 'col'=>$color);
10174
+ }
10175
+ }
10176
+ }
10177
+ }
10178
+
10179
+
10180
+ if (isset($tablehf['gradient']) && $tablehf['gradient'] && $paintcell){
10181
+ $g = $this->grad->parseBackgroundGradient($tablehf['gradient']);
10182
+ if ($g) {
10183
+ if ($table['borders_separate']) {
10184
+ $px = $x+ ($table['border_spacing_H']/2);
10185
+ $py = $y+ ($table['border_spacing_V']/2);
10186
+ $pw = $w- $table['border_spacing_H'];
10187
+ $ph = $h- $table['border_spacing_V'];
10188
+ }
10189
+ else {
10190
+ $px = $x;
10191
+ $py = $y;
10192
+ $pw = $w;
10193
+ $ph = $h;
10194
+ }
10195
+ if ($this->ColActive) {
10196
+ $this->grad->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
10197
+ }
10198
+ else {
10199
+ $this->tableBackgrounds[$level*9+7][] = array('gradient'=>true, 'x'=>$px, 'y'=>$py, 'w'=>$pw, 'h'=>$ph, 'gradtype'=>$g['type'], 'stops'=>$g['stops'], 'colorspace'=>$g['colorspace'], 'coords'=>$g['coords'], 'extend'=>$g['extend'], 'clippath'=>'');
10200
+ }
10201
+ }
10202
+ }
10203
+
10204
+ if (isset($tablehf['background-image']) && $paintcell){
10205
+ if ($tablehf['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $tablehf['background-image']['gradient'] )) {
10206
+ $g = $this->grad->parseMozGradient( $tablehf['background-image']['gradient'] );
10207
+ if ($g) {
10208
+ if ($table['borders_separate']) {
10209
+ $px = $x+ ($table['border_spacing_H']/2);
10210
+ $py = $y+ ($table['border_spacing_V']/2);
10211
+ $pw = $w- $table['border_spacing_H'];
10212
+ $ph = $h- $table['border_spacing_V'];
10213
+ }
10214
+ else {
10215
+ $px = $x;
10216
+ $py = $y;
10217
+ $pw = $w;
10218
+ $ph = $h;
10219
+ }
10220
+ if ($this->ColActive) {
10221
+ $this->grad->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
10222
+ }
10223
+ else {
10224
+ $this->tableBackgrounds[$level*9+7][] = array('gradient'=>true, 'x'=>$px, 'y'=>$py, 'w'=>$pw, 'h'=>$ph, 'gradtype'=>$g['type'], 'stops'=>$g['stops'], 'colorspace'=>$g['colorspace'], 'coords'=>$g['coords'], 'extend'=>$g['extend'], 'clippath'=>'');
10225
+ }
10226
+ }
10227
+ }
10228
+ else if ($tablehf['background-image']['image_id']) { // Background pattern
10229
+ $n = count($this->patterns)+1;
10230
+ if ($table['borders_separate']) {
10231
+ $px = $x+ ($table['border_spacing_H']/2);
10232
+ $py = $y+ ($table['border_spacing_V']/2);
10233
+ $pw = $w- $table['border_spacing_H'];
10234
+ $ph = $h- $table['border_spacing_V'];
10235
+ }
10236
+ else {
10237
+ $px = $x;
10238
+ $py = $y;
10239
+ $pw = $w;
10240
+ $ph = $h;
10241
+ }
10242
+ if ($this->ColActive) {
10243
+ list($orig_w, $orig_h, $x_repeat, $y_repeat) = $this->_resizeBackgroundImage($tablehf['background-image']['orig_w'], $tablehf['background-image']['orig_h'], $pw, $ph, $tablehf['background-image']['resize'], $tablehf['background-image']['x_repeat'] , $tablehf['background-image']['y_repeat']);
10244
+ $this->patterns[$n] = array('x'=>$px, 'y'=>$py, 'w'=>$pw, 'h'=>$ph, 'pgh'=>$this->h, 'image_id'=>$tablehf['background-image']['image_id'], 'orig_w'=>$orig_w, 'orig_h'=>$orig_h, 'x_pos'=>$tablehf['background-image']['x_pos'] , 'y_pos'=>$tablehf['background-image']['y_pos'] , 'x_repeat'=>$x_repeat, 'y_repeat'=>$y_repeat, 'itype'=>$tablehf['background-image']['itype']);
10245
+ if ($tablehf['background-image']['opacity']>0 && $tablehf['background-image']['opacity']<1) { $opac = $this->SetAlpha($tablehf['background-image']['opacity'],'Normal',true); }
10246
+ else { $opac = ''; }
10247
+ $this->_out(sprintf('q /Pattern cs /P%d scn %s %.3F %.3F %.3F %.3F re f Q', $n, $opac, $px*_MPDFK, ($this->h-$py)*_MPDFK, $pw*_MPDFK, -$ph*_MPDFK));
10248
+ }
10249
+ else {
10250
+ $this->tableBackgrounds[$level*9+8][] = array('x'=>$px, 'y'=>$py, 'w'=>$pw, 'h'=>$ph, 'image_id'=>$tablehf['background-image']['image_id'], 'orig_w'=>$tablehf['background-image']['orig_w'], 'orig_h'=>$tablehf['background-image']['orig_h'], 'x_pos'=>$tablehf['background-image']['x_pos'], 'y_pos'=>$tablehf['background-image']['y_pos'], 'x_repeat'=>$tablehf['background-image']['x_repeat'], 'y_repeat'=>$tablehf['background-image']['y_repeat'], 'clippath'=>'', 'resize'=>$tablehf['background-image']['resize'], 'opacity'=>$tablehf['background-image']['opacity'], 'itype'=>$tablehf['background-image']['itype']);
10251
+ }
10252
+ }
10253
+ }
10254
+
10255
+ //Cell Border
10256
+ if ($table['borders_separate'] && $paintcell && $border) {
10257
+ $this->_tableRect($x+ ($table['border_spacing_H']/2)+($border_details['L']['w'] /2), $y+ ($table['border_spacing_V']/2)+($border_details['T']['w'] /2), $w-$table['border_spacing_H']-($border_details['L']['w'] /2)-($border_details['R']['w'] /2), $h- $table['border_spacing_V']-($border_details['T']['w'] /2)-($border_details['B']['w']/2), $border, $border_details, false, $table['borders_separate']);
10258
+ }
10259
+ else if ($paintcell && $border) {
10260
+ $this->_tableRect($x, $y, $w, $h, $border, $border_details, true, $table['borders_separate']); // true causes buffer
10261
+ }
10262
+
10263
+ //Print cell content
10264
+ //$this->divheight = $this->table_lineheight*$this->lineheight;
10265
+ if (!empty($textbuffer)) {
10266
+ if ($horf=='F' && preg_match('/{colsum([0-9]*)[_]*}/', $textbuffer[0][0], $m)) {
10267
+ $rep = sprintf("%01.".intval($m[1])."f", $this->colsums[$colctr-1]);
10268
+ $textbuffer[0][0] = preg_replace('/{colsum[0-9_]*}/', $rep ,$textbuffer[0][0]);
10269
+ }
10270
+
10271
+ if ($R) {
10272
+ $cellPtSize = $textbuffer[0][11] / $this->shrin_k;
10273
+ if (!$cellPtSize) { $cellPtSize = $this->default_font_size; }
10274
+ $cellFontHeight = ($cellPtSize/_MPDFK);
10275
+ $opx = $this->x;
10276
+ $opy = $this->y;
10277
+ $angle = INTVAL($R);
10278
+ // Only allow 45 - 90 degrees (when bottom-aligned) or -90
10279
+ if ($angle > 90) { $angle = 90; }
10280
+ else if ($angle > 0 && (isset($va) && $va!='B')) { $angle = 90; }
10281
+ else if ($angle > 0 && $angle <45) { $angle = 45; }
10282
+ else if ($angle < 0) { $angle = -90; }
10283
+ $offset = ((sin(deg2rad($angle))) * 0.37 * $cellFontHeight);
10284
+ if (isset($align) && $align =='R') {
10285
+ $this->x += ($w) + ($offset) - ($cellFontHeight/3) - ($padding['R'] + $border_details['R']['w']);
10286
+ }
10287
+ else if (!isset($align ) || $align =='C') {
10288
+ $this->x += ($w/2) + ($offset);
10289
+ }
10290
+ else {
10291
+ $this->x += ($offset) + ($cellFontHeight/3)+($padding['L'] + $border_details['L']['w']);
10292
+ }
10293
+ $str = '';
10294
+ foreach($tablehf['textbuffer'] AS $t) { $str .= $t[0].' '; }
10295
+ $str = trim($str);
10296
+
10297
+ if (!isset($va) || $va=='M') {
10298
+ $this->y -= ($h-$mih)/2; //Undo what was added earlier VERTICAL ALIGN
10299
+ if ($angle > 0) { $this->y += (($h-$mih)/2)+($padding['T'] + $border_details['T']['w']) + ($mih-($padding['T'] + $border_details['T']['w']+$border_details['B']['w']+$padding['B'])); }
10300
+ else if ($angle < 0) { $this->y += (($h-$mih)/2)+($padding['T'] + $border_details['T']['w']); }
10301
+ }
10302
+ else if (isset($va) && $va=='B') {
10303
+ $this->y -= $h-$mih; //Undo what was added earlier VERTICAL ALIGN
10304
+ if ($angle > 0) { $this->y += $h-($border_details['B']['w']+$padding['B']); }
10305
+ else if ($angle < 0) { $this->y += $h-$mih+($padding['T'] + $border_details['T']['w']); }
10306
+ }
10307
+ else if (isset($va) && $va=='T') {
10308
+ if ($angle > 0) { $this->y += $mih-($border_details['B']['w']+$padding['B']); }
10309
+ else if ($angle < 0) { $this->y += ($padding['T'] + $border_details['T']['w']); }
10310
+ }
10311
+
10312
+ $this->Rotate($angle,$this->x,$this->y);
10313
+ $s_fs = $this->FontSizePt;
10314
+ $s_f = $this->FontFamily;
10315
+ $s_st = $this->FontStyle;
10316
+ if (!empty($textbuffer[0][3])) { //Font Color
10317
+ $cor = $textbuffer[0][3];
10318
+ $this->SetTColor($cor);
10319
+ }
10320
+ $s_str = $this->strike;
10321
+ $this->strike = $textbuffer[0][8]; //Strikethrough
10322
+ $this->SetFont($textbuffer[0][4],$textbuffer[0][2],$cellPtSize,true,true);
10323
+ $this->Text($this->x,$this->y,$str);
10324
+ $this->Rotate(0);
10325
+ $this->SetFont($s_f,$s_st,$s_fs,true,true);
10326
+ $this->SetTColor(0);
10327
+ $this->strike = $s_str;
10328
+ $this->x = $opx;
10329
+ $this->y = $opy;
10330
+ }
10331
+ else {
10332
+ if ($table['borders_separate']) { // NB twice border width
10333
+ $xadj = $border_details['L']['w'] + $padding['L'] +($table['border_spacing_H']/2);
10334
+ $wadj = $border_details['L']['w'] + $border_details['R']['w'] + $padding['L'] +$padding['R'] + $table['border_spacing_H'];
10335
+ $yadj = $border_details['T']['w'] + $padding['T'] + ($table['border_spacing_H']/2);
10336
+ }
10337
+ else {
10338
+ $xadj = $border_details['L']['w']/2 + $padding['L'];
10339
+ $wadj = ($border_details['L']['w'] + $border_details['R']['w'])/2 + $padding['L'] + $padding['R'];
10340
+ $yadj = $border_details['T']['w']/2 + $padding['T'];
10341
+ }
10342
+
10343
+ $this->divwidth=$w-($wadj);
10344
+ $this->x += $xadj;
10345
+ $this->y += $yadj;
10346
+ $this->printbuffer($textbuffer,'',true);
10347
+ }
10348
+
10349
+ }
10350
+ $textbuffer = array();
10351
+
10352
+ if (!$this->ColActive) {
10353
+ if (isset($content[$i][0]['trgradients']) && ($colctr==1 || $table['borders_separate'])) {
10354
+ $g = $this->grad->parseBackgroundGradient($content[$i][0]['trgradients']);
10355
+ if ($g) {
10356
+ $gx = $x0;
10357
+ $gy = $y;
10358
+ $gh = $h;
10359
+ $gw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
10360
+ if ($table['borders_separate']) {
10361
+ $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
10362
+ $s = '';
10363
+ $clx = $x+ ($table['border_spacing_H']/2);
10364
+ $cly = $y+ ($table['border_spacing_V']/2);
10365
+ $clw = $w- $table['border_spacing_H'];
10366
+ $clh = $h- $table['border_spacing_V'];
10367
+ // Set clipping path
10368
+ $s = ' q 0 w '; // Line width=0
10369
+ $s .= sprintf('%.3F %.3F m ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // start point TL before the arc
10370
+ $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BL
10371
+ $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BR
10372
+ $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TR
10373
+ $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TL
10374
+ $s .= ' W n '; // Ends path no-op & Sets the clipping path
10375
+ $this->tableBackgrounds[$level*9+4][] = array('gradient'=>true, 'x'=>$gx + ($table['border_spacing_H']/2), 'y'=>$gy + ($table['border_spacing_V']/2), 'w'=>$gw - $table['border_spacing_V'], 'h'=>$gh - $table['border_spacing_H'], 'gradtype'=>$g['type'], 'stops'=>$g['stops'], 'colorspace'=>$g['colorspace'], 'coords'=>$g['coords'], 'extend'=>$g['extend'], 'clippath'=>$s);
10376
+ }
10377
+ else {
10378
+ $this->tableBackgrounds[$level*9+4][] = array('gradient'=>true, 'x'=>$gx, 'y'=>$gy, 'w'=>$gw, 'h'=>$gh, 'gradtype'=>$g['type'], 'stops'=>$g['stops'], 'colorspace'=>$g['colorspace'], 'coords'=>$g['coords'], 'extend'=>$g['extend'], 'clippath'=>'');
10379
+ }
10380
+ }
10381
+ }
10382
+
10383
+ if (isset($content[$i][0]['trbackground-images']) && ($colctr==1 || $table['borders_separate'])) {
10384
+ if ($content[$i][0]['trbackground-images']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $content[$i][0]['trbackground-images']['gradient'] )) {
10385
+ $g = $this->grad->parseMozGradient( $content[$i][0]['trbackground-images']['gradient'] );
10386
+ if ($g) {
10387
+ $gx = $x0;
10388
+ $gy = $y;
10389
+ $gh = $h;
10390
+ $gw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
10391
+ if ($table['borders_separate']) {
10392
+ $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
10393
+ $s = '';
10394
+ $clx = $x+ ($table['border_spacing_H']/2);
10395
+ $cly = $y+ ($table['border_spacing_V']/2);
10396
+ $clw = $w- $table['border_spacing_H'];
10397
+ $clh = $h- $table['border_spacing_V'];
10398
+ // Set clipping path
10399
+ $s = ' q 0 w '; // Line width=0
10400
+ $s .= sprintf('%.3F %.3F m ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // start point TL before the arc
10401
+ $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BL
10402
+ $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BR
10403
+ $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TR
10404
+ $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TL
10405
+ $s .= ' W n '; // Ends path no-op & Sets the clipping path
10406
+ $this->tableBackgrounds[$level*9+4][] = array('gradient'=>true, 'x'=>$gx + ($table['border_spacing_H']/2), 'y'=>$gy + ($table['border_spacing_V']/2), 'w'=>$gw - $table['border_spacing_V'], 'h'=>$gh - $table['border_spacing_H'], 'gradtype'=>$g['type'], 'stops'=>$g['stops'], 'colorspace'=>$g['colorspace'], 'coords'=>$g['coords'], 'extend'=>$g['extend'], 'clippath'=>$s);
10407
+ }
10408
+ else {
10409
+ $this->tableBackgrounds[$level*9+4][] = array('gradient'=>true, 'x'=>$gx, 'y'=>$gy, 'w'=>$gw, 'h'=>$gh, 'gradtype'=>$g['type'], 'stops'=>$g['stops'], 'colorspace'=>$g['colorspace'], 'coords'=>$g['coords'], 'extend'=>$g['extend'], 'clippath'=>'');
10410
+ }
10411
+ }
10412
+ }
10413
+ else {
10414
+ $image_id = $content[$i][0]['trbackground-images']['image_id'];
10415
+ $orig_w = $content[$i][0]['trbackground-images']['orig_w'];
10416
+ $orig_h = $content[$i][0]['trbackground-images']['orig_h'];
10417
+ $x_pos = $content[$i][0]['trbackground-images']['x_pos'];
10418
+ $y_pos = $content[$i][0]['trbackground-images']['y_pos'];
10419
+ $x_repeat = $content[$i][0]['trbackground-images']['x_repeat'];
10420
+ $y_repeat = $content[$i][0]['trbackground-images']['y_repeat'];
10421
+ $resize = $content[$i][0]['trbackground-images']['resize'];
10422
+ $opacity = $content[$i][0]['trbackground-images']['opacity'];
10423
+ $itype = $content[$i][0]['trbackground-images']['itype'];
10424
+
10425
+ $clippath = '';
10426
+ $gx = $x0;
10427
+ $gy = $y;
10428
+ $gh = $h;
10429
+ $gw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
10430
+ if ($table['borders_separate']) {
10431
+ $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
10432
+ $s = '';
10433
+ $clx = $x+ ($table['border_spacing_H']/2);
10434
+ $cly = $y+ ($table['border_spacing_V']/2);
10435
+ $clw = $w- $table['border_spacing_H'];
10436
+ $clh = $h- $table['border_spacing_V'];
10437
+ // Set clipping path
10438
+ $s = ' q 0 w '; // Line width=0
10439
+ $s .= sprintf('%.3F %.3F m ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // start point TL before the arc
10440
+ $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BL
10441
+ $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BR
10442
+ $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TR
10443
+ $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TL
10444
+ $s .= ' W n '; // Ends path no-op & Sets the clipping path
10445
+ $this->tableBackgrounds[$level*9+5][] = array('x'=>$gx + ($table['border_spacing_H']/2), 'y'=>$gy + ($table['border_spacing_V']/2), 'w'=>$gw - $table['border_spacing_V'], 'h'=>$gh - $table['border_spacing_H'], 'image_id'=>$image_id, 'orig_w'=>$orig_w, 'orig_h'=>$orig_h, 'x_pos'=>$x_pos, 'y_pos'=>$y_pos, 'x_repeat'=>$x_repeat, 'y_repeat'=>$y_repeat, 'clippath'=>$s, 'resize'=>$resize, 'opacity'=>$opacity, 'itype'=>$itype);
10446
+ }
10447
+ else {
10448
+ $this->tableBackgrounds[$level*9+5][] = array('x'=>$gx, 'y'=>$gy, 'w'=>$gw, 'h'=>$gh, 'image_id'=>$image_id, 'orig_w'=>$orig_w, 'orig_h'=>$orig_h, 'x_pos'=>$x_pos, 'y_pos'=>$y_pos, 'x_repeat'=>$x_repeat, 'y_repeat'=>$y_repeat, 'clippath'=>'', 'resize'=>$resize, 'opacity'=>$opacity, 'itype'=>$itype);
10449
+ }
10450
+ }
10451
+ }
10452
+ }
10453
+
10454
+ // TABLE BORDER - if separate OR collapsed and only table border
10455
+ if (($table['borders_separate'] || ($this->simpleTables && !$table['simple']['border'])) && $table['border']) {
10456
+ $halfspaceL = $table['padding']['L'] + ($table['border_spacing_H']/2);
10457
+ $halfspaceR = $table['padding']['R'] + ($table['border_spacing_H']/2);
10458
+ $halfspaceT = $table['padding']['T'] + ($table['border_spacing_V']/2);
10459
+ $halfspaceB = $table['padding']['B'] + ($table['border_spacing_V']/2);
10460
+ $tbx = $x;
10461
+ $tby = $y;
10462
+ $tbw = $w;
10463
+ $tbh = $h;
10464
+ $tab_bord = 0;
10465
+ $corner = '';
10466
+ if ($i == $firstrow && $horf=='H') { // Top
10467
+ $tby -= $halfspaceT + ($table['border_details']['T']['w']/2);
10468
+ $tbh += $halfspaceT + ($table['border_details']['T']['w']/2);
10469
+ $this->setBorder($tab_bord , _BORDER_TOP);
10470
+ $corner .= 'T';
10471
+ }
10472
+ if (($i == ($lastrow) || (isset($tablehf['rowspan']) && ($i+$tablehf['rowspan']) == ($lastrow+1))) && $horf=='F') { // Bottom
10473
+ $tbh += $halfspaceB + ($table['border_details']['B']['w']/2);
10474
+ $this->setBorder($tab_bord , _BORDER_BOTTOM);
10475
+ $corner .= 'B';
10476
+ }
10477
+ if ($colctr == 1 && $firstSpread) { // Left
10478
+ $tbx -= $halfspaceL + ($table['border_details']['L']['w']/2);
10479
+ $tbw += $halfspaceL + ($table['border_details']['L']['w']/2);
10480
+ $this->setBorder($tab_bord , _BORDER_LEFT);
10481
+ $corner .= 'L';
10482
+ }
10483
+ if ($colctr == count($content[$i]) && $finalSpread) { // Right
10484
+ $tbw += $halfspaceR + ($table['border_details']['R']['w']/2);
10485
+ $this->setBorder($tab_bord , _BORDER_RIGHT);
10486
+ $corner .= 'R';
10487
+ }
10488
+ $this->_tableRect($tbx, $tby, $tbw, $tbh, $tab_bord , $table['border_details'], false, $table['borders_separate'], 'table', $corner, $table['border_spacing_V'], $table['border_spacing_H'] );
10489
+ }
10490
+
10491
+
10492
+ }// end column $content
10493
+ $this->y = $y + $h; //Update y coordinate
10494
+ }// end row $i
10495
+ unset($table );
10496
+ $this->colsums = array();
10497
+ }
10498
+ }
10499
+
10500
+ function SetHTMLHeader($header='',$OE='',$write=false) {
10501
+
10502
+ $height = 0;
10503
+ if (is_array($header) && isset($header['html']) && $header['html']) {
10504
+ $Hhtml = $header['html'];
10505
+ if ($this->setAutoTopMargin) {
10506
+ if (isset($header['h'])) { $height = $header['h']; }
10507
+ else { $height = $this->_gethtmlheight($Hhtml); }
10508
+ }
10509
+ }
10510
+ else if (!is_array($header) && $header) {
10511
+ $Hhtml = $header;
10512
+ if ($this->setAutoTopMargin) { $height = $this->_gethtmlheight($Hhtml); }
10513
+ }
10514
+ else { $Hhtml = ''; }
10515
+
10516
+ if ($OE != 'E') { $OE = 'O'; }
10517
+ if ($OE == 'E') {
10518
+
10519
+ if ($Hhtml) {
10520
+ $this->HTMLHeaderE['html'] = $Hhtml;
10521
+ $this->HTMLHeaderE['h'] = $height;
10522
+ }
10523
+ else { $this->HTMLHeaderE = ''; }
10524
+ }
10525
+ else {
10526
+
10527
+ if ($Hhtml) {
10528
+ $this->HTMLHeader['html'] = $Hhtml;
10529
+ $this->HTMLHeader['h'] = $height;
10530
+ }
10531
+ else { $this->HTMLHeader = ''; }
10532
+ }
10533
+ if (!$this->mirrorMargins && $OE == 'E') { return; }
10534
+ if ($Hhtml=='') { return; }
10535
+ if ($OE == 'E') {
10536
+ $this->headerDetails['even'] = array(); // override and clear any other non-HTML header/footer
10537
+ }
10538
+ else {
10539
+ $this->headerDetails['odd'] = array(); // override and clear any non-HTML other header/footer
10540
+ }
10541
+
10542
+ if ($this->setAutoTopMargin=='pad') {
10543
+ $this->tMargin = $this->margin_header + $height + $this->orig_tMargin;
10544
+ if (isset($this->saveHTMLHeader[$this->page][$OE]['mt'])) { $this->saveHTMLHeader[$this->page][$OE]['mt'] = $this->tMargin; }
10545
+ }
10546
+ else if ($this->setAutoTopMargin=='stretch') {
10547
+ $this->tMargin = max($this->orig_tMargin, $this->margin_header + $height + $this->autoMarginPadding);
10548
+ if (isset($this->saveHTMLHeader[$this->page][$OE]['mt'])) { $this->saveHTMLHeader[$this->page][$OE]['mt'] = $this->tMargin; }
10549
+ }
10550
+ if ($write && $this->state!=0 && (($this->mirrorMargins && $OE == 'E' && ($this->page)%2==0) || ($this->mirrorMargins && $OE != 'E' && ($this->page)%2==1) || !$this->mirrorMargins)) { $this->writeHTMLHeaders(); }
10551
+ }
10552
+
10553
+ function SetHTMLFooter($footer='',$OE='') {
10554
+
10555
+ $height = 0;
10556
+ if (is_array($footer) && isset($footer['html']) && $footer['html']) {
10557
+ $Fhtml = $footer['html'];
10558
+ if ($this->setAutoBottomMargin) {
10559
+ if (isset($footer['h'])) { $height = $footer['h']; }
10560
+ else { $height = $this->_gethtmlheight($Fhtml); }
10561
+ }
10562
+ }
10563
+ else if (!is_array($footer) && $footer) {
10564
+ $Fhtml = $footer;
10565
+ if ($this->setAutoBottomMargin) { $height = $this->_gethtmlheight($Fhtml); }
10566
+ }
10567
+ else { $Fhtml = ''; }
10568
+
10569
+ if ($OE != 'E') { $OE = 'O'; }
10570
+ if ($OE == 'E') {
10571
+
10572
+ if ($Fhtml) {
10573
+ $this->HTMLFooterE['html'] = $Fhtml;
10574
+ $this->HTMLFooterE['h'] = $height;
10575
+ }
10576
+ else { $this->HTMLFooterE = ''; }
10577
+ }
10578
+ else {
10579
+
10580
+ if ($Fhtml) {
10581
+ $this->HTMLFooter['html'] = $Fhtml;
10582
+ $this->HTMLFooter['h'] = $height;
10583
+ }
10584
+ else { $this->HTMLFooter = ''; }
10585
+ }
10586
+ if (!$this->mirrorMargins && $OE == 'E') { return; }
10587
+ if ($Fhtml=='') { return false; }
10588
+ if ($OE == 'E') {
10589
+ $this->footerDetails['even'] = array(); // override and clear any other header/footer
10590
+ }
10591
+ else {
10592
+ $this->footerDetails['odd'] = array(); // override and clear any other header/footer
10593
+ }
10594
+
10595
+ if ($this->setAutoBottomMargin=='pad') {
10596
+ $this->bMargin = $this->margin_footer + $height + $this->orig_bMargin;
10597
+ $this->PageBreakTrigger=$this->h-$this->bMargin ;
10598
+ if (isset($this->saveHTMLHeader[$this->page][$OE]['mb'])) { $this->saveHTMLHeader[$this->page][$OE]['mb'] = $this->bMargin; }
10599
+ }
10600
+ else if ($this->setAutoBottomMargin=='stretch') {
10601
+ $this->bMargin = max($this->orig_bMargin, $this->margin_footer + $height + $this->autoMarginPadding);
10602
+ $this->PageBreakTrigger=$this->h-$this->bMargin ;
10603
+ if (isset($this->saveHTMLHeader[$this->page][$OE]['mb'])) { $this->saveHTMLHeader[$this->page][$OE]['mb'] = $this->bMargin; }
10604
+ }
10605
+ }
10606
+
10607
+
10608
+ function _getHtmlHeight($html) {
10609
+ $save_state = $this->state;
10610
+ if($this->state==0) {
10611
+ $this->AddPage($this->CurOrientation);
10612
+ }
10613
+ $this->state = 2;
10614
+ $this->Reset();
10615
+ $this->pageoutput[$this->page] = array();
10616
+ $save_x = $this->x;
10617
+ $save_y = $this->y;
10618
+ $this->x = $this->lMargin;
10619
+ $this->y = $this->margin_header;
10620
+ $html = str_replace('{PAGENO}',$this->pagenumPrefix.$this->docPageNum($this->page).$this->pagenumSuffix,$html);
10621
+ $html = str_replace($this->aliasNbPgGp,$this->nbpgPrefix.$this->docPageNumTotal($this->page).$this->nbpgSuffix,$html );
10622
+ $html = str_replace($this->aliasNbPg,$this->page,$html );
10623
+ $html = preg_replace('/\{DATE\s+(.*?)\}/e',"date('\\1')",$html );
10624
+ $this->HTMLheaderPageLinks = array();
10625
+ $this->HTMLheaderPageAnnots = array();
10626
+ $this->HTMLheaderPageForms = array();
10627
+ $savepb = $this->pageBackgrounds;
10628
+ $this->writingHTMLheader = true;
10629
+ $this->WriteHTML($html , 4); // parameter 4 saves output to $this->headerbuffer
10630
+ $this->writingHTMLheader = false;
10631
+ $h = ($this->y - $this->margin_header);
10632
+ $this->Reset();
10633
+ $this->pageoutput[$this->page] = array();
10634
+ $this->headerbuffer = '';
10635
+ $this->pageBackgrounds = $savepb;
10636
+ $this->x = $save_x;
10637
+ $this->y = $save_y;
10638
+ $this->state = $save_state;
10639
+ if($save_state==0) {
10640
+ unset($this->pages[1]);
10641
+ $this->page = 0;
10642
+ }
10643
+ return $h;
10644
+ }
10645
+
10646
+
10647
+ // Called internally from Header
10648
+ function writeHTMLHeaders() {
10649
+
10650
+ if ($this->mirrorMargins && ($this->page)%2==0) { $OE = 'E'; } // EVEN
10651
+ else { $OE = 'O'; }
10652
+ if ($OE == 'E') {
10653
+ $this->saveHTMLHeader[$this->page][$OE]['html'] = $this->HTMLHeaderE['html'] ;
10654
+ }
10655
+ else {
10656
+ $this->saveHTMLHeader[$this->page][$OE]['html'] = $this->HTMLHeader['html'] ;
10657
+ }
10658
+ if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
10659
+ $this->saveHTMLHeader[$this->page][$OE]['rotate'] = true;
10660
+ $this->saveHTMLHeader[$this->page][$OE]['ml'] = $this->tMargin;
10661
+ $this->saveHTMLHeader[$this->page][$OE]['mr'] = $this->bMargin;
10662
+ $this->saveHTMLHeader[$this->page][$OE]['mh'] = $this->margin_header;
10663
+ $this->saveHTMLHeader[$this->page][$OE]['mf'] = $this->margin_footer;
10664
+ $this->saveHTMLHeader[$this->page][$OE]['pw'] = $this->h;
10665
+ $this->saveHTMLHeader[$this->page][$OE]['ph'] = $this->w;
10666
+ }
10667
+ else {
10668
+ $this->saveHTMLHeader[$this->page][$OE]['ml'] = $this->lMargin;
10669
+ $this->saveHTMLHeader[$this->page][$OE]['mr'] = $this->rMargin;
10670
+ $this->saveHTMLHeader[$this->page][$OE]['mh'] = $this->margin_header;
10671
+ $this->saveHTMLHeader[$this->page][$OE]['mf'] = $this->margin_footer;
10672
+ $this->saveHTMLHeader[$this->page][$OE]['pw'] = $this->w;
10673
+ $this->saveHTMLHeader[$this->page][$OE]['ph'] = $this->h;
10674
+ }
10675
+ }
10676
+
10677
+ function writeHTMLFooters() {
10678
+
10679
+ if ($this->mirrorMargins && ($this->page)%2==0) { $OE = 'E'; } // EVEN
10680
+ else { $OE = 'O'; }
10681
+ if ($OE == 'E') {
10682
+ $this->saveHTMLFooter[$this->page][$OE]['html'] = $this->HTMLFooterE['html'] ;
10683
+ }
10684
+ else {
10685
+ $this->saveHTMLFooter[$this->page][$OE]['html'] = $this->HTMLFooter['html'] ;
10686
+ }
10687
+ if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
10688
+ $this->saveHTMLFooter[$this->page][$OE]['rotate'] = true;
10689
+ $this->saveHTMLFooter[$this->page][$OE]['ml'] = $this->tMargin;
10690
+ $this->saveHTMLFooter[$this->page][$OE]['mr'] = $this->bMargin;
10691
+ $this->saveHTMLFooter[$this->page][$OE]['mt'] = $this->rMargin;
10692
+ $this->saveHTMLFooter[$this->page][$OE]['mb'] = $this->lMargin;
10693
+ $this->saveHTMLFooter[$this->page][$OE]['mh'] = $this->margin_header;
10694
+ $this->saveHTMLFooter[$this->page][$OE]['mf'] = $this->margin_footer;
10695
+ $this->saveHTMLFooter[$this->page][$OE]['pw'] = $this->h;
10696
+ $this->saveHTMLFooter[$this->page][$OE]['ph'] = $this->w;
10697
+ }
10698
+ else {
10699
+ $this->saveHTMLFooter[$this->page][$OE]['ml'] = $this->lMargin;
10700
+ $this->saveHTMLFooter[$this->page][$OE]['mr'] = $this->rMargin;
10701
+ $this->saveHTMLFooter[$this->page][$OE]['mt'] = $this->tMargin;
10702
+ $this->saveHTMLFooter[$this->page][$OE]['mb'] = $this->bMargin;
10703
+ $this->saveHTMLFooter[$this->page][$OE]['mh'] = $this->margin_header;
10704
+ $this->saveHTMLFooter[$this->page][$OE]['mf'] = $this->margin_footer;
10705
+ $this->saveHTMLFooter[$this->page][$OE]['pw'] = $this->w;
10706
+ $this->saveHTMLFooter[$this->page][$OE]['ph'] = $this->h;
10707
+ }
10708
+ }
10709
+
10710
+ function DefHeaderByName($name,$arr) {
10711
+ if (!$name) { $name = '_default'; }
10712
+ $this->pageheaders[$name] = $arr;
10713
+ }
10714
+
10715
+ function DefFooterByName($name,$arr) {
10716
+ if (!$name) { $name = '_default'; }
10717
+ $this->pagefooters[$name] = $arr;
10718
+ }
10719
+
10720
+ function SetHeaderByName($name,$side='O',$write=false) {
10721
+ if (!$name) { $name = '_default'; }
10722
+ if ($side=='E') { $this->headerDetails['even'] = $this->pageheaders[$name]; }
10723
+ else { $this->headerDetails['odd'] = $this->pageheaders[$name]; }
10724
+ if ($write) { $this->Header(); }
10725
+ }
10726
+
10727
+ function SetFooterByName($name,$side='O') {
10728
+ if (!$name) { $name = '_default'; }
10729
+ if ($side=='E') { $this->footerDetails['even'] = $this->pagefooters[$name]; }
10730
+ else { $this->footerDetails['odd'] = $this->pagefooters[$name]; }
10731
+ }
10732
+
10733
+ function DefHTMLHeaderByName($name,$html) {
10734
+ if (!$name) { $name = '_default'; }
10735
+
10736
+ $this->pageHTMLheaders[$name]['html'] = $html;
10737
+ $this->pageHTMLheaders[$name]['h'] = $this->_gethtmlheight($html);
10738
+ }
10739
+
10740
+ function DefHTMLFooterByName($name,$html) {
10741
+ if (!$name) { $name = '_default'; }
10742
+
10743
+ $this->pageHTMLfooters[$name]['html'] = $html;
10744
+ $this->pageHTMLfooters[$name]['h'] = $this->_gethtmlheight($html);
10745
+ }
10746
+
10747
+ function SetHTMLHeaderByName($name,$side='O',$write=false) {
10748
+ if (!$name) { $name = '_default'; }
10749
+ $this->SetHTMLHeader($this->pageHTMLheaders[$name],$side,$write);
10750
+ }
10751
+
10752
+ function SetHTMLFooterByName($name,$side='O') {
10753
+ if (!$name) { $name = '_default'; }
10754
+ $this->SetHTMLFooter($this->pageHTMLfooters[$name],$side,$write);
10755
+ }
10756
+
10757
+
10758
+ function SetHeader($Harray=array(),$side='',$write=false) {
10759
+ if (is_string($Harray)) {
10760
+ if (strlen($Harray)==0) {
10761
+ if ($side=='O') { $this->headerDetails['odd'] = array(); }
10762
+ else if ($side=='E') { $this->headerDetails['even'] = array(); }
10763
+ else { $this->headerDetails = array(); }
10764
+ }
10765
+ else if (strpos($Harray,'|') || strpos($Harray,'|')===0) {
10766
+ $hdet = explode('|',$Harray);
10767
+ $this->headerDetails = array (
10768
+ 'odd' => array (
10769
+ 'L' => array ('content' => $hdet[0], 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
10770
+ 'C' => array ('content' => $hdet[1], 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
10771
+ 'R' => array ('content' => $hdet[2], 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
10772
+ 'line' => $this->defaultheaderline,
10773
+ ),
10774
+ 'even' => array (
10775
+ 'R' => array ('content' => $hdet[0], 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
10776
+ 'C' => array ('content' => $hdet[1], 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
10777
+ 'L' => array ('content' => $hdet[2], 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
10778
+ 'line' => $this->defaultheaderline,
10779
+ )
10780
+ );
10781
+ }
10782
+ else {
10783
+ $this->headerDetails = array (
10784
+ 'odd' => array (
10785
+ 'R' => array ('content' => $Harray, 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
10786
+ 'line' => $this->defaultheaderline,
10787
+ ),
10788
+ 'even' => array (
10789
+ 'L' => array ('content' => $Harray, 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
10790
+ 'line' => $this->defaultheaderline,
10791
+ )
10792
+ );
10793
+ }
10794
+ }
10795
+ else if (is_array($Harray)) {
10796
+ if ($side=='O') { $this->headerDetails['odd'] = $Harray; }
10797
+ else if ($side=='E') { $this->headerDetails['even'] = $Harray; }
10798
+ else { $this->headerDetails = $Harray; }
10799
+ }
10800
+ // Overwrite any HTML Header previously set
10801
+ if ($side=='E') { $this->SetHTMLHeader('','E'); }
10802
+ else if ($side=='O') { $this->SetHTMLHeader(''); }
10803
+ else {
10804
+ $this->SetHTMLHeader('');
10805
+ $this->SetHTMLHeader('','E');
10806
+ }
10807
+
10808
+ if ($write) {
10809
+ $save_y = $this->y;
10810
+ $this->Header();
10811
+ $this->SetY($save_y) ;
10812
+ }
10813
+ }
10814
+
10815
+
10816
+
10817
+
10818
+ function SetFooter($Farray=array(),$side='') {
10819
+ if (is_string($Farray)) {
10820
+ if (strlen($Farray)==0) {
10821
+ if ($side=='O') { $this->footerDetails['odd'] = array(); }
10822
+ else if ($side=='E') { $this->footerDetails['even'] = array(); }
10823
+ else { $this->footerDetails = array(); }
10824
+ }
10825
+ else if (strpos($Farray,'|') || strpos($Farray,'|')===0) {
10826
+ $fdet = explode('|',$Farray);
10827
+ $this->footerDetails = array (
10828
+ 'odd' => array (
10829
+ 'L' => array ('content' => $fdet[0], 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
10830
+ 'C' => array ('content' => $fdet[1], 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
10831
+ 'R' => array ('content' => $fdet[2], 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
10832
+ 'line' => $this->defaultfooterline,
10833
+ ),
10834
+ 'even' => array (
10835
+ 'R' => array ('content' => $fdet[0], 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
10836
+ 'C' => array ('content' => $fdet[1], 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
10837
+ 'L' => array ('content' => $fdet[2], 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
10838
+ 'line' => $this->defaultfooterline,
10839
+ )
10840
+ );
10841
+ }
10842
+ else {
10843
+ $this->footerDetails = array (
10844
+ 'odd' => array (
10845
+ 'R' => array ('content' => $Farray, 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
10846
+ 'line' => $this->defaultfooterline,
10847
+ ),
10848
+ 'even' => array (
10849
+ 'L' => array ('content' => $Farray, 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
10850
+ 'line' => $this->defaultfooterline,
10851
+ )
10852
+ );
10853
+ }
10854
+ }
10855
+ else if (is_array($Farray)) {
10856
+ if ($side=='O') { $this->footerDetails['odd'] = $Farray; }
10857
+ else if ($side=='E') { $this->footerDetails['even'] = $Farray; }
10858
+ else { $this->footerDetails = $Farray; }
10859
+ }
10860
+ // Overwrite any HTML Footer previously set
10861
+ if ($side=='E') { $this->SetHTMLFooter('','E'); }
10862
+ else if ($side=='O') { $this->SetHTMLFooter(''); }
10863
+ else {
10864
+ $this->SetHTMLFooter('');
10865
+ $this->SetHTMLFooter('','E');
10866
+ }
10867
+ }
10868
+
10869
+
10870
+
10871
+ //Page footer
10872
+ function Footer() {
10873
+ // PAGED MEDIA - CROP / CROSS MARKS from @PAGE
10874
+ if ($this->show_marks == 'CROP' || $this->show_marks == 'CROPCROSS') {
10875
+ // Show TICK MARKS
10876
+ $this->SetLineWidth(0.1); // = 0.1 mm
10877
+ $this->SetDColor($this->ConvertColor(0));
10878
+ $l = $this->cropMarkLength;
10879
+ $m = $this->cropMarkMargin; // Distance of crop mark from margin
10880
+ $b = $this->nonPrintMargin; // Non-printable border at edge of paper sheet
10881
+ $ax1 = $b;
10882
+ $bx = $this->page_box['outer_width_LR'] - $m;
10883
+ $ax = max($ax1, $bx-$l);
10884
+ $cx1 = $this->w - $b;
10885
+ $dx = $this->w - $this->page_box['outer_width_LR'] + $m;
10886
+ $cx = min($cx1, $dx+$l);
10887
+ $ay1 = $b;
10888
+ $by = $this->page_box['outer_width_TB'] - $m;
10889
+ $ay = max($ay1, $by-$l);
10890
+ $cy1 = $this->h - $b;
10891
+ $dy = $this->h - $this->page_box['outer_width_TB'] + $m;
10892
+ $cy = min($cy1, $dy+$l);
10893
+
10894
+ $this->Line($ax, $this->page_box['outer_width_TB'], $bx, $this->page_box['outer_width_TB']);
10895
+ $this->Line($cx, $this->page_box['outer_width_TB'], $dx, $this->page_box['outer_width_TB']);
10896
+ $this->Line($ax, $this->h - $this->page_box['outer_width_TB'], $bx, $this->h - $this->page_box['outer_width_TB']);
10897
+ $this->Line($cx, $this->h - $this->page_box['outer_width_TB'], $dx, $this->h - $this->page_box['outer_width_TB']);
10898
+ $this->Line($this->page_box['outer_width_LR'], $ay, $this->page_box['outer_width_LR'], $by);
10899
+ $this->Line($this->page_box['outer_width_LR'], $cy, $this->page_box['outer_width_LR'], $dy);
10900
+ $this->Line($this->w - $this->page_box['outer_width_LR'], $ay, $this->w - $this->page_box['outer_width_LR'], $by);
10901
+ $this->Line($this->w - $this->page_box['outer_width_LR'], $cy, $this->w - $this->page_box['outer_width_LR'], $dy);
10902
+
10903
+ if ($this->printers_info) {
10904
+ $hd = date('Y-m-d H:i').' Page '.$this->page.' of {nb}';
10905
+ $this->SetTColor($this->ConvertColor(0));
10906
+ $this->SetFont('arial','',7.5,true,true);
10907
+ $this->x = $this->page_box['outer_width_LR'] + 1.5;
10908
+ $this->y = 1;
10909
+ $this->Cell($headerpgwidth ,$this->FontSize,$hd,0,0,'L',0,'',0,0,0,'M');
10910
+ $this->SetFont($this->default_font,'',$this->original_default_font_size);
10911
+ }
10912
+
10913
+ }
10914
+ if ($this->show_marks == 'CROSS' || $this->show_marks == 'CROPCROSS') {
10915
+ $this->SetLineWidth(0.1); // = 0.1 mm
10916
+ $this->SetDColor($this->ConvertColor(0));
10917
+ $l = 14 /2; // longer length of the cross line (half)
10918
+ $w = 6 /2; // shorter width of the cross line (half)
10919
+ $r = 1.2; // radius of circle
10920
+ $m = $this->crossMarkMargin; // Distance of cross mark from margin
10921
+ $x1 = $this->page_box['outer_width_LR'] - $m;
10922
+ $x2 = $this->w - $this->page_box['outer_width_LR'] + $m;
10923
+ $y1 = $this->page_box['outer_width_TB'] - $m;
10924
+ $y2 = $this->h - $this->page_box['outer_width_TB'] + $m;
10925
+ // Left
10926
+ $this->Circle($x1, $this->h/2, $r, 'S') ;
10927
+ $this->Line($x1-$w, $this->h/2, $x1+$w, $this->h/2);
10928
+ $this->Line($x1, $this->h/2-$l, $x1, $this->h/2+$l);
10929
+ // Right
10930
+ $this->Circle($x2, $this->h/2, $r, 'S') ;
10931
+ $this->Line($x2-$w, $this->h/2, $x2+$w, $this->h/2);
10932
+ $this->Line($x2, $this->h/2-$l, $x2, $this->h/2+$l);
10933
+ // Top
10934
+ $this->Circle($this->w/2, $y1, $r, 'S') ;
10935
+ $this->Line($this->w/2, $y1-$w, $this->w/2, $y1+$w);
10936
+ $this->Line($this->w/2-$l, $y1, $this->w/2+$l, $y1);
10937
+ // Bottom
10938
+ $this->Circle($this->w/2, $y2, $r, 'S') ;
10939
+ $this->Line($this->w/2, $y2-$w, $this->w/2, $y2+$w);
10940
+ $this->Line($this->w/2-$l, $y2, $this->w/2+$l, $y2);
10941
+ }
10942
+
10943
+
10944
+ // If @page set non-HTML headers/footers named, they were not read until later in the HTML code - so now set them
10945
+ if ($this->page==1) {
10946
+ if ($this->firstPageBoxHeader) {
10947
+ $this->headerDetails['odd'] = $this->pageheaders[$this->firstPageBoxHeader];
10948
+ $this->Header();
10949
+ }
10950
+ if ($this->firstPageBoxFooter) {
10951
+ $this->footerDetails['odd'] = $this->pagefooters[$this->firstPageBoxFooter];
10952
+ }
10953
+ $this->firstPageBoxHeader='';
10954
+ $this->firstPageBoxFooter='';
10955
+ }
10956
+
10957
+
10958
+
10959
+ if (($this->mirrorMargins && ($this->page%2==0) && $this->HTMLFooterE) || ($this->mirrorMargins && ($this->page%2==1) && $this->HTMLFooter) || (!$this->mirrorMargins && $this->HTMLFooter)) {
10960
+ $this->writeHTMLFooters();
10961
+ return;
10962
+ }
10963
+
10964
+ $this->processingHeader=true;
10965
+ $this->ResetMargins(); // necessary after columns
10966
+ $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
10967
+ $h = $this->footerDetails;
10968
+ if(count($h)) {
10969
+
10970
+ if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
10971
+ $this->_out(sprintf('q 0 -1 1 0 0 %.3F cm ',($this->h*_MPDFK)));
10972
+ $headerpgwidth = $this->h - $this->orig_lMargin - $this->orig_rMargin;
10973
+ if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
10974
+ $headerlmargin = $this->orig_rMargin;
10975
+ }
10976
+ else {
10977
+ $headerlmargin = $this->orig_lMargin;
10978
+ }
10979
+ }
10980
+ else {
10981
+ $yadj = 0;
10982
+ $headerpgwidth = $this->pgwidth;
10983
+ $headerlmargin = $this->lMargin;
10984
+ }
10985
+ $this->SetY(-$this->margin_footer);
10986
+
10987
+ $this->SetTColor($this->ConvertColor(0));
10988
+ $this->SUP = false;
10989
+ $this->SUB = false;
10990
+ $this->bullet = false;
10991
+
10992
+ // only show pagenumber if numbering on
10993
+ $pgno = $this->docPageNum($this->page, true);
10994
+
10995
+ if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
10996
+ $side = 'even';
10997
+ }
10998
+ else { // ODD // OR NOT MIRRORING MARGINS/FOOTERS = DEFAULT
10999
+ $side = 'odd';
11000
+ }
11001
+ $maxfontheight = 0;
11002
+ foreach(array('L','C','R') AS $pos) {
11003
+ if (isset($h[$side][$pos]['content']) && $h[$side][$pos]['content']) {
11004
+ if (isset($h[$side][$pos]['font-size']) && $h[$side][$pos]['font-size']) { $hfsz = $h[$side][$pos]['font-size']; }
11005
+ else { $hfsz = $this->default_font_size; }
11006
+ $maxfontheight = max($maxfontheight,$hfsz);
11007
+ }
11008
+ }
11009
+ // LEFT-CENTER-RIGHT
11010
+ foreach(array('L','C','R') AS $pos) {
11011
+ if (isset($h[$side][$pos]['content']) && $h[$side][$pos]['content']) {
11012
+ $hd = str_replace('{PAGENO}',$pgno,$h[$side][$pos]['content']);
11013
+ $hd = str_replace($this->aliasNbPgGp,$this->nbpgPrefix.$this->aliasNbPgGp.$this->nbpgSuffix,$hd);
11014
+ $hd = preg_replace('/\{DATE\s+(.*?)\}/e',"date('\\1')",$hd);
11015
+ if (isset($h[$side][$pos]['font-family']) && $h[$side][$pos]['font-family']) { $hff = $h[$side][$pos]['font-family']; }
11016
+ else { $hff = $this->original_default_font; }
11017
+ if (isset($h[$side][$pos]['font-size']) && $h[$side][$pos]['font-size']) { $hfsz = $h[$side][$pos]['font-size']; }
11018
+ else { $hfsz = $this->original_default_font_size; }
11019
+ $maxfontheight = max($maxfontheight,$hfsz);
11020
+ if (isset($h[$side][$pos]['font-style']) && $h[$side][$pos]['font-style']) { $hfst = $h[$side][$pos]['font-style']; }
11021
+ else { $hfst = ''; }
11022
+ if (isset($h[$side][$pos]['color']) && $h[$side][$pos]['color']) {
11023
+ $hfcol = $h[$side][$pos]['color'];
11024
+ $cor = $this->ConvertColor($hfcol);
11025
+ if ($cor) { $this->SetTColor($cor); }
11026
+ }
11027
+ else { $hfcol = ''; }
11028
+ $this->SetFont($hff,$hfst,$hfsz,true,true);
11029
+ $this->x = $headerlmargin ;
11030
+ $this->y = $this->h - $this->margin_footer - ($maxfontheight/_MPDFK);
11031
+ $hd = $this->purify_utf8_text($hd);
11032
+ if ($this->text_input_as_HTML) {
11033
+ $hd = $this->all_entities_to_utf8($hd);
11034
+ }
11035
+ // CONVERT CODEPAGE
11036
+ if ($this->usingCoreFont) { $hd = mb_convert_encoding($hd,$this->mb_enc,'UTF-8'); }
11037
+ // DIRECTIONALITY RTL
11038
+ // Font-specific ligature substitution for Indic fonts
11039
+ $align = $pos;
11040
+ if ($this->directionality == 'rtl') {
11041
+ if ($pos == 'L') { $align = 'R'; }
11042
+ else if ($pos == 'R') { $align = 'L'; }
11043
+ }
11044
+
11045
+ if ($pos!='L' && (strpos($hd,$this->aliasNbPg)!==false || strpos($hd,$this->aliasNbPgGp)!==false)) {
11046
+ if (strpos($hd,$this->aliasNbPgGp)!==false) { $type= 'nbpggp'; } else { $type= 'nbpg'; }
11047
+ $this->_out('{mpdfheader'.$type.' '.$pos.' ff='.$hff.' fs='.$hfst.' fz='.$hfsz.'}');
11048
+ $this->Cell($headerpgwidth ,$maxfontheight/_MPDFK ,$hd,0,0,$align,0,'',0,0,0,'M');
11049
+ $this->_out('Q');
11050
+ }
11051
+ else {
11052
+ $this->Cell($headerpgwidth ,$maxfontheight/_MPDFK ,$hd,0,0,$align,0,'',0,0,0,'M');
11053
+ }
11054
+ if ($hfcol) { $this->SetTColor($this->ConvertColor(0)); }
11055
+ }
11056
+ }
11057
+ // Return Font to normal
11058
+ $this->SetFont($this->default_font,'',$this->original_default_font_size);
11059
+
11060
+ // LINE
11061
+
11062
+ if (isset($h[$side]['line']) && $h[$side]['line']) {
11063
+ $this->SetLineWidth(0.1);
11064
+ $this->SetDColor($this->ConvertColor(0));
11065
+ $this->Line($headerlmargin , $this->y-($maxfontheight*($this->footer_line_spacing)/_MPDFK), $headerlmargin +$headerpgwidth, $this->y-($maxfontheight*($this->footer_line_spacing)/_MPDFK));
11066
+ }
11067
+ if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
11068
+ $this->_out('Q');
11069
+ }
11070
+ }
11071
+ $this->processingHeader=false;
11072
+
11073
+ }
11074
+
11075
+ ///////////////////
11076
+ // HYPHENATION
11077
+ ///////////////////
11078
+ // mPDF 5.6.21
11079
+ // Hard hyphens
11080
+ function hardHyphenate($word, $maxWidth) {
11081
+ // Don't hyphenate web addresses
11082
+ if (preg_match('/^(http:|www\.)/',$word)) { return array(false,'','',''); }
11083
+
11084
+ // Get dictionary
11085
+ $poss = array();
11086
+ $softhyphens = array();
11087
+ $offset = 0;
11088
+ $p = true;
11089
+ if ($this->usingCoreFont) {
11090
+ $wl = strlen($word);
11091
+ }
11092
+ else {
11093
+ $wl = mb_strlen($word,'UTF-8');
11094
+ }
11095
+ while($offset < $wl) {
11096
+ if (!$this->usingCoreFont) {
11097
+ $p = mb_strpos($word, "-", $offset, 'UTF-8');
11098
+ }
11099
+ else if ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
11100
+ $p = strpos($word, "-", $offset);
11101
+ }
11102
+ if ($p !== false) { $poss[] = $p - count($poss); }
11103
+ else { break; }
11104
+ $offset = $p+1;
11105
+ }
11106
+ $success = false;
11107
+ foreach($poss AS $i) {
11108
+ if ($this->usingCoreFont) {
11109
+ $a = substr($word,0,$i);
11110
+ if ($this->GetStringWidth($a.'-') > $maxWidth) { break ; }
11111
+ $pre = $a;
11112
+ $post = substr($word,$i,strlen($word));
11113
+ $prelength = strlen($pre);
11114
+ }
11115
+ else {
11116
+ $a = mb_substr($word,0,$i,'UTF-8');
11117
+ if ($this->GetStringWidth($a.'-') > $maxWidth) { break ; }
11118
+ $pre = $a;
11119
+ $post = mb_substr($word,$i,mb_strlen($word,'UTF-8'),'UTF-8');
11120
+ $prelength = mb_strlen($pre, 'UTF-8');
11121
+ }
11122
+ $success = true;
11123
+ }
11124
+ return array($success,$pre,$post,$prelength);
11125
+ }
11126
+
11127
+
11128
+
11129
+
11130
+ ///////////////////
11131
+ /// HTML parser ///
11132
+ ///////////////////
11133
+ function WriteHTML($html,$sub=0,$init=true,$close=true) {
11134
+ // $sub ADDED - 0 = default; 1=headerCSS only; 2=HTML body (parts) only; 3 - HTML parses only
11135
+ // 4 - writes HTML headers
11136
+ // $close Leaves buffers etc. in current state, so that it can continue a block etc.
11137
+ // $init - Clears and sets buffers to Top level block etc.
11138
+
11139
+ if (empty($html)) { $html = ''; }
11140
+
11141
+ if ($init) {
11142
+ $this->headerbuffer='';
11143
+ $this->textbuffer = array();
11144
+ $this->fixedPosBlockSave = array();
11145
+ }
11146
+ if ($sub == 1) { $html = '<style> '.$html.' </style>'; } // stylesheet only
11147
+
11148
+ if ($this->allow_charset_conversion) {
11149
+ if ($sub < 1) {
11150
+ $this->ReadCharset($html);
11151
+ }
11152
+ if ($this->charset_in && $sub!=4) { // mPDF 5.4.14
11153
+ $success = iconv($this->charset_in,'UTF-8//TRANSLIT',$html);
11154
+ if ($success) { $html = $success; }
11155
+ }
11156
+ }
11157
+ $html = $this->purify_utf8($html,false);
11158
+ if ($init) {
11159
+ $this->blklvl = 0;
11160
+ $this->lastblocklevelchange = 0;
11161
+ $this->blk = array();
11162
+ $this->initialiseBlock($this->blk[0]);
11163
+ $this->blk[0]['width'] =& $this->pgwidth;
11164
+ $this->blk[0]['inner_width'] =& $this->pgwidth;
11165
+ $this->blk[0]['blockContext'] = $this->blockContext;
11166
+ }
11167
+
11168
+ $zproperties = array();
11169
+ if ($sub < 2) {
11170
+ $this->ReadMetaTags($html);
11171
+
11172
+ // mPDF 5.6.18
11173
+ if (preg_match('/<base[^>]*href=["\']([^"\'>]*)["\']/i', $html, $m)) {
11174
+ $this->SetBasePath($m[1]);
11175
+ }
11176
+ // NB default stylesheet now in mPDF.css - read on initialising class
11177
+ $html = $this->cssmgr->ReadCSS($html);
11178
+
11179
+ if ($this->useLang && !$this->usingCoreFont && preg_match('/<html [^>]*lang=[\'\"](.*?)[\'\"]/ism',$html,$m)) {
11180
+ $html_lang = $m[1];
11181
+ }
11182
+
11183
+ if (preg_match('/<html [^>]*dir=[\'\"]\s*rtl\s*[\'\"]/ism',$html)) {
11184
+ $zproperties['DIRECTION'] = 'rtl';
11185
+ }
11186
+
11187
+ // allow in-line CSS for body tag to be parsed // Get <body> tag inline CSS
11188
+ if (preg_match('/<body([^>]*)>(.*?)<\/body>/ism',$html,$m) || preg_match('/<body([^>]*)>(.*)$/ism',$html,$m)) {
11189
+ $html = $m[2];
11190
+ // Changed to allow style="background: url('bg.jpg')"
11191
+ if (preg_match('/style=[\"](.*?)[\"]/ism',$m[1],$mm) || preg_match('/style=[\'](.*?)[\']/ism',$m[1],$mm)) {
11192
+ $zproperties = $this->cssmgr->readInlineCSS($mm[1]);
11193
+ }
11194
+ if (preg_match('/dir=[\'\"]\s*rtl\s*[\'\"]/ism',$m[1])) {
11195
+ $zproperties['DIRECTION'] = 'rtl';
11196
+ }
11197
+ if (isset($html_lang) && $html_lang) { $zproperties['LANG'] = $html_lang; }
11198
+ if ($this->useLang && !$this->onlyCoreFonts && preg_match('/lang=[\'\"](.*?)[\'\"]/ism',$m[1],$mm)) {
11199
+ $zproperties['LANG'] = $mm[1];
11200
+ }
11201
+
11202
+ }
11203
+ }
11204
+ $properties = $this->cssmgr->MergeCSS('BLOCK','BODY','');
11205
+ if ($zproperties) { $properties = $this->cssmgr->array_merge_recursive_unique($properties,$zproperties); }
11206
+
11207
+ if (isset($properties['DIRECTION']) && $properties['DIRECTION']) {
11208
+ $this->cssmgr->CSS['BODY']['DIRECTION'] = $properties['DIRECTION'];
11209
+ }
11210
+ if (!isset($this->cssmgr->CSS['BODY']['DIRECTION'])) {
11211
+ $this->cssmgr->CSS['BODY']['DIRECTION'] = $this->directionality;
11212
+ }
11213
+ else { $this->SetDirectionality($this->cssmgr->CSS['BODY']['DIRECTION']); }
11214
+
11215
+ $this->setCSS($properties,'','BODY');
11216
+ $this->blk[0]['InlineProperties'] = $this->saveInlineProperties();
11217
+
11218
+ if ($sub == 1) { return ''; }
11219
+ if (!isset($this->cssmgr->CSS['BODY'])) { $this->cssmgr->CSS['BODY'] = array(); }
11220
+
11221
+ if (isset($properties['BACKGROUND-GRADIENT'])) {
11222
+ $this->bodyBackgroundGradient = $properties['BACKGROUND-GRADIENT'];
11223
+ }
11224
+
11225
+ if (isset($properties['BACKGROUND-IMAGE']) && $properties['BACKGROUND-IMAGE']) {
11226
+ $ret = $this->SetBackground($properties, $this->pgwidth);
11227
+ if ($ret) { $this->bodyBackgroundImage = $ret; }
11228
+ }
11229
+
11230
+ // If page-box is set
11231
+ if ($this->state==0 && isset($this->cssmgr->CSS['@PAGE']) && $this->cssmgr->CSS['@PAGE'] ) {
11232
+ $this->page_box['current'] = '';
11233
+ $this->page_box['using'] = true;
11234
+ list($pborientation,$pbmgl,$pbmgr,$pbmgt,$pbmgb,$pbmgh,$pbmgf,$hname,$fname,$bg,$resetpagenum,$pagenumstyle,$suppress,$marks,$newformat) = $this->SetPagedMediaCSS('', false, 'O');
11235
+ $this->DefOrientation = $this->CurOrientation = $pborientation;
11236
+ $this->orig_lMargin = $this->DeflMargin = $pbmgl;
11237
+ $this->orig_rMargin = $this->DefrMargin = $pbmgr;
11238
+ $this->orig_tMargin = $this->tMargin = $pbmgt;
11239
+ $this->orig_bMargin = $this->bMargin = $pbmgb;
11240
+ $this->orig_hMargin = $this->margin_header = $pbmgh;
11241
+ $this->orig_fMargin = $this->margin_footer = $pbmgf;
11242
+ list($pborientation,$pbmgl,$pbmgr,$pbmgt,$pbmgb,$pbmgh,$pbmgf,$hname,$fname,$bg,$resetpagenum,$pagenumstyle,$suppress,$marks,$newformat) = $this->SetPagedMediaCSS('', true, 'O'); // first page
11243
+ $this->show_marks = $marks;
11244
+ if ($hname && !preg_match('/^html_(.*)$/i',$hname)) $this->firstPageBoxHeader = $hname;
11245
+ if ($fname && !preg_match('/^html_(.*)$/i',$fname)) $this->firstPageBoxFooter = $fname;
11246
+ }
11247
+
11248
+ $parseonly = false;
11249
+ $this->bufferoutput = false;
11250
+ if ($sub == 3) {
11251
+ $parseonly = true;
11252
+ // Close any open block tags
11253
+ for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag']); }
11254
+ // Output any text left in buffer
11255
+ if (count($this->textbuffer)) { $this->printbuffer($this->textbuffer); }
11256
+ $this->textbuffer=array();
11257
+ }
11258
+ else if ($sub == 4) {
11259
+ // Close any open block tags
11260
+ for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag']); }
11261
+ // Output any text left in buffer
11262
+ if (count($this->textbuffer)) { $this->printbuffer($this->textbuffer); }
11263
+ $this->bufferoutput = true;
11264
+ $this->textbuffer=array();
11265
+ $this->headerbuffer='';
11266
+ $properties = $this->cssmgr->MergeCSS('BLOCK','BODY','');
11267
+ $this->setCSS($properties,'','BODY');
11268
+ }
11269
+
11270
+ mb_internal_encoding('UTF-8');
11271
+
11272
+ $html = $this->AdjustHTML($html, $this->tabSpaces); //Try to make HTML look more like XHTML
11273
+
11274
+ if ($this->autoFontGroups) { $html = $this->AutoFont($html); }
11275
+
11276
+ preg_match_all('/<htmlpageheader([^>]*)>(.*?)<\/htmlpageheader>/si',$html,$h);
11277
+ for($i=0;$i<count($h[1]);$i++) {
11278
+ if (preg_match('/name=[\'|\"](.*?)[\'|\"]/',$h[1][$i],$n)) {
11279
+ $this->pageHTMLheaders[$n[1]]['html'] = $h[2][$i];
11280
+ $this->pageHTMLheaders[$n[1]]['h'] = $this->_gethtmlheight($h[2][$i]);
11281
+ }
11282
+ }
11283
+ preg_match_all('/<htmlpagefooter([^>]*)>(.*?)<\/htmlpagefooter>/si',$html,$f);
11284
+ for($i=0;$i<count($f[1]);$i++) {
11285
+ if (preg_match('/name=[\'|\"](.*?)[\'|\"]/',$f[1][$i],$n)) {
11286
+ $this->pageHTMLfooters[$n[1]]['html'] = $f[2][$i];
11287
+ $this->pageHTMLfooters[$n[1]]['h'] = $this->_gethtmlheight($f[2][$i]);
11288
+ }
11289
+ }
11290
+ $html = preg_replace('/<htmlpageheader.*?<\/htmlpageheader>/si','',$html);
11291
+ $html = preg_replace('/<htmlpagefooter.*?<\/htmlpagefooter>/si','',$html);
11292
+
11293
+ if($this->state==0 && $sub!=1 && $sub!=3 && $sub!=4) {
11294
+ $this->AddPage($this->CurOrientation);
11295
+ }
11296
+
11297
+
11298
+
11299
+ if (isset($hname) && preg_match('/^html_(.*)$/i',$hname,$n)) $this->SetHTMLHeader($this->pageHTMLheaders[$n[1]],'O',true);
11300
+ if (isset($fname) && preg_match('/^html_(.*)$/i',$fname,$n)) $this->SetHTMLFooter($this->pageHTMLfooters[$n[1]],'O');
11301
+
11302
+
11303
+ $html=str_replace('<?','< ',$html); //Fix '<?XML' bug from HTML code generated by MS Word
11304
+
11305
+ $this->checkSIP = false;
11306
+ $this->checkSMP = false;
11307
+ $this->checkCJK = false;
11308
+ if ($this->onlyCoreFonts) { $html = $this->SubstituteChars($html); }
11309
+ else {
11310
+ if (preg_match("/([\x{20000}-\x{2FFFF}])/u", $html)) { $this->checkSIP = true; }
11311
+ if (preg_match("/([\x{10000}-\x{1FFFF}])/u", $html)) { $this->checkSMP = true; }
11312
+ }
11313
+
11314
+ // Don't allow non-breaking spaces that are converted to substituted chars or will break anyway and mess up table width calc.
11315
+ $html = str_replace('<tta>160</tta>',chr(32),$html);
11316
+ $html = str_replace('</tta><tta>','|',$html);
11317
+ $html = str_replace('</tts><tts>','|',$html);
11318
+ $html = str_replace('</ttz><ttz>','|',$html);
11319
+
11320
+ //Add new supported tags in the DisableTags function
11321
+ $html=strip_tags($html,$this->enabledtags); //remove all unsupported tags, but the ones inside the 'enabledtags' string
11322
+
11323
+ //Explode the string in order to parse the HTML code
11324
+ $a=preg_split('/<(.*?)>/ms',$html,-1,PREG_SPLIT_DELIM_CAPTURE);
11325
+ // ? more accurate regexp that allows e.g. <a name="Silly <name>">
11326
+ // if changing - also change in fn.SubstituteChars()
11327
+ // $a = preg_split ('/<((?:[^<>]+(?:"[^"]*"|\'[^\']*\')?)+)>/ms', $html, -1, PREG_SPLIT_DELIM_CAPTURE);
11328
+
11329
+ if ($this->mb_enc) {
11330
+ mb_internal_encoding($this->mb_enc);
11331
+ }
11332
+ $pbc = 0;
11333
+ $this->subPos = -1;
11334
+ $cnt = count($a);
11335
+ for($i=0;$i<$cnt; $i++) {
11336
+ $e = $a[$i];
11337
+ if($i%2==0) {
11338
+ //TEXT
11339
+ if ($this->blk[$this->blklvl]['hide']) { continue; }
11340
+ if ($this->inlineDisplayOff) { continue; }
11341
+ if ($this->inMeter) { continue; } // mPDF 5.5.09
11342
+
11343
+ if ($this->inFixedPosBlock) { $this->fixedPosBlock .= $e; continue; } // *CSS-POSITION*
11344
+ if (strlen($e) == 0) { continue; }
11345
+
11346
+ $e = strcode2utf($e);
11347
+ $e = $this->lesser_entity_decode($e);
11348
+
11349
+ if ($this->usingCoreFont) {
11350
+ // If core font is selected in document which is not onlyCoreFonts - substitute with non-core font
11351
+ if ($this->useSubstitutions && !$this->onlyCoreFonts && $this->subPos<$i && !$this->specialcontent) {
11352
+ $cnt += $this->SubstituteCharsNonCore($a, $i, $e);
11353
+ }
11354
+ // CONVERT ENCODING
11355
+ $e = mb_convert_encoding($e,$this->mb_enc,'UTF-8');
11356
+ // mPDF 5.6.41
11357
+ if ($this->toupper) { $e = mb_strtoupper($e,$this->mb_enc); }
11358
+ if ($this->tolower) { $e = mb_strtolower($e,$this->mb_enc); }
11359
+ if ($this->capitalize) { $e = mb_convert_case($e, MB_CASE_TITLE, "UTF-8"); }
11360
+ }
11361
+ else {
11362
+ if ($this->checkSIP && $this->CurrentFont['sipext'] && $this->subPos<$i && !$this->specialcontent) {
11363
+ $cnt += $this->SubstituteCharsSIP($a, $i, $e);
11364
+ }
11365
+
11366
+ if ($this->useSubstitutions && !$this->onlyCoreFonts && $this->CurrentFont['type']!='Type0' && $this->subPos<$i && !$this->specialcontent) {
11367
+ // mPDF 5.6.62 removes U+200E/U+200F LTR and RTL mark and U+200C/U+200D Zero-width Joiner and Non-joiner
11368
+ $e = preg_replace("/[\xe2\x80\x8c\xe2\x80\x8d\xe2\x80\x8e\xe2\x80\x8f]/u",'',$e);
11369
+ $cnt += $this->SubstituteCharsMB($a, $i, $e);
11370
+ }
11371
+ // Font-specific ligature substitution for Indic fonts
11372
+
11373
+ // mPDF 5.6.62 removes U+200E/U+200F LTR and RTL mark and U+200C/U+200D Zero-width Joiner and Non-joiner
11374
+ $e = preg_replace("/[\xe2\x80\x8c\xe2\x80\x8d\xe2\x80\x8e\xe2\x80\x8f]/u",'',$e);
11375
+
11376
+ if ($this->toupper) { $e = mb_strtoupper($e,$this->mb_enc); }
11377
+ if ($this->tolower) { $e = mb_strtolower($e,$this->mb_enc); }
11378
+ if ($this->capitalize) { $e = mb_convert_case($e, MB_CASE_TITLE, "UTF-8"); }
11379
+ }
11380
+ if (($this->tts) || ($this->ttz) || ($this->tta)) {
11381
+ $es = explode('|',$e);
11382
+ $e = '';
11383
+ foreach($es AS $val) {
11384
+ $e .= chr($val);
11385
+ }
11386
+ }
11387
+ //Adjust lineheight
11388
+
11389
+ // FORM ELEMENTS
11390
+ if ($this->specialcontent) {
11391
+ }
11392
+
11393
+ // TABLE
11394
+ else if ($this->tableLevel) {
11395
+ if ($this->tdbegin) {
11396
+ if (($this->ignorefollowingspaces) && !$this->ispre) { $e = ltrim($e); }
11397
+ if ($e || $e==='0') {
11398
+ if (($this->blockjustfinished || $this->listjustfinished) && $this->cell[$this->row][$this->col]['s']>0) {
11399
+ $this->_saveCellTextBuffer("\n");
11400
+ if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
11401
+ $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
11402
+ }
11403
+ elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
11404
+ $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
11405
+ }
11406
+ $this->cell[$this->row][$this->col]['s'] = 0;// reset
11407
+ }
11408
+ $this->blockjustfinished=false;
11409
+ $this->listjustfinished=false;
11410
+
11411
+ $this->_saveCellTextBuffer($e, $this->HREF);
11412
+
11413
+ if (!isset($this->cell[$this->row][$this->col]['R']) || !$this->cell[$this->row][$this->col]['R']) {
11414
+ if (isset($this->cell[$this->row][$this->col]['s'])) {
11415
+ $this->cell[$this->row][$this->col]['s'] += $this->GetStringWidth($e, false);
11416
+ }
11417
+ else { $this->cell[$this->row][$this->col]['s'] = $this->GetStringWidth($e, false); }
11418
+ if (!empty($this->spanborddet)) {
11419
+ $this->cell[$this->row][$this->col]['s'] += $this->spanborddet['L']['w'] + $this->spanborddet['R']['w'];
11420
+ }
11421
+ }
11422
+
11423
+
11424
+ // mPDF 5.6.13 Decimal mark alignment
11425
+ if (substr($this->cell[$this->row][$this->col]['a'],0,1) == 'D') {
11426
+ $dp = $this->decimal_align[substr($this->cell[$this->row][$this->col]['a'],0,2)];
11427
+ $s = preg_split('/'.preg_quote($dp,'/').'/', $e, 2); // ? needs to be /u if not core
11428
+ $s0 = $this->GetStringWidth($s[0], false);
11429
+ if ($s[1]) { $s1 = $this->GetStringWidth(($s[1].$dp), false); }
11430
+ else $s1 = 0;
11431
+ if (!isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs0'])) {
11432
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs0'] = $s0;
11433
+ }
11434
+ else {
11435
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs0'] = max($s0, $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs0']);
11436
+ }
11437
+ if (!isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs1'])) {
11438
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs1'] = $s1;
11439
+ }
11440
+ else {
11441
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs1'] = max($s1, $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs1']);
11442
+ }
11443
+ }
11444
+
11445
+ if ($this->tableLevel==1 && $this->useGraphs) {
11446
+ $this->graphs[$this->currentGraphId]['data'][$this->row][$this->col] = $e;
11447
+ }
11448
+ $this->nestedtablejustfinished = false;
11449
+ $this->linebreakjustfinished=false;
11450
+ }
11451
+ }
11452
+ }
11453
+ // ALL ELSE
11454
+ else {
11455
+ if ($this->ignorefollowingspaces and !$this->ispre) { $e = ltrim($e); }
11456
+ if ($e || $e==='0') $this->_saveTextBuffer($e, $this->HREF);
11457
+ }
11458
+ }
11459
+
11460
+
11461
+ else { // TAG **
11462
+
11463
+ if($e[0]=='/') {
11464
+
11465
+
11466
+ // Check for tags where HTML specifies optional end tags,
11467
+ // and/or does not allow nesting e.g. P inside P, or
11468
+ $endtag = trim(strtoupper(substr($e,1))); // mPDF 5.4.20
11469
+ if($this->blk[$this->blklvl]['hide']) {
11470
+ if (in_array($endtag, $this->outerblocktags) || in_array($endtag, $this->innerblocktags)) {
11471
+ unset($this->blk[$this->blklvl]);
11472
+ $this->blklvl--;
11473
+ }
11474
+ continue;
11475
+ }
11476
+
11477
+ if ($this->inFixedPosBlock) {
11478
+ if (in_array($endtag, $this->outerblocktags) || in_array($endtag, $this->innerblocktags)) { $this->fixedPosBlockDepth--; }
11479
+ if ($this->fixedPosBlockDepth == 0) {
11480
+ $this->fixedPosBlockSave[] = array($this->fixedPosBlock, $this->fixedPosBlockBBox, $this->page);
11481
+ $this->fixedPosBlock = '';
11482
+ $this->inFixedPosBlock = false;
11483
+ continue;
11484
+ }
11485
+ $this->fixedPosBlock .= '<'.$e.'>';
11486
+ continue;
11487
+ }
11488
+ if ($this->allow_html_optional_endtags && !$parseonly) {
11489
+ if (($endtag == 'DIV' || $endtag =='FORM' || $endtag =='CENTER') && $this->lastoptionaltag == 'P') { $this->CloseTag($this->lastoptionaltag ); }
11490
+ if ($this->lastoptionaltag == 'LI' && $endtag == 'OL') { $this->CloseTag($this->lastoptionaltag ); }
11491
+ if ($this->lastoptionaltag == 'LI' && $endtag == 'UL') { $this->CloseTag($this->lastoptionaltag ); }
11492
+ if ($this->lastoptionaltag == 'DD' && $endtag == 'DL') { $this->CloseTag($this->lastoptionaltag ); }
11493
+ if ($this->lastoptionaltag == 'DT' && $endtag == 'DL') { $this->CloseTag($this->lastoptionaltag ); }
11494
+ if ($this->lastoptionaltag == 'OPTION' && $endtag == 'SELECT') { $this->CloseTag($this->lastoptionaltag ); }
11495
+ if ($endtag == 'TABLE') {
11496
+ if ($this->lastoptionaltag == 'THEAD' || $this->lastoptionaltag == 'TBODY' || $this->lastoptionaltag == 'TFOOT') {
11497
+ $this->CloseTag($this->lastoptionaltag);
11498
+ }
11499
+ if ($this->lastoptionaltag == 'TR') { $this->CloseTag('TR'); }
11500
+ if ($this->lastoptionaltag == 'TD' || $this->lastoptionaltag == 'TH') { $this->CloseTag($this->lastoptionaltag ); $this->CloseTag('TR'); }
11501
+ }
11502
+ if ($endtag == 'THEAD' || $endtag == 'TBODY' || $endtag == 'TFOOT') {
11503
+ if ($this->lastoptionaltag == 'TR') { $this->CloseTag('TR'); }
11504
+ if ($this->lastoptionaltag == 'TD' || $this->lastoptionaltag == 'TH') { $this->CloseTag($this->lastoptionaltag ); $this->CloseTag('TR'); }
11505
+ }
11506
+ if ($endtag == 'TR') {
11507
+ if ($this->lastoptionaltag == 'TD' || $this->lastoptionaltag == 'TH') { $this->CloseTag($this->lastoptionaltag ); }
11508
+ }
11509
+ }
11510
+ $this->CloseTag($endtag);
11511
+ }
11512
+
11513
+ else { // OPENING TAG
11514
+ if($this->blk[$this->blklvl]['hide']) {
11515
+ if (strpos($e,' ')) { $te = strtoupper(substr($e,0,strpos($e,' '))); }
11516
+ else { $te = strtoupper($e); }
11517
+ if (in_array($te, $this->outerblocktags) || in_array($te, $this->innerblocktags)) {
11518
+ $this->blklvl++;
11519
+ $this->blk[$this->blklvl]['hide']=true;
11520
+ }
11521
+ continue;
11522
+ }
11523
+
11524
+ if ($this->inFixedPosBlock) {
11525
+ if (strpos($e,' ')) { $te = strtoupper(substr($e,0,strpos($e,' '))); }
11526
+ else { $te = strtoupper($e); }
11527
+ $this->fixedPosBlock .= '<'.$e.'>';
11528
+ if (in_array($te, $this->outerblocktags) || in_array($te, $this->innerblocktags)) { $this->fixedPosBlockDepth++; }
11529
+ continue;
11530
+ }
11531
+ $regexp = '|=\'(.*?)\'|s'; // eliminate single quotes, if any
11532
+ $e = preg_replace($regexp,"=\"\$1\"",$e);
11533
+ // changes anykey=anyvalue to anykey="anyvalue" (only do this inside [some] tags)
11534
+ if (substr($e,0,10)!='pageheader' && substr($e,0,10)!='pagefooter' && substr($e,0,12)!='tocpagebreak') { // mPDF 5.6.69
11535
+ $regexp = '| (\\w+?)=([^\\s>"]+)|si';
11536
+ $e = preg_replace($regexp," \$1=\"\$2\"",$e);
11537
+ }
11538
+
11539
+ $e = preg_replace('/ (\\S+?)\s*=\s*"/i', " \\1=\"", $e);
11540
+
11541
+ //Fix path values, if needed
11542
+ $orig_srcpath = '';
11543
+ if ((stristr($e,"href=") !== false) or (stristr($e,"src=") !== false) ) {
11544
+ $regexp = '/ (href|src)\s*=\s*"(.*?)"/i';
11545
+ preg_match($regexp,$e,$auxiliararray);
11546
+ if (isset($auxiliararray[2])) { $path = $auxiliararray[2]; }
11547
+ else { $path = ''; }
11548
+ if (trim($path) != '' && !(stristr($e,"src=") !== false && substr($path,0,4)=='var:')) {
11549
+ $orig_srcpath = $path;
11550
+ $this->GetFullPath($path);
11551
+ $regexp = '/ (href|src)="(.*?)"/i';
11552
+ $e = preg_replace($regexp,' \\1="'.$path.'"',$e);
11553
+ }
11554
+ }//END of Fix path values
11555
+
11556
+
11557
+ //Extract attributes
11558
+ $contents=array();
11559
+ $contents1=array(); // mPDF 5.5.17
11560
+ $contents2=array();
11561
+ // Changed to allow style="background: url('bg.jpg')"
11562
+ // mPDF 5.5.17 Changed to improve performance; maximum length of \S (attribute) = 16
11563
+ // mPDF 5.6.30 Increase allowed attribute name to 32 - cutting off "toc-even-header-name" etc.
11564
+ preg_match_all('/\\S{1,32}=["][^"]*["]/',$e,$contents1);
11565
+ preg_match_all('/\\S{1,32}=[\'][^\']*[\']/i',$e,$contents2);
11566
+
11567
+ $contents = array_merge($contents1, $contents2);
11568
+ preg_match('/\\S+/',$e,$a2);
11569
+ $tag=strtoupper($a2[0]);
11570
+ $attr=array();
11571
+ if ($orig_srcpath) { $attr['ORIG_SRC'] = $orig_srcpath; }
11572
+ if (!empty($contents)) {
11573
+ foreach($contents[0] as $v) {
11574
+ // Changed to allow style="background: url('bg.jpg')"
11575
+ if(preg_match('/^([^=]*)=["]?([^"]*)["]?$/',$v,$a3) || preg_match('/^([^=]*)=[\']?([^\']*)[\']?$/',$v,$a3)) {
11576
+ if (strtoupper($a3[1])=='ID' || strtoupper($a3[1])=='CLASS') { // 4.2.013 Omits STYLE
11577
+ $attr[strtoupper($a3[1])]=trim(strtoupper($a3[2]));
11578
+ }
11579
+ // includes header-style-right etc. used for <pageheader>
11580
+ else if (preg_match('/^(HEADER|FOOTER)-STYLE/i',$a3[1])) {
11581
+ $attr[strtoupper($a3[1])]=trim(strtoupper($a3[2]));
11582
+ }
11583
+ else {
11584
+ $attr[strtoupper($a3[1])]=trim($a3[2]);
11585
+ }
11586
+ }
11587
+ }
11588
+ }
11589
+ $this->OpenTag($tag,$attr);
11590
+ if ($this->inFixedPosBlock) {
11591
+ $this->fixedPosBlockBBox = array($tag,$attr, $this->x, $this->y);
11592
+ $this->fixedPosBlock = '';
11593
+ $this->fixedPosBlockDepth = 1;
11594
+ }
11595
+ // mPDF 5.5.09
11596
+ if (preg_match('/\/$/',$e)) { $this->closeTag($tag); }
11597
+
11598
+ }
11599
+
11600
+ } // end TAG
11601
+ } //end of foreach($a as $i=>$e)
11602
+
11603
+ if ($close) {
11604
+
11605
+ // Close any open block tags
11606
+ for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag']); }
11607
+
11608
+ // Output any text left in buffer
11609
+ if (count($this->textbuffer) && !$parseonly) { $this->printbuffer($this->textbuffer); }
11610
+ if (!$parseonly) $this->textbuffer=array();
11611
+
11612
+ // If ended with a float, need to move to end page
11613
+ $currpos = $this->page*1000 + $this->y;
11614
+ if (isset($this->blk[$this->blklvl]['float_endpos']) && $this->blk[$this->blklvl]['float_endpos'] > $currpos) {
11615
+ $old_page = $this->page;
11616
+ $new_page = intval($this->blk[$this->blklvl]['float_endpos'] /1000);
11617
+ if ($old_page != $new_page) {
11618
+ $s = $this->PrintPageBackgrounds();
11619
+ // Writes after the marker so not overwritten later by page background etc.
11620
+ $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
11621
+ $this->pageBackgrounds = array();
11622
+ $this->page = $new_page;
11623
+ $this->ResetMargins();
11624
+ $this->Reset();
11625
+ $this->pageoutput[$this->page] = array();
11626
+ }
11627
+ $this->y = (($this->blk[$this->blklvl]['float_endpos'] *1000) % 1000000)/1000; // mod changes operands to integers before processing
11628
+ }
11629
+
11630
+ $this->printfloatbuffer();
11631
+
11632
+ //Create Internal Links, if needed
11633
+ if (!empty($this->internallink) ) {
11634
+ foreach($this->internallink as $k=>$v) {
11635
+ if (strpos($k,"#") !== false ) { continue; } //ignore
11636
+ $ypos = $v['Y'];
11637
+ $pagenum = $v['PAGE'];
11638
+ $sharp = "#";
11639
+ while (array_key_exists($sharp.$k,$this->internallink)) {
11640
+ $internallink = $this->internallink[$sharp.$k];
11641
+ $this->SetLink($internallink,$ypos,$pagenum);
11642
+ $sharp .= "#";
11643
+ }
11644
+ }
11645
+ }
11646
+
11647
+ $this->linemaxfontsize = '';
11648
+ $this->lineheight_correction = $this->default_lineheight_correction;
11649
+
11650
+ $this->bufferoutput = false;
11651
+
11652
+ if (count($this->fixedPosBlockSave) && $sub != 4) {
11653
+ foreach($this->fixedPosBlockSave AS $fpbs) {
11654
+ $old_page = $this->page;
11655
+ $this->page = $fpbs[2];
11656
+ $this->WriteFixedPosHTML($fpbs[0], 0, 0, 100, 100,'auto', $fpbs[1]); // 0,0,10,10 are overwritten by bbox
11657
+ $this->page = $old_page;
11658
+ }
11659
+ }
11660
+
11661
+ }
11662
+ }
11663
+
11664
+
11665
+ function WriteFixedPosHTML($html='',$x, $y, $w, $h, $overflow='visible', $bounding=array()) {
11666
+ // $overflow can be 'hidden', 'visible' or 'auto' - 'auto' causes autofit to size
11667
+ // Annotations disabled - enabled in mPDF 5.0
11668
+ // Links do work
11669
+ // Will always go on current page (or start Page 1 if required)
11670
+ // Probably INCOMPATIBLE WITH keep with table, columns etc.
11671
+ // Called externally or interally via <div style="position: [fixed|absolute]">
11672
+ // When used internally, $x $y $w $h and $overflow are all overridden by $bounding
11673
+
11674
+ $overflow = strtolower($overflow);
11675
+ if($this->state==0) {
11676
+ $this->AddPage($this->CurOrientation);
11677
+ }
11678
+ $save_y = $this->y;
11679
+ $save_x = $this->x;
11680
+ $this->fullImageHeight = $this->h;
11681
+ $save_cols = false;
11682
+ $this->writingHTMLheader = true; // a FIX to stop pagebreaks etc.
11683
+ $this->writingHTMLfooter = true;
11684
+ $this->InFooter = true; // suppresses autopagebreaks
11685
+ $save_bgs = $this->pageBackgrounds;
11686
+ $checkinnerhtml = preg_replace('/\s/','',$html);
11687
+
11688
+ if ($w > $this->w) { $x = 0; $w = $this->w; }
11689
+ if ($h > $this->h) { $y = 0; $h = $this->h; }
11690
+ if ($x > $this->w) { $x = $this->w - $w; }
11691
+ if ($y > $this->h) { $y = $this->h - $h; }
11692
+
11693
+ if (!empty($bounding)) {
11694
+ // $cont_ containing block = full physical page (position: absolute) or page inside margins (position: fixed)
11695
+ // $bbox_ Bounding box is the <div> which is positioned absolutely/fixed
11696
+ // top/left/right/bottom/width/height/background*/border*/padding*/margin* are taken from bounding
11697
+ // font*[family/size/style/weight]/line-height/text*[align/decoration/transform/indent]/color are transferred to $inner
11698
+ // as an enclosing <div> (after having checked ID/CLASS)
11699
+ // $x, $y, $w, $h are inside of $bbox_ = containing box for $inner_
11700
+ // $inner_ InnerHTML is the contents of that block to be output
11701
+ $tag = $bounding[0];
11702
+ $attr = $bounding[1];
11703
+ $orig_x0 = $bounding[2];
11704
+ $orig_y0 = $bounding[3];
11705
+
11706
+ // As in WriteHTML() initialising
11707
+ $this->blklvl = 0;
11708
+ $this->lastblocklevelchange = 0;
11709
+ $this->blk = array();
11710
+ $this->initialiseBlock($this->blk[0]);
11711
+
11712
+ $this->blk[0]['width'] =& $this->pgwidth;
11713
+ $this->blk[0]['inner_width'] =& $this->pgwidth;
11714
+
11715
+ $this->blk[0]['blockContext'] = $this->blockContext;
11716
+
11717
+ $properties = $this->cssmgr->MergeCSS('BLOCK','BODY','');
11718
+ $this->setCSS($properties,'','BODY');
11719
+ $this->blklvl = 1;
11720
+ $this->initialiseBlock($this->blk[1]);
11721
+ $this->blk[1]['tag'] = $tag;
11722
+ $this->blk[1]['attr'] = $attr;
11723
+ $this->Reset();
11724
+ $p = $this->cssmgr->MergeCSS('BLOCK',$tag,$attr);
11725
+ if (isset($p['ROTATE']) && ($p['ROTATE']==90 || $p['ROTATE']==-90)) { $rotate = $p['ROTATE']; }
11726
+ else { $rotate = 0; }
11727
+ if (isset($p['OVERFLOW'])) { $overflow = strtolower($p['OVERFLOW']); }
11728
+ if (strtolower($p['POSITION']) == 'fixed') {
11729
+ $cont_w = $this->pgwidth; // $this->blk[0]['inner_width'];
11730
+ $cont_h = $this->h - $this->tMargin - $this->bMargin;
11731
+ $cont_x = $this->lMargin;
11732
+ $cont_y = $this->tMargin;
11733
+ }
11734
+ else {
11735
+ $cont_w = $this->w; // ABSOLUTE;
11736
+ $cont_h = $this->h;
11737
+ $cont_x = 0;
11738
+ $cont_y = 0;
11739
+ }
11740
+
11741
+ // Pass on in-line properties to the innerhtml
11742
+ $css = '';
11743
+ if (isset($p['TEXT-ALIGN'])) { $css .= 'text-align: '.strtolower($p['TEXT-ALIGN']).'; '; }
11744
+ if (isset($p['TEXT-TRANSFORM'])) { $css .= 'text-transform: '.strtolower($p['TEXT-TRANSFORM']).'; '; }
11745
+ if (isset($p['TEXT-INDENT'])) { $css .= 'text-indent: '.strtolower($p['TEXT-INDENT']).'; '; }
11746
+ if (isset($p['TEXT-DECORATION'])) { $css .= 'text-decoration: '.strtolower($p['TEXT-DECORATION']).'; '; }
11747
+ if (isset($p['FONT-FAMILY'])) { $css .= 'font-family: '.strtolower($p['FONT-FAMILY']).'; '; }
11748
+ if (isset($p['FONT-STYLE'])) { $css .= 'font-style: '.strtolower($p['FONT-STYLE']).'; '; }
11749
+ if (isset($p['FONT-WEIGHT'])) { $css .= 'font-weight: '.strtolower($p['FONT-WEIGHT']).'; '; }
11750
+ if (isset($p['FONT-SIZE'])) { $css .= 'font-size: '.strtolower($p['FONT-SIZE']).'; '; }
11751
+ if (isset($p['LINE-HEIGHT'])) { $css .= 'line-height: '.strtolower($p['LINE-HEIGHT']).'; '; }
11752
+ if (isset($p['TEXT-SHADOW'])) { $css .= 'text-shadow: '.strtolower($p['TEXT-SHADOW']).'; '; }
11753
+ if (isset($p['LETTER-SPACING'])) { $css .= 'letter-spacing: '.strtolower($p['LETTER-SPACING']).'; '; }
11754
+ if (isset($p['FONT-VARIANT'])) { $css .= 'font-variant: '.strtolower($p['FONT-VARIANT']).'; '; }
11755
+ if (isset($p['COLOR'])) { $css .= 'color: '.strtolower($p['COLOR']).'; '; }
11756
+ if (isset($p['Z-INDEX'])) { $css .= 'z-index: '.$p['Z-INDEX'].'; '; } // mPDF 5.6.01
11757
+ if ($css) {
11758
+ $html = '<div style="'.$css.'">'.$html.'</div>';
11759
+ }
11760
+ // Copy over (only) the properties to set for border and background
11761
+ $pb = array();
11762
+ $pb['MARGIN-TOP'] = $p['MARGIN-TOP'];
11763
+ $pb['MARGIN-RIGHT'] = $p['MARGIN-RIGHT'];
11764
+ $pb['MARGIN-BOTTOM'] = $p['MARGIN-BOTTOM'];
11765
+ $pb['MARGIN-LEFT'] = $p['MARGIN-LEFT'];
11766
+ $pb['PADDING-TOP'] = $p['PADDING-TOP'];
11767
+ $pb['PADDING-RIGHT'] = $p['PADDING-RIGHT'];
11768
+ $pb['PADDING-BOTTOM'] = $p['PADDING-BOTTOM'];
11769
+ $pb['PADDING-LEFT'] = $p['PADDING-LEFT'];
11770
+ $pb['BORDER-TOP'] = $p['BORDER-TOP'];
11771
+ $pb['BORDER-RIGHT'] = $p['BORDER-RIGHT'];
11772
+ $pb['BORDER-BOTTOM'] = $p['BORDER-BOTTOM'];
11773
+ $pb['BORDER-LEFT'] = $p['BORDER-LEFT'];
11774
+ $pb['BORDER-TOP-LEFT-RADIUS-H'] = $p['BORDER-TOP-LEFT-RADIUS-H'];
11775
+ $pb['BORDER-TOP-LEFT-RADIUS-V'] = $p['BORDER-TOP-LEFT-RADIUS-V'];
11776
+ $pb['BORDER-TOP-RIGHT-RADIUS-H'] = $p['BORDER-TOP-RIGHT-RADIUS-H'];
11777
+ $pb['BORDER-TOP-RIGHT-RADIUS-V'] = $p['BORDER-TOP-RIGHT-RADIUS-V'];
11778
+ $pb['BORDER-BOTTOM-LEFT-RADIUS-H'] = $p['BORDER-BOTTOM-LEFT-RADIUS-H'];
11779
+ $pb['BORDER-BOTTOM-LEFT-RADIUS-V'] = $p['BORDER-BOTTOM-LEFT-RADIUS-V'];
11780
+ $pb['BORDER-BOTTOM-RIGHT-RADIUS-H'] = $p['BORDER-BOTTOM-RIGHT-RADIUS-H'];
11781
+ $pb['BORDER-BOTTOM-RIGHT-RADIUS-V'] = $p['BORDER-BOTTOM-RIGHT-RADIUS-V'];
11782
+ if (isset($p['BACKGROUND-COLOR'])) { $pb['BACKGROUND-COLOR'] = $p['BACKGROUND-COLOR']; }
11783
+ if (isset($p['BOX-SHADOW'])) { $pb['BOX-SHADOW'] = $p['BOX-SHADOW']; }
11784
+ if (isset($p['BACKGROUND-IMAGE'])) { $pb['BACKGROUND-IMAGE'] = $p['BACKGROUND-IMAGE']; }
11785
+ if (isset($p['BACKGROUND-IMAGE-RESIZE'])) { $pb['BACKGROUND-IMAGE-RESIZE'] = $p['BACKGROUND-IMAGE-RESIZE']; }
11786
+ if (isset($p['BACKGROUND-IMAGE-OPACITY'])) { $pb['BACKGROUND-IMAGE-OPACITY'] = $p['BACKGROUND-IMAGE-OPACITY']; }
11787
+ if (isset($p['BACKGROUND-REPEAT'])) { $pb['BACKGROUND-REPEAT'] = $p['BACKGROUND-REPEAT']; }
11788
+ if (isset($p['BACKGROUND-POSITION'])) { $pb['BACKGROUND-POSITION'] = $p['BACKGROUND-POSITION']; }
11789
+ if (isset($p['BACKGROUND-GRADIENT'])) { $pb['BACKGROUND-GRADIENT'] = $p['BACKGROUND-GRADIENT']; }
11790
+ if (isset($p['BACKGROUND-SIZE'])) { $pb['BACKGROUND-SIZE'] = $p['BACKGROUND-SIZE']; } // mPDF 5.6.12
11791
+ if (isset($p['BACKGROUND-ORIGIN'])) { $pb['BACKGROUND-ORIGIN'] = $p['BACKGROUND-ORIGIN']; } // mPDF 5.6.12
11792
+ if (isset($p['BACKGROUND-CLIP'])) { $pb['BACKGROUND-CLIP'] = $p['BACKGROUND-CLIP']; } // mPDF 5.6.12
11793
+
11794
+
11795
+ $this->setCSS($pb,'BLOCK',$tag);
11796
+
11797
+ //================================================================
11798
+ $bbox_br = $this->blk[1]['border_right']['w'];
11799
+ $bbox_bl = $this->blk[1]['border_left']['w'];
11800
+ $bbox_bt = $this->blk[1]['border_top']['w'];
11801
+ $bbox_bb = $this->blk[1]['border_bottom']['w'];
11802
+ $bbox_pr = $this->blk[1]['padding_right'];
11803
+ $bbox_pl = $this->blk[1]['padding_left'];
11804
+ $bbox_pt = $this->blk[1]['padding_top'];
11805
+ $bbox_pb = $this->blk[1]['padding_bottom'];
11806
+ $bbox_mr = $this->blk[1]['margin_right'];
11807
+ if (strtolower($p['MARGIN-RIGHT'])=='auto') { $bbox_mr = 'auto'; }
11808
+ $bbox_ml = $this->blk[1]['margin_left'];
11809
+ if (strtolower($p['MARGIN-LEFT'])=='auto') { $bbox_ml = 'auto'; }
11810
+ $bbox_mt = $this->blk[1]['margin_top'];
11811
+ if (strtolower($p['MARGIN-TOP'])=='auto') { $bbox_mt = 'auto'; }
11812
+ $bbox_mb = $this->blk[1]['margin_bottom'];
11813
+ if (strtolower($p['MARGIN-BOTTOM'])=='auto') { $bbox_mb = 'auto'; }
11814
+ if (isset($p['LEFT']) && strtolower($p['LEFT'])!='auto') { $bbox_left = $this->ConvertSize($p['LEFT'], $cont_w, $this->FontSize,false); }
11815
+ else { $bbox_left = 'auto'; }
11816
+ if (isset($p['TOP']) && strtolower($p['TOP'])!='auto') { $bbox_top = $this->ConvertSize($p['TOP'], $cont_h, $this->FontSize,false); }
11817
+ else { $bbox_top = 'auto'; }
11818
+ if (isset($p['RIGHT']) && strtolower($p['RIGHT'])!='auto') { $bbox_right = $this->ConvertSize($p['RIGHT'], $cont_w, $this->FontSize,false); }
11819
+ else { $bbox_right = 'auto'; }
11820
+ if (isset($p['BOTTOM']) && strtolower($p['BOTTOM'])!='auto') { $bbox_bottom = $this->ConvertSize($p['BOTTOM'], $cont_h, $this->FontSize,false); }
11821
+ else { $bbox_bottom = 'auto'; }
11822
+ if (isset($p['WIDTH']) && strtolower($p['WIDTH'])!='auto') { $inner_w = $this->ConvertSize($p['WIDTH'], $cont_w, $this->FontSize,false); }
11823
+ else { $inner_w = 'auto'; }
11824
+ if (isset($p['HEIGHT']) && strtolower($p['HEIGHT'])!='auto') { $inner_h = $this->ConvertSize($p['HEIGHT'], $cont_h, $this->FontSize,false); }
11825
+ else { $inner_h = 'auto'; }
11826
+
11827
+ // If bottom or right pos are set and not left / top - save this to adjust rotated block later
11828
+ if ($rotate) {
11829
+ if ($bbox_left === 'auto' && $bbox_right !== 'auto') { $rot_rpos = $bbox_right; }
11830
+ else { $rot_rpos = false; }
11831
+ if ($bbox_top === 'auto' && $bbox_bottom !== 'auto') { $rot_bpos = $bbox_bottom; }
11832
+ else { $rot_bpos = false; }
11833
+ }
11834
+
11835
+ //================================================================
11836
+ if ($checkinnerhtml=='' && $inner_h==='auto') { $inner_h = 0.0001; }
11837
+ if ($checkinnerhtml=='' && $inner_w==='auto') { $inner_w = 2*$this->GetCharWidth('W',false); }
11838
+ //================================================================
11839
+ // Algorithm from CSS2.1 See http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-height
11840
+ // mPD 5.3.14
11841
+ // Special case (not CSS) if all not specified, centre vertically on page
11842
+ if ($bbox_top==='auto' && $inner_h==='auto' && $bbox_bottom==='auto' && $bbox_mt==='auto' && $bbox_mb==='auto') {
11843
+ $bbox_top_orig = $bbox_top;
11844
+ if ($bbox_mt==='auto') { $bbox_mt = 0; }
11845
+ if ($bbox_mb==='auto') { $bbox_mb = 0; }
11846
+ $bbox_top = $orig_y0 - $bbox_mt - $cont_y;
11847
+ // solve for $bbox_bottom when content_h known - $inner_h=='auto' && $bbox_bottom=='auto'
11848
+ }
11849
+ // mPD 5.3.14
11850
+ else if ($bbox_top==='auto' && $inner_h==='auto' && $bbox_bottom==='auto') {
11851
+ $bbox_top_orig = $bbox_top = $orig_y0 - $cont_y;
11852
+ if ($bbox_mt==='auto') { $bbox_mt = 0; }
11853
+ if ($bbox_mb==='auto') { $bbox_mb = 0; }
11854
+ // solve for $bbox_bottom when content_h known - $inner_h=='auto' && $bbox_bottom=='auto'
11855
+ }
11856
+ else if ($bbox_top!=='auto' && $inner_h!=='auto' && $bbox_bottom!=='auto') {
11857
+ if ($bbox_mt==='auto' && $bbox_mb==='auto') {
11858
+ $x = $cont_h - $bbox_top - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_bottom;
11859
+ $bbox_mt = $bbox_mb = ($x/2);
11860
+ }
11861
+ else if ($bbox_mt==='auto') {
11862
+ $bbox_mt = $cont_h - $bbox_top - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom;
11863
+ }
11864
+ else if ($bbox_mb==='auto') {
11865
+ $bbox_mb = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_bottom;
11866
+ }
11867
+ else {
11868
+ $bbox_bottom = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mt;
11869
+ }
11870
+ }
11871
+ else {
11872
+ if ($bbox_mt==='auto') { $bbox_mt = 0; }
11873
+ if ($bbox_mb==='auto') { $bbox_mb = 0; }
11874
+ if ($bbox_top==='auto' && $inner_h==='auto' && $bbox_bottom!=='auto') {
11875
+ // solve for $bbox_top when content_h known - $inner_h=='auto' && $bbox_top =='auto'
11876
+ }
11877
+ else if ($bbox_top==='auto' && $bbox_bottom==='auto' && $inner_h!=='auto') {
11878
+ $bbox_top = $orig_y0 - $bbox_mt - $cont_y;
11879
+ $bbox_bottom = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mt;
11880
+ }
11881
+ else if ($inner_h==='auto' && $bbox_bottom==='auto' && $bbox_top!=='auto') {
11882
+ // solve for $bbox_bottom when content_h known - $inner_h=='auto' && $bbox_bottom=='auto'
11883
+ }
11884
+ else if ($bbox_top==='auto' && $inner_h!=='auto' && $bbox_bottom!=='auto') {
11885
+ $bbox_top = $cont_h - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mt - $bbox_bottom;
11886
+ }
11887
+ else if ($inner_h==='auto' && $bbox_top!=='auto' && $bbox_bottom!=='auto') {
11888
+ $inner_h = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $bbox_pb - $bbox_bb - $bbox_mt - $bbox_bottom;
11889
+ }
11890
+ else if ($bbox_bottom==='auto' && $bbox_top!=='auto' && $inner_h!=='auto') {
11891
+ $bbox_bottom = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mt;
11892
+ }
11893
+ }
11894
+
11895
+ // THEN DO SAME FOR WIDTH
11896
+ // http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width
11897
+ if ($bbox_left==='auto' && $inner_w==='auto' && $bbox_right==='auto') {
11898
+ if ($bbox_ml==='auto') { $bbox_ml = 0; }
11899
+ if ($bbox_mr==='auto') { $bbox_mr = 0; }
11900
+ // IF containing element RTL, should set $bbox_right
11901
+ $bbox_left = $orig_x0 - $bbox_ml - $cont_x;
11902
+ // solve for $bbox_right when content_w known - $inner_w=='auto' && $bbox_right=='auto'
11903
+ }
11904
+ else if ($bbox_left!=='auto' && $inner_w!=='auto' && $bbox_right!=='auto') {
11905
+ if ($bbox_ml==='auto' && $bbox_mr==='auto') {
11906
+ $x = $cont_w - $bbox_left - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_right;
11907
+ $bbox_ml = $bbox_mr = ($x/2);
11908
+ }
11909
+ else if ($bbox_ml==='auto') {
11910
+ $bbox_ml = $cont_w - $bbox_left - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_mr - $bbox_right;
11911
+ }
11912
+ else if ($bbox_mr==='auto') {
11913
+ $bbox_mr = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_right;
11914
+ }
11915
+ else {
11916
+ $bbox_right = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml;
11917
+ }
11918
+ }
11919
+ else {
11920
+ if ($bbox_ml==='auto') { $bbox_ml = 0; }
11921
+ if ($bbox_mr==='auto') { $bbox_mr = 0; }
11922
+ if ($bbox_left==='auto' && $inner_w==='auto' && $bbox_right!=='auto') {
11923
+ // solve for $bbox_left when content_w known - $inner_w=='auto' && $bbox_left =='auto'
11924
+ }
11925
+ else if ($bbox_left==='auto' && $bbox_right==='auto' && $inner_w!=='auto') {
11926
+ // IF containing element RTL, should set $bbox_right
11927
+ $bbox_left = $orig_x0 - $bbox_ml - $cont_x;
11928
+ $bbox_right = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml;
11929
+ }
11930
+ else if ($inner_w==='auto' && $bbox_right==='auto' && $bbox_left!=='auto') {
11931
+ // solve for $bbox_right when content_w known - $inner_w=='auto' && $bbox_right=='auto'
11932
+ }
11933
+ else if ($bbox_left==='auto' && $inner_w!=='auto' && $bbox_right!=='auto') {
11934
+ $bbox_left = $cont_w - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml - $bbox_right;
11935
+ }
11936
+ else if ($inner_w==='auto' && $bbox_left!=='auto' && $bbox_right!=='auto') {
11937
+ $inner_w = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $bbox_pr - $bbox_br - $bbox_ml - $bbox_right;
11938
+ }
11939
+ else if ($bbox_right==='auto' && $bbox_left!=='auto' && $inner_w!=='auto') {
11940
+ $bbox_right = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml;
11941
+ }
11942
+ }
11943
+
11944
+ //================================================================
11945
+ //================================================================
11946
+ if (isset($pb['BACKGROUND-IMAGE']) && $pb['BACKGROUND-IMAGE']) {
11947
+ $ret = $this->SetBackground($pb, $this->blk[1]['inner_width']);
11948
+ if ($ret) { $this->blk[1]['background-image'] = $ret; }
11949
+ }
11950
+
11951
+ //================================================================
11952
+ $y = $cont_y + $bbox_top + $bbox_mt + $bbox_bt + $bbox_pt;
11953
+ $h = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom;
11954
+ $x = $cont_x + $bbox_left + $bbox_ml + $bbox_bl + $bbox_pl;
11955
+ $w = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $bbox_pr - $bbox_br - $bbox_mr - $bbox_right;
11956
+ // Set (temporary) values for x y w h to do first paint, if values are auto
11957
+ if ($inner_h==='auto' && $bbox_top==='auto') {
11958
+ $y = $cont_y + $bbox_mt + $bbox_bt + $bbox_pt;
11959
+ $h = $cont_h - ($bbox_bottom + $bbox_mt + $bbox_mb + $bbox_bt + $bbox_bb + $bbox_pt + $bbox_pb);
11960
+ }
11961
+ else if ($inner_h==='auto' && $bbox_bottom==='auto') {
11962
+ $y = $cont_y + $bbox_top + $bbox_mt + $bbox_bt + $bbox_pt;
11963
+ $h = $cont_h - ($bbox_top + $bbox_mt + $bbox_mb + $bbox_bt + $bbox_bb + $bbox_pt + $bbox_pb);
11964
+ }
11965
+ if ($inner_w==='auto' && $bbox_left==='auto') {
11966
+ $x = $cont_x + $bbox_ml + $bbox_bl + $bbox_pl;
11967
+ $w = $cont_w - ($bbox_right + $bbox_ml + $bbox_mr + $bbox_bl + $bbox_br + $bbox_pl + $bbox_pr);
11968
+ }
11969
+ else if ($inner_w==='auto' && $bbox_right==='auto') {
11970
+ $x = $cont_x + $bbox_left + $bbox_ml + $bbox_bl + $bbox_pl;
11971
+ $w = $cont_w - ($bbox_left + $bbox_ml + $bbox_mr + $bbox_bl + $bbox_br + $bbox_pl + $bbox_pr);
11972
+ }
11973
+ $bbox_y = $cont_y + $bbox_top + $bbox_mt;
11974
+ $bbox_x = $cont_x + $bbox_left + $bbox_ml;
11975
+ $saved_block1 = $this->blk[1];
11976
+ unset($p);
11977
+ unset($pb);
11978
+ //================================================================
11979
+ if ($inner_w==='auto') { // do a first write
11980
+ $this->lMargin=$x;
11981
+ $this->rMargin=$this->w - $w - $x;
11982
+ // SET POSITION & FONT VALUES
11983
+ $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
11984
+ $this->pageoutput[$this->page]=array();
11985
+ $this->x = $x;
11986
+ $this->y = $y;
11987
+ $this->HTMLheaderPageLinks = array();
11988
+ $this->HTMLheaderPageAnnots = array();
11989
+ $this->HTMLheaderPageForms = array();
11990
+ $this->pageBackgrounds = array();
11991
+ $this->maxPosR = 0;
11992
+ $this->maxPosL = $this->w; // For RTL
11993
+ $this->WriteHTML($html , 4);
11994
+ $inner_w = $this->maxPosR - $this->lMargin;
11995
+ if ($bbox_right==='auto') {
11996
+ $bbox_right = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml;
11997
+ }
11998
+ else if ($bbox_left==='auto') {
11999
+ $bbox_left = $cont_w - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml - $bbox_right;
12000
+ $bbox_x = $cont_x + $bbox_left + $bbox_ml ;
12001
+ $inner_x = $bbox_x + $bbox_bl + $bbox_pl;
12002
+ $x = $inner_x;
12003
+ }
12004
+ $w = $inner_w;
12005
+ $bbox_y = $cont_y + $bbox_top + $bbox_mt;
12006
+ $bbox_x = $cont_x + $bbox_left + $bbox_ml;
12007
+ }
12008
+
12009
+ if ($inner_h==='auto') { // do a first write
12010
+ $this->lMargin=$x;
12011
+ $this->rMargin=$this->w - $w - $x;
12012
+ // SET POSITION & FONT VALUES
12013
+ $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
12014
+ $this->pageoutput[$this->page]=array();
12015
+ $this->x = $x;
12016
+ $this->y = $y;
12017
+ $this->HTMLheaderPageLinks = array();
12018
+ $this->HTMLheaderPageAnnots = array();
12019
+ $this->HTMLheaderPageForms = array();
12020
+ $this->pageBackgrounds = array();
12021
+ $this->WriteHTML($html , 4);
12022
+ $inner_h = $this->y - $y;
12023
+ if ($overflow!='hidden' && $overflow!='visible') { // constrained
12024
+ if (($this->y + $bbox_pb + $bbox_bb) > ($cont_y + $cont_h)) {
12025
+ $adj = ($this->y + $bbox_pb + $bbox_bb) - ($cont_y + $cont_h);
12026
+ $inner_h -= $adj;
12027
+ }
12028
+ }
12029
+ if ($bbox_bottom==='auto' && $bbox_top_orig==='auto') {
12030
+ $bbox_bottom = $bbox_top = ($cont_h - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mb)/2;
12031
+ if ($overflow!='hidden' && $overflow!='visible') { // constrained
12032
+ if ($bbox_top < 0) {
12033
+ $bbox_top = 0;
12034
+ $inner_h = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom;
12035
+ }
12036
+ }
12037
+ $bbox_y = $cont_y + $bbox_top + $bbox_mt;
12038
+ $inner_y = $bbox_y + $bbox_bt + $bbox_pt;
12039
+ $y = $inner_y;
12040
+
12041
+ }
12042
+ else if ($bbox_bottom==='auto') {
12043
+ $bbox_bottom = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mb;
12044
+ }
12045
+ else if ($bbox_top==='auto') {
12046
+ $bbox_top = $cont_h - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom;
12047
+ if ($overflow!='hidden' && $overflow!='visible') { // constrained
12048
+ if ($bbox_top < 0) {
12049
+ $bbox_top = 0;
12050
+ $inner_h = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom;
12051
+ }
12052
+ }
12053
+ $bbox_y = $cont_y + $bbox_top + $bbox_mt;
12054
+ $inner_y = $bbox_y + $bbox_bt + $bbox_pt;
12055
+ $y = $inner_y;
12056
+ }
12057
+ $h = $inner_h;
12058
+ $bbox_y = $cont_y + $bbox_top + $bbox_mt;
12059
+ $bbox_x = $cont_x + $bbox_left + $bbox_ml;
12060
+ }
12061
+ $inner_w = $w;
12062
+ $inner_h = $h;
12063
+
12064
+ }
12065
+ $this->lMargin=$x;
12066
+ $this->rMargin=$this->w - $w - $x;
12067
+ // SET POSITION & FONT VALUES
12068
+ $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
12069
+ $this->pageoutput[$this->page]=array();
12070
+ $this->x = $x;
12071
+ $this->y = $y;
12072
+ $this->HTMLheaderPageLinks = array();
12073
+ $this->HTMLheaderPageAnnots = array();
12074
+ $this->HTMLheaderPageForms = array();
12075
+ $this->pageBackgrounds = array();
12076
+ $this->WriteHTML($html , 4); // parameter 4 saves output to $this->headerbuffer
12077
+ $actual_h = $this->y - $y;
12078
+ $use_w = $w;
12079
+ $use_h = $h;
12080
+ $ratio = $actual_h / $use_w;
12081
+
12082
+ if ($overflow!='hidden' && $overflow!='visible') {
12083
+ $target = $h/$w;
12084
+ if (($ratio / $target ) > 1) {
12085
+ $nl = CEIL($actual_h / $this->lineheight);
12086
+ $l = $use_w * $nl;
12087
+ $est_w = sqrt(($l * $this->lineheight) / $target) * 0.8;
12088
+ $use_w += ($est_w - $use_w) - ($w/100);
12089
+ }
12090
+ $bpcstart = ($ratio / $target);
12091
+ $bpcctr = 1;
12092
+ while(($ratio / $target ) > 1) {
12093
+
12094
+
12095
+ $this->x = $x;
12096
+ $this->y = $y;
12097
+
12098
+ if (($ratio / $target) > 1.5 || ($ratio / $target) < 0.6) {
12099
+ $use_w += ($w/$this->incrementFPR1);
12100
+ }
12101
+ else if (($ratio / $target) > 1.2 || ($ratio / $target) < 0.85) {
12102
+ $use_w += ($w/$this->incrementFPR2);
12103
+ }
12104
+ else if (($ratio / $target) > 1.1 || ($ratio / $target) < 0.91) {
12105
+ $use_w += ($w/$this->incrementFPR3);
12106
+ }
12107
+ else {
12108
+ $use_w += ($w/$this->incrementFPR4);
12109
+ }
12110
+
12111
+ $use_h = $use_w * $target ;
12112
+ $this->rMargin=$this->w - $use_w - $x;
12113
+ $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
12114
+ $this->HTMLheaderPageLinks = array();
12115
+ $this->HTMLheaderPageAnnots = array();
12116
+ $this->HTMLheaderPageForms = array();
12117
+ $this->pageBackgrounds = array();
12118
+ $this->WriteHTML($html , 4); // parameter 4 saves output to $this->headerbuffer
12119
+ $actual_h = $this->y - $y;
12120
+ $ratio = $actual_h / $use_w;
12121
+ }
12122
+ }
12123
+ $shrink_f = $w/$use_w;
12124
+
12125
+ //================================================================
12126
+
12127
+ $this->pages[$this->page] .= '___BEFORE_BORDERS___';
12128
+ $block_s = $this->PrintPageBackgrounds(); // Save to print later inside clipping path
12129
+ $this->pageBackgrounds = array();
12130
+
12131
+ //================================================================
12132
+
12133
+ if ($rotate) {
12134
+ $prerotw = $bbox_bl + $bbox_pl + $inner_w + $bbox_pr + $bbox_br;
12135
+ $preroth = $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb;
12136
+ $rot_start = " q\n";
12137
+ if ($rotate == 90) {
12138
+ if ($rot_rpos !== false) { $adjw = $prerotw; } // width before rotation
12139
+ else { $adjw = $preroth; } // height before rotation
12140
+ if ($rot_bpos !== false) { $adjh = -$prerotw + $preroth; }
12141
+ else { $adjh = 0; }
12142
+ }
12143
+ else {
12144
+ if ($rot_rpos !== false) { $adjw = $prerotw - $preroth; }
12145
+ else { $adjw = 0; }
12146
+ if ($rot_bpos !== false) { $adjh = $preroth; } // height before rotation
12147
+ else { $adjh = $prerotw; } // width before rotation
12148
+ }
12149
+ $rot_start .= $this->transformTranslate($adjw, $adjh, true)."\n";
12150
+ $rot_start .= $this->transformRotate($rotate, $bbox_x, $bbox_y, true)."\n";
12151
+ $rot_end = " Q\n";
12152
+ }
12153
+ else {
12154
+ $rot_start = '';
12155
+ $rot_end = '';
12156
+ }
12157
+
12158
+ //================================================================
12159
+ if (!empty($bounding)) {
12160
+ // WHEN HEIGHT // BOTTOM EDGE IS KNOWN and $this->y is set to the bottom
12161
+ // Re-instate saved $this->blk[1]
12162
+ $this->blk[1] = $saved_block1;
12163
+
12164
+ // These are only needed when painting border/background
12165
+ $this->blk[1]['width'] = $bbox_w = $cont_w - $bbox_left - $bbox_ml - $bbox_mr - $bbox_right;
12166
+ $this->blk[1]['x0'] = $bbox_x;
12167
+ $this->blk[1]['y0'] = $bbox_y;
12168
+ $this->blk[1]['startpage'] = $this->page;
12169
+ $this->blk[1]['y1'] = $bbox_y + $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb ;
12170
+ $this->_out($rot_start); // mPDF 5.0
12171
+ $this->PaintDivBB('',0,1); // Prints borders and sets backgrounds in $this->pageBackgrounds
12172
+ $this->_out($rot_end);
12173
+ }
12174
+
12175
+ $s = $this->PrintPageBackgrounds();
12176
+ $s = $rot_start.$s.$rot_end;
12177
+ $this->pages[$this->page] = preg_replace('/___BEFORE_BORDERS___/', "\n".$s."\n", $this->pages[$this->page]);
12178
+ $this->pageBackgrounds = array();
12179
+
12180
+ $this->_out($rot_start);
12181
+
12182
+ // Clipping Output
12183
+ if ($overflow=='hidden') {
12184
+ //Bounding rectangle to clip
12185
+ $clip_y1 = $this->y;
12186
+ if (!empty($bounding) && ($this->y + $bbox_pb + $bbox_bb) > ($bbox_y + $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb )) {
12187
+ $clip_y1 = ($bbox_y + $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb ) - ($bbox_pb + $bbox_bb);
12188
+ }
12189
+ //$op = 'W* n'; // Clipping
12190
+ $op = 'W n'; // Clipping alternative mode
12191
+ $this->_out("q");
12192
+ $ch = $clip_y1 - $y;
12193
+ $this->_out(sprintf('%.3F %.3F %.3F %.3F re %s',$x*_MPDFK,($this->h-$y)*_MPDFK,$w*_MPDFK,-$ch*_MPDFK,$op));
12194
+ if (!empty($block_s)) {
12195
+ $tmp = "q\n".sprintf('%.3F %.3F %.3F %.3F re %s',$x*_MPDFK,($this->h-$y)*_MPDFK,$w*_MPDFK,-$ch*_MPDFK,$op);
12196
+ $tmp .= "\n".$block_s."\nQ";
12197
+ $block_s = $tmp ;
12198
+ }
12199
+ }
12200
+
12201
+
12202
+ if (!empty($block_s)) {
12203
+ if ($shrink_f != 1) { // i.e. autofit has resized the box
12204
+ $tmp = "q\n".$this->transformScale(($shrink_f*100),($shrink_f*100), $x, $y, true);
12205
+ $tmp .= "\n".$block_s."\nQ";
12206
+ $block_s = $tmp ;
12207
+ }
12208
+ $this->_out($block_s);
12209
+ }
12210
+
12211
+
12212
+
12213
+ if ($shrink_f != 1) { // i.e. autofit has resized the box
12214
+ $this->StartTransform();
12215
+ $this->transformScale(($shrink_f*100),($shrink_f*100), $x, $y);
12216
+ }
12217
+
12218
+ $this->_out($this->headerbuffer);
12219
+
12220
+ if ($shrink_f != 1) { // i.e. autofit has resized the box
12221
+ $this->StopTransform();
12222
+ }
12223
+
12224
+ if ($overflow=='hidden') {
12225
+ //End clipping
12226
+ $this->_out("Q");
12227
+ }
12228
+
12229
+ $this->_out($rot_end);
12230
+
12231
+
12232
+ // Page Links
12233
+ foreach($this->HTMLheaderPageLinks AS $lk) {
12234
+ if ($rotate) {
12235
+ $tmp = $lk[2]; // Switch h - w
12236
+ $lk[2] = $lk[3];
12237
+ $lk[3] = $tmp;
12238
+
12239
+ $lx1 = (($lk[0]/_MPDFK));
12240
+ $ly1 = (($this->h-($lk[1]/_MPDFK)));
12241
+ if ($rotate == 90) {
12242
+ $adjx = -($lx1-$bbox_x) + ($preroth - ($ly1-$bbox_y));
12243
+ $adjy = -($ly1-$bbox_y) + ($lx1-$bbox_x);
12244
+ $lk[2] = -$lk[2];
12245
+ }
12246
+ else if ($rotate == -90) {
12247
+ $adjx = -($lx1-$bbox_x) + ($ly1-$bbox_y);
12248
+ $adjy = -($ly1-$bbox_y) - ($lx1-$bbox_x) + $prerotw;
12249
+ $lk[3] = -$lk[3];
12250
+ }
12251
+ if ($rot_rpos !== false) { $adjx += $prerotw - $preroth; }
12252
+ if ($rot_bpos !== false) { $adjy += $preroth - $prerotw; }
12253
+ $lx1 += $adjx;
12254
+ $ly1 += $adjy;
12255
+
12256
+ $lk[0] = $lx1*_MPDFK;
12257
+ $lk[1] = ($this->h-$ly1)*_MPDFK;
12258
+ }
12259
+ if ($shrink_f != 1) { // i.e. autofit has resized the box
12260
+ $lx1 = (($lk[0]/_MPDFK)-$x);
12261
+ $lx2 = $x + ($lx1 * $shrink_f);
12262
+ $lk[0] = $lx2*_MPDFK;
12263
+ $ly1 = (($this->h-($lk[1]/_MPDFK))-$y);
12264
+ $ly2 = $y + ($ly1 * $shrink_f);
12265
+ $lk[1] = ($this->h-$ly2)*_MPDFK;
12266
+ $lk[2] *= $shrink_f; // width
12267
+ $lk[3] *= $shrink_f; // height
12268
+ }
12269
+ $this->PageLinks[$this->page][]=$lk;
12270
+ }
12271
+
12272
+ foreach($this->HTMLheaderPageForms AS $n=>$f) {
12273
+ if ($shrink_f != 1) { // i.e. autofit has resized the box
12274
+ $f['x'] = $x + (($f['x'] -$x) * $shrink_f);
12275
+ $f['y'] = $y + (($f['y'] -$y) * $shrink_f);
12276
+ $f['w'] *= $shrink_f;
12277
+ $f['h'] *= $shrink_f;
12278
+ $f['style']['fontsize'] *= $shrink_f;
12279
+ }
12280
+ $this->form->forms[$f['n']] = $f;
12281
+ }
12282
+ // Page Annotations
12283
+ foreach($this->HTMLheaderPageAnnots AS $lk) {
12284
+ if ($rotate) {
12285
+ if ($rotate == 90) {
12286
+ $adjx = -($lk['x']-$bbox_x) + ($preroth - ($lk['y']-$bbox_y));
12287
+ $adjy = -($lk['y']-$bbox_y) + ($lk['x']-$bbox_x);
12288
+ }
12289
+ else if ($rotate == -90) {
12290
+ $adjx = -($lk['x']-$bbox_x) + ($lk['y']-$bbox_y);
12291
+ $adjy = -($lk['y']-$bbox_y) - ($lk['x']-$bbox_x) + $prerotw;
12292
+ }
12293
+ if ($rot_rpos !== false) { $adjx += $prerotw - $preroth; }
12294
+ if ($rot_bpos !== false) { $adjy += $preroth - $prerotw; }
12295
+ $lk['x'] += $adjx;
12296
+ $lk['y'] += $adjy;
12297
+ }
12298
+ if ($shrink_f != 1) { // i.e. autofit has resized the box
12299
+ $lk['x'] = $x + (($lk['x']-$x) * $shrink_f);
12300
+ $lk['y'] = $y + (($lk['y']-$y) * $shrink_f);
12301
+ }
12302
+ $this->PageAnnots[$this->page][]=$lk;
12303
+ }
12304
+
12305
+ // Restore
12306
+ $this->headerbuffer = '';
12307
+ $this->HTMLheaderPageLinks = array();
12308
+ $this->HTMLheaderPageAnnots = array();
12309
+ $this->HTMLheaderPageForms = array();
12310
+ $this->pageBackgrounds = $save_bgs;
12311
+ $this->writingHTMLheader = false;
12312
+
12313
+ $this->writingHTMLfooter = false;
12314
+ $this->fullImageHeight = false;
12315
+ $this->ResetMargins();
12316
+ $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
12317
+ $this->SetXY($save_x,$save_y) ;
12318
+ $this->InFooter = false; // turns back on autopagebreaks
12319
+ $this->pageoutput[$this->page]=array();
12320
+ $this->pageoutput[$this->page]['Font']='';
12321
+ }
12322
+
12323
+
12324
+
12325
+ function initialiseBlock(&$blk) {
12326
+ $blk['margin_top'] = 0;
12327
+ $blk['margin_left'] = 0;
12328
+ $blk['margin_bottom'] = 0;
12329
+ $blk['margin_right'] = 0;
12330
+ $blk['padding_top'] = 0;
12331
+ $blk['padding_left'] = 0;
12332
+ $blk['padding_bottom'] = 0;
12333
+ $blk['padding_right'] = 0;
12334
+ $blk['border_top']['w'] = 0;
12335
+ $blk['border_left']['w'] = 0;
12336
+ $blk['border_bottom']['w'] = 0;
12337
+ $blk['border_right']['w'] = 0;
12338
+ $blk['hide'] = false;
12339
+ $blk['outer_left_margin'] = 0;
12340
+ $blk['outer_right_margin'] = 0;
12341
+ $blk['cascadeCSS'] = array();
12342
+ $blk['block-align'] = false;
12343
+ $blk['bgcolor'] = false;
12344
+ $blk['page_break_after_avoid'] = false;
12345
+ $blk['keep_block_together'] = false;
12346
+ $blk['float'] = false;
12347
+ $blk['line_height'] = '';
12348
+ $blk['margin_collapse'] = false;
12349
+ }
12350
+
12351
+
12352
+ function border_details($bd) {
12353
+ $prop = preg_split('/\s+/',trim($bd));
12354
+
12355
+ if (isset($this->blk[$this->blklvl]['inner_width'])) { $refw = $this->blk[$this->blklvl]['inner_width']; }
12356
+ else if (isset($this->blk[$this->blklvl-1]['inner_width'])) { $refw = $this->blk[$this->blklvl-1]['inner_width']; }
12357
+ else { $refw = $this->w; }
12358
+ if ( count($prop) == 1 ) {
12359
+ $bsize = $this->ConvertSize($prop[0],$refw,$this->FontSize,false);
12360
+ if ($bsize > 0) {
12361
+ return array('s' => 1, 'w' => $bsize, 'c' => $this->ConvertColor(0), 'style'=>'solid');
12362
+ }
12363
+ else { return array('w' => 0, 's' => 0); }
12364
+ }
12365
+
12366
+ else if (count($prop) == 2 ) {
12367
+ // 1px solid
12368
+ if (in_array($prop[1],$this->borderstyles) || $prop[1] == 'none' || $prop[1] == 'hidden' ) { $prop[2] = ''; }
12369
+ // solid #000000
12370
+ else if (in_array($prop[0],$this->borderstyles) || $prop[0] == 'none' || $prop[0] == 'hidden' ) { $prop[0] = ''; $prop[1] = $prop[0]; $prop[2] = $prop[1]; }
12371
+ // 1px #000000
12372
+ else { $prop[1] = ''; $prop[2] = $prop[1]; }
12373
+ }
12374
+ else if ( count($prop) == 3 ) {
12375
+ // Change #000000 1px solid to 1px solid #000000 (proper)
12376
+ if (substr($prop[0],0,1) == '#') { $tmp = $prop[0]; $prop[0] = $prop[1]; $prop[1] = $prop[2]; $prop[2] = $tmp; }
12377
+ // Change solid #000000 1px to 1px solid #000000 (proper)
12378
+ else if (substr($prop[0],1,1) == '#') { $tmp = $prop[1]; $prop[0] = $prop[2]; $prop[1] = $prop[0]; $prop[2] = $tmp; }
12379
+ // Change solid 1px #000000 to 1px solid #000000 (proper)
12380
+ else if (in_array($prop[0],$this->borderstyles) || $prop[0] == 'none' || $prop[0] == 'hidden' ) {
12381
+ $tmp = $prop[0]; $prop[0] = $prop[1]; $prop[1] = $tmp;
12382
+ }
12383
+ }
12384
+ else { return array(); }
12385
+ // Size
12386
+ $bsize = $this->ConvertSize($prop[0],$refw,$this->FontSize,false);
12387
+ //color
12388
+ $coul = $this->ConvertColor($prop[2]); // returns array
12389
+ // Style
12390
+ $prop[1] = strtolower($prop[1]);
12391
+ if (in_array($prop[1],$this->borderstyles) && $bsize > 0) { $on = 1; }
12392
+ else if ($prop[1] == 'hidden') { $on = 1; $bsize = 0; $coul = ''; }
12393
+ else if ($prop[1] == 'none') { $on = 0; $bsize = 0; $coul = ''; }
12394
+ else { $on = 0; $bsize = 0; $coul = ''; $prop[1] = ''; }
12395
+ return array('s' => $on, 'w' => $bsize, 'c' => $coul, 'style'=> $prop[1] );
12396
+ }
12397
+
12398
+
12399
+
12400
+
12401
+
12402
+ // Return either a number (factor) - based on current set fontsize (if % or em) - or exact lineheight (with 'mm' after it)
12403
+ function fixLineheight($v) {
12404
+ $lh = false;
12405
+ if (preg_match('/^[0-9\.,]*$/',$v) && $v >= 0) { return ($v + 0); }
12406
+ else if (strtoupper($v) == 'NORMAL') {
12407
+ return $this->normalLineheight;
12408
+ }
12409
+ else {
12410
+ $tlh = $this->ConvertSize($v,$this->FontSize,$this->FontSize,true);
12411
+ if ($tlh) { return ($tlh.'mm'); }
12412
+ }
12413
+ return $this->normalLineheight;
12414
+ }
12415
+
12416
+
12417
+
12418
+
12419
+
12420
+
12421
+
12422
+ function SetPagedMediaCSS($name='', $first, $oddEven) {
12423
+ if ($oddEven == 'E') {
12424
+ if ($this->directionality=='rtl') { $side = 'R'; }
12425
+ else { $side = 'L'; }
12426
+ }
12427
+ else {
12428
+ if ($this->directionality=='rtl') { $side = 'L'; }
12429
+ else { $side = 'R'; }
12430
+ }
12431
+ $name = strtoupper($name);
12432
+ $p = array();
12433
+ $p['SIZE'] = 'AUTO';
12434
+
12435
+ // Uses mPDF original margins as default
12436
+ $p['MARGIN-RIGHT'] = strval($this->orig_rMargin).'mm';
12437
+ $p['MARGIN-LEFT'] = strval($this->orig_lMargin).'mm';
12438
+ $p['MARGIN-TOP'] = strval($this->orig_tMargin).'mm';
12439
+ $p['MARGIN-BOTTOM'] = strval($this->orig_bMargin).'mm';
12440
+ $p['MARGIN-HEADER'] = strval($this->orig_hMargin).'mm';
12441
+ $p['MARGIN-FOOTER'] = strval($this->orig_fMargin).'mm';
12442
+
12443
+ // Basic page + selector
12444
+ if (isset($this->cssmgr->CSS['@PAGE'])) { $zp = $this->cssmgr->CSS['@PAGE']; }
12445
+ else { $zp = array(); }
12446
+ if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
12447
+
12448
+ if (isset($p['EVEN-HEADER-NAME']) && $oddEven=='E') {
12449
+ $p['HEADER'] = $p['EVEN-HEADER-NAME']; unset($p['EVEN-HEADER-NAME']);
12450
+ }
12451
+ if (isset($p['ODD-HEADER-NAME']) && $oddEven!='E') {
12452
+ $p['HEADER'] = $p['ODD-HEADER-NAME']; unset($p['ODD-HEADER-NAME']);
12453
+ }
12454
+ if (isset($p['EVEN-FOOTER-NAME']) && $oddEven=='E') {
12455
+ $p['FOOTER'] = $p['EVEN-FOOTER-NAME']; unset($p['EVEN-FOOTER-NAME']);
12456
+ }
12457
+ if (isset($p['ODD-FOOTER-NAME']) && $oddEven!='E') {
12458
+ $p['FOOTER'] = $p['ODD-FOOTER-NAME']; unset($p['ODD-FOOTER-NAME']);
12459
+ }
12460
+
12461
+ // If right/Odd page
12462
+ if (isset($this->cssmgr->CSS['@PAGE>>PSEUDO>>RIGHT']) && $side=='R') {
12463
+ $zp = $this->cssmgr->CSS['@PAGE>>PSEUDO>>RIGHT'];
12464
+ }
12465
+ else { $zp = array(); }
12466
+ if (isset($zp['SIZE'])) { unset($zp['SIZE']); }
12467
+ if (isset($zp['SHEET-SIZE'])) { unset($zp['SHEET-SIZE']); }
12468
+ // Disallow margin-left or -right on :LEFT or :RIGHT
12469
+ if (isset($zp['MARGIN-LEFT'])) { unset($zp['MARGIN-LEFT']); }
12470
+ if (isset($zp['MARGIN-RIGHT'])) { unset($zp['MARGIN-RIGHT']); }
12471
+ if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
12472
+
12473
+ // If left/Even page
12474
+ if (isset($this->cssmgr->CSS['@PAGE>>PSEUDO>>LEFT']) && $side=='L') {
12475
+ $zp = $this->cssmgr->CSS['@PAGE>>PSEUDO>>LEFT'];
12476
+ }
12477
+ else { $zp = array(); }
12478
+ if (isset($zp['SIZE'])) { unset($zp['SIZE']); }
12479
+ if (isset($zp['SHEET-SIZE'])) { unset($zp['SHEET-SIZE']); }
12480
+ // Disallow margin-left or -right on :LEFT or :RIGHT
12481
+ if (isset($zp['MARGIN-LEFT'])) { unset($zp['MARGIN-LEFT']); }
12482
+ if (isset($zp['MARGIN-RIGHT'])) { unset($zp['MARGIN-RIGHT']); }
12483
+ if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
12484
+
12485
+ // If first page
12486
+ if (isset($this->cssmgr->CSS['@PAGE>>PSEUDO>>FIRST']) && $first) { $zp = $this->cssmgr->CSS['@PAGE>>PSEUDO>>FIRST']; }
12487
+ else { $zp = array(); }
12488
+ if (isset($zp['SIZE'])) { unset($zp['SIZE']); }
12489
+ if (isset($zp['SHEET-SIZE'])) { unset($zp['SHEET-SIZE']); }
12490
+ if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
12491
+
12492
+ // If named page
12493
+ if ($name) {
12494
+ if (isset($this->cssmgr->CSS['@PAGE>>NAMED>>'.$name])) { $zp = $this->cssmgr->CSS['@PAGE>>NAMED>>'.$name]; }
12495
+ else { $zp = array(); }
12496
+ if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
12497
+
12498
+ if (isset($p['EVEN-HEADER-NAME']) && $oddEven=='E') {
12499
+ $p['HEADER'] = $p['EVEN-HEADER-NAME']; unset($p['EVEN-HEADER-NAME']);
12500
+ }
12501
+ if (isset($p['ODD-HEADER-NAME']) && $oddEven!='E') {
12502
+ $p['HEADER'] = $p['ODD-HEADER-NAME']; unset($p['ODD-HEADER-NAME']);
12503
+ }
12504
+ if (isset($p['EVEN-FOOTER-NAME']) && $oddEven=='E') {
12505
+ $p['FOOTER'] = $p['EVEN-FOOTER-NAME']; unset($p['EVEN-FOOTER-NAME']);
12506
+ }
12507
+ if (isset($p['ODD-FOOTER-NAME']) && $oddEven!='E') {
12508
+ $p['FOOTER'] = $p['ODD-FOOTER-NAME']; unset($p['ODD-FOOTER-NAME']);
12509
+ }
12510
+
12511
+ // If named right/Odd page
12512
+ if (isset($this->cssmgr->CSS['@PAGE>>NAMED>>'.$name.'>>PSEUDO>>RIGHT']) && $side=='R') { $zp = $this->cssmgr->CSS['@PAGE>>NAMED>>'.$name.'>>PSEUDO>>RIGHT']; }
12513
+ else { $zp = array(); }
12514
+ if (isset($zp['SIZE'])) { unset($zp['SIZE']); }
12515
+ if (isset($zp['SHEET-SIZE'])) { unset($zp['SHEET-SIZE']); }
12516
+ // Disallow margin-left or -right on :LEFT or :RIGHT
12517
+ if (isset($zp['MARGIN-LEFT'])) { unset($zp['MARGIN-LEFT']); }
12518
+ if (isset($zp['MARGIN-RIGHT'])) { unset($zp['MARGIN-RIGHT']); }
12519
+ if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
12520
+
12521
+ // If named left/Even page
12522
+ if (isset($this->cssmgr->CSS['@PAGE>>NAMED>>'.$name.'>>PSEUDO>>LEFT']) && $side=='L') { $zp = $this->cssmgr->CSS['@PAGE>>NAMED>>'.$name.'>>PSEUDO>>LEFT']; }
12523
+ else { $zp = array(); }
12524
+ if (isset($zp['SIZE'])) { unset($zp['SIZE']); }
12525
+ if (isset($zp['SHEET-SIZE'])) { unset($zp['SHEET-SIZE']); }
12526
+ // Disallow margin-left or -right on :LEFT or :RIGHT
12527
+ if (isset($zp['MARGIN-LEFT'])) { unset($zp['MARGIN-LEFT']); }
12528
+ if (isset($zp['MARGIN-RIGHT'])) { unset($zp['MARGIN-RIGHT']); }
12529
+ if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
12530
+
12531
+ // If named first page
12532
+ if (isset($this->cssmgr->CSS['@PAGE>>NAMED>>'.$name.'>>PSEUDO>>FIRST']) && $first) { $zp = $this->cssmgr->CSS['@PAGE>>NAMED>>'.$name.'>>PSEUDO>>FIRST']; }
12533
+ else { $zp = array(); }
12534
+ if (isset($zp['SIZE'])) { unset($zp['SIZE']); }
12535
+ if (isset($zp['SHEET-SIZE'])) { unset($zp['SHEET-SIZE']); }
12536
+ if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
12537
+ }
12538
+
12539
+ $orientation = $mgl = $mgr = $mgt = $mgb = $mgh = $mgf = '';
12540
+ $header = $footer = '';
12541
+ $resetpagenum = $pagenumstyle = $suppress = '';
12542
+ $marks = '';
12543
+ $bg = array();
12544
+
12545
+ $newformat = '';
12546
+
12547
+
12548
+ if (isset($p['SHEET-SIZE']) && is_array($p['SHEET-SIZE'])) {
12549
+ $newformat = $p['SHEET-SIZE'];
12550
+ if ($newformat[0] > $newformat[1]) { // landscape
12551
+ $newformat = array_reverse($newformat);
12552
+ $p['ORIENTATION'] = 'L';
12553
+ }
12554
+ else { $p['ORIENTATION'] = 'P'; }
12555
+ $this->_setPageSize($newformat, $p['ORIENTATION']);
12556
+ }
12557
+
12558
+ if (isset($p['SIZE']) && is_array($p['SIZE']) && !$newformat) {
12559
+ if ($p['SIZE']['W'] > $p['SIZE']['H']) { $p['ORIENTATION'] = 'L'; }
12560
+ else { $p['ORIENTATION'] = 'P'; }
12561
+ }
12562
+ if (is_array($p['SIZE'])) {
12563
+ if ($p['SIZE']['W'] > $this->fw) { $p['SIZE']['W'] = $this->fw; } // mPD 4.2 use fw not fPt
12564
+ if ($p['SIZE']['H'] > $this->fh) { $p['SIZE']['H'] = $this->fh; }
12565
+ if (($p['ORIENTATION']==$this->DefOrientation && !$newformat) || ($newformat && $p['ORIENTATION']=='P')) {
12566
+ $outer_width_LR = ($this->fw - $p['SIZE']['W'])/2;
12567
+ $outer_width_TB = ($this->fh - $p['SIZE']['H'])/2;
12568
+ }
12569
+ else {
12570
+ $outer_width_LR = ($this->fh - $p['SIZE']['W'])/2;
12571
+ $outer_width_TB = ($this->fw - $p['SIZE']['H'])/2;
12572
+ }
12573
+ $pgw = $p['SIZE']['W'];
12574
+ $pgh = $p['SIZE']['H'];
12575
+ }
12576
+ else { // AUTO LANDSCAPE PORTRAIT
12577
+ $outer_width_LR = 0;
12578
+ $outer_width_TB = 0;
12579
+ if (!$newformat) {
12580
+ if (strtoupper($p['SIZE']) == 'AUTO') { $p['ORIENTATION']=$this->DefOrientation; }
12581
+ else if (strtoupper($p['SIZE']) == 'LANDSCAPE') { $p['ORIENTATION']='L'; }
12582
+ else { $p['ORIENTATION']='P'; }
12583
+ }
12584
+ if (($p['ORIENTATION']==$this->DefOrientation && !$newformat) || ($newformat && $p['ORIENTATION']=='P')) {
12585
+ $pgw = $this->fw;
12586
+ $pgh = $this->fh;
12587
+ }
12588
+ else {
12589
+ $pgw = $this->fh;
12590
+ $pgh = $this->fw;
12591
+ }
12592
+ }
12593
+
12594
+ if (isset($p['HEADER']) && $p['HEADER']) { $header = $p['HEADER']; }
12595
+ if (isset($p['FOOTER']) && $p['FOOTER']) { $footer = $p['FOOTER']; }
12596
+ if (isset($p['RESETPAGENUM']) && $p['RESETPAGENUM']) { $resetpagenum = $p['RESETPAGENUM']; }
12597
+ if (isset($p['PAGENUMSTYLE']) && $p['PAGENUMSTYLE']) { $pagenumstyle = $p['PAGENUMSTYLE']; }
12598
+ if (isset($p['SUPPRESS']) && $p['SUPPRESS']) { $suppress = $p['SUPPRESS']; }
12599
+
12600
+ if (preg_match('/cross/i', $p['MARKS']) && preg_match('/crop/i', $p['MARKS'])) { $marks = 'CROPCROSS'; }
12601
+ else if (strtoupper($p['MARKS']) == 'CROP') { $marks = 'CROP'; }
12602
+ else if (strtoupper($p['MARKS']) == 'CROSS') { $marks = 'CROSS'; }
12603
+
12604
+
12605
+ if (isset($p['BACKGROUND-COLOR']) && $p['BACKGROUND-COLOR']) { $bg['BACKGROUND-COLOR'] = $p['BACKGROUND-COLOR']; }
12606
+ if (isset($p['BACKGROUND-GRADIENT']) && $p['BACKGROUND-GRADIENT']) { $bg['BACKGROUND-GRADIENT'] = $p['BACKGROUND-GRADIENT']; }
12607
+ if (isset($p['BACKGROUND-IMAGE']) && $p['BACKGROUND-IMAGE']) { $bg['BACKGROUND-IMAGE'] = $p['BACKGROUND-IMAGE']; }
12608
+ if (isset($p['BACKGROUND-REPEAT']) && $p['BACKGROUND-REPEAT']) { $bg['BACKGROUND-REPEAT'] = $p['BACKGROUND-REPEAT']; }
12609
+ if (isset($p['BACKGROUND-POSITION']) && $p['BACKGROUND-POSITION']) { $bg['BACKGROUND-POSITION'] = $p['BACKGROUND-POSITION']; }
12610
+ if (isset($p['BACKGROUND-IMAGE-RESIZE']) && $p['BACKGROUND-IMAGE-RESIZE']) { $bg['BACKGROUND-IMAGE-RESIZE'] = $p['BACKGROUND-IMAGE-RESIZE']; }
12611
+ if (isset($p['BACKGROUND-IMAGE-OPACITY'])) { $bg['BACKGROUND-IMAGE-OPACITY'] = $p['BACKGROUND-IMAGE-OPACITY']; }
12612
+
12613
+ if (isset($p['MARGIN-LEFT'])) { $mgl = $this->ConvertSize($p['MARGIN-LEFT'],$pgw) + $outer_width_LR; }
12614
+ if (isset($p['MARGIN-RIGHT'])) { $mgr = $this->ConvertSize($p['MARGIN-RIGHT'],$pgw) + $outer_width_LR; }
12615
+ if (isset($p['MARGIN-BOTTOM'])) { $mgb = $this->ConvertSize($p['MARGIN-BOTTOM'],$pgh) + $outer_width_TB; }
12616
+ if (isset($p['MARGIN-TOP'])) { $mgt = $this->ConvertSize($p['MARGIN-TOP'],$pgh) + $outer_width_TB; }
12617
+ if (isset($p['MARGIN-HEADER'])) { $mgh = $this->ConvertSize($p['MARGIN-HEADER'],$pgh) + $outer_width_TB; }
12618
+ if (isset($p['MARGIN-FOOTER'])) { $mgf = $this->ConvertSize($p['MARGIN-FOOTER'],$pgh) + $outer_width_TB; }
12619
+
12620
+ if (isset($p['ORIENTATION']) && $p['ORIENTATION']) { $orientation = $p['ORIENTATION']; }
12621
+ $this->page_box['outer_width_LR'] = $outer_width_LR; // Used in MARKS:crop etc.
12622
+ $this->page_box['outer_width_TB'] = $outer_width_TB;
12623
+
12624
+ return array($orientation,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$header,$footer,$bg,$resetpagenum,$pagenumstyle,$suppress,$marks,$newformat);
12625
+ }
12626
+
12627
+
12628
+
12629
+ // Added mPDF 3.0 Float DIV - CLEAR
12630
+ function ClearFloats($clear, $blklvl=0) {
12631
+ list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($blklvl,true);
12632
+ $end = $currpos = ($this->page*1000 + $this->y);
12633
+ if ($clear == 'BOTH' && ($l_exists || $r_exists)) {
12634
+ $this->pageoutput[$this->page] = array();
12635
+ $end = max($l_max, $r_max, $currpos);
12636
+ }
12637
+ else if ($clear == 'RIGHT' && $r_exists) {
12638
+ $this->pageoutput[$this->page] = array();
12639
+ $end = max($r_max, $currpos);
12640
+ }
12641
+ else if ($clear == 'LEFT' && $l_exists ) {
12642
+ $this->pageoutput[$this->page] = array();
12643
+ $end = max($l_max, $currpos);
12644
+ }
12645
+ else { return; }
12646
+ $old_page = $this->page;
12647
+ $new_page = intval($end/1000);
12648
+ if ($old_page != $new_page) {
12649
+ $s = $this->PrintPageBackgrounds();
12650
+ // Writes after the marker so not overwritten later by page background etc.
12651
+ $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
12652
+ $this->pageBackgrounds = array();
12653
+ $this->page = $new_page;
12654
+ }
12655
+ $this->ResetMargins();
12656
+ $this->pageoutput[$this->page] = array();
12657
+ $this->y = (($end*1000) % 1000000)/1000; // mod changes operands to integers before processing
12658
+ }
12659
+
12660
+
12661
+ // Added mPDF 3.0 Float DIV
12662
+ function GetFloatDivInfo($blklvl=0,$clear=false) {
12663
+ // If blklvl specified, only returns floats at that level - for ClearFloats
12664
+ $l_exists = false;
12665
+ $r_exists = false;
12666
+ $l_max = 0;
12667
+ $r_max = 0;
12668
+ $l_width = 0;
12669
+ $r_width = 0;
12670
+ if (count($this->floatDivs)) {
12671
+ $currpos = ($this->page*1000 + $this->y);
12672
+ foreach($this->floatDivs AS $f) {
12673
+ if (($clear && $f['blockContext'] == $this->blk[$blklvl]['blockContext']) || (!$clear && $currpos >= $f['startpos'] && $currpos < ($f['endpos']-0.001) && $f['blklvl'] > $blklvl && $f['blockContext'] == $this->blk[$blklvl]['blockContext'])) {
12674
+ if ($f['side']=='L') {
12675
+ $l_exists= true;
12676
+ $l_max = max($l_max, $f['endpos']);
12677
+ $l_width = max($l_width , $f['w']);
12678
+ }
12679
+ if ($f['side']=='R') {
12680
+ $r_exists= true;
12681
+ $r_max = max($r_max, $f['endpos']);
12682
+ $r_width = max($r_width , $f['w']);
12683
+ }
12684
+ }
12685
+ }
12686
+ }
12687
+ return array($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width);
12688
+ }
12689
+
12690
+
12691
+
12692
+
12693
+ function OpenTag($tag,$attr)
12694
+ {
12695
+
12696
+ // What this gets: < $tag $attr['WIDTH']="90px" > does not get content here </closeTag here>
12697
+ // Correct tags where HTML specifies optional end tags,
12698
+ // and/or does not allow nesting e.g. P inside P, or
12699
+ if ($this->allow_html_optional_endtags) {
12700
+ if (($tag == 'P' || $tag == 'DIV' || $tag == 'H1' || $tag == 'H2' || $tag == 'H3' || $tag == 'H4' || $tag == 'H5' || $tag == 'H6' || $tag == 'UL' || $tag == 'OL' || $tag == 'TABLE' || $tag=='PRE' || $tag=='FORM' || $tag=='ADDRESS' || $tag=='BLOCKQUOTE' || $tag=='CENTER' || $tag=='DL' || $tag == 'HR' ) && $this->lastoptionaltag == 'P') { $this->CloseTag($this->lastoptionaltag ); }
12701
+ if ($tag == 'DD' && $this->lastoptionaltag == 'DD') { $this->CloseTag($this->lastoptionaltag ); }
12702
+ if ($tag == 'DD' && $this->lastoptionaltag == 'DT') { $this->CloseTag($this->lastoptionaltag ); }
12703
+ if ($tag == 'DT' && $this->lastoptionaltag == 'DD') { $this->CloseTag($this->lastoptionaltag ); }
12704
+ if ($tag == 'DT' && $this->lastoptionaltag == 'DT') { $this->CloseTag($this->lastoptionaltag ); }
12705
+ if ($tag == 'LI' && $this->lastoptionaltag == 'LI') { $this->CloseTag($this->lastoptionaltag ); }
12706
+ if (($tag == 'TD' || $tag == 'TH') && $this->lastoptionaltag == 'TD') { $this->CloseTag($this->lastoptionaltag ); } // *TABLES*
12707
+ if (($tag == 'TD' || $tag == 'TH') && $this->lastoptionaltag == 'TH') { $this->CloseTag($this->lastoptionaltag ); } // *TABLES*
12708
+ if ($tag == 'TR' && $this->lastoptionaltag == 'TR') { $this->CloseTag($this->lastoptionaltag ); } // *TABLES*
12709
+ if ($tag == 'TR' && $this->lastoptionaltag == 'TD') { $this->CloseTag($this->lastoptionaltag ); $this->CloseTag('TR'); $this->CloseTag('THEAD'); } // *TABLES*
12710
+ if ($tag == 'TR' && $this->lastoptionaltag == 'TH') { $this->CloseTag($this->lastoptionaltag ); $this->CloseTag('TR'); $this->CloseTag('THEAD'); } // *TABLES*
12711
+ if ($tag == 'OPTION' && $this->lastoptionaltag == 'OPTION') { $this->CloseTag($this->lastoptionaltag ); }
12712
+ }
12713
+
12714
+ $align = array('left'=>'L','center'=>'C','right'=>'R','top'=>'T','text-top'=>'TT','middle'=>'M','baseline'=>'BS','bottom'=>'B','text-bottom'=>'TB','justify'=>'J');
12715
+
12716
+ $this->ignorefollowingspaces=false;
12717
+
12718
+ //Opening tag
12719
+ switch($tag){
12720
+
12721
+ case 'DOTTAB':
12722
+ $objattr = array();
12723
+ $objattr['type'] = 'dottab';
12724
+ $dots=str_repeat('.', 3)." "; // minimum number of dots
12725
+ $objattr['width'] = $this->GetStringWidth($dots);
12726
+ $objattr['margin_top'] = 0;
12727
+ $objattr['margin_bottom'] = 0;
12728
+ $objattr['margin_left'] = 0;
12729
+ $objattr['margin_right'] = 0;
12730
+ $objattr['height'] = 0;
12731
+ $objattr['colorarray'] = $this->colorarray;
12732
+ $objattr['border_top']['w'] = 0;
12733
+ $objattr['border_bottom']['w'] = 0;
12734
+ $objattr['border_left']['w'] = 0;
12735
+ $objattr['border_right']['w'] = 0;
12736
+
12737
+ // mPDF 5.6.19
12738
+ $properties = $this->cssmgr->MergeCSS('INLINE',$tag,$attr); // mPDF 5.6.33
12739
+ if (isset($properties['OUTDENT'])) { // mPDF 5.6.33
12740
+ $objattr['outdent'] = $this->ConvertSize($properties['OUTDENT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
12741
+ }
12742
+ else if (isset($attr['OUTDENT'])) {
12743
+ $objattr['outdent'] = $this->ConvertSize($attr['OUTDENT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
12744
+ }
12745
+ else { $objattr['outdent'] = 0; }
12746
+
12747
+ $objattr['fontfamily'] = $this->FontFamily;
12748
+ $objattr['fontsize'] = $this->FontSizePt;
12749
+
12750
+ $e = "\xbb\xa4\xactype=dottab,objattr=".serialize($objattr)."\xbb\xa4\xac";
12751
+ // Output it to buffers
12752
+ if ($this->tableLevel) {
12753
+ if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
12754
+ $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
12755
+ }
12756
+ elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
12757
+ $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
12758
+ }
12759
+ $this->cell[$this->row][$this->col]['s'] = 0 ;// reset
12760
+ $this->_saveCellTextBuffer($e);
12761
+ }
12762
+ else {
12763
+ $this->_saveTextBuffer($e);
12764
+ } // *TABLES*
12765
+ break;
12766
+
12767
+ case 'PAGEHEADER':
12768
+ case 'PAGEFOOTER':
12769
+ $this->ignorefollowingspaces = true;
12770
+ if ($attr['NAME']) { $pname = $attr['NAME']; }
12771
+ else { $pname = '_default'; }
12772
+
12773
+ if ($tag=='PAGEHEADER') { $p = &$this->pageheaders[$pname]; }
12774
+ else { $p = &$this->pagefooters[$pname]; }
12775
+
12776
+ $p['L']=array();
12777
+ $p['C']=array();
12778
+ $p['R']=array();
12779
+ $p['L']['font-style'] = '';
12780
+ $p['C']['font-style'] = '';
12781
+ $p['R']['font-style'] = '';
12782
+
12783
+ if (isset($attr['CONTENT-LEFT'])) {
12784
+ $p['L']['content'] = $attr['CONTENT-LEFT'];
12785
+ }
12786
+ if (isset($attr['CONTENT-CENTER'])) {
12787
+ $p['C']['content'] = $attr['CONTENT-CENTER'];
12788
+ }
12789
+ if (isset($attr['CONTENT-RIGHT'])) {
12790
+ $p['R']['content'] = $attr['CONTENT-RIGHT'];
12791
+ }
12792
+
12793
+ if (isset($attr['HEADER-STYLE']) || isset($attr['FOOTER-STYLE'])) { // font-family,size,weight,style,color
12794
+ if ($tag=='PAGEHEADER') { $properties = $this->cssmgr->readInlineCSS($attr['HEADER-STYLE']); }
12795
+ else { $properties = $this->cssmgr->readInlineCSS($attr['FOOTER-STYLE']); }
12796
+ if (isset($properties['FONT-FAMILY'])) {
12797
+ $p['L']['font-family'] = $properties['FONT-FAMILY'];
12798
+ $p['C']['font-family'] = $properties['FONT-FAMILY'];
12799
+ $p['R']['font-family'] = $properties['FONT-FAMILY'];
12800
+ }
12801
+ if (isset($properties['FONT-SIZE'])) {
12802
+ $p['L']['font-size'] = $this->ConvertSize($properties['FONT-SIZE']) * _MPDFK;
12803
+ $p['C']['font-size'] = $this->ConvertSize($properties['FONT-SIZE']) * _MPDFK;
12804
+ $p['R']['font-size'] = $this->ConvertSize($properties['FONT-SIZE']) * _MPDFK;
12805
+ }
12806
+ if (isset($properties['FONT-WEIGHT']) && $properties['FONT-WEIGHT']=='bold') {
12807
+ $p['L']['font-style'] = 'B';
12808
+ $p['C']['font-style'] = 'B';
12809
+ $p['R']['font-style'] = 'B';
12810
+ }
12811
+ if (isset($properties['FONT-STYLE']) && $properties['FONT-STYLE']=='italic') {
12812
+ $p['L']['font-style'] .= 'I';
12813
+ $p['C']['font-style'] .= 'I';
12814
+ $p['R']['font-style'] .= 'I';
12815
+ }
12816
+ if (isset($properties['COLOR'])) {
12817
+ $p['L']['color'] = $properties['COLOR'];
12818
+ $p['C']['color'] = $properties['COLOR'];
12819
+ $p['R']['color'] = $properties['COLOR'];
12820
+ }
12821
+ }
12822
+ if (isset($attr['HEADER-STYLE-LEFT']) || isset($attr['FOOTER-STYLE-LEFT'])) {
12823
+ if ($tag=='PAGEHEADER') { $properties = $this->cssmgr->readInlineCSS($attr['HEADER-STYLE-LEFT']); }
12824
+ else { $properties = $this->cssmgr->readInlineCSS($attr['FOOTER-STYLE-LEFT']); }
12825
+ if (isset($properties['FONT-FAMILY'])) { $p['L']['font-family'] = $properties['FONT-FAMILY']; }
12826
+ if (isset($properties['FONT-SIZE'])) { $p['L']['font-size'] = $this->ConvertSize($properties['FONT-SIZE']) * _MPDFK; }
12827
+ if (isset($properties['FONT-WEIGHT']) && $properties['FONT-WEIGHT']=='bold') { $p['L']['font-style'] ='B'; }
12828
+ if (isset($properties['FONT-STYLE']) && $properties['FONT-STYLE']=='italic') { $p['L']['font-style'] .='I'; }
12829
+ if (isset($properties['COLOR'])) { $p['L']['color'] = $properties['COLOR']; }
12830
+ }
12831
+ if (isset($attr['HEADER-STYLE-CENTER']) || isset($attr['FOOTER-STYLE-CENTER'])) {
12832
+ if ($tag=='PAGEHEADER') { $properties = $this->cssmgr->readInlineCSS($attr['HEADER-STYLE-CENTER']); }
12833
+ else { $properties = $this->cssmgr->readInlineCSS($attr['FOOTER-STYLE-CENTER']); }
12834
+ if (isset($properties['FONT-FAMILY'])) { $p['C']['font-family'] = $properties['FONT-FAMILY']; }
12835
+ if (isset($properties['FONT-SIZE'])) { $p['C']['font-size'] = $this->ConvertSize($properties['FONT-SIZE']) * _MPDFK; }
12836
+ if (isset($properties['FONT-WEIGHT']) && $properties['FONT-WEIGHT']=='bold') { $p['C']['font-style'] = 'B'; }
12837
+ if (isset($properties['FONT-STYLE']) && $properties['FONT-STYLE']=='italic') { $p['C']['font-style'] .= 'I'; }
12838
+ if (isset($properties['COLOR'])) { $p['C']['color'] = $properties['COLOR']; }
12839
+ }
12840
+ if (isset($attr['HEADER-STYLE-RIGHT']) || isset($attr['FOOTER-STYLE-RIGHT'])) {
12841
+ if ($tag=='PAGEHEADER') { $properties = $this->cssmgr->readInlineCSS($attr['HEADER-STYLE-RIGHT']); }
12842
+ else { $properties = $this->cssmgr->readInlineCSS($attr['FOOTER-STYLE-RIGHT']); }
12843
+ if (isset($properties['FONT-FAMILY'])) { $p['R']['font-family'] = $properties['FONT-FAMILY']; }
12844
+ if (isset($properties['FONT-SIZE'])) { $p['R']['font-size'] = $this->ConvertSize($properties['FONT-SIZE']) * _MPDFK; }
12845
+ if (isset($properties['FONT-WEIGHT']) && $properties['FONT-WEIGHT']=='bold') { $p['R']['font-style'] = 'B'; }
12846
+ if (isset($properties['FONT-STYLE']) && $properties['FONT-STYLE']=='italic') { $p['R']['font-style'] .= 'I'; }
12847
+ if (isset($properties['COLOR'])) { $p['R']['color'] = $properties['COLOR']; }
12848
+ }
12849
+ if (isset($attr['LINE']) && $attr['LINE']) { // 0|1|on|off
12850
+ if ($attr['LINE']=='1' || strtoupper($attr['LINE'])=='ON') { $lineset=1; }
12851
+ else { $lineset=0; }
12852
+ $p['line'] = $lineset;
12853
+ }
12854
+ break;
12855
+
12856
+
12857
+ case 'SETHTMLPAGEHEADER':
12858
+ case 'SETHTMLPAGEFOOTER':
12859
+ $this->ignorefollowingspaces = true;
12860
+ if (isset($attr['NAME']) && $attr['NAME']) { $pname = $attr['NAME']; }
12861
+ else { $pname = '_default'; }
12862
+ if (isset($attr['PAGE']) && $attr['PAGE']) { // O|odd|even|E|ALL|[blank]
12863
+ if (strtoupper($attr['PAGE'])=='O' || strtoupper($attr['PAGE'])=='ODD') { $side='odd'; }
12864
+ else if (strtoupper($attr['PAGE'])=='E' || strtoupper($attr['PAGE'])=='EVEN') { $side='even'; }
12865
+ else if (strtoupper($attr['PAGE'])=='ALL') { $side='both'; }
12866
+ else { $side='odd'; }
12867
+ }
12868
+ else { $side='odd'; }
12869
+ if (isset($attr['VALUE']) && $attr['VALUE']) { // -1|1|on|off
12870
+ if ($attr['VALUE']=='1' || strtoupper($attr['VALUE'])=='ON') { $set=1; }
12871
+ else if ($attr['VALUE']=='-1' || strtoupper($attr['VALUE'])=='OFF') { $set=0; }
12872
+ else { $set=1; }
12873
+ }
12874
+ else { $set=1; }
12875
+ if (isset($attr['SHOW-THIS-PAGE']) && $attr['SHOW-THIS-PAGE'] && $tag=='SETHTMLPAGEHEADER') { $write = 1; }
12876
+ else { $write = 0; }
12877
+ if ($side=='odd' || $side=='both') {
12878
+ if ($set && $tag=='SETHTMLPAGEHEADER') { $this->SetHTMLHeader($this->pageHTMLheaders[$pname],'O',$write); }
12879
+ else if ($set && $tag=='SETHTMLPAGEFOOTER') { $this->SetHTMLFooter($this->pageHTMLfooters[$pname],'O'); }
12880
+ else if ($tag=='SETHTMLPAGEHEADER') { $this->SetHTMLHeader('','O'); }
12881
+ else { $this->SetHTMLFooter('','O'); }
12882
+ }
12883
+ if ($side=='even' || $side=='both') {
12884
+ if ($set && $tag=='SETHTMLPAGEHEADER') { $this->SetHTMLHeader($this->pageHTMLheaders[$pname],'E',$write); }
12885
+ else if ($set && $tag=='SETHTMLPAGEFOOTER') { $this->SetHTMLFooter($this->pageHTMLfooters[$pname],'E'); }
12886
+ else if ($tag=='SETHTMLPAGEHEADER') { $this->SetHTMLHeader('','E'); }
12887
+ else { $this->SetHTMLFooter('','E'); }
12888
+ }
12889
+ break;
12890
+
12891
+ case 'SETPAGEHEADER':
12892
+ case 'SETPAGEFOOTER':
12893
+ $this->ignorefollowingspaces = true;
12894
+ if (isset($attr['NAME']) && $attr['NAME']) { $pname = $attr['NAME']; }
12895
+ else { $pname = '_default'; }
12896
+ if (isset($attr['PAGE']) && $attr['PAGE']) { // O|odd|even|E|ALL|[blank]
12897
+ if (strtoupper($attr['PAGE'])=='O' || strtoupper($attr['PAGE'])=='ODD') { $side='odd'; }
12898
+ else if (strtoupper($attr['PAGE'])=='E' || strtoupper($attr['PAGE'])=='EVEN') { $side='even'; }
12899
+ else if (strtoupper($attr['PAGE'])=='ALL') { $side='both'; }
12900
+ else { $side='odd'; }
12901
+ }
12902
+ else { $side='odd'; }
12903
+ if (isset($attr['VALUE']) && $attr['VALUE']) { // -1|1|on|off
12904
+ if ($attr['VALUE']=='1' || strtoupper($attr['VALUE'])=='ON') { $set=1; }
12905
+ else if ($attr['VALUE']=='-1' || strtoupper($attr['VALUE'])=='OFF') { $set=0; }
12906
+ else { $set=1; }
12907
+ }
12908
+ else { $set=1; }
12909
+ if ($side=='odd' || $side=='both') {
12910
+ if ($set && $tag=='SETPAGEHEADER') { $this->headerDetails['odd'] = $this->pageheaders[$pname]; }
12911
+ else if ($set && $tag=='SETPAGEFOOTER') { $this->footerDetails['odd'] = $this->pagefooters[$pname]; }
12912
+ else if ($tag=='SETPAGEHEADER') { $this->headerDetails['odd'] = array(); }
12913
+ else { $this->footerDetails['odd'] = array(); }
12914
+ if (!$this->mirrorMargins || ($this->page)%2!=0) { // ODD
12915
+ if ($tag=='SETPAGEHEADER') { $this->_setAutoHeaderHeight($this->headerDetails['odd'],$this->HTMLHeader); }
12916
+ if ($tag=='SETPAGEFOOTER') { $this->_setAutoFooterHeight($this->footerDetails['odd'],$this->HTMLFooter); }
12917
+ }
12918
+ }
12919
+ if ($side=='even' || $side=='both') {
12920
+ if ($set && $tag=='SETPAGEHEADER') { $this->headerDetails['even'] = $this->pageheaders[$pname]; }
12921
+ else if ($set && $tag=='SETPAGEFOOTER') { $this->footerDetails['even'] = $this->pagefooters[$pname]; }
12922
+ else if ($tag=='SETPAGEHEADER') { $this->headerDetails['even'] = array(); }
12923
+ else { $this->footerDetails['even'] = array(); }
12924
+ if ($this->mirrorMargins && ($this->page)%2==0) { // EVEN
12925
+ if ($tag=='SETPAGEHEADER') { $this->_setAutoHeaderHeight($this->headerDetails['even'],$this->HTMLHeaderE); }
12926
+ if ($tag=='SETPAGEFOOTER') { $this->_setAutoFooterHeight($this->footerDetails['even'],$this->HTMLFooterE); }
12927
+ }
12928
+ }
12929
+ if (isset($attr['SHOW-THIS-PAGE']) && $attr['SHOW-THIS-PAGE'] && $tag=='SETPAGEHEADER') {
12930
+ $this->Header();
12931
+ }
12932
+ break;
12933
+
12934
+
12935
+
12936
+
12937
+ case 'PAGE_BREAK': //custom-tag
12938
+ case 'PAGEBREAK': //custom-tag
12939
+ case 'NEWPAGE': //custom-tag
12940
+ case 'FORMFEED': //custom-tag
12941
+
12942
+ $save_blklvl = $this->blklvl;
12943
+ $save_blk = $this->blk;
12944
+ $save_silp = $this->saveInlineProperties();
12945
+ $save_spanlvl = $this->spanlvl;
12946
+ $save_ilp = $this->InlineProperties;
12947
+
12948
+ // Close any open block tags
12949
+ for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag']); }
12950
+ if(!empty($this->textbuffer)) { //Output previously buffered content
12951
+ $this->printbuffer($this->textbuffer);
12952
+ $this->textbuffer=array();
12953
+ }
12954
+ $this->ignorefollowingspaces = true;
12955
+ $save_cols = false;
12956
+
12957
+
12958
+ if (isset($attr['SHEET-SIZE']) && $tag != 'FORMFEED' && !$this->restoreBlockPageBreaks) {
12959
+ // Convert to same types as accepted in initial mPDF() A4, A4-L, or array(w,h)
12960
+ $prop = preg_split('/\s+/',trim($attr['SHEET-SIZE']));
12961
+ if (count($prop) == 2 ) {
12962
+ $newformat = array($this->ConvertSize($prop[0]), $this->ConvertSize($prop[1]));
12963
+ }
12964
+ else { $newformat = $attr['SHEET-SIZE']; }
12965
+ }
12966
+ else { $newformat = ''; }
12967
+
12968
+ $mgr = $mgl = $mgt = $mgb = $mgh = $mgf = '';
12969
+ if (isset($attr['MARGIN-RIGHT'])) { $mgr = $this->ConvertSize($attr['MARGIN-RIGHT'],$this->w,$this->FontSize,false); }
12970
+ if (isset($attr['MARGIN-LEFT'])) { $mgl = $this->ConvertSize($attr['MARGIN-LEFT'],$this->w,$this->FontSize,false); }
12971
+ if (isset($attr['MARGIN-TOP'])) { $mgt = $this->ConvertSize($attr['MARGIN-TOP'],$this->w,$this->FontSize,false); }
12972
+ if (isset($attr['MARGIN-BOTTOM'])) { $mgb = $this->ConvertSize($attr['MARGIN-BOTTOM'],$this->w,$this->FontSize,false); }
12973
+ if (isset($attr['MARGIN-HEADER'])) { $mgh = $this->ConvertSize($attr['MARGIN-HEADER'],$this->w,$this->FontSize,false); }
12974
+ if (isset($attr['MARGIN-FOOTER'])) { $mgf = $this->ConvertSize($attr['MARGIN-FOOTER'],$this->w,$this->FontSize,false); }
12975
+ $ohname = $ehname = $ofname = $efname = '';
12976
+ if (isset($attr['ODD-HEADER-NAME'])) { $ohname = $attr['ODD-HEADER-NAME']; }
12977
+ if (isset($attr['EVEN-HEADER-NAME'])) { $ehname = $attr['EVEN-HEADER-NAME']; }
12978
+ if (isset($attr['ODD-FOOTER-NAME'])) { $ofname = $attr['ODD-FOOTER-NAME']; }
12979
+ if (isset($attr['EVEN-FOOTER-NAME'])) { $efname = $attr['EVEN-FOOTER-NAME']; }
12980
+ $ohvalue = $ehvalue = $ofvalue = $efvalue = 0;
12981
+ if (isset($attr['ODD-HEADER-VALUE']) && ($attr['ODD-HEADER-VALUE']=='1' || strtoupper($attr['ODD-HEADER-VALUE'])=='ON')) { $ohvalue = 1; }
12982
+ else if (isset($attr['ODD-HEADER-VALUE']) && ($attr['ODD-HEADER-VALUE']=='-1' || strtoupper($attr['ODD-HEADER-VALUE'])=='OFF')) { $ohvalue = -1; }
12983
+ if (isset($attr['EVEN-HEADER-VALUE']) && ($attr['EVEN-HEADER-VALUE']=='1' || strtoupper($attr['EVEN-HEADER-VALUE'])=='ON')) { $ehvalue = 1; }
12984
+ else if (isset($attr['EVEN-HEADER-VALUE']) && ($attr['EVEN-HEADER-VALUE']=='-1' || strtoupper($attr['EVEN-HEADER-VALUE'])=='OFF')) { $ehvalue = -1; }
12985
+ if (isset($attr['ODD-FOOTER-VALUE']) && ($attr['ODD-FOOTER-VALUE']=='1' || strtoupper($attr['ODD-FOOTER-VALUE'])=='ON')) { $ofvalue = 1; }
12986
+ else if (isset($attr['ODD-FOOTER-VALUE']) && ($attr['ODD-FOOTER-VALUE']=='-1' || strtoupper($attr['ODD-FOOTER-VALUE'])=='OFF')) { $ofvalue = -1; }
12987
+ if (isset($attr['EVEN-FOOTER-VALUE']) && ($attr['EVEN-FOOTER-VALUE']=='1' || strtoupper($attr['EVEN-FOOTER-VALUE'])=='ON')) { $efvalue = 1; }
12988
+ else if (isset($attr['EVEN-FOOTER-VALUE']) && ($attr['EVEN-FOOTER-VALUE']=='-1' || strtoupper($attr['EVEN-FOOTER-VALUE'])=='OFF')) { $efvalue = -1; }
12989
+
12990
+ if (isset($attr['ORIENTATION']) && (strtoupper($attr['ORIENTATION'])=='L' || strtoupper($attr['ORIENTATION'])=='LANDSCAPE')) { $orient = 'L'; }
12991
+ else if (isset($attr['ORIENTATION']) && (strtoupper($attr['ORIENTATION'])=='P' || strtoupper($attr['ORIENTATION'])=='PORTRAIT')) { $orient = 'P'; }
12992
+ else { $orient = $this->CurOrientation; }
12993
+
12994
+ if (isset($attr['PAGE-SELECTOR']) && $attr['PAGE-SELECTOR']) { $pagesel = $attr['PAGE-SELECTOR']; }
12995
+ else { $pagesel = ''; }
12996
+
12997
+ $resetpagenum = '';
12998
+ $pagenumstyle = '';
12999
+ $suppress = '';
13000
+ if (isset($attr['RESETPAGENUM'])) { $resetpagenum = $attr['RESETPAGENUM']; }
13001
+ if (isset($attr['PAGENUMSTYLE'])) { $pagenumstyle = $attr['PAGENUMSTYLE']; }
13002
+ if (isset($attr['SUPPRESS'])) { $suppress = $attr['SUPPRESS']; }
13003
+
13004
+ if ($tag == 'TOCPAGEBREAK') { $type = 'NEXT-ODD'; }
13005
+ else if(isset($attr['TYPE'])) { $type = strtoupper($attr['TYPE']); }
13006
+ else { $type = ''; }
13007
+
13008
+ if ($type == 'E' || $type == 'EVEN') { $this->AddPage($orient,'E', $resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$ohname,$ehname,$ofname,$efname,$ohvalue,$ehvalue,$ofvalue,$efvalue,$pagesel,$newformat); }
13009
+ else if ($type == 'O' || $type == 'ODD') { $this->AddPage($orient,'O', $resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$ohname,$ehname,$ofname,$efname,$ohvalue,$ehvalue,$ofvalue,$efvalue,$pagesel,$newformat); }
13010
+ else if ($type == 'NEXT-ODD') { $this->AddPage($orient,'NEXT-ODD', $resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$ohname,$ehname,$ofname,$efname,$ohvalue,$ehvalue,$ofvalue,$efvalue,$pagesel,$newformat); }
13011
+ else if ($type == 'NEXT-EVEN') { $this->AddPage($orient,'NEXT-EVEN', $resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$ohname,$ehname,$ofname,$efname,$ohvalue,$ehvalue,$ofvalue,$efvalue,$pagesel,$newformat); }
13012
+ else { $this->AddPage($orient,'', $resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$ohname,$ehname,$ofname,$efname,$ohvalue,$ehvalue,$ofvalue,$efvalue,$pagesel,$newformat); }
13013
+
13014
+
13015
+ if (($tag == 'FORMFEED' || $this->restoreBlockPagebreaks) && !$this->tableLevel && !$this->listlvl) {
13016
+ $this->blk = $save_blk;
13017
+ // Re-open block tags
13018
+ $t = $this->blk[0]['tag'];
13019
+ $a = $this->blk[0]['attr'];
13020
+ $this->blklvl = 0;
13021
+ for ($b=0; $b<=$save_blklvl;$b++) {
13022
+ $tc = $t;
13023
+ $ac = $a;
13024
+ $t = $this->blk[$b+1]['tag'];
13025
+ $a = $this->blk[$b+1]['attr'];
13026
+ unset($this->blk[$b+1]);
13027
+ $this->OpenTag($tc,$ac);
13028
+ }
13029
+ $this->spanlvl = $save_spanlvl;
13030
+ $this->InlineProperties = $save_ilp;
13031
+ $this->restoreInlineProperties($save_silp);
13032
+ }
13033
+
13034
+ break;
13035
+
13036
+
13037
+
13038
+
13039
+
13040
+
13041
+
13042
+
13043
+
13044
+
13045
+ case 'BDO':
13046
+ // $this->biDirectional = true;
13047
+ break;
13048
+
13049
+
13050
+ case 'TTZ':
13051
+ $this->ttz = true;
13052
+ $this->InlineProperties[$tag] = $this->saveInlineProperties();
13053
+ $this->setCSS(array('FONT-FAMILY'=>'czapfdingbats','FONT-WEIGHT'=>'normal','FONT-STYLE'=>'normal'),'INLINE');
13054
+ break;
13055
+
13056
+ case 'TTS':
13057
+ $this->tts = true;
13058
+ $this->InlineProperties[$tag] = $this->saveInlineProperties();
13059
+ $this->setCSS(array('FONT-FAMILY'=>'csymbol','FONT-WEIGHT'=>'normal','FONT-STYLE'=>'normal'),'INLINE');
13060
+ break;
13061
+
13062
+ case 'TTA':
13063
+ $this->tta = true;
13064
+ $this->InlineProperties[$tag] = $this->saveInlineProperties();
13065
+
13066
+ if (in_array($this->FontFamily,$this->mono_fonts)) {
13067
+ $this->setCSS(array('FONT-FAMILY'=>'ccourier'),'INLINE');
13068
+ }
13069
+ else if (in_array($this->FontFamily,$this->serif_fonts)) {
13070
+ $this->setCSS(array('FONT-FAMILY'=>'ctimes'),'INLINE');
13071
+ }
13072
+ else {
13073
+ $this->setCSS(array('FONT-FAMILY'=>'chelvetica'),'INLINE');
13074
+ }
13075
+ break;
13076
+
13077
+
13078
+
13079
+ // INLINE PHRASES OR STYLES
13080
+ case 'SUB':
13081
+ case 'SUP':
13082
+ case 'ACRONYM':
13083
+ case 'BIG':
13084
+ case 'SMALL':
13085
+ case 'INS':
13086
+ case 'S':
13087
+ case 'STRIKE':
13088
+ case 'DEL':
13089
+ case 'STRONG':
13090
+ case 'CITE':
13091
+ case 'Q':
13092
+ case 'EM':
13093
+ case 'B':
13094
+ case 'I':
13095
+ case 'U':
13096
+ case 'SAMP':
13097
+ case 'CODE':
13098
+ case 'KBD':
13099
+ case 'TT':
13100
+ case 'VAR':
13101
+ case 'FONT':
13102
+ case 'MARK': // mPDF 5.5.09
13103
+ case 'TIME':
13104
+
13105
+ case 'SPAN':
13106
+
13107
+ if ($tag == 'SPAN') {
13108
+ $this->spanlvl++;
13109
+ $this->InlineProperties['SPAN'][$this->spanlvl] = $this->saveInlineProperties();
13110
+ }
13111
+ else {
13112
+ if (!isset($this->InlineProperties[$tag])) $this->InlineProperties[$tag] = $this->saveInlineProperties(); // mPDF 5.4.13
13113
+ }
13114
+ $properties = $this->cssmgr->MergeCSS('INLINE',$tag,$attr);
13115
+ if (!empty($properties)) $this->setCSS($properties,'INLINE');
13116
+ break;
13117
+
13118
+
13119
+ case 'A':
13120
+ if (isset($attr['NAME']) and $attr['NAME'] != '') {
13121
+ $e = '';
13122
+ if($this->tableLevel) { // *TABLES*
13123
+ $this->_saveCellTextBuffer($e, '', $attr['NAME']); // *TABLES*
13124
+ } // *TABLES*
13125
+ else { // *TABLES*
13126
+ $this->_saveTextBuffer($e, '', $attr['NAME']); //an internal link (adds a space for recognition)
13127
+ } // *TABLES*
13128
+ }
13129
+ if (isset($attr['HREF'])) {
13130
+ $this->InlineProperties['A'] = $this->saveInlineProperties();
13131
+ $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
13132
+ if (!empty($properties)) $this->setCSS($properties,'INLINE');
13133
+ $this->HREF=htmlspecialchars_decode(urldecode($attr['HREF']));
13134
+ }
13135
+ break;
13136
+
13137
+ case 'LEGEND': // mPDF 5.4.18
13138
+ $this->InlineProperties['LEGEND'] = $this->saveInlineProperties();
13139
+ $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
13140
+ if (!empty($properties)) $this->setCSS($properties,'INLINE');
13141
+ break;
13142
+
13143
+
13144
+
13145
+ case 'PROGRESS': // mPDF 5.5.09
13146
+ case 'METER': // mPDF 5.5.09
13147
+ $this->inMeter = true; // mPDF 5.5.09
13148
+
13149
+ if (isset($attr['MAX']) && $attr['MAX']) { $max = $attr['MAX']; }
13150
+ else { $max = 1; }
13151
+ if (isset($attr['MIN']) && $attr['MIN'] && $tag=='METER') { $min = $attr['MIN']; }
13152
+ else { $min = 0; }
13153
+ if ($max < $min) { $max = $min; }
13154
+
13155
+ if (isset($attr['VALUE']) && ($attr['VALUE'] || $attr['VALUE']==='0')) {
13156
+ $value = $attr['VALUE'];
13157
+ if ($value < $min) { $value = $min; }
13158
+ else if ($value > $max) { $value = $max; }
13159
+ }
13160
+ else { $value = ''; }
13161
+
13162
+ if (isset($attr['LOW']) && $attr['LOW']) { $low = $attr['LOW']; }
13163
+ else { $low = $min; }
13164
+ if ($low < $min) { $low = $min; }
13165
+ else if ($low > $max) { $low = $max; }
13166
+ if (isset($attr['HIGH']) && $attr['HIGH']) { $high = $attr['HIGH']; }
13167
+ else { $high = $max; }
13168
+ if ($high < $low) { $high = $low; }
13169
+ else if ($high > $max) { $high = $max; }
13170
+ if (isset($attr['OPTIMUM']) && $attr['OPTIMUM']) { $optimum = $attr['OPTIMUM']; }
13171
+ else { $optimum = $min + (($max-$min)/2); }
13172
+ if ($optimum < $min) { $optimum = $min; }
13173
+ else if ($optimum > $max) { $optimum = $max; }
13174
+ if (isset($attr['TYPE']) && $attr['TYPE']) { $type = $attr['TYPE']; }
13175
+ else { $type = ''; }
13176
+ $objattr = array();
13177
+ $objattr['margin_top'] = 0;
13178
+ $objattr['margin_bottom'] = 0;
13179
+ $objattr['margin_left'] = 0;
13180
+ $objattr['margin_right'] = 0;
13181
+ $objattr['padding_top'] = 0;
13182
+ $objattr['padding_bottom'] = 0;
13183
+ $objattr['padding_left'] = 0;
13184
+ $objattr['padding_right'] = 0;
13185
+ $objattr['width'] = 0;
13186
+ $objattr['height'] = 0;
13187
+ $objattr['border_top']['w'] = 0;
13188
+ $objattr['border_bottom']['w'] = 0;
13189
+ $objattr['border_left']['w'] = 0;
13190
+ $objattr['border_right']['w'] = 0;
13191
+
13192
+ $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
13193
+ if(isset($properties ['DISPLAY']) && strtolower($properties ['DISPLAY'])=='none') {
13194
+ return;
13195
+ }
13196
+ $objattr['visibility'] = 'visible';
13197
+ if (isset($properties['VISIBILITY'])) {
13198
+ $v = strtolower($properties['VISIBILITY']);
13199
+ if (($v == 'hidden' || $v == 'printonly' || $v == 'screenonly') && $this->visibility=='visible') {
13200
+ $objattr['visibility'] = $v;
13201
+ }
13202
+ }
13203
+
13204
+ if (isset($properties['MARGIN-TOP'])) { $objattr['margin_top']=$this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
13205
+ if (isset($properties['MARGIN-BOTTOM'])) { $objattr['margin_bottom'] = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
13206
+ if (isset($properties['MARGIN-LEFT'])) { $objattr['margin_left'] = $this->ConvertSize($properties['MARGIN-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
13207
+ if (isset($properties['MARGIN-RIGHT'])) { $objattr['margin_right'] = $this->ConvertSize($properties['MARGIN-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
13208
+
13209
+ if (isset($properties['PADDING-TOP'])) { $objattr['padding_top']=$this->ConvertSize($properties['PADDING-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
13210
+ if (isset($properties['PADDING-BOTTOM'])) { $objattr['padding_bottom'] = $this->ConvertSize($properties['PADDING-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
13211
+ if (isset($properties['PADDING-LEFT'])) { $objattr['padding_left'] = $this->ConvertSize($properties['PADDING-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
13212
+ if (isset($properties['PADDING-RIGHT'])) { $objattr['padding_right'] = $this->ConvertSize($properties['PADDING-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
13213
+
13214
+ if (isset($properties['BORDER-TOP'])) { $objattr['border_top'] = $this->border_details($properties['BORDER-TOP']); }
13215
+ if (isset($properties['BORDER-BOTTOM'])) { $objattr['border_bottom'] = $this->border_details($properties['BORDER-BOTTOM']); }
13216
+ if (isset($properties['BORDER-LEFT'])) { $objattr['border_left'] = $this->border_details($properties['BORDER-LEFT']); }
13217
+ if (isset($properties['BORDER-RIGHT'])) { $objattr['border_right'] = $this->border_details($properties['BORDER-RIGHT']); }
13218
+
13219
+ if (isset($properties['VERTICAL-ALIGN'])) { $objattr['vertical-align'] = $align[strtolower($properties['VERTICAL-ALIGN'])]; }
13220
+ $w = 0;
13221
+ $h = 0;
13222
+ if(isset($properties['WIDTH'])) $w = $this->ConvertSize($properties['WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
13223
+ else if(isset($attr['WIDTH'])) $w = $this->ConvertSize($attr['WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
13224
+
13225
+ if(isset($properties['HEIGHT'])) $h = $this->ConvertSize($properties['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
13226
+ else if(isset($attr['HEIGHT'])) $h = $this->ConvertSize($attr['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
13227
+
13228
+ if (isset($properties['OPACITY']) && $properties['OPACITY'] > 0 && $properties['OPACITY'] <= 1) { $objattr['opacity'] = $properties['OPACITY']; }
13229
+ if ($this->HREF) {
13230
+ if (strpos($this->HREF,".") === false && strpos($this->HREF,"@") !== 0) {
13231
+ $href = $this->HREF;
13232
+ while(array_key_exists($href,$this->internallink)) $href="#".$href;
13233
+ $this->internallink[$href] = $this->AddLink();
13234
+ $objattr['link'] = $this->internallink[$href];
13235
+ }
13236
+ else { $objattr['link'] = $this->HREF; }
13237
+ }
13238
+ $extraheight = $objattr['padding_top'] + $objattr['padding_bottom'] + $objattr['margin_top'] + $objattr['margin_bottom'] + $objattr['border_top']['w'] + $objattr['border_bottom']['w'];
13239
+ $extrawidth = $objattr['padding_left'] + $objattr['padding_right'] + $objattr['margin_left'] + $objattr['margin_right'] + $objattr['border_left']['w'] + $objattr['border_right']['w'];
13240
+
13241
+ // Image file
13242
+ if (!class_exists('meter', false)) {
13243
+ include(_MPDF_PATH.'classes/meter.php');
13244
+ }
13245
+ $this->meter = new meter();
13246
+ $svg = $this->meter->makeSVG(strtolower($tag), $type, $value, $max, $min, $optimum, $low, $high);
13247
+ //Save to local file
13248
+ $srcpath= _MPDF_TEMP_PATH.'_tempSVG'.RAND(1,10000).'_'.strtolower($tag).'.svg';
13249
+ file_put_contents($srcpath, $svg);
13250
+ $orig_srcpath = $srcpath;
13251
+ $this->GetFullPath($srcpath);
13252
+
13253
+ $info=$this->_getImage($srcpath, true, true, $orig_srcpath);
13254
+ if(!$info) {
13255
+ $info = $this->_getImage($this->noImageFile);
13256
+ if ($info) {
13257
+ $srcpath = $this->noImageFile;
13258
+ $w = ($info['w'] * (25.4/$this->dpi));
13259
+ $h = ($info['h'] * (25.4/$this->dpi));
13260
+ }
13261
+ }
13262
+ if(!$info) break;
13263
+
13264
+ $objattr['file'] = $srcpath;
13265
+ //Default width and height calculation if needed
13266
+ if($w==0 and $h==0) {
13267
+ // SVG units are pixels
13268
+ $w = $this->FontSize/(10/_MPDFK) * abs($info['w'])/_MPDFK; // mPDF 5.5.21
13269
+ $h = $this->FontSize/(10/_MPDFK) * abs($info['h'])/_MPDFK;
13270
+ }
13271
+ // IF WIDTH OR HEIGHT SPECIFIED
13272
+ if($w==0) $w=abs($h*$info['w']/$info['h']);
13273
+ if($h==0) $h=abs($w*$info['h']/$info['w']);
13274
+
13275
+ // Resize to maximum dimensions of page
13276
+ $maxWidth = $this->blk[$this->blklvl]['inner_width'];
13277
+ $maxHeight = $this->h - ($this->tMargin + $this->bMargin + 1) ;
13278
+ if ($this->fullImageHeight) { $maxHeight = $this->fullImageHeight; }
13279
+ if ($w + $extrawidth > $maxWidth ) {
13280
+ $w = $maxWidth - $extrawidth;
13281
+ $h=abs($w*$info['h']/$info['w']);
13282
+ }
13283
+
13284
+ if ($h + $extraheight > $maxHeight ) {
13285
+ $h = $maxHeight - $extraheight;
13286
+ $w=abs($h*$info['w']/$info['h']);
13287
+ }
13288
+ $objattr['type'] = 'image';
13289
+ $objattr['itype'] = $info['type'];
13290
+
13291
+ $objattr['orig_h'] = $info['h'];
13292
+ $objattr['orig_w'] = $info['w'];
13293
+ $objattr['wmf_x'] = $info['x'];
13294
+ $objattr['wmf_y'] = $info['y'];
13295
+ $objattr['height'] = $h + $extraheight;
13296
+ $objattr['width'] = $w + $extrawidth;
13297
+ $objattr['image_height'] = $h;
13298
+ $objattr['image_width'] = $w;
13299
+ $e = "\xbb\xa4\xactype=image,objattr=".serialize($objattr)."\xbb\xa4\xac";
13300
+ $properties = array();
13301
+ if ($this->tableLevel) {
13302
+ $this->_saveCellTextBuffer($e, $this->HREF);
13303
+ $this->cell[$this->row][$this->col]['s'] += $objattr['width'] ;
13304
+ }
13305
+ else {
13306
+ $this->_saveTextBuffer($e, $this->HREF);
13307
+ }
13308
+
13309
+ break;
13310
+
13311
+
13312
+ case 'BR':
13313
+ // Added mPDF 3.0 Float DIV - CLEAR
13314
+ if (isset($attr['STYLE'])) {
13315
+ $properties = $this->cssmgr->readInlineCSS($attr['STYLE']);
13316
+ if (isset($properties['CLEAR'])) { $this->ClearFloats(strtoupper($properties['CLEAR']),$this->blklvl); } // *CSS-FLOAT*
13317
+ }
13318
+
13319
+
13320
+ if($this->tableLevel) {
13321
+
13322
+ if ($this->blockjustfinished || $this->listjustfinished) {
13323
+ $this->_saveCellTextBuffer("\n");
13324
+ }
13325
+
13326
+ $this->_saveCellTextBuffer("\n");
13327
+ if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
13328
+ $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
13329
+ }
13330
+ elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
13331
+ $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
13332
+ }
13333
+ $this->cell[$this->row][$this->col]['s'] = 0 ;// reset
13334
+ }
13335
+ else {
13336
+ if (count($this->textbuffer)) {
13337
+ $this->textbuffer[count($this->textbuffer)-1][0] = preg_replace('/ $/','',$this->textbuffer[count($this->textbuffer)-1][0]);
13338
+ }
13339
+ $this->_saveTextBuffer("\n");
13340
+ } // *TABLES*
13341
+ $this->ignorefollowingspaces = true;
13342
+ $this->blockjustfinished=false;
13343
+ $this->listjustfinished=false;
13344
+
13345
+ $this->linebreakjustfinished=true;
13346
+ break;
13347
+
13348
+
13349
+ // *********** BLOCKS ********************
13350
+
13351
+
13352
+ case 'PRE':
13353
+ $this->ispre=true; // ADDED - Prevents left trim of textbuffer in printbuffer()
13354
+
13355
+ case 'DIV':
13356
+ case 'FORM':
13357
+ case 'CENTER':
13358
+
13359
+ case 'BLOCKQUOTE':
13360
+ case 'ADDRESS':
13361
+
13362
+ case 'CAPTION':
13363
+ case 'P':
13364
+ case 'H1':
13365
+ case 'H2':
13366
+ case 'H3':
13367
+ case 'H4':
13368
+ case 'H5':
13369
+ case 'H6':
13370
+ case 'DL':
13371
+ case 'DT':
13372
+ case 'DD':
13373
+ case 'FIELDSET':
13374
+ // mPDF 5.5.22
13375
+ case 'DETAILS':
13376
+ case 'SUMMARY':
13377
+ // mPDF 5.5.09
13378
+ case 'ARTICLE':
13379
+ case 'ASIDE':
13380
+ case 'FIGURE':
13381
+ case 'FIGCAPTION':
13382
+ case 'FOOTER':
13383
+ case 'HEADER':
13384
+ case 'HGROUP':
13385
+ case 'NAV':
13386
+ case 'SECTION':
13387
+ $p = $this->cssmgr->PreviewBlockCSS($tag,$attr);
13388
+ if(isset($p['DISPLAY']) && strtolower($p['DISPLAY'])=='none') {
13389
+ $this->blklvl++;
13390
+ $this->blk[$this->blklvl]['hide'] = true;
13391
+ return;
13392
+ }
13393
+ if($tag == 'CAPTION') {
13394
+ // position is written in AdjstHTML
13395
+ if (isset($attr['POSITION']) && strtolower($attr['POSITION'])=='bottom') { $divpos = 'B'; }
13396
+ else { $divpos = 'T'; }
13397
+ if (isset($attr['ALIGN']) && strtolower($attr['ALIGN'])=='bottom') { $cappos = 'B'; }
13398
+ else if (isset($p['CAPTION-SIDE']) && strtolower($p['CAPTION-SIDE'])=='bottom') { $cappos = 'B'; }
13399
+ else { $cappos = 'T'; }
13400
+ if (isset($attr['ALIGN'])) { unset($attr['ALIGN']); }
13401
+ if ($cappos != $divpos) {
13402
+ $this->blklvl++;
13403
+ $this->blk[$this->blklvl]['hide'] = true;
13404
+ return;
13405
+ }
13406
+ }
13407
+
13408
+
13409
+
13410
+ if ((isset($p['POSITION']) && (strtolower($p['POSITION'])=='fixed' || strtolower($p['POSITION'])=='absolute')) && $this->blklvl==0) {
13411
+ if ($this->inFixedPosBlock) {
13412
+ $this->Error("Cannot nest block with position:fixed or position:absolute");
13413
+ }
13414
+ $this->inFixedPosBlock = true;
13415
+ return;
13416
+ }
13417
+ // Start Block
13418
+ $this->ignorefollowingspaces = true;
13419
+
13420
+ if ($this->blockjustfinished && !count($this->textbuffer) && $this->y != $this->tMargin && $this->collapseBlockMargins) { $lastbottommargin = $this->lastblockbottommargin; }
13421
+ else { $lastbottommargin = 0; }
13422
+ $this->lastblockbottommargin = 0;
13423
+ $this->blockjustfinished=false;
13424
+
13425
+ if ($this->listlvl>0) { return; }
13426
+
13427
+ $this->InlineProperties = array();
13428
+ $this->spanlvl = 0;
13429
+ $this->listjustfinished=false;
13430
+ $this->divbegin=true;
13431
+
13432
+ $this->linebreakjustfinished=false;
13433
+
13434
+ if ($this->tableLevel) {
13435
+
13436
+ // If already something on the line
13437
+ if ($this->cell[$this->row][$this->col]['s'] > 0 && !$this->nestedtablejustfinished ) {
13438
+ $this->_saveCellTextBuffer("\n");
13439
+ if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
13440
+ $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
13441
+ }
13442
+ elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
13443
+ $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
13444
+ }
13445
+ $this->cell[$this->row][$this->col]['s'] = 0 ;// reset
13446
+ }
13447
+ // Cannot set block properties inside table - use Bold to indicate h1-h6
13448
+ if ($tag == 'CENTER' && $this->tdbegin) { $this->cell[$this->row][$this->col]['a'] = $align['center']; }
13449
+
13450
+ $this->InlineProperties['BLOCKINTABLE'] = $this->saveInlineProperties();
13451
+ $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
13452
+ if (!empty($properties)) $this->setCSS($properties,'INLINE');
13453
+
13454
+
13455
+ break;
13456
+ }
13457
+
13458
+ if ($tag == 'P' || $tag == 'DT' || $tag == 'DD') { $this->lastoptionaltag = $tag; } // Save current HTML specified optional endtag
13459
+ else { $this->lastoptionaltag = ''; }
13460
+
13461
+ if ($this->lastblocklevelchange == 1) { $blockstate = 1; } // Top margins/padding only
13462
+ else if ($this->lastblocklevelchange < 1) { $blockstate = 0; } // NO margins/padding
13463
+ $this->printbuffer($this->textbuffer,$blockstate);
13464
+ $this->textbuffer=array();
13465
+
13466
+ $save_blklvl = $this->blklvl;
13467
+ $save_blk = $this->blk;
13468
+ $save_silp = $this->saveInlineProperties();
13469
+ $save_spanlvl = $this->spanlvl;
13470
+ $save_ilp = $this->InlineProperties;
13471
+
13472
+ $this->blklvl++;
13473
+
13474
+ $currblk =& $this->blk[$this->blklvl];
13475
+ $this->initialiseBlock($currblk);
13476
+ $prevblk =& $this->blk[$this->blklvl-1];
13477
+
13478
+ $currblk['tag'] = $tag;
13479
+ $currblk['attr'] = $attr;
13480
+
13481
+ $this->Reset();
13482
+ $properties = $this->cssmgr->MergeCSS('BLOCK',$tag,$attr);
13483
+ $pagesel = '';
13484
+
13485
+ if (isset($properties['PAGE'])) { $pagesel = $properties['PAGE']; }
13486
+
13487
+ // If page-box has changed AND/OR PAGE-BREAK-BEFORE
13488
+ $save_cols = false;
13489
+ if (($pagesel && $pagesel != $this->page_box['current']) || (isset($properties['PAGE-BREAK-BEFORE']) && $properties['PAGE-BREAK-BEFORE'])) {
13490
+ if ($this->blklvl>1) {
13491
+ // Close any open block tags
13492
+ for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag']); }
13493
+ // Output any text left in buffer
13494
+ if (count($this->textbuffer)) { $this->printbuffer($this->textbuffer); $this->textbuffer=array(); }
13495
+ }
13496
+
13497
+
13498
+ // Must Add new page if changed page properties
13499
+ if (isset($properties['PAGE-BREAK-BEFORE'])) {
13500
+ if (strtoupper($properties['PAGE-BREAK-BEFORE']) == 'RIGHT') { $this->AddPage($this->CurOrientation,'NEXT-ODD','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
13501
+ else if (strtoupper($properties['PAGE-BREAK-BEFORE']) == 'LEFT') { $this->AddPage($this->CurOrientation,'NEXT-EVEN','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
13502
+ else if (strtoupper($properties['PAGE-BREAK-BEFORE']) == 'ALWAYS') { $this->AddPage($this->CurOrientation,'','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
13503
+ else if ($this->page_box['current'] != $pagesel) { $this->AddPage($this->CurOrientation,'','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); } // *CSS-PAGE*
13504
+ }
13505
+ else if ($pagesel != $this->page_box['current']) { $this->AddPage($this->CurOrientation,'','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
13506
+
13507
+ // if using htmlheaders, the headers need to be rewritten when new page
13508
+ // done by calling WriteHTML() within resethtmlheaders
13509
+ // so block is reset to 0 - now we need to resurrect it
13510
+ // As in WriteHTML() initialising
13511
+ if (!($this->restoreBlockPagebreaks && isset($properties['PAGE-BREAK-BEFORE']) && $properties['PAGE-BREAK-BEFORE'])) {
13512
+ $this->blklvl = 0;
13513
+ $this->lastblocklevelchange = 0;
13514
+ $this->blk = array();
13515
+ $this->initialiseBlock($this->blk[0]);
13516
+ $this->blk[0]['width'] =& $this->pgwidth;
13517
+ $this->blk[0]['inner_width'] =& $this->pgwidth;
13518
+ $this->blk[0]['blockContext'] = $this->blockContext;
13519
+ $properties = $this->cssmgr->MergeCSS('BLOCK','BODY','');
13520
+ $this->setCSS($properties,'','BODY');
13521
+ $this->blklvl++;
13522
+ $currblk =& $this->blk[$this->blklvl];
13523
+ $prevblk =& $this->blk[$this->blklvl-1];
13524
+
13525
+ $this->initialiseBlock($currblk);
13526
+ $currblk['tag'] = $tag;
13527
+ $currblk['attr'] = $attr;
13528
+
13529
+ $this->Reset();
13530
+ $properties = $this->cssmgr->MergeCSS('BLOCK',$tag,$attr);
13531
+ }
13532
+ if ($this->restoreBlockPagebreaks && isset($properties['PAGE-BREAK-BEFORE']) && $properties['PAGE-BREAK-BEFORE']) {
13533
+ $this->blk = $save_blk;
13534
+ // Re-open block tags
13535
+ $t = $this->blk[0]['tag'];
13536
+ $a = $this->blk[0]['attr'];
13537
+ $this->blklvl = 0;
13538
+ for ($b=0; $b<=$save_blklvl;$b++) {
13539
+ $tc = $t;
13540
+ $ac = $a;
13541
+ $t = $this->blk[$b+1]['tag'];
13542
+ $a = $this->blk[$b+1]['attr'];
13543
+ unset($this->blk[$b+1]);
13544
+ $this->OpenTag($tc,$ac);
13545
+ }
13546
+ $this->spanlvl = $save_spanlvl;
13547
+ $this->InlineProperties = $save_ilp;
13548
+ $this->restoreInlineProperties($save_silp);
13549
+ }
13550
+ }
13551
+
13552
+ if (isset($properties['PAGE-BREAK-INSIDE']) && strtoupper($properties['PAGE-BREAK-INSIDE']) == 'AVOID' && !$this->ColActive && !$this->keep_block_together) {
13553
+ $currblk['keep_block_together'] = 1;
13554
+ $this->kt_y00 = $this->y;
13555
+ $this->kt_p00 = $this->page;
13556
+ $this->keep_block_together = 1;
13557
+ $this->divbuffer = array();
13558
+ $this->ktLinks = array();
13559
+ $this->ktAnnots = array();
13560
+ $this->ktForms = array();
13561
+ $this->ktBlock = array();
13562
+ $this->ktReference = array();
13563
+ $this->ktBMoutlines = array();
13564
+ $this->_kttoc = array();
13565
+ }
13566
+ if ($lastbottommargin && isset($properties['MARGIN-TOP']) && $properties['MARGIN-TOP'] && empty($properties['FLOAT'])) { $currblk['lastbottommargin'] = $lastbottommargin; }
13567
+
13568
+ // mPDF 5.6.01 - LAYERS
13569
+ if (isset($properties['Z-INDEX']) && $this->currentlayer==0) {
13570
+ $v = intval($properties['Z-INDEX']);
13571
+ if ($v > 0) {
13572
+ $currblk['z-index'] = $v;
13573
+ $this->BeginLayer($v);
13574
+ }
13575
+ }
13576
+
13577
+ $this->setCSS($properties,'BLOCK',$tag); //name(id/class/style) found in the CSS array!
13578
+ $currblk['InlineProperties'] = $this->saveInlineProperties();
13579
+
13580
+ if (isset($properties['VISIBILITY'])) {
13581
+ $v = strtolower($properties['VISIBILITY']);
13582
+ if (($v == 'hidden' || $v == 'printonly' || $v == 'screenonly') && $this->visibility=='visible' && !$this->tableLevel) {
13583
+ $currblk['visibility'] = $v;
13584
+ $this->SetVisibility($v);
13585
+ }
13586
+ }
13587
+
13588
+ if(isset($attr['DIR']) && $attr['DIR']) { $currblk['direction'] = strtolower($attr['DIR']); }
13589
+ if(isset($attr['ALIGN']) && $attr['ALIGN']) { $currblk['block-align'] = $align[strtolower($attr['ALIGN'])]; }
13590
+
13591
+ if (isset($properties['HEIGHT'])) {
13592
+ $currblk['css_set_height'] = $this->ConvertSize($properties['HEIGHT'],($this->h - $this->tMargin - $this->bMargin),$this->FontSize,false);
13593
+ if (($currblk['css_set_height'] + $this->y) > $this->PageBreakTrigger && $this->y > $this->tMargin+5 && $currblk['css_set_height'] < ($this->h - ($this->tMargin + $this->bMargin))) { $this->AddPage($this->CurOrientation); }
13594
+ }
13595
+ else { $currblk['css_set_height'] = false; }
13596
+
13597
+
13598
+ // Added mPDF 3.0 Float DIV
13599
+ if (isset($prevblk['blockContext'])) { $currblk['blockContext'] = $prevblk['blockContext'] ; } // *CSS-FLOAT*
13600
+
13601
+ if (isset($properties['CLEAR'])) { $this->ClearFloats(strtoupper($properties['CLEAR']), $this->blklvl-1); } // *CSS-FLOAT*
13602
+
13603
+ $container_w = $prevblk['inner_width'];
13604
+ $bdr = $currblk['border_right']['w'];
13605
+ $bdl = $currblk['border_left']['w'];
13606
+ $pdr = $currblk['padding_right'];
13607
+ $pdl = $currblk['padding_left'];
13608
+
13609
+ if (isset($currblk['css_set_width'])) { $setwidth = $currblk['css_set_width']; }
13610
+ else { $setwidth = 0; }
13611
+
13612
+ if (isset($properties['FLOAT']) && strtoupper($properties['FLOAT']) == 'RIGHT' && !$this->ColActive) {
13613
+ // Cancel Keep-Block-together
13614
+ $currblk['keep_block_together'] = false;
13615
+ $this->kt_y00 = '';
13616
+ $this->keep_block_together = 0;
13617
+
13618
+ $this->blockContext++;
13619
+ $currblk['blockContext'] = $this->blockContext;
13620
+
13621
+ list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl-1);
13622
+
13623
+ // DIV is too narrow for text to fit!
13624
+ $maxw = $container_w - $l_width - $r_width;
13625
+ if (($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) > $maxw || ($maxw - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) < (2*$this->GetCharWidth('W',false))) {
13626
+ // Too narrow to fit - try to move down past L or R float
13627
+ if ($l_max < $r_max && ($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $r_width) && (($container_w - $r_width) - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) > (2*$this->GetCharWidth('W',false))) {
13628
+ $this->ClearFloats('LEFT', $this->blklvl-1);
13629
+ }
13630
+ else if ($r_max < $l_max && ($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $l_width) && (($container_w - $l_width) - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) > (2*$this->GetCharWidth('W',false))) {
13631
+ $this->ClearFloats('RIGHT', $this->blklvl-1);
13632
+ }
13633
+ else { $this->ClearFloats('BOTH', $this->blklvl-1); }
13634
+ list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl-1);
13635
+ }
13636
+
13637
+ if ($r_exists) { $currblk['margin_right'] += $r_width; }
13638
+
13639
+ $currblk['float'] = 'R';
13640
+ $currblk['float_start_y'] = $this->y;
13641
+ if ($currblk['css_set_width']) {
13642
+ $currblk['margin_left'] = $container_w - ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_right']);
13643
+ $currblk['float_width'] = ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_right']);
13644
+ }
13645
+ else {
13646
+ // *** If no width set - would need to buffer and keep track of max width, then Right-align if not full width
13647
+ // and do borders and backgrounds - For now - just set to maximum width left
13648
+
13649
+ if ($l_exists) { $currblk['margin_left'] += $l_width; }
13650
+ $currblk['css_set_width'] = $container_w - ($currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr);
13651
+
13652
+ $currblk['float_width'] = ($currblk['css_set_width'] + $bdl + $pdl + $bdr + $pdr + $currblk['margin_right']);
13653
+ }
13654
+ }
13655
+ else if (isset($properties['FLOAT']) && strtoupper($properties['FLOAT']) == 'LEFT' && !$this->ColActive) {
13656
+ // Cancel Keep-Block-together
13657
+ $currblk['keep_block_together'] = false;
13658
+ $this->kt_y00 = '';
13659
+ $this->keep_block_together = 0;
13660
+
13661
+ $this->blockContext++;
13662
+ $currblk['blockContext'] = $this->blockContext;
13663
+
13664
+ list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl-1);
13665
+
13666
+ // DIV is too narrow for text to fit!
13667
+ $maxw = $container_w - $l_width - $r_width;
13668
+ if (($setwidth + $currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr) > $maxw || ($maxw - ($currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr)) < (2*$this->GetCharWidth('W',false))) {
13669
+ // Too narrow to fit - try to move down past L or R float
13670
+ if ($l_max < $r_max && ($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $r_width) && (($container_w - $r_width) - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) > (2*$this->GetCharWidth('W',false))) {
13671
+ $this->ClearFloats('LEFT', $this->blklvl-1);
13672
+ }
13673
+ else if ($r_max < $l_max && ($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $l_width) && (($container_w - $l_width) - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) > (2*$this->GetCharWidth('W',false))) {
13674
+ $this->ClearFloats('RIGHT', $this->blklvl-1);
13675
+ }
13676
+ else { $this->ClearFloats('BOTH', $this->blklvl-1); }
13677
+ list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl-1);
13678
+ }
13679
+
13680
+ if ($l_exists) { $currblk['margin_left'] += $l_width; }
13681
+
13682
+ $currblk['float'] = 'L';
13683
+ $currblk['float_start_y'] = $this->y;
13684
+ if ($setwidth) {
13685
+ $currblk['margin_right'] = $container_w - ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_left']);
13686
+ $currblk['float_width'] = ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_left']);
13687
+ }
13688
+ else {
13689
+ // *** If no width set - would need to buffer and keep track of max width, then Right-align if not full width
13690
+ // and do borders and backgrounds - For now - just set to maximum width left
13691
+
13692
+ if ($r_exists) { $currblk['margin_right'] += $r_width; }
13693
+ $currblk['css_set_width'] = $container_w - ($currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr);
13694
+
13695
+ $currblk['float_width'] = ($currblk['css_set_width'] + $bdl + $pdl + $bdr + $pdr + $currblk['margin_left']);
13696
+ }
13697
+ }
13698
+
13699
+ else {
13700
+ // Don't allow overlap - if floats present - adjust padding to avoid overlap with Floats
13701
+ list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl-1);
13702
+ $maxw = $container_w - $l_width - $r_width;
13703
+ if (($setwidth + $currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) > $maxw || ($maxw - ($currblk['margin_right'] + $currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr)) < (2*$this->GetCharWidth('W',false))) {
13704
+ // Too narrow to fit - try to move down past L or R float
13705
+ if ($l_max < $r_max && ($setwidth + $currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $r_width) && (($container_w - $r_width) - ($currblk['margin_right'] + $currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr)) > (2*$this->GetCharWidth('W',false))) {
13706
+ $this->ClearFloats('LEFT', $this->blklvl-1);
13707
+ }
13708
+ else if ($r_max < $l_max && ($setwidth + $currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $l_width) && (($container_w - $l_width) - ($currblk['margin_right'] + $currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr)) > (2*$this->GetCharWidth('W',false))) {
13709
+ $this->ClearFloats('RIGHT', $this->blklvl-1);
13710
+ }
13711
+ else { $this->ClearFloats('BOTH', $this->blklvl-1); }
13712
+ list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl-1);
13713
+ }
13714
+ if ($r_exists) { $currblk['padding_right'] = max(($r_width-$currblk['margin_right']-$bdr), $pdr); }
13715
+ if ($l_exists) { $currblk['padding_left'] = max(($l_width-$currblk['margin_left']-$bdl), $pdl); }
13716
+ }
13717
+
13718
+
13719
+
13720
+
13721
+ // Hanging indent - if negative indent: ensure padding is >= indent
13722
+ if(!isset($currblk['text_indent'])) { $currblk['text_indent'] = null; }
13723
+ if(!isset($currblk['inner_width'])) { $currblk['inner_width'] = null; }
13724
+ $cbti = $this->ConvertSize($currblk['text_indent'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
13725
+ if ($cbti < 0) {
13726
+ $hangind = -($cbti);
13727
+ $currblk['padding_left'] = max($currblk['padding_left'],$hangind);
13728
+ }
13729
+
13730
+ if (isset($currblk['css_set_width'])) {
13731
+ if (isset($properties['MARGIN-LEFT']) && isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-LEFT'])=='auto' && strtolower($properties['MARGIN-RIGHT'])=='auto') {
13732
+ // Try to reduce margins to accomodate - if still too wide, set margin-right/left=0 (reduces width)
13733
+ $anyextra = $prevblk['inner_width'] - ($currblk['css_set_width'] + $currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + $currblk['padding_right']);
13734
+ if ($anyextra>0) {
13735
+ $currblk['margin_left'] = $currblk['margin_right'] = $anyextra /2;
13736
+ }
13737
+ else {
13738
+ $currblk['margin_left'] = $currblk['margin_right'] = 0;
13739
+ }
13740
+ }
13741
+ else if (isset($properties['MARGIN-LEFT']) && strtolower($properties['MARGIN-LEFT'])=='auto') {
13742
+ // Try to reduce margin-left to accomodate - if still too wide, set margin-left=0 (reduces width)
13743
+ $currblk['margin_left'] = $prevblk['inner_width'] - ($currblk['css_set_width'] + $currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + $currblk['padding_right'] + $currblk['margin_right']);
13744
+ if ($currblk['margin_left'] < 0) {
13745
+ $currblk['margin_left'] = 0;
13746
+ }
13747
+ }
13748
+ else if (isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-RIGHT'])=='auto') {
13749
+ // Try to reduce margin-right to accomodate - if still too wide, set margin-right=0 (reduces width)
13750
+ $currblk['margin_right'] = $prevblk['inner_width'] - ($currblk['css_set_width'] + $currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + $currblk['padding_right'] + $currblk['margin_left']);
13751
+ if ($currblk['margin_right'] < 0) {
13752
+ $currblk['margin_right'] = 0;
13753
+ }
13754
+ }
13755
+ else {
13756
+ // Try to reduce margin-left to accomodate - if still too wide, set margin-left=0 (reduces width)
13757
+ // Try to reduce margin-right to accomodate - if still too wide, set margin-right=0 (reduces width)
13758
+ $currblk['margin_right'] = $prevblk['inner_width'] - ($currblk['css_set_width'] + $currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + $currblk['padding_right'] + $currblk['margin_left']);
13759
+ if ($currblk['margin_right'] < 0) {
13760
+ $currblk['margin_right'] = 0;
13761
+ }
13762
+ }
13763
+ }
13764
+
13765
+ $currblk['outer_left_margin'] = $prevblk['outer_left_margin'] + $currblk['margin_left'] + $prevblk['border_left']['w'] + $prevblk['padding_left'];
13766
+ $currblk['outer_right_margin'] = $prevblk['outer_right_margin'] + $currblk['margin_right'] + $prevblk['border_right']['w'] + $prevblk['padding_right'];
13767
+
13768
+ $currblk['width'] = $this->pgwidth - ($currblk['outer_right_margin'] + $currblk['outer_left_margin']);
13769
+ $currblk['inner_width'] = $currblk['width'] - ($currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + $currblk['padding_right']);
13770
+
13771
+ // Check DIV is not now too narrow to fit text
13772
+ $mw = 2*$this->GetCharWidth('W',false);
13773
+ if ($currblk['inner_width'] < $mw) {
13774
+ $currblk['padding_left'] = 0;
13775
+ $currblk['padding_right'] = 0;
13776
+ $currblk['border_left']['w'] = 0.2;
13777
+ $currblk['border_right']['w'] = 0.2;
13778
+ $currblk['margin_left'] = 0;
13779
+ $currblk['margin_right'] = 0;
13780
+ $currblk['outer_left_margin'] = $prevblk['outer_left_margin'] + $currblk['margin_left'] + $prevblk['border_left']['w'] + $prevblk['padding_left'];
13781
+ $currblk['outer_right_margin'] = $prevblk['outer_right_margin'] + $currblk['margin_right'] + $prevblk['border_right']['w'] + $prevblk['padding_right'];
13782
+ $currblk['width'] = $this->pgwidth - ($currblk['outer_right_margin'] + $currblk['outer_left_margin']);
13783
+ $currblk['inner_width'] = $this->pgwidth - ($currblk['outer_right_margin'] + $currblk['outer_left_margin'] + $currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + $currblk['padding_right']);
13784
+ // if ($currblk['inner_width'] < $mw) { $this->Error("DIV is too narrow for text to fit!"); }
13785
+ }
13786
+
13787
+ $this->x = $this->lMargin + $currblk['outer_left_margin'];
13788
+
13789
+ if (isset($properties['BACKGROUND-IMAGE']) && $properties['BACKGROUND-IMAGE'] && !$this->kwt && !$this->ColActive && !$this->keep_block_together) {
13790
+ $ret = $this->SetBackground($properties, $currblk['inner_width']);
13791
+ if ($ret) { $currblk['background-image'] = $ret; }
13792
+ }
13793
+
13794
+ if ($this->use_kwt && isset($attr['KEEP-WITH-TABLE']) && !$this->ColActive && !$this->keep_block_together) {
13795
+ $this->kwt = true;
13796
+ $this->kwt_y0 = $this->y;
13797
+ $this->kwt_x0 = $this->x;
13798
+ $this->kwt_height = 0;
13799
+ $this->kwt_buffer = array();
13800
+ $this->kwt_Links = array();
13801
+ $this->kwt_Annots = array();
13802
+ $this->kwt_moved = false;
13803
+ $this->kwt_saved = false;
13804
+ $this->kwt_Reference = array();
13805
+ $this->kwt_BMoutlines = array();
13806
+ $this->kwt_toc = array();
13807
+ }
13808
+ else {
13809
+ $this->kwt = false;
13810
+ } // *TABLES*
13811
+
13812
+ //Save x,y coords in case we need to print borders...
13813
+ $currblk['y0'] = $this->y;
13814
+ $currblk['x0'] = $this->x;
13815
+ $currblk['startpage'] = $this->page;
13816
+ $this->oldy = $this->y;
13817
+
13818
+ $this->lastblocklevelchange = 1 ;
13819
+
13820
+ break;
13821
+
13822
+ case 'HR':
13823
+ // Added mPDF 3.0 Float DIV - CLEAR
13824
+ if (isset($attr['STYLE'])) {
13825
+ $properties = $this->cssmgr->readInlineCSS($attr['STYLE']);
13826
+ if (isset($properties['CLEAR'])) { $this->ClearFloats(strtoupper($properties['CLEAR']),$this->blklvl); } // *CSS-FLOAT*
13827
+ }
13828
+
13829
+ $this->ignorefollowingspaces = true;
13830
+
13831
+ $objattr = array();
13832
+ $objattr['margin_top'] = 0;
13833
+ $objattr['margin_bottom'] = 0;
13834
+ $objattr['margin_left'] = 0;
13835
+ $objattr['margin_right'] = 0;
13836
+ $objattr['width'] = 0;
13837
+ $objattr['height'] = 0;
13838
+ $objattr['border_top']['w'] = 0;
13839
+ $objattr['border_bottom']['w'] = 0;
13840
+ $objattr['border_left']['w'] = 0;
13841
+ $objattr['border_right']['w'] = 0;
13842
+ $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
13843
+ if (isset($properties['MARGIN-TOP'])) { $objattr['margin_top'] = $this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
13844
+ if (isset($properties['MARGIN-BOTTOM'])) { $objattr['margin_bottom'] = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
13845
+ if (isset($properties['WIDTH'])) { $objattr['width'] = $this->ConvertSize($properties['WIDTH'],$this->blk[$this->blklvl]['inner_width']); }
13846
+ else if(isset($attr['WIDTH']) && $attr['WIDTH'] != '') $objattr['width'] = $this->ConvertSize($attr['WIDTH'],$this->blk[$this->blklvl]['inner_width']);
13847
+ if (isset($properties['TEXT-ALIGN'])) { $objattr['align'] = $align[strtolower($properties['TEXT-ALIGN'])]; }
13848
+ else if(isset($attr['ALIGN']) && $attr['ALIGN'] != '') $objattr['align'] = $align[strtolower($attr['ALIGN'])];
13849
+
13850
+ if (isset($properties['MARGIN-LEFT']) && strtolower($properties['MARGIN-LEFT'])=='auto') {
13851
+ $objattr['align'] = 'R';
13852
+ }
13853
+ if (isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-RIGHT'])=='auto') {
13854
+ $objattr['align'] = 'L';
13855
+ if (isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-RIGHT'])=='auto' && isset($properties['MARGIN-LEFT']) && strtolower($properties['MARGIN-LEFT'])=='auto') {
13856
+ $objattr['align'] = 'C';
13857
+ }
13858
+ }
13859
+ if (isset($properties['COLOR'])) { $objattr['color'] = $this->ConvertColor($properties['COLOR']); }
13860
+ else if(isset($attr['COLOR']) && $attr['COLOR'] != '') $objattr['color'] = $this->ConvertColor($attr['COLOR']);
13861
+ if (isset($properties['HEIGHT'])) { $objattr['linewidth'] = $this->ConvertSize($properties['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
13862
+
13863
+
13864
+ if ($this->tableLevel) {
13865
+ $objattr['W-PERCENT'] = 100;
13866
+ if (isset($properties['WIDTH']) && stristr($properties['WIDTH'],'%')) {
13867
+ $properties['WIDTH'] += 0; //make "90%" become simply "90"
13868
+ $objattr['W-PERCENT'] = $properties['WIDTH'];
13869
+ }
13870
+ if (isset($attr['WIDTH']) && stristr($attr['WIDTH'],'%')) {
13871
+ $attr['WIDTH'] += 0; //make "90%" become simply "90"
13872
+ $objattr['W-PERCENT'] = $attr['WIDTH'];
13873
+ }
13874
+ }
13875
+
13876
+ $objattr['type'] = 'hr';
13877
+ $objattr['height'] = $objattr['linewidth'] + $objattr['margin_top'] + $objattr['margin_bottom'];
13878
+ $e = "\xbb\xa4\xactype=image,objattr=".serialize($objattr)."\xbb\xa4\xac";
13879
+
13880
+ // Clear properties - tidy up
13881
+ $properties = array();
13882
+
13883
+ // Output it to buffers
13884
+ if ($this->tableLevel) {
13885
+ if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
13886
+ $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
13887
+ }
13888
+ elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
13889
+ $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
13890
+ }
13891
+ $this->cell[$this->row][$this->col]['s'] = 0 ;// reset
13892
+ $this->_saveCellTextBuffer($e, $this->HREF);
13893
+ }
13894
+ else {
13895
+ $this->_saveTextBuffer($e, $this->HREF);
13896
+ } // *TABLES*
13897
+
13898
+ break;
13899
+
13900
+
13901
+
13902
+
13903
+ // *********** FORM ELEMENTS ********************
13904
+
13905
+
13906
+
13907
+ // *********** GRAPH ********************
13908
+ case 'JPGRAPH':
13909
+ if (!$this->useGraphs) { break; }
13910
+ if ($attr['TABLE']) { $gid = strtoupper($attr['TABLE']); }
13911
+ else { $gid = '0'; }
13912
+ if (!is_array($this->graphs[$gid]) || count($this->graphs[$gid])==0 ) { break; }
13913
+ include_once(_MPDF_PATH.'graph.php');
13914
+ $this->graphs[$gid]['attr'] = $attr;
13915
+
13916
+
13917
+ if (isset($this->graphs[$gid]['attr']['WIDTH']) && $this->graphs[$gid]['attr']['WIDTH']) {
13918
+ $this->graphs[$gid]['attr']['cWIDTH']=$this->ConvertSize($this->graphs[$gid]['attr']['WIDTH'],$pgwidth);
13919
+ } // mm
13920
+ if (isset($this->graphs[$gid]['attr']['HEIGHT']) && $this->graphs[$gid]['attr']['HEIGHT']) {
13921
+ $this->graphs[$gid]['attr']['cHEIGHT']=$this->ConvertSize($this->graphs[$gid]['attr']['HEIGHT'],$pgwidth);
13922
+ }
13923
+
13924
+ $graph_img = print_graph($this->graphs[$gid],$this->blk[$this->blklvl]['inner_width']);
13925
+ if ($graph_img) {
13926
+ if(isset($attr['ROTATE'])) {
13927
+ if ($attr['ROTATE']==90 || $attr['ROTATE']==-90) {
13928
+ $tmpw = $graph_img['w'];
13929
+ $graph_img['w']= $graph_img['h'];
13930
+ $graph_img['h']= $tmpw;
13931
+ }
13932
+ }
13933
+ $attr['SRC'] = $graph_img['file'];
13934
+ $attr['WIDTH'] = $graph_img['w'];
13935
+ $attr['HEIGHT'] = $graph_img['h'];
13936
+ }
13937
+ else { break; }
13938
+
13939
+ // *********** IMAGE ********************
13940
+ case 'IMG':
13941
+ $objattr = array();
13942
+ $objattr['margin_top'] = 0;
13943
+ $objattr['margin_bottom'] = 0;
13944
+ $objattr['margin_left'] = 0;
13945
+ $objattr['margin_right'] = 0;
13946
+ $objattr['padding_top'] = 0;
13947
+ $objattr['padding_bottom'] = 0;
13948
+ $objattr['padding_left'] = 0;
13949
+ $objattr['padding_right'] = 0;
13950
+ $objattr['width'] = 0;
13951
+ $objattr['height'] = 0;
13952
+ $objattr['border_top']['w'] = 0;
13953
+ $objattr['border_bottom']['w'] = 0;
13954
+ $objattr['border_left']['w'] = 0;
13955
+ $objattr['border_right']['w'] = 0;
13956
+ if(isset($attr['SRC'])) {
13957
+ $srcpath = $attr['SRC'];
13958
+ $orig_srcpath = $attr['ORIG_SRC'];
13959
+ $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
13960
+ if(isset($properties ['DISPLAY']) && strtolower($properties ['DISPLAY'])=='none') {
13961
+ return;
13962
+ }
13963
+ // mPDF 5.6.01 - LAYERS
13964
+ if (isset($properties['Z-INDEX']) && $this->currentlayer==0) {
13965
+ $v = intval($properties['Z-INDEX']);
13966
+ if ($v > 0) {
13967
+ $objattr['z-index'] = $v;
13968
+ }
13969
+ }
13970
+
13971
+ $objattr['visibility'] = 'visible';
13972
+ if (isset($properties['VISIBILITY'])) {
13973
+ $v = strtolower($properties['VISIBILITY']);
13974
+ if (($v == 'hidden' || $v == 'printonly' || $v == 'screenonly') && $this->visibility=='visible') {
13975
+ $objattr['visibility'] = $v;
13976
+ }
13977
+ }
13978
+
13979
+ // VSPACE and HSPACE converted to margins in MergeCSS
13980
+ if (isset($properties['MARGIN-TOP'])) { $objattr['margin_top']=$this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
13981
+ if (isset($properties['MARGIN-BOTTOM'])) { $objattr['margin_bottom'] = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
13982
+ if (isset($properties['MARGIN-LEFT'])) { $objattr['margin_left'] = $this->ConvertSize($properties['MARGIN-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
13983
+ if (isset($properties['MARGIN-RIGHT'])) { $objattr['margin_right'] = $this->ConvertSize($properties['MARGIN-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
13984
+
13985
+ if (isset($properties['PADDING-TOP'])) { $objattr['padding_top']=$this->ConvertSize($properties['PADDING-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
13986
+ if (isset($properties['PADDING-BOTTOM'])) { $objattr['padding_bottom'] = $this->ConvertSize($properties['PADDING-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
13987
+ if (isset($properties['PADDING-LEFT'])) { $objattr['padding_left'] = $this->ConvertSize($properties['PADDING-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
13988
+ if (isset($properties['PADDING-RIGHT'])) { $objattr['padding_right'] = $this->ConvertSize($properties['PADDING-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
13989
+
13990
+ if (isset($properties['BORDER-TOP'])) { $objattr['border_top'] = $this->border_details($properties['BORDER-TOP']); }
13991
+ if (isset($properties['BORDER-BOTTOM'])) { $objattr['border_bottom'] = $this->border_details($properties['BORDER-BOTTOM']); }
13992
+ if (isset($properties['BORDER-LEFT'])) { $objattr['border_left'] = $this->border_details($properties['BORDER-LEFT']); }
13993
+ if (isset($properties['BORDER-RIGHT'])) { $objattr['border_right'] = $this->border_details($properties['BORDER-RIGHT']); }
13994
+
13995
+ if (isset($properties['VERTICAL-ALIGN'])) { $objattr['vertical-align'] = $align[strtolower($properties['VERTICAL-ALIGN'])]; }
13996
+ $w = 0;
13997
+ $h = 0;
13998
+ if(isset($properties['WIDTH'])) $w = $this->ConvertSize($properties['WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
13999
+ else if(isset($attr['WIDTH'])) $w = $this->ConvertSize($attr['WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14000
+ if(isset($properties['HEIGHT'])) $h = $this->ConvertSize($properties['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14001
+ else if(isset($attr['HEIGHT'])) $h = $this->ConvertSize($attr['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14002
+ // mPDF 5.5.15 // mPDF 5.6.60
14003
+ $maxw=$maxh=$minw=$minh=false;
14004
+ if(isset($properties['MAX-WIDTH'])) $maxw = $this->ConvertSize($properties['MAX-WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14005
+ else if(isset($attr['MAX-WIDTH'])) $maxw = $this->ConvertSize($attr['MAX-WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14006
+ if(isset($properties['MAX-HEIGHT'])) $maxh = $this->ConvertSize($properties['MAX-HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14007
+ else if(isset($attr['MAX-HEIGHT'])) $maxh = $this->ConvertSize($attr['MAX-HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14008
+ if(isset($properties['MIN-WIDTH'])) $minw = $this->ConvertSize($properties['MIN-WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14009
+ else if(isset($attr['MIN-WIDTH'])) $minw = $this->ConvertSize($attr['MIN-WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14010
+ if(isset($properties['MIN-HEIGHT'])) $minh = $this->ConvertSize($properties['MIN-HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14011
+ else if(isset($attr['MIN-HEIGHT'])) $minh = $this->ConvertSize($attr['MIN-HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14012
+
14013
+ if (isset($properties['OPACITY']) && $properties['OPACITY'] > 0 && $properties['OPACITY'] <= 1) { $objattr['opacity'] = $properties['OPACITY']; }
14014
+ if ($this->HREF) {
14015
+ if (strpos($this->HREF,".") === false && strpos($this->HREF,"@") !== 0) {
14016
+ $href = $this->HREF;
14017
+ while(array_key_exists($href,$this->internallink)) $href="#".$href;
14018
+ $this->internallink[$href] = $this->AddLink();
14019
+ $objattr['link'] = $this->internallink[$href];
14020
+ }
14021
+ else { $objattr['link'] = $this->HREF; }
14022
+ }
14023
+ $extraheight = $objattr['padding_top'] + $objattr['padding_bottom'] + $objattr['margin_top'] + $objattr['margin_bottom'] + $objattr['border_top']['w'] + $objattr['border_bottom']['w'];
14024
+ $extrawidth = $objattr['padding_left'] + $objattr['padding_right'] + $objattr['margin_left'] + $objattr['margin_right'] + $objattr['border_left']['w'] + $objattr['border_right']['w'];
14025
+
14026
+ if(isset($properties['GRADIENT-MASK']) && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/',$properties['GRADIENT-MASK'])) {
14027
+ $objattr['GRADIENT-MASK'] = $properties['GRADIENT-MASK'];
14028
+ }
14029
+
14030
+ // Image file
14031
+ $info=$this->_getImage($srcpath, true, true, $orig_srcpath);
14032
+ if(!$info) {
14033
+ $info = $this->_getImage($this->noImageFile);
14034
+ if ($info) {
14035
+ $srcpath = $this->noImageFile;
14036
+ $w = ($info['w'] * (25.4/$this->dpi));
14037
+ $h = ($info['h'] * (25.4/$this->dpi));
14038
+ }
14039
+ }
14040
+ if(!$info) break;
14041
+
14042
+ if(isset($attr['ROTATE'])) { $image_orientation = $attr['ROTATE']; }
14043
+ else if(isset($properties['IMAGE-ORIENTATION'])) { $image_orientation = $properties['IMAGE-ORIENTATION']; }
14044
+ else { $image_orientation = 0; }
14045
+ if($image_orientation) {
14046
+ if ($image_orientation==90 || $image_orientation==-90 || $image_orientation==270) {
14047
+ $tmpw = $info['w'];
14048
+ $info['w'] = $info['h'];
14049
+ $info['h'] = $tmpw;
14050
+ }
14051
+ $objattr['ROTATE'] = $image_orientation;
14052
+ }
14053
+
14054
+ $objattr['file'] = $srcpath;
14055
+ //Default width and height calculation if needed
14056
+ if($w==0 and $h==0) {
14057
+ if ($info['type']=='svg') {
14058
+ // SVG units are pixels
14059
+ $w = abs($info['w'])/_MPDFK;
14060
+ $h = abs($info['h'])/_MPDFK;
14061
+ }
14062
+ else {
14063
+ //Put image at default image dpi
14064
+ $w=($info['w']/_MPDFK) * (72/$this->img_dpi);
14065
+ $h=($info['h']/_MPDFK) * (72/$this->img_dpi);
14066
+ }
14067
+ if (isset($properties['IMAGE-RESOLUTION'])) {
14068
+ if (preg_match('/from-image/i', $properties['IMAGE-RESOLUTION']) && isset($info['set-dpi']) && $info['set-dpi']>0) {
14069
+ $w *= $this->img_dpi / $info['set-dpi'];
14070
+ $h *= $this->img_dpi / $info['set-dpi'];
14071
+ }
14072
+ else if (preg_match('/(\d+)dpi/i', $properties['IMAGE-RESOLUTION'], $m)) {
14073
+ $dpi = $m[1];
14074
+ if ($dpi > 0) {
14075
+ $w *= $this->img_dpi / $dpi;
14076
+ $h *= $this->img_dpi / $dpi;
14077
+ }
14078
+ }
14079
+ }
14080
+ }
14081
+ // IF WIDTH OR HEIGHT SPECIFIED
14082
+ if($w==0) $w=abs($h*$info['w']/$info['h']);
14083
+ if($h==0) $h=abs($w*$info['h']/$info['w']);
14084
+
14085
+ // mPDF 5.5.15
14086
+ if ($minw && $w<$minw) { $w = $minw; $h=abs($w*$info['h']/$info['w']); }
14087
+ if ($maxw && $w>$maxw) { $w = $maxw; $h=abs($w*$info['h']/$info['w']); }
14088
+ if ($minh && $h<$minh) { $h = $minh; $w=abs($h*$info['w']/$info['h']); }
14089
+ if ($maxh && $h>$maxh) { $h = $maxh; $w=abs($h*$info['w']/$info['h']); }
14090
+
14091
+ // Resize to maximum dimensions of page
14092
+ $maxWidth = $this->blk[$this->blklvl]['inner_width'];
14093
+ $maxHeight = $this->h - ($this->tMargin + $this->bMargin + 1) ;
14094
+ if ($this->fullImageHeight) { $maxHeight = $this->fullImageHeight; }
14095
+ if ($w + $extrawidth > $maxWidth ) {
14096
+ $w = $maxWidth - $extrawidth;
14097
+ $h=abs($w*$info['h']/$info['w']);
14098
+ }
14099
+
14100
+ if ($h + $extraheight > $maxHeight ) {
14101
+ $h = $maxHeight - $extraheight;
14102
+ $w=abs($h*$info['w']/$info['h']);
14103
+ }
14104
+ $objattr['type'] = 'image';
14105
+ $objattr['itype'] = $info['type'];
14106
+
14107
+ $objattr['orig_h'] = $info['h'];
14108
+ $objattr['orig_w'] = $info['w'];
14109
+ if ($info['type']=='svg') {
14110
+ $objattr['wmf_x'] = $info['x'];
14111
+ $objattr['wmf_y'] = $info['y'];
14112
+ }
14113
+ $objattr['height'] = $h + $extraheight;
14114
+ $objattr['width'] = $w + $extrawidth;
14115
+ $objattr['image_height'] = $h;
14116
+ $objattr['image_width'] = $w;
14117
+ if (!$this->ColActive && !$this->tableLevel && !$this->listlvl && !$this->kwt && !$this->keep_block_together) {
14118
+ if (isset($properties['FLOAT']) && (strtoupper($properties['FLOAT']) == 'RIGHT' || strtoupper($properties['FLOAT']) == 'LEFT')) {
14119
+ $objattr['float'] = substr(strtoupper($properties['FLOAT']),0,1);
14120
+ }
14121
+ }
14122
+
14123
+ $e = "\xbb\xa4\xactype=image,objattr=".serialize($objattr)."\xbb\xa4\xac";
14124
+
14125
+ // Clear properties - tidy up
14126
+ $properties = array();
14127
+
14128
+ // Output it to buffers
14129
+ if ($this->tableLevel) {
14130
+ $this->_saveCellTextBuffer($e, $this->HREF);
14131
+ $this->cell[$this->row][$this->col]['s'] += $objattr['width'] ;
14132
+ }
14133
+ else {
14134
+ $this->_saveTextBuffer($e, $this->HREF);
14135
+ } // *TABLES*
14136
+ }
14137
+ break;
14138
+
14139
+
14140
+ // *********** CIRCULAR TEXT = TEXTCIRCLE ********************
14141
+ case 'TEXTCIRCLE':
14142
+ $objattr = array();
14143
+ $objattr['margin_top'] = 0;
14144
+ $objattr['margin_bottom'] = 0;
14145
+ $objattr['margin_left'] = 0;
14146
+ $objattr['margin_right'] = 0;
14147
+ $objattr['padding_top'] = 0;
14148
+ $objattr['padding_bottom'] = 0;
14149
+ $objattr['padding_left'] = 0;
14150
+ $objattr['padding_right'] = 0;
14151
+ $objattr['width'] = 0;
14152
+ $objattr['height'] = 0;
14153
+ $objattr['border_top']['w'] = 0;
14154
+ $objattr['border_bottom']['w'] = 0;
14155
+ $objattr['border_left']['w'] = 0;
14156
+ $objattr['border_right']['w'] = 0;
14157
+ $objattr['top-text'] = '';
14158
+ $objattr['bottom-text'] = '';
14159
+ $objattr['r'] = 20; // radius (default value here for safety)
14160
+ $objattr['space-width'] = 120;
14161
+ $objattr['char-width'] = 100;
14162
+
14163
+ $this->InlineProperties[$tag] = $this->saveInlineProperties();
14164
+ $properties = $this->cssmgr->MergeCSS('INLINE',$tag,$attr);
14165
+
14166
+ if(isset($properties ['DISPLAY']) && strtolower($properties ['DISPLAY'])=='none') {
14167
+ return;
14168
+ }
14169
+ if (isset($attr['R'])) { $objattr['r']=$this->ConvertSize($attr['R'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
14170
+ if(isset($attr['TOP-TEXT'])) {
14171
+ $objattr['top-text'] = strcode2utf($attr['TOP-TEXT']);
14172
+ $objattr['top-text'] = $this->lesser_entity_decode($objattr['top-text']);
14173
+ if ($this->onlyCoreFonts)
14174
+ $objattr['top-text'] = mb_convert_encoding($objattr['top-text'], $this->mb_enc,'UTF-8');
14175
+ }
14176
+ if(isset($attr['BOTTOM-TEXT'])) {
14177
+ $objattr['bottom-text'] = strcode2utf($attr['BOTTOM-TEXT']);
14178
+ $objattr['bottom-text'] = $this->lesser_entity_decode($objattr['bottom-text']);
14179
+ if ($this->onlyCoreFonts)
14180
+ $objattr['bottom-text'] = mb_convert_encoding($objattr['bottom-text'], $this->mb_enc,'UTF-8');
14181
+ }
14182
+ if(isset($attr['SPACE-WIDTH']) && $attr['SPACE-WIDTH']) { $objattr['space-width'] = $attr['SPACE-WIDTH']; }
14183
+ if(isset($attr['CHAR-WIDTH']) && $attr['CHAR-WIDTH']) { $objattr['char-width'] = $attr['CHAR-WIDTH']; }
14184
+
14185
+ // VISIBILITY
14186
+ $objattr['visibility'] = 'visible';
14187
+ if (isset($properties['VISIBILITY'])) {
14188
+ $v = strtolower($properties['VISIBILITY']);
14189
+ if (($v == 'hidden' || $v == 'printonly' || $v == 'screenonly') && $this->visibility=='visible') {
14190
+ $objattr['visibility'] = $v;
14191
+ }
14192
+ }
14193
+ // mPDF 5.5.23
14194
+ if (isset($properties['FONT-SIZE'])) {
14195
+ if (strtolower($properties['FONT-SIZE'])=='auto') {
14196
+ if ($objattr['top-text'] && $objattr['bottom-text']) {
14197
+ $objattr['fontsize'] = -2;
14198
+ }
14199
+ else {
14200
+ $objattr['fontsize'] = -1;
14201
+ }
14202
+ }
14203
+ else {
14204
+ $mmsize = $this->ConvertSize($properties['FONT-SIZE'],($this->default_font_size/_MPDFK));
14205
+ $this->SetFontSize($mmsize*_MPDFK,false);
14206
+ $objattr['fontsize'] = $this->FontSizePt;
14207
+ }
14208
+ }
14209
+ // mPDF 5.5.23
14210
+ if(isset($attr['DIVIDER'])) {
14211
+ $objattr['divider'] = strcode2utf($attr['DIVIDER']);
14212
+ $objattr['divider'] = $this->lesser_entity_decode($objattr['divider']);
14213
+ if ($this->onlyCoreFonts)
14214
+ $objattr['divider'] = mb_convert_encoding($objattr['divider'], $this->mb_enc,'UTF-8');
14215
+
14216
+ }
14217
+
14218
+ if (isset($properties['COLOR'])) { $objattr['color'] = $this->ConvertColor($properties['COLOR']); }
14219
+
14220
+ $objattr['fontstyle'] = '';
14221
+ if (isset($properties['FONT-WEIGHT'])) {
14222
+ if (strtoupper($properties['FONT-WEIGHT']) == 'BOLD') { $objattr['fontstyle'] .= 'B'; }
14223
+ }
14224
+ if (isset($properties['FONT-STYLE'])) {
14225
+ if (strtoupper($properties['FONT-STYLE']) == 'ITALIC') { $objattr['fontstyle'] .= 'I'; }
14226
+ }
14227
+
14228
+ if (isset($properties['FONT-FAMILY'])) {
14229
+ $this->SetFont($properties['FONT-FAMILY'],$this->FontStyle,0,false);
14230
+ }
14231
+ $objattr['fontfamily'] = $this->FontFamily;
14232
+
14233
+ // VSPACE and HSPACE converted to margins in MergeCSS
14234
+ if (isset($properties['MARGIN-TOP'])) { $objattr['margin_top']=$this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
14235
+ if (isset($properties['MARGIN-BOTTOM'])) { $objattr['margin_bottom'] = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
14236
+ if (isset($properties['MARGIN-LEFT'])) { $objattr['margin_left'] = $this->ConvertSize($properties['MARGIN-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
14237
+ if (isset($properties['MARGIN-RIGHT'])) { $objattr['margin_right'] = $this->ConvertSize($properties['MARGIN-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
14238
+
14239
+ if (isset($properties['PADDING-TOP'])) { $objattr['padding_top']=$this->ConvertSize($properties['PADDING-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
14240
+ if (isset($properties['PADDING-BOTTOM'])) { $objattr['padding_bottom'] = $this->ConvertSize($properties['PADDING-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
14241
+ if (isset($properties['PADDING-LEFT'])) { $objattr['padding_left'] = $this->ConvertSize($properties['PADDING-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
14242
+ if (isset($properties['PADDING-RIGHT'])) { $objattr['padding_right'] = $this->ConvertSize($properties['PADDING-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
14243
+
14244
+ if (isset($properties['BORDER-TOP'])) { $objattr['border_top'] = $this->border_details($properties['BORDER-TOP']); }
14245
+ if (isset($properties['BORDER-BOTTOM'])) { $objattr['border_bottom'] = $this->border_details($properties['BORDER-BOTTOM']); }
14246
+ if (isset($properties['BORDER-LEFT'])) { $objattr['border_left'] = $this->border_details($properties['BORDER-LEFT']); }
14247
+ if (isset($properties['BORDER-RIGHT'])) { $objattr['border_right'] = $this->border_details($properties['BORDER-RIGHT']); }
14248
+
14249
+ if (isset($properties['OPACITY']) && $properties['OPACITY'] > 0 && $properties['OPACITY'] <= 1) { $objattr['opacity'] = $properties['OPACITY']; }
14250
+ if (isset($properties['BACKGROUND-COLOR']) && $properties['BACKGROUND-COLOR'] != '') { $objattr['bgcolor'] = $this->ConvertColor($properties['BACKGROUND-COLOR']); }
14251
+ else { $objattr['bgcolor'] = false; }
14252
+ if ($this->HREF) {
14253
+ if (strpos($this->HREF,".") === false && strpos($this->HREF,"@") !== 0) {
14254
+ $href = $this->HREF;
14255
+ while(array_key_exists($href,$this->internallink)) $href="#".$href;
14256
+ $this->internallink[$href] = $this->AddLink();
14257
+ $objattr['link'] = $this->internallink[$href];
14258
+ }
14259
+ else { $objattr['link'] = $this->HREF; }
14260
+ }
14261
+ $extraheight = $objattr['padding_top'] + $objattr['padding_bottom'] + $objattr['margin_top'] + $objattr['margin_bottom'] + $objattr['border_top']['w'] + $objattr['border_bottom']['w'];
14262
+ $extrawidth = $objattr['padding_left'] + $objattr['padding_right'] + $objattr['margin_left'] + $objattr['margin_right'] + $objattr['border_left']['w'] + $objattr['border_right']['w'];
14263
+
14264
+
14265
+ $w = $objattr['r']*2;
14266
+ $h = $w;
14267
+ $objattr['height'] = $h + $extraheight;
14268
+ $objattr['width'] = $w + $extrawidth;
14269
+ $objattr['type'] = 'textcircle';
14270
+
14271
+ $e = "\xbb\xa4\xactype=image,objattr=".serialize($objattr)."\xbb\xa4\xac";
14272
+
14273
+ // Clear properties - tidy up
14274
+ $properties = array();
14275
+
14276
+ // Output it to buffers
14277
+ if ($this->tableLevel) {
14278
+ $this->_saveCellTextBuffer($e, $this->HREF);
14279
+ $this->cell[$this->row][$this->col]['s'] += $objattr['width'] ;
14280
+ }
14281
+ else {
14282
+ $this->_saveTextBuffer($e, $this->HREF);
14283
+ } // *TABLES*
14284
+
14285
+ if ($this->InlineProperties[$tag]) { $this->restoreInlineProperties($this->InlineProperties[$tag]); }
14286
+ unset($this->InlineProperties[$tag]);
14287
+
14288
+ break;
14289
+
14290
+
14291
+
14292
+ case 'TABLE': // TABLE-BEGIN
14293
+ $this->tdbegin = false;
14294
+ $this->lastoptionaltag = '';
14295
+ // Disable vertical justification in columns
14296
+ if ($this->lastblocklevelchange == 1) { $blockstate = 1; } // Top margins/padding only
14297
+ else if ($this->lastblocklevelchange < 1) { $blockstate = 0; } // NO margins/padding
14298
+ // called from block after new div e.g. <div> ... <table> ... Outputs block top margin/border and padding
14299
+ if (count($this->textbuffer) == 0 && $this->lastblocklevelchange == 1 && !$this->tableLevel && !$this->kwt) {
14300
+ $this->newFlowingBlock( $this->blk[$this->blklvl]['width'],$this->lineheight,'',false,false,1,true, $this->blk[$this->blklvl]['direction']);
14301
+ $this->finishFlowingBlock(true); // true = END of flowing block
14302
+ }
14303
+ else if (!$this->tableLevel && count($this->textbuffer)) { $this->printbuffer($this->textbuffer,$blockstate); }
14304
+
14305
+ $this->textbuffer=array();
14306
+ $this->lastblocklevelchange = -1;
14307
+ if ($this->tableLevel) { // i.e. now a nested table coming...
14308
+ // Save current level table
14309
+ // mPDF 5.4.10
14310
+ $this->cell['PARENTCELL'] = $this->saveInlineProperties();
14311
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['baseProperties']= $this->base_table_properties;
14312
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cells'] = $this->cell;
14313
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['currrow'] = $this->row;
14314
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['currcol'] = $this->col;
14315
+ }
14316
+ $this->tableLevel++;
14317
+ $this->cssmgr->tbCSSlvl++;
14318
+
14319
+ if ($this->tableLevel>1) { // inherit table properties from cell in which nested
14320
+ $this->base_table_properties['FONT-KERNING'] = $this->kerning ;
14321
+ $this->base_table_properties['LETTER-SPACING'] = $this->lSpacingCSS ;
14322
+ $this->base_table_properties['WORD-SPACING'] = $this->wSpacingCSS ;
14323
+ }
14324
+
14325
+ if (isset($this->tbctr[$this->tableLevel])) { $this->tbctr[$this->tableLevel]++; }
14326
+ else { $this->tbctr[$this->tableLevel] = 1; }
14327
+
14328
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['level'] = $this->tableLevel;
14329
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['levelid'] = $this->tbctr[$this->tableLevel];
14330
+
14331
+ if ($this->tableLevel > $this->innermostTableLevel) { $this->innermostTableLevel = $this->tableLevel; }
14332
+ if ($this->tableLevel > 1) {
14333
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nestedpos'] = array($this->row,$this->col,$this->tbctr[($this->tableLevel-1)]);
14334
+ }
14335
+ //++++++++++++++++++++++++++++
14336
+
14337
+ $this->cell = array();
14338
+ $this->col=-1; //int
14339
+ $this->row=-1; //int
14340
+ $table = &$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]];
14341
+
14342
+ // New table - any level
14343
+ if ($this->cacheTables) {
14344
+ $this->packTableData = true; // required for cacheTables
14345
+ $this->simpleTables = false; // Cannot co-exist with cacheTables
14346
+ $table['cache'] = _MPDF_TEMP_PATH.'_tempTblCache'.RAND(1,1000000).'.dat';
14347
+ $fh = fopen($table['cache'] , "wb") or $this->Error("When using cacheTables, you must have read/write access to cache files (".$table['cache'] .")");
14348
+ fwrite($fh, "\x00");
14349
+ fclose($fh);
14350
+ $table['ptr'] = 1 ; // Must not be 0
14351
+ }
14352
+
14353
+ $table['direction'] = $this->directionality;
14354
+ $table['bgcolor'] = false;
14355
+ $table['va'] = false;
14356
+ $table['txta'] = false;
14357
+ $table['topntail'] = false;
14358
+ $table['thead-underline'] = false;
14359
+ $table['border'] = false;
14360
+ $table['border_details']['R']['w'] = 0;
14361
+ $table['border_details']['L']['w'] = 0;
14362
+ $table['border_details']['T']['w'] = 0;
14363
+ $table['border_details']['B']['w'] = 0;
14364
+ $table['border_details']['R']['style'] = '';
14365
+ $table['border_details']['L']['style'] = '';
14366
+ $table['border_details']['T']['style'] = '';
14367
+ $table['border_details']['B']['style'] = '';
14368
+ $table['max_cell_border_width']['R'] = 0;
14369
+ $table['max_cell_border_width']['L'] = 0;
14370
+ $table['max_cell_border_width']['T'] = 0;
14371
+ $table['max_cell_border_width']['B'] = 0;
14372
+ $table['padding']['L'] = false;
14373
+ $table['padding']['R'] = false;
14374
+ $table['padding']['T'] = false;
14375
+ $table['padding']['B'] = false;
14376
+ $table['margin']['L'] = false;
14377
+ $table['margin']['R'] = false;
14378
+ $table['margin']['T'] = false;
14379
+ $table['margin']['B'] = false;
14380
+ $table['a'] = false;
14381
+ $table['border_spacing_H'] = false;
14382
+ $table['border_spacing_V'] = false;
14383
+ $table['decimal_align'] = false; // mPDF 5.6.13
14384
+ $this->Reset();
14385
+ $this->InlineProperties = array();
14386
+ $this->spanlvl = 0;
14387
+ $table['nc'] = $table['nr'] = 0;
14388
+ $this->tablethead = 0;
14389
+ $this->tabletfoot = 0;
14390
+ $this->tabletheadjustfinished = false;
14391
+
14392
+
14393
+ if ($this->blockjustfinished && !count($this->textbuffer) && $this->y != $this->tMargin && $this->collapseBlockMargins && $this->tableLevel==1) { $lastbottommargin = $this->lastblockbottommargin; }
14394
+ else { $lastbottommargin = 0; }
14395
+ $this->lastblockbottommargin = 0;
14396
+ $this->blockjustfinished=false;
14397
+
14398
+ if ($this->tableLevel==1) {
14399
+ $this->tableCJK = false;
14400
+ $this->table_lineheight = $this->normalLineheight;
14401
+ $table['headernrows'] = 0;
14402
+ $table['footernrows'] = 0;
14403
+ $this->base_table_properties = array();
14404
+ }
14405
+
14406
+ // ADDED CSS FUNCIONS FOR TABLE
14407
+ if ($this->cssmgr->tbCSSlvl==1) {
14408
+ $properties = $this->cssmgr->MergeCSS('TOPTABLE',$tag,$attr);
14409
+ }
14410
+ else {
14411
+ $properties = $this->cssmgr->MergeCSS('TABLE',$tag,$attr);
14412
+ }
14413
+ $w = '';
14414
+ if (isset($properties['WIDTH'])) { $w = $properties['WIDTH']; }
14415
+ else if (isset($attr['WIDTH']) && $attr['WIDTH']) { $w = $attr['WIDTH']; }
14416
+
14417
+
14418
+ if(isset($properties['DIRECTION']) && $properties['DIRECTION']) { $table['direction'] = strtolower($properties['DIRECTION']); }
14419
+ else if(isset($attr['DIR']) && $attr['DIR']) { $table['direction'] = strtolower($attr['DIR']); }
14420
+ else if (!isset($table['direction'])){ $table['direction'] = $this->blk[$this->blklvl]['direction']; }
14421
+
14422
+ if (isset($properties['BACKGROUND-COLOR'])) { $table['bgcolor'][-1] = $properties['BACKGROUND-COLOR']; }
14423
+ else if (isset($properties['BACKGROUND'])) { $table['bgcolor'][-1] = $properties['BACKGROUND']; }
14424
+ else if (isset($attr['BGCOLOR'])) { $table['bgcolor'][-1] = $attr['BGCOLOR']; }
14425
+ if (isset($properties['VERTICAL-ALIGN'])) { $table['va'] = $align[strtolower($properties['VERTICAL-ALIGN'])]; }
14426
+ if (isset($properties['TEXT-ALIGN'])) { $table['txta'] = $align[strtolower($properties['TEXT-ALIGN'])]; }
14427
+ if (isset($attr['ALIGN'])) { $table['a'] = $align[strtolower($attr['ALIGN'])]; }
14428
+ if (!$table['a']) {
14429
+ if ($table['direction'] == 'rtl' ) { $table['a'] = 'R'; }
14430
+ else { $table['a'] = 'L'; }
14431
+ }
14432
+
14433
+ if (isset($properties['AUTOSIZE']) && $properties['AUTOSIZE'] && $this->tableLevel ==1) {
14434
+ $this->shrink_this_table_to_fit = $properties['AUTOSIZE'];
14435
+ if ($this->shrink_this_table_to_fit < 1) { $this->shrink_this_table_to_fit = 0; }
14436
+ }
14437
+ if (isset($properties['ROTATE']) && $properties['ROTATE'] && $this->tableLevel ==1) {
14438
+ $this->table_rotate = $properties['ROTATE'];
14439
+ }
14440
+ if (isset($properties['TOPNTAIL'])) { $table['topntail'] = $properties['TOPNTAIL']; }
14441
+ if (isset($properties['THEAD-UNDERLINE'])) { $table['thead-underline'] = $properties['THEAD-UNDERLINE']; }
14442
+
14443
+ if (isset($properties['BORDER'])) {
14444
+ $bord = $this->border_details($properties['BORDER']);
14445
+ if ($bord['s']) {
14446
+ $table['border'] = _BORDER_ALL;
14447
+ $table['border_details']['R'] = $bord;
14448
+ $table['border_details']['L'] = $bord;
14449
+ $table['border_details']['T'] = $bord;
14450
+ $table['border_details']['B'] = $bord;
14451
+ }
14452
+ }
14453
+ if (isset($properties['BORDER-RIGHT'])) {
14454
+ $table['border_details']['R'] = $this->border_details($properties['BORDER-RIGHT']);
14455
+ $this->setBorder($table['border'], _BORDER_RIGHT, $table['border_details']['R']['s']);
14456
+ }
14457
+ if (isset($properties['BORDER-LEFT'])) {
14458
+ $table['border_details']['L'] = $this->border_details($properties['BORDER-LEFT']);
14459
+ $this->setBorder($table['border'], _BORDER_LEFT, $table['border_details']['L']['s']);
14460
+ }
14461
+ if (isset($properties['BORDER-BOTTOM'])) {
14462
+ $table['border_details']['B'] = $this->border_details($properties['BORDER-BOTTOM']);
14463
+ $this->setBorder($table['border'], _BORDER_BOTTOM, $table['border_details']['B']['s']);
14464
+ }
14465
+ if (isset($properties['BORDER-TOP'])) {
14466
+ $table['border_details']['T'] = $this->border_details($properties['BORDER-TOP']);
14467
+ $this->setBorder($table['border'], _BORDER_TOP, $table['border_details']['T']['s']);
14468
+ }
14469
+ if ($table['border']){
14470
+ $this->table_border_css_set = 1;
14471
+ }
14472
+ else {
14473
+ $this->table_border_css_set = 0;
14474
+ }
14475
+
14476
+ if (isset($properties['FONT-FAMILY'])) {
14477
+ $this->default_font = $properties['FONT-FAMILY'];
14478
+ $this->SetFont($this->default_font,'',0,false);
14479
+ }
14480
+ $this->base_table_properties['FONT-FAMILY'] = $this->FontFamily; // mPDF 5.4.10
14481
+
14482
+ if (isset($properties['FONT-SIZE'])) {
14483
+ // mPDF 5.4.10
14484
+ if ($this->tableLevel>1) { $mmsize = $this->ConvertSize($properties['FONT-SIZE'], $this->base_table_properties['FONT-SIZE']); }
14485
+ else { $mmsize = $this->ConvertSize($properties['FONT-SIZE'],$this->default_font_size/_MPDFK); }
14486
+ if ($mmsize) {
14487
+ $this->default_font_size = $mmsize*(_MPDFK);
14488
+ $this->SetFontSize($this->default_font_size,false);
14489
+ }
14490
+ }
14491
+ $this->base_table_properties['FONT-SIZE'] = $this->FontSize.'mm'; // mPDF 5.4.10
14492
+
14493
+ if (isset($properties['FONT-WEIGHT'])) {
14494
+ if (strtoupper($properties['FONT-WEIGHT']) == 'BOLD') { $this->base_table_properties['FONT-WEIGHT'] = 'BOLD'; }
14495
+ }
14496
+ if (isset($properties['FONT-STYLE'])) {
14497
+ if (strtoupper($properties['FONT-STYLE']) == 'ITALIC') { $this->base_table_properties['FONT-STYLE'] = 'ITALIC'; }
14498
+ }
14499
+ if (isset($properties['COLOR'])) {
14500
+ $this->base_table_properties['COLOR'] = $properties['COLOR'];
14501
+ }
14502
+ if (isset($properties['FONT-KERNING'])) {
14503
+ $this->base_table_properties['FONT-KERNING'] = $properties['FONT-KERNING'];
14504
+ }
14505
+ if (isset($properties['LETTER-SPACING'])) {
14506
+ $this->base_table_properties['LETTER-SPACING'] = $properties['LETTER-SPACING'];
14507
+ }
14508
+ if (isset($properties['WORD-SPACING'])) {
14509
+ $this->base_table_properties['WORD-SPACING'] = $properties['WORD-SPACING'];
14510
+ }
14511
+
14512
+ if (isset($properties['PADDING-LEFT'])) {
14513
+ $table['padding']['L'] = $this->ConvertSize($properties['PADDING-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14514
+ }
14515
+ if (isset($properties['PADDING-RIGHT'])) {
14516
+ $table['padding']['R'] = $this->ConvertSize($properties['PADDING-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14517
+ }
14518
+ if (isset($properties['PADDING-TOP'])) {
14519
+ $table['padding']['T'] = $this->ConvertSize($properties['PADDING-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14520
+ }
14521
+ if (isset($properties['PADDING-BOTTOM'])) {
14522
+ $table['padding']['B'] = $this->ConvertSize($properties['PADDING-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14523
+ }
14524
+
14525
+ if (isset($properties['MARGIN-TOP'])) {
14526
+ if ($lastbottommargin) {
14527
+ $tmp = $this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14528
+ if ($tmp > $lastbottommargin) { $properties['MARGIN-TOP'] -= $lastbottommargin; }
14529
+ else { $properties['MARGIN-TOP'] = 0; }
14530
+ }
14531
+ $table['margin']['T'] = $this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14532
+ }
14533
+
14534
+ if (isset($properties['MARGIN-BOTTOM'])) {
14535
+ $table['margin']['B'] = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14536
+ }
14537
+ if (isset($properties['MARGIN-LEFT'])) {
14538
+ $table['margin']['L'] = $this->ConvertSize($properties['MARGIN-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14539
+ }
14540
+
14541
+ if (isset($properties['MARGIN-RIGHT'])) {
14542
+ $table['margin']['R'] = $this->ConvertSize($properties['MARGIN-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14543
+ }
14544
+ if (isset($properties['MARGIN-LEFT']) && isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-LEFT'])=='auto' && strtolower($properties['MARGIN-RIGHT'])=='auto') {
14545
+ $table['a'] = 'C';
14546
+ }
14547
+ else if (isset($properties['MARGIN-LEFT']) && strtolower($properties['MARGIN-LEFT'])=='auto') {
14548
+ $table['a'] = 'R';
14549
+ }
14550
+ else if (isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-RIGHT'])=='auto') {
14551
+ $table['a'] = 'L';
14552
+ }
14553
+
14554
+ if (isset($properties['LINE-HEIGHT']) && $this->tableLevel==1) {
14555
+ $this->table_lineheight = $this->fixLineheight($properties['LINE-HEIGHT']);
14556
+ if (!$this->table_lineheight) { $this->table_lineheight = $this->normalLineheight; }
14557
+ }
14558
+
14559
+ if (isset($properties['BORDER-COLLAPSE']) && strtoupper($properties['BORDER-COLLAPSE'])=='SEPARATE') {
14560
+ $table['borders_separate'] = true;
14561
+ }
14562
+ else {
14563
+ $table['borders_separate'] = false;
14564
+ }
14565
+
14566
+ if (!$table['borders_separate']) { $table['border_spacing_H'] = $table['border_spacing_V'] = 0; }
14567
+ else if (isset($attr['CELLSPACING'])) {
14568
+ $table['border_spacing_H'] = $table['border_spacing_V'] = $this->ConvertSize($attr['CELLSPACING'],$this->blk[$this->blklvl]['inner_width']);
14569
+ }
14570
+ if (isset($properties['BORDER-SPACING-H'])) {
14571
+ $table['border_spacing_H'] = $this->ConvertSize($properties['BORDER-SPACING-H'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14572
+ }
14573
+ if (isset($properties['BORDER-SPACING-V'])) {
14574
+ $table['border_spacing_V'] = $this->ConvertSize($properties['BORDER-SPACING-V'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14575
+ }
14576
+
14577
+ if (isset($properties['EMPTY-CELLS'])) {
14578
+ $table['empty_cells'] = strtolower($properties['EMPTY-CELLS']); // 'hide' or 'show'
14579
+ }
14580
+ else { $table['empty_cells'] = ''; }
14581
+
14582
+ if (isset($properties['PAGE-BREAK-INSIDE']) && strtoupper($properties['PAGE-BREAK-INSIDE'])=='AVOID' && $this->tableLevel==1 && !$this->writingHTMLfooter) {
14583
+ $this->table_keep_together = true;
14584
+ }
14585
+ else if ($this->tableLevel==1) {
14586
+ $this->table_keep_together = false;
14587
+ }
14588
+ if (isset($properties['PAGE-BREAK-AFTER']) && $this->tableLevel==1) {
14589
+ $table['page_break_after'] = strtoupper($properties['PAGE-BREAK-AFTER']);
14590
+ }
14591
+
14592
+ if (isset($properties['BACKGROUND-GRADIENT']) && !$this->kwt && !$this->ColActive) { $table['gradient'] = $properties['BACKGROUND-GRADIENT']; }
14593
+
14594
+ if (isset($properties['BACKGROUND-IMAGE']) && $properties['BACKGROUND-IMAGE'] && !$this->kwt && !$this->ColActive) {
14595
+ $ret = $this->SetBackground($properties, $currblk['inner_width']);
14596
+ if ($ret) { $table['background-image'] = $ret; }
14597
+ }
14598
+
14599
+ if (isset($properties['OVERFLOW'])) {
14600
+ $table['overflow'] = strtolower($properties['OVERFLOW']); // 'hidden' 'wrap' or 'visible' or 'auto'
14601
+ if (($this->ColActive || $this->tableLevel>1) && $table['overflow']=='visible') { unset($table['overflow']); }
14602
+ }
14603
+
14604
+ $properties = array();
14605
+
14606
+
14607
+
14608
+ if (isset($attr['CELLPADDING'])) {
14609
+ $table['cell_padding'] = $attr['CELLPADDING'];
14610
+ }
14611
+ else {
14612
+ $table['cell_padding'] = false;
14613
+ }
14614
+
14615
+ if (isset($attr['BORDER']) && $attr['BORDER']=='1') { // mPDF 5.5.08
14616
+ $this->table_border_attr_set = 1; // mPDF 5.5.08
14617
+ $bord = $this->border_details('#000000 1px solid');
14618
+ if ($bord['s']) {
14619
+ $table['border'] = _BORDER_ALL;
14620
+ $table['border_details']['R'] = $bord;
14621
+ $table['border_details']['L'] = $bord;
14622
+ $table['border_details']['T'] = $bord;
14623
+ $table['border_details']['B'] = $bord;
14624
+ }
14625
+ }
14626
+ else {
14627
+ $this->table_border_attr_set = 0;
14628
+ }
14629
+
14630
+ if ($w) {
14631
+ $maxwidth = $this->blk[$this->blklvl]['inner_width'];
14632
+ if ($table['borders_separate']) {
14633
+ $tblblw = $table['margin']['L'] + $table['margin']['R'] + $table['border_details']['L']['w']/2 + $table['border_details']['R']['w']/2;
14634
+ }
14635
+ else {
14636
+ $tblblw = $table['margin']['L'] + $table['margin']['R'] + $table['max_cell_border_width']['L']/2 + $table['max_cell_border_width']['R']/2;
14637
+ }
14638
+ if (strpos($w,'%') && $this->tableLevel == 1 && !$this->ignore_table_percents ) {
14639
+ // % needs to be of inner box without table margins etc.
14640
+ $maxwidth -= $tblblw ;
14641
+ $wmm = $this->ConvertSize($w,$maxwidth,$this->FontSize,false);
14642
+ $table['w'] = $wmm + $tblblw ;
14643
+ }
14644
+ if (strpos($w,'%') && $this->tableLevel > 1 && !$this->ignore_table_percents && $this->keep_table_proportions) {
14645
+ $table['wpercent'] = $w + 0; // makes 80% -> 80
14646
+ }
14647
+ if (!strpos($w,'%') && !$this->ignore_table_widths ) {
14648
+ $wmm = $this->ConvertSize($w,$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14649
+ $table['w'] = $wmm + $tblblw ;
14650
+ }
14651
+ if (!$this->keep_table_proportions) {
14652
+ if (isset($table['w']) && $table['w'] > $this->blk[$this->blklvl]['inner_width']) { $table['w'] = $this->blk[$this->blklvl]['inner_width']; }
14653
+ }
14654
+ }
14655
+
14656
+ if (isset($attr['AUTOSIZE']) && $this->tableLevel==1) {
14657
+ $this->shrink_this_table_to_fit = $attr['AUTOSIZE'];
14658
+ if ($this->shrink_this_table_to_fit < 1) { $this->shrink_this_table_to_fit = 1; }
14659
+ }
14660
+ if (isset($attr['ROTATE']) && $this->tableLevel==1) {
14661
+ $this->table_rotate = $attr['ROTATE'];
14662
+ }
14663
+
14664
+ //++++++++++++++++++++++++++++
14665
+ // keeping block together on one page
14666
+ // Autosize is now forced therefore keep block together disabled
14667
+ if ($this->keep_block_together) {
14668
+ $this->keep_block_together = 0;
14669
+ $this->printdivbuffer();
14670
+ $this->blk[$this->blklvl]['keep_block_together'] = 0;
14671
+ }
14672
+ if ($this->table_rotate) {
14673
+ $this->tbrot_Links = array();
14674
+ $this->tbrot_Annots = array();
14675
+ $this->tbrotForms = array();
14676
+ $this->tbrot_Reference = array();
14677
+ $this->tbrot_BMoutlines = array();
14678
+ $this->tbrot_toc = array();
14679
+ }
14680
+
14681
+ if ($this->kwt) {
14682
+ if ($this->table_rotate) { $this->table_keep_together = true; }
14683
+ $this->kwt = false;
14684
+ $this->kwt_saved = true;
14685
+ }
14686
+
14687
+ if ($this->tableLevel==1 && $this->useGraphs) {
14688
+ if (isset($attr['ID']) && $attr['ID']) { $this->currentGraphId = strtoupper($attr['ID']); }
14689
+ else { $this->currentGraphId = '0'; }
14690
+ $this->graphs[$this->currentGraphId] = array();
14691
+ }
14692
+ //++++++++++++++++++++++++++++
14693
+ $this->plainCell_properties = array();
14694
+ unset($table);
14695
+ break;
14696
+
14697
+ case 'THEAD':
14698
+ $this->lastoptionaltag = $tag; // Save current HTML specified optional endtag
14699
+ $this->cssmgr->tbCSSlvl++;
14700
+ $this->tablethead = 1;
14701
+ $this->tabletfoot = 0;
14702
+ $properties = $this->cssmgr->MergeCSS('TABLE',$tag,$attr);
14703
+ if (isset($properties['FONT-WEIGHT'])) {
14704
+ if (strtoupper($properties['FONT-WEIGHT']) == 'BOLD') { $this->thead_font_weight = 'B'; }
14705
+ else { $this->thead_font_weight = ''; }
14706
+ }
14707
+
14708
+ if (isset($properties['FONT-STYLE'])) {
14709
+ if (strtoupper($properties['FONT-STYLE']) == 'ITALIC') { $this->thead_font_style = 'I'; }
14710
+ else { $this->thead_font_style = ''; }
14711
+ }
14712
+ if (isset($properties['FONT-VARIANT'])) {
14713
+ if (strtoupper($properties['FONT-VARIANT']) == 'SMALL-CAPS') { $this->thead_font_smCaps = 'S'; }
14714
+ else { $this->thead_font_smCaps = ''; }
14715
+ }
14716
+
14717
+ if (isset($properties['VERTICAL-ALIGN'])) {
14718
+ $this->thead_valign_default = $properties['VERTICAL-ALIGN'];
14719
+ }
14720
+ if (isset($properties['TEXT-ALIGN'])) {
14721
+ $this->thead_textalign_default = $properties['TEXT-ALIGN'];
14722
+ }
14723
+ $properties = array();
14724
+ break;
14725
+
14726
+ case 'TFOOT':
14727
+ $this->lastoptionaltag = $tag; // Save current HTML specified optional endtag
14728
+ $this->cssmgr->tbCSSlvl++;
14729
+ $this->tabletfoot = 1;
14730
+ $this->tablethead = 0;
14731
+ $properties = $this->cssmgr->MergeCSS('TABLE',$tag,$attr);
14732
+ if (isset($properties['FONT-WEIGHT'])) {
14733
+ if (strtoupper($properties['FONT-WEIGHT']) == 'BOLD') { $this->tfoot_font_weight = 'B'; }
14734
+ else { $this->tfoot_font_weight = ''; }
14735
+ }
14736
+
14737
+ if (isset($properties['FONT-STYLE'])) {
14738
+ if (strtoupper($properties['FONT-STYLE']) == 'ITALIC') { $this->tfoot_font_style = 'I'; }
14739
+ else { $this->tfoot_font_style = ''; }
14740
+ }
14741
+ if (isset($properties['FONT-VARIANT'])) {
14742
+ if (strtoupper($properties['FONT-VARIANT']) == 'SMALL-CAPS') { $this->tfoot_font_smCaps = 'S'; }
14743
+ else { $this->tfoot_font_smCaps = ''; }
14744
+ }
14745
+
14746
+ if (isset($properties['VERTICAL-ALIGN'])) {
14747
+ $this->tfoot_valign_default = $properties['VERTICAL-ALIGN'];
14748
+ }
14749
+ if (isset($properties['TEXT-ALIGN'])) {
14750
+ $this->tfoot_textalign_default = $properties['TEXT-ALIGN'];
14751
+ }
14752
+ $properties = array();
14753
+ break;
14754
+
14755
+
14756
+ case 'TBODY':
14757
+ $this->tablethead = 0;
14758
+ $this->tabletfoot = 0;
14759
+ $this->lastoptionaltag = $tag; // Save current HTML specified optional endtag
14760
+ $this->cssmgr->tbCSSlvl++;
14761
+ $this->cssmgr->MergeCSS('TABLE',$tag,$attr);
14762
+ break;
14763
+
14764
+
14765
+ case 'TR':
14766
+ $this->lastoptionaltag = $tag; // Save current HTML specified optional endtag
14767
+ $this->cssmgr->tbCSSlvl++;
14768
+ $this->row++;
14769
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nr']++;
14770
+ $this->col = -1;
14771
+ $properties = $this->cssmgr->MergeCSS('TABLE',$tag,$attr);
14772
+
14773
+ if (!$this->simpleTables && (!isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['borders_separate']) || !$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['borders_separate'])) {
14774
+ if (isset($properties['BORDER-LEFT']) && $properties['BORDER-LEFT']) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trborder-left'][$this->row] = $properties['BORDER-LEFT']; }
14775
+ if (isset($properties['BORDER-RIGHT']) && $properties['BORDER-RIGHT']) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trborder-right'][$this->row] = $properties['BORDER-RIGHT']; }
14776
+ if (isset($properties['BORDER-TOP']) && $properties['BORDER-TOP']) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trborder-top'][$this->row] = $properties['BORDER-TOP']; }
14777
+ if (isset($properties['BORDER-BOTTOM']) && $properties['BORDER-BOTTOM']) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trborder-bottom'][$this->row] = $properties['BORDER-BOTTOM']; }
14778
+ }
14779
+
14780
+ if (isset($properties['BACKGROUND-COLOR'])) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'][$this->row] = $properties['BACKGROUND-COLOR']; }
14781
+ else if (isset($attr['BGCOLOR'])) $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'][$this->row] = $attr['BGCOLOR'];
14782
+
14783
+ if (isset($properties['BACKGROUND-GRADIENT']) && !$this->kwt && !$this->ColActive) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trgradients'][$this->row] = $properties['BACKGROUND-GRADIENT']; }
14784
+
14785
+ if (isset($properties['BACKGROUND-IMAGE']) && $properties['BACKGROUND-IMAGE'] && !$this->kwt && !$this->ColActive) {
14786
+ $ret = $this->SetBackground($properties, $currblk['inner_width']);
14787
+ if ($ret) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trbackground-images'][$this->row] = $ret; }
14788
+ }
14789
+
14790
+
14791
+ if (isset($properties['TEXT-ROTATE'])) {
14792
+ $this->trow_text_rotate = $properties['TEXT-ROTATE'];
14793
+ }
14794
+ if (isset($attr['TEXT-ROTATE'])) $this->trow_text_rotate = $attr['TEXT-ROTATE'];
14795
+
14796
+ if ($this->tablethead) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_thead'][$this->row] = true; }
14797
+ if ($this->tabletfoot) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot'][$this->row] = true; }
14798
+ $properties = array();
14799
+ break;
14800
+
14801
+
14802
+ case 'TH':
14803
+ case 'TD':
14804
+ $this->ignorefollowingspaces = true;
14805
+ $this->lastoptionaltag = $tag; // Save current HTML specified optional endtag
14806
+ $this->cssmgr->tbCSSlvl++;
14807
+ $this->InlineProperties = array();
14808
+ $this->spanlvl = 0;
14809
+ $this->tdbegin = true;
14810
+ $this->col++;
14811
+ while (isset($this->cell[$this->row][$this->col])) { $this->col++; }
14812
+
14813
+ //Update number column
14814
+ if ($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nc'] < $this->col+1) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nc'] = $this->col+1; }
14815
+
14816
+ $table = &$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]];
14817
+
14818
+ $c = array('a' => false,
14819
+ 'R' => false,
14820
+ 'nowrap' => false,
14821
+ 'bgcolor' => false,
14822
+ 'padding' => array('L' => false,
14823
+ 'R' => false,
14824
+ 'T' => false,
14825
+ 'B' => false
14826
+ )
14827
+ );
14828
+
14829
+ if ($this->simpleTables && $this->row==0 && $this->col==0){
14830
+ $table['simple']['border'] = false;
14831
+ $table['simple']['border_details']['R']['w'] = 0;
14832
+ $table['simple']['border_details']['L']['w'] = 0;
14833
+ $table['simple']['border_details']['T']['w'] = 0;
14834
+ $table['simple']['border_details']['B']['w'] = 0;
14835
+ $table['simple']['border_details']['R']['style'] = '';
14836
+ $table['simple']['border_details']['L']['style'] = '';
14837
+ $table['simple']['border_details']['T']['style'] = '';
14838
+ $table['simple']['border_details']['B']['style'] = '';
14839
+ }
14840
+ else if (!$this->simpleTables) {
14841
+ $c['border'] = false;
14842
+ $c['border_details']['R']['w'] = 0;
14843
+ $c['border_details']['L']['w'] = 0;
14844
+ $c['border_details']['T']['w'] = 0;
14845
+ $c['border_details']['B']['w'] = 0;
14846
+ $c['border_details']['mbw']['BL'] = 0;
14847
+ $c['border_details']['mbw']['BR'] = 0;
14848
+ $c['border_details']['mbw']['RT'] = 0;
14849
+ $c['border_details']['mbw']['RB'] = 0;
14850
+ $c['border_details']['mbw']['TL'] = 0;
14851
+ $c['border_details']['mbw']['TR'] = 0;
14852
+ $c['border_details']['mbw']['LT'] = 0;
14853
+ $c['border_details']['mbw']['LB'] = 0;
14854
+ $c['border_details']['R']['style'] = '';
14855
+ $c['border_details']['L']['style'] = '';
14856
+ $c['border_details']['T']['style'] = '';
14857
+ $c['border_details']['B']['style'] = '';
14858
+ $c['border_details']['R']['s'] = 0;
14859
+ $c['border_details']['L']['s'] = 0;
14860
+ $c['border_details']['T']['s'] = 0;
14861
+ $c['border_details']['B']['s'] = 0;
14862
+ $c['border_details']['R']['c'] = $this->ConvertColor(0);
14863
+ $c['border_details']['L']['c'] = $this->ConvertColor(0);
14864
+ $c['border_details']['T']['c'] = $this->ConvertColor(0);
14865
+ $c['border_details']['B']['c'] = $this->ConvertColor(0);
14866
+ $c['border_details']['R']['dom'] = 0;
14867
+ $c['border_details']['L']['dom'] = 0;
14868
+ $c['border_details']['T']['dom'] = 0;
14869
+ $c['border_details']['B']['dom'] = 0;
14870
+ }
14871
+
14872
+
14873
+ if ($table['va']) { $c['va'] = $table['va']; }
14874
+ if ($table['txta']) { $c['a'] = $table['txta']; }
14875
+ if ($this->table_border_attr_set) {
14876
+ if ($table['border_details']) {
14877
+ if (!$this->simpleTables){
14878
+ $c['border_details']['R'] = $table['border_details']['R'];
14879
+ $c['border_details']['L'] = $table['border_details']['L'];
14880
+ $c['border_details']['T'] = $table['border_details']['T'];
14881
+ $c['border_details']['B'] = $table['border_details']['B'];
14882
+ $c['border'] = $table['border'];
14883
+ $c['border_details']['L']['dom'] = 1;
14884
+ $c['border_details']['R']['dom'] = 1;
14885
+ $c['border_details']['T']['dom'] = 1;
14886
+ $c['border_details']['B']['dom'] = 1;
14887
+ }
14888
+ else if ($this->simpleTables && $this->row==0 && $this->col==0){
14889
+ $table['simple']['border_details']['R'] = $table['border_details']['R'];
14890
+ $table['simple']['border_details']['L'] = $table['border_details']['L'];
14891
+ $table['simple']['border_details']['T'] = $table['border_details']['T'];
14892
+ $table['simple']['border_details']['B'] = $table['border_details']['B'];
14893
+ $table['simple']['border'] = $table['border'];
14894
+ }
14895
+ }
14896
+ }
14897
+ // INHERITED THEAD CSS Properties
14898
+ if ($this->tablethead) {
14899
+ if ($this->thead_valign_default) $c['va'] = $align[strtolower($this->thead_valign_default)];
14900
+ if ($this->thead_textalign_default) $c['a'] = $align[strtolower($this->thead_textalign_default)];
14901
+ if ($this->thead_font_weight == 'B') { $this->SetStyle('B',true); }
14902
+ if ($this->thead_font_style == 'I') { $this->SetStyle('I',true); }
14903
+ if ($this->thead_font_smCaps == 'S') { $this->SetStyle('S',true); }
14904
+ }
14905
+
14906
+ // INHERITED TFOOT CSS Properties
14907
+ if ($this->tabletfoot) {
14908
+ if ($this->tfoot_valign_default) $c['va'] = $align[strtolower($this->tfoot_valign_default)];
14909
+ if ($this->tfoot_textalign_default) $c['a'] = $align[strtolower($this->tfoot_textalign_default)];
14910
+ if ($this->tfoot_font_weight == 'B') { $this->SetStyle('B',true); }
14911
+ if ($this->tfoot_font_style == 'I') { $this->SetStyle('I',true); }
14912
+ if ($this->tfoot_font_style == 'S') { $this->SetStyle('S',true); }
14913
+ }
14914
+
14915
+
14916
+ if ($this->trow_text_rotate){
14917
+ $c['R'] = $this->trow_text_rotate;
14918
+ }
14919
+
14920
+ $this->cell_border_dominance_L = 0;
14921
+ $this->cell_border_dominance_R = 0;
14922
+ $this->cell_border_dominance_T = 0;
14923
+ $this->cell_border_dominance_B = 0;
14924
+
14925
+ $properties = $this->cssmgr->MergeCSS('TABLE',$tag,$attr);
14926
+ $properties = $this->cssmgr->array_merge_recursive_unique($this->base_table_properties, $properties);
14927
+
14928
+ if (isset($properties['FONT-KERNING']) && (strtoupper($properties['FONT-KERNING'])=='NORMAL' || strtoupper($properties['FONT-KERNING'])=='AUTO')) {
14929
+ $this->kerning = true;
14930
+ }
14931
+ else { $this->kerning = false; }
14932
+
14933
+ if (isset($properties['LETTER-SPACING']) && ($properties['LETTER-SPACING'] || $properties['LETTER-SPACING']==='0') && strtoupper($properties['LETTER-SPACING']) != 'NORMAL') {
14934
+ $this->lSpacingCSS = strtoupper($properties['LETTER-SPACING']);
14935
+ $this->fixedlSpacing = $this->ConvertSize($this->lSpacingCSS,$this->FontSize);
14936
+ }
14937
+ else {
14938
+ $this->lSpacingCSS = '';
14939
+ $this->fixedlSpacing = false;
14940
+ }
14941
+ if (isset($properties['WORD-SPACING']) && strtoupper($properties['WORD-SPACING']) != 'NORMAL') {
14942
+ $this->wSpacingCSS = strtoupper($properties['WORD-SPACING']);
14943
+ $this->minwSpacing = $this->ConvertSize($this->wSpacingCSS,$this->FontSize);
14944
+ }
14945
+ else {
14946
+ $this->minwSpacing = 0;
14947
+ $this->wSpacingCSS = '';
14948
+ }
14949
+ // mPDF 5.6.08
14950
+ if (isset($properties['HYPHENS']) && $properties['HYPHENS']) {
14951
+ if (strtoupper($properties['HYPHENS']) == 'NONE') { $this->textparam['hyphens'] = 2; }
14952
+ else if (strtoupper($properties['HYPHENS']) == 'AUTO') { $this->textparam['hyphens'] = 1; }
14953
+ else if (strtoupper($properties['HYPHENS']) == 'MANUAL') { $this->textparam['hyphens'] = 0; }
14954
+ }
14955
+
14956
+ if (isset($properties['BACKGROUND-COLOR'])) { $c['bgcolor'] = $properties['BACKGROUND-COLOR']; }
14957
+ else if (isset($properties['BACKGROUND'])) { $c['bgcolor'] = $properties['BACKGROUND']; }
14958
+ else if (isset($attr['BGCOLOR'])) $c['bgcolor'] = $attr['BGCOLOR'];
14959
+
14960
+
14961
+
14962
+ if (isset($properties['BACKGROUND-GRADIENT'])) { $c['gradient'] = $properties['BACKGROUND-GRADIENT']; }
14963
+ else { $c['gradient'] = false; }
14964
+
14965
+ if (isset($properties['BACKGROUND-IMAGE']) && $properties['BACKGROUND-IMAGE'] && !$this->keep_block_together) {
14966
+ $ret = $this->SetBackground($properties, $this->blk[$this->blklvl]['inner_width']);
14967
+ if ($ret) { $c['background-image'] = $ret; }
14968
+ }
14969
+ if (isset($properties['VERTICAL-ALIGN'])) { $c['va']=$align[strtolower($properties['VERTICAL-ALIGN'])]; }
14970
+ else if (isset($attr['VALIGN'])) $c['va'] = $align[strtolower($attr['VALIGN'])];
14971
+
14972
+
14973
+ // mPDF 5.6.13
14974
+ if (isset($properties['TEXT-ALIGN']) && $properties['TEXT-ALIGN']) {
14975
+ if (substr($properties['TEXT-ALIGN'],0,1)=='D') { $c['a'] = $properties['TEXT-ALIGN']; }
14976
+ else { $c['a'] = $align[strtolower($properties['TEXT-ALIGN'])]; }
14977
+ }
14978
+ // mPDF 5.6.13
14979
+ if (isset($attr['ALIGN']) && $attr['ALIGN']) {
14980
+ if (strtolower($attr['ALIGN']) == 'char') {
14981
+ if (isset($attr['CHAR']) && $attr['CHAR']) {
14982
+ $char = html_entity_decode($attr['CHAR']);
14983
+ $char = strcode2utf($char);
14984
+ $d = array_search($char,$this->decimal_align);
14985
+ if ($d !== false) { $c['a'] = $d.'R'; }
14986
+ }
14987
+ else { $c['a'] = 'DPR'; }
14988
+ }
14989
+ else { $c['a'] = $align[strtolower($attr['ALIGN'])]; }
14990
+ }
14991
+
14992
+ if (!$c['a']) {
14993
+ if (isset($table['direction']) && $table['direction'] == 'rtl' ) { $c['a'] = 'R'; }
14994
+ else { $c['a'] = 'L'; }
14995
+ }
14996
+
14997
+
14998
+ if (isset($properties['TEXT-ROTATE']) && ($properties['TEXT-ROTATE'] || $properties['TEXT-ROTATE']==="0")){
14999
+ $c['R'] = $properties['TEXT-ROTATE'];
15000
+ }
15001
+ if (isset($properties['BORDER'])) {
15002
+ $bord = $this->border_details($properties['BORDER']);
15003
+ if ($bord['s']) {
15004
+ if (!$this->simpleTables){
15005
+ $c['border'] = _BORDER_ALL;
15006
+ $c['border_details']['R'] = $bord;
15007
+ $c['border_details']['L'] = $bord;
15008
+ $c['border_details']['T'] = $bord;
15009
+ $c['border_details']['B'] = $bord;
15010
+ $c['border_details']['L']['dom'] = $this->cell_border_dominance_L;
15011
+ $c['border_details']['R']['dom'] = $this->cell_border_dominance_R;
15012
+ $c['border_details']['T']['dom'] = $this->cell_border_dominance_T;
15013
+ $c['border_details']['B']['dom'] = $this->cell_border_dominance_B;
15014
+ }
15015
+ else if ($this->simpleTables && $this->row==0 && $this->col==0){
15016
+ $table['simple']['border'] = _BORDER_ALL;
15017
+ $table['simple']['border_details']['R'] = $bord;
15018
+ $table['simple']['border_details']['L'] = $bord;
15019
+ $table['simple']['border_details']['T'] = $bord;
15020
+ $table['simple']['border_details']['B'] = $bord;
15021
+ }
15022
+ }
15023
+ }
15024
+ if (!$this->simpleTables){
15025
+ if (isset($properties['BORDER-RIGHT']) && $properties['BORDER-RIGHT']) {
15026
+ $c['border_details']['R'] = $this->border_details($properties['BORDER-RIGHT']);
15027
+ $this->setBorder($c['border'], _BORDER_RIGHT, $c['border_details']['R']['s']);
15028
+ $c['border_details']['R']['dom'] = $this->cell_border_dominance_R;
15029
+ }
15030
+ if (isset($properties['BORDER-LEFT']) && $properties['BORDER-LEFT']) {
15031
+ $c['border_details']['L'] = $this->border_details($properties['BORDER-LEFT']);
15032
+ $this->setBorder($c['border'], _BORDER_LEFT, $c['border_details']['L']['s']);
15033
+ $c['border_details']['L']['dom'] = $this->cell_border_dominance_L;
15034
+ }
15035
+ if (isset($properties['BORDER-BOTTOM']) && $properties['BORDER-BOTTOM']) {
15036
+ $c['border_details']['B'] = $this->border_details($properties['BORDER-BOTTOM']);
15037
+ $this->setBorder($c['border'], _BORDER_BOTTOM, $c['border_details']['B']['s']);
15038
+ $c['border_details']['B']['dom'] = $this->cell_border_dominance_B;
15039
+ }
15040
+ if (isset($properties['BORDER-TOP']) && $properties['BORDER-TOP']) {
15041
+ $c['border_details']['T'] = $this->border_details($properties['BORDER-TOP']);
15042
+ $this->setBorder($c['border'], _BORDER_TOP, $c['border_details']['T']['s']);
15043
+ $c['border_details']['T']['dom'] = $this->cell_border_dominance_T;
15044
+ }
15045
+ }
15046
+ else if ($this->simpleTables && $this->row==0 && $this->col==0){
15047
+ if (isset($properties['BORDER-LEFT']) && $properties['BORDER-LEFT']) {
15048
+ $bord = $this->border_details($properties['BORDER-LEFT']);
15049
+ if ($bord['s']) { $table['simple']['border'] = _BORDER_ALL; }
15050
+ else { $table['simple']['border'] = 0; }
15051
+ $table['simple']['border_details']['R'] = $bord;
15052
+ $table['simple']['border_details']['L'] = $bord;
15053
+ $table['simple']['border_details']['T'] = $bord;
15054
+ $table['simple']['border_details']['B'] = $bord;
15055
+ }
15056
+ }
15057
+
15058
+ if ($this->simpleTables && $this->row==0 && $this->col==0 && !$table['borders_separate'] && $table['simple']['border'] ){
15059
+ $table['border_details'] = $table['simple']['border_details'];
15060
+ $table['border'] = $table['simple']['border'];
15061
+ }
15062
+
15063
+ // Border set on TR (if collapsed only)
15064
+ if (!$table['borders_separate'] && !$this->simpleTables && isset($table['trborder-left'][$this->row])) {
15065
+ if ($this->col==0) {
15066
+ $left = $this->border_details($table['trborder-left'][$this->row]);
15067
+ $c['border_details']['L'] = $left;
15068
+ $this->setBorder($c['border'], _BORDER_LEFT, $c['border_details']['L']['s']);
15069
+ }
15070
+ $c['border_details']['B'] = $this->border_details($table['trborder-bottom'][$this->row]);
15071
+ $this->setBorder($c['border'], _BORDER_BOTTOM, $c['border_details']['B']['s']);
15072
+ $c['border_details']['T'] = $this->border_details($table['trborder-top'][$this->row]);
15073
+ $this->setBorder($c['border'], _BORDER_TOP, $c['border_details']['T']['s']);
15074
+ }
15075
+
15076
+ if ($this->packTableData && !$this->simpleTables) {
15077
+ $c['borderbin'] = $this->_packCellBorder($c);
15078
+ unset($c['border']);
15079
+ unset($c['border_details']);
15080
+ }
15081
+
15082
+ if (isset($properties['PADDING-LEFT'])) {
15083
+ $c['padding']['L'] = $this->ConvertSize($properties['PADDING-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
15084
+ }
15085
+ if (isset($properties['PADDING-RIGHT'])) {
15086
+ $c['padding']['R'] = $this->ConvertSize($properties['PADDING-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
15087
+ }
15088
+ if (isset($properties['PADDING-BOTTOM'])) {
15089
+ $c['padding']['B'] = $this->ConvertSize($properties['PADDING-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
15090
+ }
15091
+ if (isset($properties['PADDING-TOP'])) {
15092
+ $c['padding']['T'] = $this->ConvertSize($properties['PADDING-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
15093
+ }
15094
+
15095
+ $w = '';
15096
+ if (isset($properties['WIDTH'])) { $w = $properties['WIDTH']; }
15097
+ else if (isset($attr['WIDTH'])) { $w = $attr['WIDTH']; }
15098
+ if ($w) {
15099
+ if (strpos($w,'%') && !$this->ignore_table_percents ) { $c['wpercent'] = $w + 0; } // makes 80% -> 80
15100
+ else if (!strpos($w,'%') && !$this->ignore_table_widths ) { $c['w'] = $this->ConvertSize($w,$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
15101
+ }
15102
+
15103
+ if (isset($properties['HEIGHT']) && !strpos($properties['HEIGHT'],'%')) { $c['h'] = $this->ConvertSize($properties['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
15104
+ else if (isset($attr['HEIGHT']) && !strpos($attr['HEIGHT'],'%')) $c['h'] = $this->ConvertSize($attr['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
15105
+
15106
+
15107
+ if (isset($properties['COLOR'])) {
15108
+ $cor = $this->ConvertColor($properties['COLOR']);
15109
+ if ($cor) {
15110
+ $this->colorarray = $cor;
15111
+ $this->SetTColor($cor);
15112
+ }
15113
+ }
15114
+ if (isset($properties['FONT-FAMILY'])) {
15115
+ $this->SetFont($properties['FONT-FAMILY'],'',0,false);
15116
+ }
15117
+ if (isset($properties['FONT-SIZE'])) {
15118
+ $mmsize = $this->ConvertSize($properties['FONT-SIZE'],$this->default_font_size/_MPDFK);
15119
+ if ($mmsize) {
15120
+ $this->SetFontSize($mmsize*(_MPDFK),false);
15121
+ }
15122
+ }
15123
+ $c['dfs'] = $this->FontSize; // Default Font size
15124
+ if (isset($properties['FONT-WEIGHT'])) {
15125
+ if (strtoupper($properties['FONT-WEIGHT']) == 'BOLD') { $this->SetStyle('B',true); }
15126
+ }
15127
+ if (isset($properties['FONT-STYLE'])) {
15128
+ if (strtoupper($properties['FONT-STYLE']) == 'ITALIC') { $this->SetStyle('I',true); }
15129
+ }
15130
+ if (isset($properties['FONT-VARIANT'])) {
15131
+ if (strtoupper($properties['FONT-VARIANT']) == 'SMALL-CAPS') { $this->SetStyle('S',true); }
15132
+ }
15133
+ if (isset($properties['TEXT-DECORATION'])) {
15134
+ if (strtoupper($properties['TEXT-DECORATION']) == 'LINE-THROUGH') { $this->strike = true; }
15135
+ else if (strtoupper($properties['TEXT-DECORATION']) == 'UNDERLINE') { $this->SetStyle('U',true); }
15136
+ }
15137
+ if (isset($properties['TEXT-SHADOW'])) {
15138
+ $ts = $this->cssmgr->setCSStextshadow($properties['TEXT-SHADOW']);
15139
+ if ($ts) { $this->textshadow = $ts; }
15140
+ }
15141
+ if (isset($properties['TEXT-TRANSFORM'])) {
15142
+ if (strtoupper($properties['TEXT-TRANSFORM']) == 'CAPITALIZE') { $this->capitalize = true; }
15143
+ else if (strtoupper($properties['TEXT-TRANSFORM']) == 'UPPERCASE') { $this->toupper = true; }
15144
+ else if (strtoupper($properties['TEXT-TRANSFORM']) == 'LOWERCASE') { $this->tolower = true; }
15145
+ }
15146
+ if (isset($properties['WHITE-SPACE'])) {
15147
+ if (strtoupper($properties['WHITE-SPACE']) == 'NOWRAP') { $c['nowrap']= 1; }
15148
+ }
15149
+ $properties = array();
15150
+
15151
+ if (isset($attr['TEXT-ROTATE'])) {
15152
+ $c['R'] = $attr['TEXT-ROTATE'];
15153
+ }
15154
+ if (isset($attr['NOWRAP']) && $attr['NOWRAP']) $c['nowrap']= 1;
15155
+
15156
+ $this->cell[$this->row][$this->col] = $c;
15157
+ unset($c);
15158
+ $this->cell[$this->row][$this->col]['s'] = 0 ;
15159
+
15160
+ $cs = $rs = 1;
15161
+ if (isset($attr['COLSPAN']) && $attr['COLSPAN']>1) $cs = $this->cell[$this->row][$this->col]['colspan'] = $attr['COLSPAN'];
15162
+ if ($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nc'] < $this->col+$cs) {
15163
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nc'] = $this->col+$cs;
15164
+ } // following code moved outside if...
15165
+ for($l=$this->col; $l < $this->col+$cs ;$l++) {
15166
+ if ($l-$this->col) $this->cell[$this->row][$l] = 0;
15167
+ }
15168
+ if (isset($attr['ROWSPAN']) && $attr['ROWSPAN']>1) $rs = $this->cell[$this->row][$this->col]['rowspan'] = $attr['ROWSPAN'];
15169
+ for ($k=$this->row ; $k < $this->row+$rs ;$k++) {
15170
+ for($l=$this->col; $l < $this->col+$cs ;$l++) {
15171
+ if ($k-$this->row || $l-$this->col) $this->cell[$k][$l] = 0;
15172
+ }
15173
+ }
15174
+ unset($table);
15175
+ break;
15176
+
15177
+
15178
+ // *********** LISTS ********************
15179
+ case 'OL':
15180
+ case 'UL':
15181
+ $this->listjustfinished = false;
15182
+
15183
+ if ($this->blockjustfinished && !count($this->textbuffer) && $this->y != $this->tMargin && $this->collapseBlockMargins) { $lastbottommargin = $this->lastblockbottommargin; }
15184
+ else { $lastbottommargin = 0; }
15185
+ $this->lastblockbottommargin = 0;
15186
+ $this->blockjustfinished=false;
15187
+
15188
+ $this->linebreakjustfinished=false;
15189
+ $this->lastoptionaltag = ''; // Save current HTML specified optional endtag
15190
+ $this->cssmgr->listCSSlvl++;
15191
+ if((!$this->tableLevel) && ($this->listlvl == 0)) {
15192
+ $blockstate = 0;
15193
+ //if ($this->lastblocklevelchange == 1) { $blockstate = -1; } // Top margins/padding only
15194
+ //else if ($this->lastblocklevelchange < 1) { $blockstate = 0; } // NO margins/padding
15195
+ // called from block after new div e.g. <div> ... <ol> ... Outputs block top margin/border and padding
15196
+ if (count($this->textbuffer) == 0 && $this->lastblocklevelchange == 1 && !$this->tableLevel && !$this->kwt) {
15197
+ $this->newFlowingBlock( $this->blk[$this->blklvl]['width'],$this->lineheight,'',false,false,1,true, $this->blk[$this->blklvl]['direction']);
15198
+ $this->finishFlowingBlock(true); // true = END of flowing block
15199
+ }
15200
+ else if (count($this->textbuffer)) { $this->printbuffer($this->textbuffer,$blockstate); }
15201
+ $this->textbuffer=array();
15202
+ $this->lastblocklevelchange = -1;
15203
+ }
15204
+ // ol and ul types are mixed here
15205
+ if ($this->listlvl == 0) {
15206
+ $this->list_indent = array();
15207
+ $this->list_align = array();
15208
+ $this->list_lineheight = array();
15209
+ $this->InlineProperties['LIST'] = array();
15210
+ $this->InlineProperties['LISTITEM'] = array();
15211
+ }
15212
+
15213
+ // A simple list for inside a table
15214
+ if($this->tableLevel) {
15215
+ $this->list_indent[$this->listlvl] = 0; // mm default indent for each level
15216
+ if ($tag == 'OL') $this->listtype = '1';
15217
+ else if ($tag == 'UL') $this->listtype = 'disc';
15218
+ if ($this->listlvl > 0) {
15219
+ $this->listlist[$this->listlvl]['MAXNUM'] = $this->listnum; //save previous lvl's maxnum
15220
+ }
15221
+ $this->listlvl++;
15222
+ // mPDF 5.6.15
15223
+ if (isset($attr['START'])) { $this->listnum = intval($attr['START']); }
15224
+ else { $this->listnum = 0; }
15225
+ $this->listlist[$this->listlvl] = array('TYPE'=>$this->listtype,'MAXNUM'=>$this->listnum);
15226
+ break;
15227
+ }
15228
+
15229
+
15230
+ if (($this->PDFA || $this->PDFX) && $tag == 'UL') {
15231
+ if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "List bullets cannot use core font Zapfdingbats in PDFA1-b or PDFX/1-a. (Substitute characters from current font used if available, otherwise substitutes hyphen '-')"; }
15232
+ }
15233
+
15234
+ if ($this->cssmgr->listCSSlvl==1) {
15235
+ $properties = $this->cssmgr->MergeCSS('TOPLIST',$tag,$attr);
15236
+ }
15237
+ else {
15238
+ $properties = $this->cssmgr->MergeCSS('LIST',$tag,$attr);
15239
+ }
15240
+ if (!empty($properties)) $this->setCSS($properties,'LIST');
15241
+ // List-type
15242
+
15243
+ $this->listtype = '';
15244
+ if (isset($properties['LIST-STYLE-TYPE'])) {
15245
+ $this->listtype = $this->_getListStyle($properties['LIST-STYLE-TYPE']);
15246
+ }
15247
+ else if (isset($properties['LIST-STYLE'])) {
15248
+ $this->listtype = $this->_getListStyle($properties['LIST-STYLE']);
15249
+ }
15250
+ else if (isset($attr['TYPE']) && $attr['TYPE']) { $this->listtype = $attr['TYPE']; }
15251
+ if (!$this->listtype) {
15252
+ if ($tag == 'OL') $this->listtype = '1';
15253
+ if ($tag == 'UL') {
15254
+ if ($this->listlvl % 3 == 0) $this->listtype = 'disc';
15255
+ elseif ($this->listlvl % 3 == 1) $this->listtype = 'circle';
15256
+ else $this->listtype = 'square';
15257
+ }
15258
+ }
15259
+ if ($this->listlvl == 0) {
15260
+ $this->inherit_lineheight = 0;
15261
+ $this->listlvl++; // first depth level
15262
+ // mPDF 5.6.15
15263
+ if (isset($attr['START'])) { $this->listnum = intval($attr['START']); }
15264
+ else { $this->listnum = 0; }
15265
+ $this->listDir = (isset($this->blk[$this->blklvl]['direction']) ? $this->blk[$this->blklvl]['direction'] : null);
15266
+ $occur = $this->listoccur[$this->listlvl] = 1;
15267
+ $this->listlist[$this->listlvl][1] = array('TYPE'=>$this->listtype,'MAXNUM'=>$this->listnum);
15268
+ }
15269
+ else {
15270
+ if (!empty($this->textbuffer))
15271
+ {
15272
+ $this->listitem[] = array($this->listlvl,$this->listnum,$this->textbuffer,$this->listoccur[$this->listlvl],$this->listitemtype);
15273
+ $this->listnum++;
15274
+ }
15275
+ // Save current lineheight to inherit
15276
+ $this->textbuffer = array();
15277
+ $occur = $this->listoccur[$this->listlvl];
15278
+ $this->listlist[$this->listlvl][$occur]['MAXNUM'] = $this->listnum; //save previous lvl's maxnum
15279
+ $this->listlvl++;
15280
+ // mPDF 5.6.15
15281
+ if (isset($attr['START'])) { $this->listnum = intval($attr['START']); }
15282
+ else { $this->listnum = 0; }
15283
+
15284
+
15285
+ if (!isset($this->listoccur[$this->listlvl]) || $this->listoccur[$this->listlvl] == 0) $this->listoccur[$this->listlvl] = 1;
15286
+ else $this->listoccur[$this->listlvl]++;
15287
+ $occur = $this->listoccur[$this->listlvl];
15288
+ $this->listlist[$this->listlvl][$occur] = array('TYPE'=>$this->listtype,'MAXNUM'=>$this->listnum);
15289
+ }
15290
+
15291
+
15292
+ // TOP LEVEL ONLY
15293
+ if ($this->listlvl == 1) {
15294
+ if (isset($properties['MARGIN-TOP'])) {
15295
+ if ($lastbottommargin) {
15296
+ $tmp = $this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
15297
+ if ($tmp > $lastbottommargin) { $properties['MARGIN-TOP'] -= $lastbottommargin; }
15298
+ else { $properties['MARGIN-TOP'] = 0; }
15299
+ }
15300
+ $this->DivLn($this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false),$this->blklvl,true,1); // collapsible
15301
+ }
15302
+ if (isset($properties['MARGIN-BOTTOM'])) {
15303
+ $this->list_margin_bottom = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
15304
+ }
15305
+
15306
+ if (isset($this->blk[$this->blklvl]['line_height'])) {
15307
+ $this->list_lineheight[$this->listlvl][$occur] = $this->blk[$this->blklvl]['line_height'];
15308
+ }
15309
+
15310
+ if (isset($properties['DIRECTION']) && $properties['DIRECTION']) { $this->listDir = strtolower($properties['DIRECTION']); }
15311
+ else if (isset($attr['DIR']) && $attr['DIR']) { $this->listDir = strtolower($attr['DIR']); }
15312
+
15313
+ }
15314
+ $this->list_indent[$this->listlvl][$occur] = 5; // mm default indent for each level
15315
+ if (isset($properties['TEXT-INDENT'])) { $this->list_indent[$this->listlvl][$occur] = $this->ConvertSize($properties['TEXT-INDENT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
15316
+
15317
+ if (isset($properties['TEXT-ALIGN'])) {
15318
+ $this->list_align[$this->listlvl][$occur] = $align[strtolower($properties['TEXT-ALIGN'])];
15319
+ }
15320
+
15321
+
15322
+ if (isset($properties['LINE-HEIGHT'])) {
15323
+ $this->list_lineheight[$this->listlvl][$occur] = $this->fixLineheight($properties['LINE-HEIGHT']);
15324
+ }
15325
+ else if ($this->listlvl>1 && isset($this->list_lineheight[($this->listlvl - 1)][1])) {
15326
+ $this->list_lineheight[$this->listlvl][$occur] = end($this->list_lineheight[($this->listlvl - 1)]);
15327
+ }
15328
+ if (!isset($this->list_lineheight[$this->listlvl][$occur]) || !$this->list_lineheight[$this->listlvl][$occur]) {
15329
+ $this->list_lineheight[$this->listlvl][$occur] = $this->normalLineheight;
15330
+ }
15331
+
15332
+ $this->InlineProperties['LIST'][$this->listlvl][$occur] = $this->saveInlineProperties();
15333
+ $properties = array();
15334
+ break;
15335
+
15336
+
15337
+
15338
+ case 'LI':
15339
+ // Start Block
15340
+ $this->lastoptionaltag = $tag; // Save current HTML specified optional endtag
15341
+ $this->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces
15342
+ // A simple list for inside a table
15343
+ if($this->tableLevel) {
15344
+ $this->blockjustfinished=false;
15345
+
15346
+ // If already something in the Cell
15347
+ if ((isset($this->cell[$this->row][$this->col]['maxs']) && $this->cell[$this->row][$this->col]['maxs'] > 0 ) || $this->cell[$this->row][$this->col]['s'] > 0 ) {
15348
+ $this->_saveCellTextBuffer("\n");
15349
+ if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
15350
+ $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
15351
+ }
15352
+ elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
15353
+ $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
15354
+ }
15355
+ $this->cell[$this->row][$this->col]['s'] = 0 ;
15356
+ }
15357
+ if ($this->listlvl == 0) { //in case of malformed HTML code. Example:(...)</p><li>Content</li><p>Paragraph1</p>(...)
15358
+ $this->listlvl++; // first depth level
15359
+ $this->listnum = 0; // reset
15360
+ $this->listlist[$this->listlvl] = array('TYPE'=>'disc','MAXNUM'=>$this->listnum);
15361
+ }
15362
+
15363
+ $this->listnum++;
15364
+ switch($this->listlist[$this->listlvl]['TYPE']) {
15365
+ case 'A':
15366
+ $blt = $this->dec2alpha($this->listnum,true).$this->list_number_suffix;
15367
+ break;
15368
+ case 'a':
15369
+ $blt = $this->dec2alpha($this->listnum,false).$this->list_number_suffix;
15370
+ break;
15371
+ case 'I':
15372
+ $blt = $this->dec2roman($this->listnum,true).$this->list_number_suffix;
15373
+ break;
15374
+ case 'i':
15375
+ $blt = $this->dec2roman($this->listnum,false).$this->list_number_suffix;
15376
+ break;
15377
+ case '1':
15378
+ $blt = $this->listnum.$this->list_number_suffix;
15379
+ break;
15380
+ default:
15381
+ if ($this->listlvl % 3 == 1 && $this->_charDefined($this->CurrentFont['cw'],8226)) { $blt = "\xe2\x80\xa2"; } // &#8226;
15382
+ else if ($this->listlvl % 3 == 2 && $this->_charDefined($this->CurrentFont['cw'],9900)) { $blt = "\xe2\x9a\xac"; } // &#9900;
15383
+ else if ($this->listlvl % 3 == 0 && $this->_charDefined($this->CurrentFont['cw'],9642)) { $blt = "\xe2\x96\xaa"; } // &#9642;
15384
+ else { $blt = '-'; }
15385
+ break;
15386
+ }
15387
+
15388
+ // change to &nbsp; spaces
15389
+ if ($this->usingCoreFont) {
15390
+ $ls = str_repeat(chr(160).chr(160),($this->listlvl-1)*2) . $blt . ' ';
15391
+ }
15392
+ else {
15393
+ $ls = str_repeat("\xc2\xa0\xc2\xa0",($this->listlvl-1)*2) . $blt . ' ';
15394
+ }
15395
+
15396
+ $this->_saveCellTextBuffer($ls, $this->HREF);
15397
+ $this->cell[$this->row][$this->col]['s'] += $this->GetStringWidth($ls);
15398
+ break;
15399
+ }
15400
+ //Observation: </LI> is ignored
15401
+ if ($this->listlvl == 0) { //in case of malformed HTML code. Example:(...)</p><li>Content</li><p>Paragraph1</p>(...)
15402
+ //First of all, skip a line
15403
+ $this->listlvl++; // first depth level
15404
+ $this->listnum = 0; // reset
15405
+ $this->listoccur[$this->listlvl] = 1;
15406
+ $this->listlist[$this->listlvl][1] = array('TYPE'=>'disc','MAXNUM'=>$this->listnum);
15407
+ }
15408
+ if ($this->listnum == 0) {
15409
+ $this->listnum++;
15410
+ $this->textbuffer = array();
15411
+ }
15412
+ else {
15413
+ if (!empty($this->textbuffer)) {
15414
+ if (!$this->listjustfinished) {
15415
+ $this->listitem[] = array($this->listlvl,$this->listnum,$this->textbuffer,$this->listoccur[$this->listlvl],$this->listitemtype);
15416
+ $this->listnum++;
15417
+ }
15418
+ else {
15419
+ $this->listitem[] = array($this->listlvl,$this->listnum,$this->textbuffer,$this->listoccur[$this->listlvl],$this->listitemtype, true);
15420
+ }
15421
+ }
15422
+ $this->textbuffer = array();
15423
+ }
15424
+ $this->listjustfinished = false;
15425
+
15426
+ $this->cssmgr->listCSSlvl++;
15427
+ $properties = $this->cssmgr->MergeCSS('LIST',$tag,$attr);
15428
+ if (!empty($properties)) $this->setCSS($properties,'LIST');
15429
+ $this->InlineProperties['LISTITEM'][$this->listlvl][$this->listoccur[$this->listlvl]][$this->listnum] = $this->saveInlineProperties();
15430
+
15431
+ // List-type
15432
+ if (isset($properties['LIST-STYLE-TYPE'])) {
15433
+ $this->listitemtype = $this->_getListStyle($properties['LIST-STYLE-TYPE']);
15434
+ }
15435
+ else if (isset($properties['LIST-STYLE'])) {
15436
+ $this->listitemtype = $this->_getListStyle($properties['LIST-STYLE']);
15437
+ }
15438
+ else if (isset($attr['TYPE']) && $attr['TYPE']) { $this->listitemtype = $attr['TYPE']; }
15439
+ else $this->listitemtype = '';
15440
+ break;
15441
+
15442
+ }//end of switch
15443
+ }
15444
+
15445
+
15446
+ function _getListStyle($ls) {
15447
+ if (stristr($ls,'decimal')) { return '1'; }
15448
+ /* CSS3 list-styles numeric (selected) + I added tamil
15449
+ arabic-indic | bengali | devanagari | gujarati | gurmukhi | kannada | malayalam | oriya | persian | telugu | thai | urdu
15450
+ */
15451
+ else if (preg_match('/(disc|circle|square|arabic-indic|bengali|devanagari|gujarati|gurmukhi|kannada|malayalam|oriya|persian|tamil|telugu|thai|urdu)/i',$ls,$m)) {
15452
+ return strtolower(trim($m[1]));
15453
+ }
15454
+ else if (stristr($ls,'lower-roman')) { return 'i'; }
15455
+ else if (stristr($ls,'upper-roman')) { return 'I'; }
15456
+ else if (stristr($ls,'lower-latin')|| stristr($ls,'lower-alpha')) { return 'a'; }
15457
+ else if (stristr($ls,'upper-latin') || stristr($ls,'upper-alpha')) { return 'A'; }
15458
+ else if (stristr($ls,'none')) { return 'none'; }
15459
+ else if (preg_match('/U\+([a-fA-F0-9]+)/i',$ls)) { return $ls; }
15460
+ else { return ''; }
15461
+ }
15462
+
15463
+
15464
+
15465
+ function CloseTag($tag)
15466
+ {
15467
+ $this->ignorefollowingspaces = false; //Eliminate exceeding left-side spaces
15468
+ //Closing tag
15469
+ if($tag=='OPTION') { $this->selectoption['ACTIVE'] = false; $this->lastoptionaltag = ''; }
15470
+
15471
+ if($tag=='TTS' or $tag=='TTA' or $tag=='TTZ') {
15472
+ if ($this->InlineProperties[$tag]) { $this->restoreInlineProperties($this->InlineProperties[$tag]); }
15473
+ unset($this->InlineProperties[$tag]);
15474
+ $ltag = strtolower($tag);
15475
+ $this->$ltag = false;
15476
+ }
15477
+
15478
+
15479
+ if($tag=='FONT' || $tag=='SPAN' || $tag=='CODE' || $tag=='KBD' || $tag=='SAMP' || $tag=='TT' || $tag=='VAR'
15480
+ || $tag=='INS' || $tag=='STRONG' || $tag=='CITE' || $tag=='SUB' || $tag=='SUP' || $tag=='S' || $tag=='STRIKE' || $tag=='DEL'
15481
+ || $tag=='Q' || $tag=='EM' || $tag=='B' || $tag=='I' || $tag=='U' | $tag=='SMALL' || $tag=='BIG' || $tag=='ACRONYM'
15482
+ || $tag=='MARK' || $tag=='TIME' || $tag=='PROGRESS' || $tag=='METER'
15483
+ ) { // mPDF 5.5.09
15484
+
15485
+ if ($tag == 'SPAN') {
15486
+ if (isset($this->InlineProperties['SPAN'][$this->spanlvl]) && $this->InlineProperties['SPAN'][$this->spanlvl]) { $this->restoreInlineProperties($this->InlineProperties['SPAN'][$this->spanlvl]); }
15487
+ unset($this->InlineProperties['SPAN'][$this->spanlvl]);
15488
+ $this->spanlvl--;
15489
+ }
15490
+ else {
15491
+ if (isset($this->InlineProperties[$tag]) && $this->InlineProperties[$tag]) { $this->restoreInlineProperties($this->InlineProperties[$tag]); }
15492
+ unset($this->InlineProperties[$tag]);
15493
+ }
15494
+
15495
+ }
15496
+
15497
+ if($tag=='METER' || $tag=='PROGRESS') {
15498
+ $this->inMeter = false; // mPDF 5.5.09
15499
+ }
15500
+
15501
+
15502
+ if($tag=='A') {
15503
+ $this->HREF='';
15504
+ if (isset($this->InlineProperties['A'])) { $this->restoreInlineProperties($this->InlineProperties['A']); }
15505
+ unset($this->InlineProperties['A']);
15506
+ }
15507
+
15508
+ if($tag=='LEGEND') { // mPDF 5.4.18
15509
+ if (count($this->textbuffer) && !$this->tableLevel) {
15510
+ $leg = $this->textbuffer[(count($this->textbuffer)-1)];
15511
+ unset($this->textbuffer[(count($this->textbuffer)-1)]);
15512
+ $this->textbuffer = array_values($this->textbuffer);
15513
+ $this->blk[$this->blklvl]['border_legend'] = $leg;
15514
+ $this->blk[$this->blklvl]['margin_top'] += ($leg[11]/2)/_MPDFK;
15515
+ $this->blk[$this->blklvl]['padding_top'] += ($leg[11]/2)/_MPDFK;
15516
+ }
15517
+ if (isset($this->InlineProperties['LEGEND'])) { $this->restoreInlineProperties($this->InlineProperties['LEGEND']); }
15518
+ unset($this->InlineProperties['LEGEND']);
15519
+ $this->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces
15520
+ }
15521
+
15522
+
15523
+
15524
+
15525
+
15526
+ // *********** BLOCKS ********************
15527
+ // mPDF 5.4.18
15528
+ if($tag=='P' || $tag=='DIV' || $tag=='H1' || $tag=='H2' || $tag=='H3' || $tag=='H4' || $tag=='H5' || $tag=='H6' || $tag=='PRE'
15529
+ || $tag=='FORM' || $tag=='ADDRESS' || $tag=='BLOCKQUOTE' || $tag=='CENTER' || $tag=='DT' || $tag=='DD' || $tag=='DL'
15530
+ || $tag=='CAPTION' || $tag=='FIELDSET'
15531
+ || $tag=='ARTICLE' || $tag=='ASIDE' || $tag=='FIGURE' || $tag=='FIGCAPTION' || $tag=='FOOTER' || $tag=='HEADER' || $tag=='HGROUP'
15532
+ || $tag=='NAV' || $tag=='SECTION' || $tag=='DETAILS' || $tag=='SUMMARY'
15533
+ ) { // mPDF 5.5.09 // mPDF 5.5.22
15534
+
15535
+ $this->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces
15536
+ $this->blockjustfinished=true;
15537
+
15538
+ $this->lastblockbottommargin = $this->blk[$this->blklvl]['margin_bottom'];
15539
+ if ($this->listlvl>0) { return; }
15540
+
15541
+ // mPDF 5.6.34
15542
+ if (preg_match('/^H\d/',$tag) && !$this->tableLevel && !$this->writingToC) { // mPDF 5.6.38
15543
+ if (isset($this->h2toc[$tag]) || isset($this->h2bookmarks[$tag])) {
15544
+ $content = '';
15545
+ if (count($this->textbuffer)==1) { $content = $this->textbuffer[0][0]; }
15546
+ else {
15547
+ for ($i=0;$i<count($this->textbuffer);$i++) {
15548
+ if (substr($this->textbuffer[$i][0],0,3) != "\xbb\xa4\xac") { //inline object
15549
+ $content .= $this->textbuffer[$i][0];
15550
+ }
15551
+ }
15552
+ }
15553
+ }
15554
+ }
15555
+
15556
+ if($this->tableLevel) {
15557
+ if ($this->linebreakjustfinished) { $this->blockjustfinished=false; }
15558
+ if (isset($this->InlineProperties['BLOCKINTABLE'])) {
15559
+ if ($this->InlineProperties['BLOCKINTABLE']) { $this->restoreInlineProperties($this->InlineProperties['BLOCKINTABLE']); }
15560
+ unset($this->InlineProperties['BLOCKINTABLE']);
15561
+ }
15562
+ if($tag=='PRE') { $this->ispre=false; }
15563
+ return;
15564
+ }
15565
+ $this->lastoptionaltag = '';
15566
+ $this->divbegin=false;
15567
+
15568
+ $this->linebreakjustfinished=false;
15569
+
15570
+ $this->x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'];
15571
+
15572
+ // If float contained in a float, need to extend bottom to allow for it
15573
+ $currpos = $this->page*1000 + $this->y;
15574
+ if (isset($this->blk[$this->blklvl]['float_endpos']) && $this->blk[$this->blklvl]['float_endpos'] > $currpos) {
15575
+ $old_page = $this->page;
15576
+ $new_page = intval($this->blk[$this->blklvl]['float_endpos'] /1000);
15577
+ if ($old_page != $new_page) {
15578
+ $s = $this->PrintPageBackgrounds();
15579
+ // Writes after the marker so not overwritten later by page background etc.
15580
+ $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
15581
+ $this->pageBackgrounds = array();
15582
+ $this->page = $new_page;
15583
+ $this->ResetMargins();
15584
+ $this->Reset();
15585
+ $this->pageoutput[$this->page] = array();
15586
+ }
15587
+ $this->y = (($this->blk[$this->blklvl]['float_endpos'] *1000) % 1000000)/1000; // mod changes operands to integers before processing
15588
+ }
15589
+
15590
+
15591
+ //Print content
15592
+ if ($this->lastblocklevelchange == 1) { $blockstate = 3; } // Top & bottom margins/padding
15593
+ else if ($this->lastblocklevelchange == -1) { $blockstate = 2; } // Bottom margins/padding only
15594
+ else { $blockstate = 0; }
15595
+ // called from after e.g. </table> </div> </div> ... Outputs block margin/border and padding
15596
+ if (count($this->textbuffer) && $this->textbuffer[count($this->textbuffer)-1]) {
15597
+ if (substr($this->textbuffer[count($this->textbuffer)-1][0],0,3) != "\xbb\xa4\xac") { // not special content
15598
+ if ($this->usingCoreFont) {
15599
+ $this->textbuffer[count($this->textbuffer)-1][0] = preg_replace('/[ ]+$/', '', $this->textbuffer[count($this->textbuffer)-1][0]);
15600
+ }
15601
+ else {
15602
+ $this->textbuffer[count($this->textbuffer)-1][0] = preg_replace('/[ ]+$/u', '', $this->textbuffer[count($this->textbuffer)-1][0]); }
15603
+ }
15604
+ }
15605
+
15606
+ if (count($this->textbuffer) == 0 && $this->lastblocklevelchange != 0) {
15607
+ //$this->newFlowingBlock( $this->blk[$this->blklvl]['width'],$this->lineheight,'',false,false,2,true, $this->blk[$this->blklvl]['direction']);
15608
+ $this->newFlowingBlock( $this->blk[$this->blklvl]['width'],$this->lineheight,'',false,false,$blockstate,true, $this->blk[$this->blklvl]['direction']);
15609
+ $this->finishFlowingBlock(true); // true = END of flowing block
15610
+ $this->PaintDivBB('',$blockstate);
15611
+ }
15612
+ else {
15613
+ $this->printbuffer($this->textbuffer,$blockstate);
15614
+ }
15615
+
15616
+
15617
+ $this->textbuffer=array();
15618
+
15619
+ if ($this->blk[$this->blklvl]['keep_block_together']) {
15620
+ $this->printdivbuffer();
15621
+ }
15622
+
15623
+ if ($this->kwt) {
15624
+ $this->kwt_height = $this->y - $this->kwt_y0;
15625
+ }
15626
+
15627
+ $this->printfloatbuffer();
15628
+
15629
+ if($tag=='PRE') { $this->ispre=false; }
15630
+
15631
+ if ($this->blk[$this->blklvl]['float'] == 'R') {
15632
+ // If width not set, here would need to adjust and output buffer
15633
+ $s = $this->PrintPageBackgrounds();
15634
+ // Writes after the marker so not overwritten later by page background etc.
15635
+ $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
15636
+ $this->pageBackgrounds = array();
15637
+ $this->Reset();
15638
+ $this->pageoutput[$this->page] = array();
15639
+
15640
+ for($i=($this->blklvl-1); $i >= 0; $i--) {
15641
+ if (isset($this->blk[$i]['float_endpos'])) { $this->blk[$i]['float_endpos'] = max($this->blk[$i]['float_endpos'], ($this->page*1000 + $this->y)); }
15642
+ else { $this->blk[$i]['float_endpos'] = $this->page*1000 + $this->y; }
15643
+ }
15644
+
15645
+ $this->floatDivs[] = array(
15646
+ 'side'=>'R',
15647
+ 'startpage'=>$this->blk[$this->blklvl]['startpage'] ,
15648
+ 'y0'=>$this->blk[$this->blklvl]['float_start_y'] ,
15649
+ 'startpos'=> ($this->blk[$this->blklvl]['startpage']*1000 + $this->blk[$this->blklvl]['float_start_y']),
15650
+ 'endpage'=>$this->page ,
15651
+ 'y1'=>$this->y ,
15652
+ 'endpos'=> ($this->page*1000 + $this->y),
15653
+ 'w'=> $this->blk[$this->blklvl]['float_width'],
15654
+ 'blklvl'=>$this->blklvl,
15655
+ 'blockContext' => $this->blk[$this->blklvl-1]['blockContext']
15656
+ );
15657
+
15658
+ $this->y = $this->blk[$this->blklvl]['float_start_y'] ;
15659
+ $this->page = $this->blk[$this->blklvl]['startpage'] ;
15660
+ $this->ResetMargins();
15661
+ $this->pageoutput[$this->page] = array();
15662
+ }
15663
+ if ($this->blk[$this->blklvl]['float'] == 'L') {
15664
+ // If width not set, here would need to adjust and output buffer
15665
+ $s = $this->PrintPageBackgrounds();
15666
+ // Writes after the marker so not overwritten later by page background etc.
15667
+ $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
15668
+ $this->pageBackgrounds = array();
15669
+ $this->Reset();
15670
+ $this->pageoutput[$this->page] = array();
15671
+
15672
+ for($i=($this->blklvl-1); $i >= 0; $i--) {
15673
+ if (isset($this->blk[$i]['float_endpos'])) { $this->blk[$i]['float_endpos'] = max($this->blk[$i]['float_endpos'], ($this->page*1000 + $this->y)); }
15674
+ else { $this->blk[$i]['float_endpos'] = $this->page*1000 + $this->y; }
15675
+ }
15676
+
15677
+ $this->floatDivs[] = array(
15678
+ 'side'=>'L',
15679
+ 'startpage'=>$this->blk[$this->blklvl]['startpage'] ,
15680
+ 'y0'=>$this->blk[$this->blklvl]['float_start_y'] ,
15681
+ 'startpos'=> ($this->blk[$this->blklvl]['startpage']*1000 + $this->blk[$this->blklvl]['float_start_y']),
15682
+ 'endpage'=>$this->page ,
15683
+ 'y1'=>$this->y ,
15684
+ 'endpos'=> ($this->page*1000 + $this->y),
15685
+ 'w'=> $this->blk[$this->blklvl]['float_width'],
15686
+ 'blklvl'=>$this->blklvl,
15687
+ 'blockContext' => $this->blk[$this->blklvl-1]['blockContext']
15688
+ );
15689
+
15690
+ $this->y = $this->blk[$this->blklvl]['float_start_y'] ;
15691
+ $this->page = $this->blk[$this->blklvl]['startpage'] ;
15692
+ $this->ResetMargins();
15693
+ $this->pageoutput[$this->page] = array();
15694
+ }
15695
+
15696
+ if (isset($this->blk[$this->blklvl]['visibility']) && $this->blk[$this->blklvl]['visibility']!='visible') {
15697
+ $this->SetVisibility('visible');
15698
+ }
15699
+
15700
+ if (isset($this->blk[$this->blklvl]['page_break_after'])) { $page_break_after = $this->blk[$this->blklvl]['page_break_after']; }
15701
+ else { $page_break_after = ''; }
15702
+
15703
+ //Reset values
15704
+ $this->Reset();
15705
+
15706
+ // mPDF 5.6.01 - LAYERS
15707
+ if (isset($this->blk[$this->blklvl]['z-index']) && $this->blk[$this->blklvl]['z-index'] > 0) {
15708
+ $this->EndLayer();
15709
+ }
15710
+
15711
+ if ($this->blklvl > 0) { // ==0 SHOULDN'T HAPPEN - NOT XHTML
15712
+ if ($this->blk[$this->blklvl]['tag'] == $tag) {
15713
+ unset($this->blk[$this->blklvl]);
15714
+ $this->blklvl--;
15715
+ }
15716
+ //else { echo $tag; exit; } // debug - forces error if incorrectly nested html tags
15717
+ }
15718
+
15719
+ $this->lastblocklevelchange = -1 ;
15720
+ // Reset Inline-type properties
15721
+ if (isset($this->blk[$this->blklvl]['InlineProperties'])) { $this->restoreInlineProperties($this->blk[$this->blklvl]['InlineProperties']); }
15722
+
15723
+ $this->x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'];
15724
+
15725
+ if ($page_break_after) {
15726
+ $save_blklvl = $this->blklvl;
15727
+ $save_blk = $this->blk;
15728
+ $save_silp = $this->saveInlineProperties();
15729
+ $save_spanlvl = $this->spanlvl;
15730
+ $save_ilp = $this->InlineProperties;
15731
+ if ($this->blklvl>1) {
15732
+ // Close any open block tags
15733
+ for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag']); }
15734
+ // Output any text left in buffer
15735
+ if (count($this->textbuffer)) { $this->printbuffer($this->textbuffer); $this->textbuffer=array(); }
15736
+ }
15737
+ if ($page_break_after == 'RIGHT') { $this->AddPage($this->CurOrientation,'NEXT-ODD','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
15738
+ else if ($page_break_after == 'LEFT') { $this->AddPage($this->CurOrientation,'NEXT-EVEN','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
15739
+ else { $this->AddPage($this->CurOrientation,'','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
15740
+ if (!$this->restoreBlockPagebreaks) {
15741
+ $this->blklvl = 0;
15742
+ $this->lastblocklevelchange = 0;
15743
+ $this->blk = array();
15744
+ $this->initialiseBlock($this->blk[0]);
15745
+ $this->blk[0]['width'] =& $this->pgwidth;
15746
+ $this->blk[0]['inner_width'] =& $this->pgwidth;
15747
+ $this->blk[0]['blockContext'] = $this->blockContext;
15748
+ $properties = $this->cssmgr->MergeCSS('BLOCK','BODY','');
15749
+ $this->setCSS($properties,'','BODY');
15750
+ $this->blklvl++;
15751
+ $currblk =& $this->blk[$this->blklvl];
15752
+ $prevblk =& $this->blk[$this->blklvl-1];
15753
+
15754
+ $this->initialiseBlock($currblk);
15755
+ $currblk['tag'] = $tag;
15756
+ $currblk['attr'] = $attr;
15757
+
15758
+ $this->Reset();
15759
+ $properties = $this->cssmgr->MergeCSS('BLOCK',$tag,$attr);
15760
+ }
15761
+ if ($this->restoreBlockPagebreaks && !$this->tableLevel && !$this->listlvl) {
15762
+ $this->blk = $save_blk;
15763
+ // Re-open block tags
15764
+ $t = $this->blk[0]['tag'];
15765
+ $a = $this->blk[0]['attr'];
15766
+ $this->blklvl = 0;
15767
+ for ($b=0; $b<=$save_blklvl;$b++) {
15768
+ $tc = $t;
15769
+ $ac = $a;
15770
+ $t = $this->blk[$b+1]['tag'];
15771
+ $a = $this->blk[$b+1]['attr'];
15772
+ unset($this->blk[$b+1]);
15773
+ $this->OpenTag($tc,$ac);
15774
+ }
15775
+ $this->spanlvl = $save_spanlvl;
15776
+ $this->InlineProperties = $save_ilp;
15777
+ $this->restoreInlineProperties($save_silp);
15778
+ }
15779
+ }
15780
+
15781
+ }
15782
+
15783
+
15784
+
15785
+ if($tag=='TH') $this->SetStyle('B',false);
15786
+
15787
+ if(($tag=='TH' or $tag=='TD') && $this->tableLevel) {
15788
+ $this->lastoptionaltag = 'TR';
15789
+ unset($this->cssmgr->tablecascadeCSS[$this->cssmgr->tbCSSlvl]);
15790
+ $this->cssmgr->tbCSSlvl--;
15791
+ if (!$this->tdbegin) { return; }
15792
+ $this->tdbegin = false;
15793
+ // Added for correct calculation of cell column width - otherwise misses the last line if not end </p> etc.
15794
+ if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
15795
+ if (!is_array($this->cell[$this->row][$this->col])) { $this->Error("You may have an error in your HTML code e.g. &lt;/td&gt;&lt;/td&gt;"); }
15796
+ $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
15797
+ }
15798
+ elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
15799
+ $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
15800
+ }
15801
+
15802
+ // Remove last <br> if at end of cell
15803
+ if (isset($this->cell[$this->row][$this->col]['textbuffer'])) { $ntb = count($this->cell[$this->row][$this->col]['textbuffer']); }
15804
+ else { $ntb = 0; }
15805
+ if ($ntb>1 && $this->cell[$this->row][$this->col]['textbuffer'][$ntb-1][0] == "\n") {
15806
+ unset($this->cell[$this->row][$this->col]['textbuffer'][$ntb-1]);
15807
+ }
15808
+
15809
+ if ($this->cacheTables) {
15810
+ $clen = $this->_cacheCell($this->cell[$this->row][$this->col], $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cache']);
15811
+ $this->cell[$this->row][$this->col] = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['ptr'];
15812
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['ptr'] += $clen;
15813
+ }
15814
+
15815
+ if ($this->tablethead) {
15816
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_thead'][$this->row] = true;
15817
+ if ($this->tableLevel==1) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['headernrows'] = max($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['headernrows'] , ($this->row+1)); }
15818
+ }
15819
+ if ($this->tabletfoot) {
15820
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot'][$this->row] = true;
15821
+ if ($this->tableLevel==1) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['footernrows'] = max($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['footernrows'] , ($this->row+1 - $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['headernrows'] )); }
15822
+ }
15823
+ $this->Reset();
15824
+ }
15825
+
15826
+ if($tag=='TR' && $this->tableLevel) {
15827
+ // If Border set on TR - Update right border
15828
+ if (isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trborder-left'][$this->row])) {
15829
+ if ($this->cacheTables) {
15830
+ $c = $this->_uncacheCell($this->cell[$this->row][$this->col], $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cache'], null);
15831
+ }
15832
+ else { $c =& $this->cell[$this->row][$this->col]; }
15833
+ if ($c) {
15834
+ if ($this->packTableData) {
15835
+ $cell = $this->_unpackCellBorder($c['borderbin'] );
15836
+ }
15837
+ else { $cell = $c; }
15838
+ $cell['border_details']['R'] = $this->border_details($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trborder-right'][$this->row]);
15839
+ $this->setBorder($cell['border'], _BORDER_RIGHT, $cell['border_details']['R']['s']);
15840
+ if ($this->packTableData) {
15841
+ $c['borderbin'] = $this->_packCellBorder($cell);
15842
+ unset($c['border']);
15843
+ unset($c['border_details']);
15844
+ }
15845
+ else { $c = $cell; }
15846
+ }
15847
+ if ($this->cacheTables) {
15848
+ $fh = fopen($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cache'], "r+b");
15849
+ $this->_cacheUpdateBorder($c, $fh, $this->cell[$this->row][$this->col]);
15850
+ fclose($fh);
15851
+ }
15852
+ }
15853
+ $this->lastoptionaltag = '';
15854
+ unset($this->cssmgr->tablecascadeCSS[$this->cssmgr->tbCSSlvl]);
15855
+ $this->cssmgr->tbCSSlvl--;
15856
+ $this->trow_text_rotate = '';
15857
+ $this->tabletheadjustfinished = false;
15858
+ }
15859
+
15860
+ if($tag=='TBODY') {
15861
+ $this->lastoptionaltag = '';
15862
+ unset($this->cssmgr->tablecascadeCSS[$this->cssmgr->tbCSSlvl]);
15863
+ $this->cssmgr->tbCSSlvl--;
15864
+ }
15865
+
15866
+ if($tag=='THEAD') {
15867
+ $this->lastoptionaltag = '';
15868
+ unset($this->cssmgr->tablecascadeCSS[$this->cssmgr->tbCSSlvl]);
15869
+ $this->cssmgr->tbCSSlvl--;
15870
+ $this->tablethead = 0;
15871
+ $this->tabletheadjustfinished = true;
15872
+ $this->ResetStyles();
15873
+ $this->thead_font_weight = '';
15874
+ $this->thead_font_style = '';
15875
+ $this->thead_font_smCaps = '';
15876
+
15877
+ $this->thead_valign_default = '';
15878
+ $this->thead_textalign_default = '';
15879
+ }
15880
+
15881
+ if($tag=='TFOOT') {
15882
+ $this->lastoptionaltag = '';
15883
+ unset($this->cssmgr->tablecascadeCSS[$this->cssmgr->tbCSSlvl]);
15884
+ $this->cssmgr->tbCSSlvl--;
15885
+ $this->tabletfoot = 0;
15886
+ $this->ResetStyles();
15887
+ $this->tfoot_font_weight = '';
15888
+ $this->tfoot_font_style = '';
15889
+ $this->tfoot_font_smCaps = '';
15890
+
15891
+ $this->tfoot_valign_default = '';
15892
+ $this->tfoot_textalign_default = '';
15893
+ }
15894
+
15895
+ if($tag=='TABLE') { // TABLE-END (
15896
+ $this->lastoptionaltag = '';
15897
+ unset($this->cssmgr->tablecascadeCSS[$this->cssmgr->tbCSSlvl]);
15898
+ $this->cssmgr->tbCSSlvl--;
15899
+ $this->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces
15900
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cells'] = $this->cell;
15901
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['wc'] = array_pad(array(),$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nc'],array('miw'=>0,'maw'=>0));
15902
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['hr'] = array_pad(array(),$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nr'],0);
15903
+
15904
+ // Move table footer <tfoot> row to end of table
15905
+ if (isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot']) && count($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot'])) {
15906
+ $tfrows = array();
15907
+ foreach($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot'] AS $r=>$val) {
15908
+ if ($val) { $tfrows[] = $r; }
15909
+ }
15910
+ $temp = array();
15911
+ $temptf = array();
15912
+ foreach($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cells'] AS $k=>$row) {
15913
+ if (in_array($k,$tfrows)) {
15914
+ $temptf[] = $row;
15915
+ }
15916
+ else {
15917
+ $temp[] = $row;
15918
+ }
15919
+ }
15920
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot'] = array();
15921
+ for($i=count($temp) ; $i<(count($temp)+count($temptf)); $i++) {
15922
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot'][$i] = true;
15923
+ }
15924
+ // Update nestedpos row references
15925
+ if (count($this->table[($this->tableLevel+1)])) {
15926
+ foreach($this->table[($this->tableLevel+1)] AS $nid=>$nested) {
15927
+ $this->table[($this->tableLevel+1)][$nid]['nestedpos'][0] -= count($temptf);
15928
+ }
15929
+ }
15930
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cells'] = array_merge($temp, $temptf);
15931
+
15932
+ // Update other arays set on row number
15933
+ // [trbackground-images] [trgradients]
15934
+ $temptrbgi = array();
15935
+ $temptrbgg = array();
15936
+ $temptrbgc = array();
15937
+ $temptrbgc[-1] = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'][-1];
15938
+ for($k=0; $k<$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nr']; $k++) {
15939
+ if (!in_array($k,$tfrows)) {
15940
+ $temptrbgi[] = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trbackground-images'][$k];
15941
+ $temptrbgg[] = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trgradients'][$k];
15942
+ $temptrbgc[] = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'][$k];
15943
+ }
15944
+ }
15945
+ for($k=0; $k<$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nr']; $k++) {
15946
+ if (in_array($k,$tfrows)) {
15947
+ $temptrbgi[] = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trbackground-images'][$k];
15948
+ $temptrbgg[] = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trgradients'][$k];
15949
+ $temptrbgc[] = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'][$k];
15950
+ }
15951
+ }
15952
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trbackground-images'] = $temptrbgi;
15953
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trgradients'] = $temptrbgg;
15954
+ $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'] = $temptrbgc ;
15955
+ // Should Update all other arays set on row number, but cell properties have been set so not needed
15956
+ // [bgcolor] [trborder-left] [trborder-right] [trborder-top] [trborder-bottom]
15957
+ }
15958
+
15959
+ if ($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['direction']=='rtl') {
15960
+ $this->_reverseTableDir($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]);
15961
+ }
15962
+
15963
+ // Fix Borders *********************************************
15964
+ $this->_fixTableBorders($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]);
15965
+
15966
+
15967
+ if ($this->table_rotate <> 0) {
15968
+ $this->tablebuffer = '';
15969
+ // Max width for rotated table
15970
+ $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 1);
15971
+ $this->tbrot_maxh = $this->blk[$this->blklvl]['inner_width'] ; // Max width for rotated table
15972
+ $this->tbrot_align = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['a'] ;
15973
+ }
15974
+ $this->shrin_k = 1;
15975
+
15976
+ if ($this->shrink_tables_to_fit < 1) { $this->shrink_tables_to_fit = 1; }
15977
+ if (!$this->shrink_this_table_to_fit) { $this->shrink_this_table_to_fit = $this->shrink_tables_to_fit; }
15978
+
15979
+ if ($this->tableLevel>1) {
15980
+ // deal with nested table
15981
+
15982
+ $this->_tableColumnWidth($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]],true);
15983
+
15984
+ $tmiw = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['miw'];
15985
+ $tmaw = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['maw'];
15986
+ $tl = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['tl'];
15987
+
15988
+ // Go down to lower table level
15989
+ $this->tableLevel--;
15990
+
15991
+ // Reset lower level table
15992
+ $this->base_table_properties = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['baseProperties'];
15993
+ $this->cell = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cells'];
15994
+ // mPDF 5.4.10
15995
+ if (isset($this->cell['PARENTCELL'])) {
15996
+ if ($this->cell['PARENTCELL']) { $this->restoreInlineProperties($this->cell['PARENTCELL']); }
15997
+ unset($this->cell['PARENTCELL']);
15998
+ }
15999
+ $this->row = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['currrow'];
16000
+ $this->col = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['currcol'];
16001
+ $objattr = array();
16002
+ $objattr['type'] = 'nestedtable';
16003
+ $objattr['nestedcontent'] = $this->tbctr[($this->tableLevel+1)];
16004
+ $objattr['table'] = $this->tbctr[$this->tableLevel];
16005
+ $objattr['row'] = $this->row;
16006
+ $objattr['col'] = $this->col;
16007
+ $objattr['level'] = $this->tableLevel;
16008
+ $e = "\xbb\xa4\xactype=nestedtable,objattr=".serialize($objattr)."\xbb\xa4\xac";
16009
+ $this->_saveCellTextBuffer($e);
16010
+ $this->cell[$this->row][$this->col]['s'] += $tl ;
16011
+ if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
16012
+ $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
16013
+ }
16014
+ elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
16015
+ $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
16016
+ }
16017
+ $this->cell[$this->row][$this->col]['s'] = 0;// reset
16018
+ if ((isset($this->cell[$this->row][$this->col]['nestedmaw']) && $this->cell[$this->row][$this->col]['nestedmaw'] < $tmaw) || !isset($this->cell[$this->row][$this->col]['nestedmaw'])) { $this->cell[$this->row][$this->col]['nestedmaw'] = $tmaw ; }
16019
+ if ((isset($this->cell[$this->row][$this->col]['nestedmiw']) && $this->cell[$this->row][$this->col]['nestedmiw'] < $tmiw) || !isset($this->cell[$this->row][$this->col]['nestedmiw'])) { $this->cell[$this->row][$this->col]['nestedmiw'] = $tmiw ; }
16020
+ $this->tdbegin = true;
16021
+ $this->nestedtablejustfinished = true;
16022
+ $this->ignorefollowingspaces = true;
16023
+ return;
16024
+ }
16025
+ $this->cMarginL = 0;
16026
+ $this->cMarginR = 0;
16027
+ $this->cMarginT = 0;
16028
+ $this->cMarginB = 0;
16029
+ $this->cellPaddingL = 0;
16030
+ $this->cellPaddingR = 0;
16031
+ $this->cellPaddingT = 0;
16032
+ $this->cellPaddingB = 0;
16033
+
16034
+ if (isset($this->table[1][1]['overflow']) && $this->table[1][1]['overflow']=='visible') {
16035
+ if ($this->kwt || $this->table_rotate || $this->table_keep_together || $this->ColActive) {
16036
+ $this->kwt = false;
16037
+ $this->table_rotate = 0;
16038
+ $this->table_keep_together = false;
16039
+ //die("mPDF Warning: You cannot use CSS overflow:visible together with any of these functions: 'Keep-with-table', rotated tables, page-break-inside:avoid, or columns");
16040
+ }
16041
+ $this->_tableColumnWidth($this->table[1][1],true);
16042
+ $this->_tableWidth($this->table[1][1]);
16043
+ }
16044
+ else {
16045
+ if (!$this->kwt_saved) { $this->kwt_height = 0; }
16046
+
16047
+ list($check,$tablemiw) = $this->_tableColumnWidth($this->table[1][1],true);
16048
+ $save_table = $this->table;
16049
+ if ($this->cacheTables) { $this->_backupCacheFiles(); }
16050
+ $reset_to_minimum_width = false;
16051
+ $added_page = false;
16052
+
16053
+ if ($check > 1) {
16054
+ if ($check > $this->shrink_this_table_to_fit && $this->table_rotate) {
16055
+ if ($this->y != $this->tMargin) {
16056
+ $this->AddPage($this->CurOrientation);
16057
+ $this->kwt_moved = true;
16058
+ }
16059
+ $added_page = true;
16060
+ $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
16061
+ //$check = $tablemiw/$this->tbrot_maxw; // undo any shrink
16062
+ $check = 1; // undo any shrink
16063
+ }
16064
+ $reset_to_minimum_width = true;
16065
+ }
16066
+
16067
+ if ($reset_to_minimum_width) {
16068
+
16069
+ $this->shrin_k = $check;
16070
+
16071
+ $this->default_font_size /= $this->shrin_k;
16072
+ $this->SetFontSize($this->default_font_size, false );
16073
+
16074
+ $this->shrinkTable($this->table[1][1],$this->shrin_k);
16075
+
16076
+ $this->_tableColumnWidth($this->table[1][1],false); // repeat
16077
+
16078
+ // Starting at $this->innermostTableLevel
16079
+ // Shrink table values - and redo columnWidth
16080
+ for($lvl=2;$lvl<=$this->innermostTableLevel;$lvl++) {
16081
+ for ($nid=1; $nid<=$this->tbctr[$lvl]; $nid++) {
16082
+ $this->shrinkTable($this->table[$lvl][$nid],$this->shrin_k);
16083
+ $this->_tableColumnWidth($this->table[$lvl][$nid],false);
16084
+ }
16085
+ }
16086
+ }
16087
+
16088
+ // Set table cell widths for top level table
16089
+ // Use $shrin_k to resize but don't change again
16090
+ $this->SetLineHeight('',$this->table_lineheight);
16091
+
16092
+ // Top level table
16093
+ $this->_tableWidth($this->table[1][1]);
16094
+
16095
+ }
16096
+
16097
+
16098
+ // Now work through any nested tables setting child table[w'] = parent cell['w']
16099
+ // Now do nested tables _tableWidth
16100
+ for($lvl=2;$lvl<=$this->innermostTableLevel;$lvl++) {
16101
+ for ($nid=1; $nid<=$this->tbctr[$lvl]; $nid++) {
16102
+ // HERE set child table width = cell width
16103
+
16104
+ list($parentrow, $parentcol, $parentnid) = $this->table[$lvl][$nid]['nestedpos'];
16105
+
16106
+ if ($this->cacheTables) {
16107
+ $c = $this->_uncacheCell($this->table[($lvl-1)][$parentnid]['cells'][$parentrow][$parentcol], $this->table[($lvl-1)][$parentnid]['cache'], null);
16108
+ }
16109
+ else
16110
+ $c =& $this->table[($lvl-1)][$parentnid]['cells'][$parentrow][$parentcol];
16111
+
16112
+ if (isset($c['colspan']) && $c['colspan']> 1) {
16113
+ $parentwidth = 0;
16114
+ for($cs=0;$cs<$c['colspan'] ; $cs++) {
16115
+ $parentwidth += $this->table[($lvl-1)][$parentnid]['wc'][$parentcol+$cs];
16116
+ }
16117
+ }
16118
+ else { $parentwidth = $this->table[($lvl-1)][$parentnid]['wc'][$parentcol]; }
16119
+
16120
+
16121
+ //$parentwidth -= ALLOW FOR PADDING ETC.in parent cell
16122
+ if (!$this->simpleTables){
16123
+ if ($this->packTableData) {
16124
+ list($bt,$br,$bb,$bl) = $this->_getBorderWidths($c['borderbin']);
16125
+ }
16126
+ else {
16127
+ $br = $c['border_details']['R']['w'];
16128
+ $bl = $c['border_details']['L']['w'];
16129
+ }
16130
+ if ($this->table[$lvl-1][$parentnid]['borders_separate']) {
16131
+ $parentwidth -= $br + $bl
16132
+ + $c['padding']['L']
16133
+ + $c['padding']['R']
16134
+ + $this->table[($lvl-1)][$parentnid]['border_spacing_H'];
16135
+ }
16136
+ else {
16137
+ $parentwidth -= $br/2 + $bl/2
16138
+ + $c['padding']['L']
16139
+ + $c['padding']['R'];
16140
+ }
16141
+ }
16142
+ else if ($this->simpleTables){
16143
+ if ($this->table[$lvl-1][$parentnid]['borders_separate']) {
16144
+ $parentwidth -= $this->table[($lvl-1)][$parentnid]['simple']['border_details']['L']['w']
16145
+ + $this->table[($lvl-1)][$parentnid]['simple']['border_details']['R']['w']
16146
+ + $c['padding']['L']
16147
+ + $c['padding']['R']
16148
+ + $this->table[($lvl-1)][$parentnid]['border_spacing_H'];
16149
+ }
16150
+ else {
16151
+ $parentwidth -= $this->table[($lvl-1)][$parentnid]['simple']['border_details']['L']['w']/2
16152
+ + $this->table[($lvl-1)][$parentnid]['simple']['border_details']['R']['w']/2
16153
+ + $c['padding']['L']
16154
+ + $c['padding']['R'];
16155
+ }
16156
+ }
16157
+ if (isset($this->table[$lvl][$nid]['wpercent']) && $this->table[$lvl][$nid]['wpercent'] && $lvl>1) {
16158
+ $this->table[$lvl][$nid]['w'] = $parentwidth;
16159
+ }
16160
+ else if ($parentwidth > $this->table[$lvl][$nid]['maw']) {
16161
+ $this->table[$lvl][$nid]['w'] = $this->table[$lvl][$nid]['maw'];
16162
+ }
16163
+ else {
16164
+ $this->table[$lvl][$nid]['w'] = $parentwidth;
16165
+ }
16166
+ unset($c);
16167
+ $this->_tableWidth($this->table[$lvl][$nid]);
16168
+ }
16169
+ }
16170
+
16171
+ // Starting at $this->innermostTableLevel
16172
+ // Cascade back up nested tables: setting heights back up the tree
16173
+ for($lvl=$this->innermostTableLevel;$lvl>0;$lvl--) {
16174
+ for ($nid=1; $nid<=$this->tbctr[$lvl]; $nid++) {
16175
+ list($tableheight,$maxrowheight,$fullpage,$remainingpage, $maxfirstrowheight) = $this->_tableHeight($this->table[$lvl][$nid]); }
16176
+ }
16177
+ if ($this->table[1][1]['overflow']=='visible') {
16178
+ if ($maxrowheight > $fullpage) { die("mPDF Warning: A Table row is greater than available height. You cannot use CSS overflow:visible"); }
16179
+ if ($maxfirstrowheight > $remainingpage) { $this->AddPage($this->CurOrientation); }
16180
+ $r = 0; $c = 0; $p = 0; $y = 0;
16181
+ while (!$finished) {
16182
+ list($finished,$r,$c,$p,$y,$y0) = $this->_tableWrite($this->table[1][1],true,$r,$c,$p,$y);
16183
+ if (!$finished) {
16184
+ $this->AddPage($this->CurOrientation);
16185
+ // If printed something on first spread, set same y
16186
+ if ($r==0 && $y0 > -1) { $this->y = $y0; }
16187
+ }
16188
+ }
16189
+ }
16190
+ else {
16191
+ $recalculate = 1;
16192
+ $forcerecalc = false;
16193
+ // RESIZING ALGORITHM
16194
+ if ($maxrowheight > $fullpage) {
16195
+ $recalculate = $this->tbsqrt($maxrowheight / $fullpage, 1);
16196
+ $forcerecalc = true;
16197
+ }
16198
+ else if ($this->table_rotate) { // NB $remainingpage == $fullpage == the width of the page
16199
+ if ($tableheight > $remainingpage) {
16200
+ // If can fit on remainder of page whilst respecting autsize value..
16201
+ if (($this->shrin_k * $this->tbsqrt($tableheight / $remainingpage, 1)) <= $this->shrink_this_table_to_fit) {
16202
+ $recalculate = $this->tbsqrt($tableheight / $remainingpage, 1);
16203
+ }
16204
+ else if (!$added_page) {
16205
+ if ($this->y != $this->tMargin) {
16206
+ $this->AddPage($this->CurOrientation);
16207
+ $this->kwt_moved = true;
16208
+ }
16209
+ $added_page = true;
16210
+ $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
16211
+ // 0.001 to force it to recalculate
16212
+ $recalculate = (1 / $this->shrin_k) + 0.001; // undo any shrink
16213
+ }
16214
+ }
16215
+ else { $recalculate = 1; }
16216
+ }
16217
+ else if ($this->table_keep_together || ($this->table[1][1]['nr']==1 && !$this->writingHTMLfooter)) {
16218
+ if ($tableheight > $fullpage) {
16219
+ if (($this->shrin_k * $this->tbsqrt($tableheight / $fullpage, 1)) <= $this->shrink_this_table_to_fit) {
16220
+ $recalculate = $this->tbsqrt($tableheight / $fullpage, 1);
16221
+ }
16222
+ else if ($this->tableMinSizePriority) {
16223
+ $this->table_keep_together = false;
16224
+ $recalculate = 1.001;
16225
+ }
16226
+ else {
16227
+ if ($this->y != $this->tMargin) { // mPDF 5.1
16228
+ $this->AddPage($this->CurOrientation);
16229
+ $this->kwt_moved = true;
16230
+ }
16231
+ $added_page = true;
16232
+ $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
16233
+ $recalculate = $this->tbsqrt($tableheight / $fullpage, 1);
16234
+ }
16235
+ }
16236
+ else if ($tableheight > $remainingpage) {
16237
+ // If can fit on remainder of page whilst respecting autsize value..
16238
+ if (($this->shrin_k * $this->tbsqrt($tableheight / $remainingpage, 1)) <= $this->shrink_this_table_to_fit) {
16239
+ $recalculate = $this->tbsqrt($tableheight / $remainingpage, 1);
16240
+ }
16241
+ else {
16242
+ if ($this->y != $this->tMargin) {
16243
+ $this->AddPage($this->CurOrientation);
16244
+ $this->kwt_moved = true;
16245
+ }
16246
+ $added_page = true;
16247
+ $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
16248
+ $recalculate = 1.001;
16249
+ }
16250
+ }
16251
+ else { $recalculate = 1; }
16252
+ }
16253
+ else { $recalculate = 1; }
16254
+
16255
+ if ($recalculate > $this->shrink_this_table_to_fit && !$forcerecalc) { $recalculate = $this->shrink_this_table_to_fit; }
16256
+
16257
+ $iteration = 1;
16258
+
16259
+ // RECALCULATE
16260
+ while($recalculate <> 1) {
16261
+ $this->shrin_k1 = $recalculate ;
16262
+ $this->shrin_k *= $recalculate ;
16263
+ $this->default_font_size /= ($this->shrin_k1) ;
16264
+ $this->SetFontSize($this->default_font_size, false );
16265
+ $this->SetLineHeight('',$this->table_lineheight);
16266
+ $this->table = $save_table;
16267
+ if ($this->cacheTables) { $this->_restoreCacheFiles(); }
16268
+ if ($this->shrin_k <> 1) { $this->shrinkTable($this->table[1][1],$this->shrin_k); }
16269
+ $this->_tableColumnWidth($this->table[1][1],false); // repeat
16270
+
16271
+ // Starting at $this->innermostTableLevel
16272
+ // Shrink table values - and redo columnWidth
16273
+ for($lvl=2;$lvl<=$this->innermostTableLevel;$lvl++) {
16274
+ for ($nid=1; $nid<=$this->tbctr[$lvl]; $nid++) {
16275
+ if ($this->shrin_k <> 1) { $this->shrinkTable($this->table[$lvl][$nid],$this->shrin_k); }
16276
+ $this->_tableColumnWidth($this->table[$lvl][$nid],false);
16277
+ }
16278
+ }
16279
+ // Set table cell widths for top level table
16280
+
16281
+ // Top level table
16282
+ $this->_tableWidth($this->table[1][1]);
16283
+
16284
+ // Now work through any nested tables setting child table[w'] = parent cell['w']
16285
+ // Now do nested tables _tableWidth
16286
+ for($lvl=2;$lvl<=$this->innermostTableLevel;$lvl++) {
16287
+ for ($nid=1; $nid<=$this->tbctr[$lvl]; $nid++) {
16288
+ // HERE set child table width = cell width
16289
+
16290
+ list($parentrow, $parentcol, $parentnid) = $this->table[$lvl][$nid]['nestedpos'];
16291
+ if ($this->cacheTables) {
16292
+ $c = $this->_uncacheCell($this->table[($lvl-1)][$parentnid]['cells'][$parentrow][$parentcol], $this->table[($lvl-1)][$parentnid]['cache'], null);
16293
+ }
16294
+ else
16295
+ $c =& $this->table[($lvl-1)][$parentnid]['cells'][$parentrow][$parentcol];
16296
+
16297
+ if (isset($c['colspan']) && $c['colspan']> 1) {
16298
+ $parentwidth = 0;
16299
+ for($cs=0;$cs<$c['colspan'] ; $cs++) {
16300
+ $parentwidth += $this->table[($lvl-1)][$parentnid]['wc'][$parentcol+$cs];
16301
+ }
16302
+ }
16303
+ else { $parentwidth = $this->table[($lvl-1)][$parentnid]['wc'][$parentcol]; }
16304
+
16305
+ //$parentwidth -= ALLOW FOR PADDING ETC.in parent cell
16306
+ if (!$this->simpleTables){
16307
+ if ($this->packTableData) {
16308
+ list($bt,$br,$bb,$bl) = $this->_getBorderWidths($c['borderbin']);
16309
+ }
16310
+ else {
16311
+ $br = $c['border_details']['R']['w'];
16312
+ $bl = $c['border_details']['L']['w'];
16313
+ }
16314
+ if ($this->table[$lvl-1][$parentnid]['borders_separate']) {
16315
+ $parentwidth -= $br + $bl
16316
+ + $c['padding']['L']
16317
+ + $c['padding']['R']
16318
+ + $this->table[($lvl-1)][$parentnid]['border_spacing_H'];
16319
+ }
16320
+ else {
16321
+ $parentwidth -= $br/2 + $bl/2
16322
+ + $c['padding']['L']
16323
+ + $c['padding']['R'];
16324
+ }
16325
+ }
16326
+ else if ($this->simpleTables){
16327
+ if ($this->table[$lvl-1][$parentnid]['borders_separate']) {
16328
+ $parentwidth -= $this->table[($lvl-1)][$parentnid]['simple']['border_details']['L']['w']
16329
+ + $this->table[($lvl-1)][$parentnid]['simple']['border_details']['R']['w']
16330
+ + $c['padding']['L']
16331
+ + $c['padding']['R']
16332
+ + $this->table[($lvl-1)][$parentnid]['border_spacing_H'];
16333
+ }
16334
+ else {
16335
+ $parentwidth -= ($this->table[($lvl-1)][$parentnid]['simple']['border_details']['L']['w']
16336
+ + $this->table[($lvl-1)][$parentnid]['simple']['border_details']['R']['w']) /2
16337
+ + $c['padding']['L']
16338
+ + $c['padding']['R'];
16339
+ }
16340
+ }
16341
+ if (isset($this->table[$lvl][$nid]['wpercent']) && $this->table[$lvl][$nid]['wpercent'] && $lvl>1) {
16342
+ $this->table[$lvl][$nid]['w'] = $parentwidth;
16343
+ }
16344
+ else if ($parentwidth > $this->table[$lvl][$nid]['maw']) {
16345
+ $this->table[$lvl][$nid]['w'] = $this->table[$lvl][$nid]['maw'] ;
16346
+ }
16347
+ else {
16348
+ $this->table[$lvl][$nid]['w'] = $parentwidth;
16349
+ }
16350
+ unset($c);
16351
+ $this->_tableWidth($this->table[$lvl][$nid]);
16352
+ }
16353
+ }
16354
+
16355
+ // Starting at $this->innermostTableLevel
16356
+ // Cascade back up nested tables: setting heights back up the tree
16357
+ for($lvl=$this->innermostTableLevel;$lvl>0;$lvl--) {
16358
+ for ($nid=1; $nid<=$this->tbctr[$lvl]; $nid++) {
16359
+ list($tableheight,$maxrowheight,$fullpage,$remainingpage, $maxfirstrowheight) = $this->_tableHeight($this->table[$lvl][$nid]); }
16360
+ }
16361
+
16362
+ // RESIZING ALGORITHM
16363
+
16364
+ if ($maxrowheight > $fullpage) { $recalculate = $this->tbsqrt($maxrowheight / $fullpage, $iteration); $iteration++; }
16365
+ else if ($this->table_rotate && $tableheight > $remainingpage && !$added_page) {
16366
+ // If can fit on remainder of page whilst respecting autosize value..
16367
+ if (($this->shrin_k * $this->tbsqrt($tableheight / $remainingpage, $iteration)) <= $this->shrink_this_table_to_fit) {
16368
+ $recalculate = $this->tbsqrt($tableheight / $remainingpage, $iteration); $iteration++;
16369
+ }
16370
+ else {
16371
+ if (!$added_page) {
16372
+ $this->AddPage($this->CurOrientation);
16373
+ $added_page = true;
16374
+ $this->kwt_moved = true;
16375
+ $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
16376
+ }
16377
+ // 0.001 to force it to recalculate
16378
+ $recalculate = (1 / $this->shrin_k) + 0.001; // undo any shrink
16379
+ }
16380
+ }
16381
+ else if ($this->table_keep_together || ($this->table[1][1]['nr']==1 && !$this->writingHTMLfooter)) {
16382
+ if ($tableheight > $fullpage) {
16383
+ if (($this->shrin_k * $this->tbsqrt($tableheight / $fullpage, $iteration)) <= $this->shrink_this_table_to_fit) {
16384
+ $recalculate = $this->tbsqrt($tableheight / $fullpage, $iteration); $iteration++;
16385
+ }
16386
+ else if ($this->tableMinSizePriority) {
16387
+ $this->table_keep_together = false;
16388
+ $recalculate = (1 / $this->shrin_k) + 0.001;
16389
+ }
16390
+ else {
16391
+ if (!$added_page && $this->y != $this->tMargin) {
16392
+ $this->AddPage($this->CurOrientation);
16393
+ $added_page = true;
16394
+ $this->kwt_moved = true;
16395
+ $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
16396
+ }
16397
+ $recalculate = $this->tbsqrt($tableheight / $fullpage, $iteration); $iteration++;
16398
+ }
16399
+ }
16400
+ else if ($tableheight > $remainingpage) {
16401
+ // If can fit on remainder of page whilst respecting autosize value..
16402
+ if (($this->shrin_k * $this->tbsqrt($tableheight / $remainingpage, $iteration)) <= $this->shrink_this_table_to_fit) {
16403
+ $recalculate = $this->tbsqrt($tableheight / $remainingpage, $iteration); $iteration++;
16404
+ }
16405
+ else {
16406
+ if (!$added_page) {
16407
+ $this->AddPage($this->CurOrientation);
16408
+ $added_page = true;
16409
+ $this->kwt_moved = true;
16410
+ $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
16411
+ }
16412
+
16413
+ //$recalculate = $this->tbsqrt($tableheight / $fullpage, $iteration); $iteration++;
16414
+ $recalculate = (1 / $this->shrin_k) + 0.001; // undo any shrink
16415
+ }
16416
+ }
16417
+ else { $recalculate = 1; }
16418
+ }
16419
+ else { $recalculate = 1; }
16420
+ }
16421
+
16422
+
16423
+ if ($maxfirstrowheight > $remainingpage && !$added_page && !$this->table_rotate && !$this->ColActive && !$this->table_keep_together && !$this->writingHTMLheader && !$this->writingHTMLfooter) {
16424
+ $this->AddPage($this->CurOrientation);
16425
+ $this->kwt_moved = true;
16426
+ }
16427
+
16428
+ // keep-with-table: if page has advanced, print out buffer now, else done in fn. _Tablewrite()
16429
+ if ($this->kwt_saved && $this->kwt_moved) {
16430
+ $this->printkwtbuffer();
16431
+ $this->kwt_moved = false;
16432
+ $this->kwt_saved = false;
16433
+ }
16434
+
16435
+ // Recursively writes all tables starting at top level
16436
+ $this->_tableWrite($this->table[1][1]);
16437
+
16438
+ if ($this->table_rotate && $this->tablebuffer) {
16439
+ $this->PageBreakTrigger=$this->h-$this->bMargin;
16440
+ $save_tr = $this->table_rotate;
16441
+ $save_y = $this->y;
16442
+ $this->table_rotate = 0;
16443
+ $this->y = $this->tbrot_y0;
16444
+ $h = $this->tbrot_w;
16445
+ $this->DivLn($h,$this->blklvl,true);
16446
+
16447
+ $this->table_rotate = $save_tr;
16448
+ $this->y = $save_y;
16449
+
16450
+ $this->printtablebuffer();
16451
+ }
16452
+ $this->table_rotate = 0;
16453
+ }
16454
+
16455
+
16456
+ $this->x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'];
16457
+
16458
+ $this->maxPosR = max($this->maxPosR , ($this->x + $this->table[1][1]['w']));
16459
+
16460
+ $this->blockjustfinished=true;
16461
+ $this->lastblockbottommargin = $this->table[1][1]['margin']['B'];
16462
+ //Reset values
16463
+
16464
+ if (isset($this->table[1][1]['page_break_after'])) { $page_break_after = $this->table[1][1]['page_break_after']; }
16465
+ else { $page_break_after = ''; }
16466
+
16467
+ // Keep-with-table
16468
+ $this->kwt = false;
16469
+ $this->kwt_y0 = 0;
16470
+ $this->kwt_x0 = 0;
16471
+ $this->kwt_height = 0;
16472
+ $this->kwt_buffer = array();
16473
+ $this->kwt_Links = array();
16474
+ $this->kwt_Annots = array();
16475
+ $this->kwt_moved = false;
16476
+ $this->kwt_saved = false;
16477
+
16478
+ $this->kwt_Reference = array();
16479
+ $this->kwt_BMoutlines = array();
16480
+ $this->kwt_toc = array();
16481
+
16482
+ $this->shrin_k = 1;
16483
+ $this->shrink_this_table_to_fit = 0;
16484
+
16485
+ unset($this->table);
16486
+ $this->table=array(); //array
16487
+ $this->tableLevel=0;
16488
+ $this->tbctr=array();
16489
+ $this->innermostTableLevel=0;
16490
+ $this->cssmgr->tbCSSlvl = 0;
16491
+ $this->cssmgr->tablecascadeCSS = array();
16492
+
16493
+ unset($this->cell);
16494
+ $this->cell=array(); //array
16495
+
16496
+ $this->col=-1; //int
16497
+ $this->row=-1; //int
16498
+ $this->Reset();
16499
+
16500
+ $this->cellPaddingL = 0;
16501
+ $this->cellPaddingT = 0;
16502
+ $this->cellPaddingR = 0;
16503
+ $this->cellPaddingB = 0;
16504
+ $this->cMarginL = 0;
16505
+ $this->cMarginT = 0;
16506
+ $this->cMarginR = 0;
16507
+ $this->cMarginB = 0;
16508
+ $this->default_font_size = $this->original_default_font_size;
16509
+ $this->default_font = $this->original_default_font;
16510
+ $this->SetFontSize($this->default_font_size, false);
16511
+ $this->SetFont($this->default_font,'',0,false);
16512
+ $this->SetLineHeight();
16513
+ if (isset($this->blk[$this->blklvl]['InlineProperties'])) { $this->restoreInlineProperties($this->blk[$this->blklvl]['InlineProperties']);}
16514
+
16515
+ if ($page_break_after) {
16516
+ $save_blklvl = $this->blklvl;
16517
+ $save_blk = $this->blk;
16518
+ $save_silp = $this->saveInlineProperties();
16519
+ $save_spanlvl = $this->spanlvl;
16520
+ $save_ilp = $this->InlineProperties;
16521
+ if ($this->blklvl>1) {
16522
+ // Close any open block tags
16523
+ for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag']); }
16524
+ // Output any text left in buffer
16525
+ if (count($this->textbuffer)) { $this->printbuffer($this->textbuffer); $this->textbuffer=array(); }
16526
+ }
16527
+ if ($page_break_after == 'RIGHT') { $this->AddPage($this->CurOrientation,'NEXT-ODD','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
16528
+ else if ($page_break_after == 'LEFT') { $this->AddPage($this->CurOrientation,'NEXT-EVEN','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
16529
+ else { $this->AddPage($this->CurOrientation,'','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
16530
+ if (!$this->restoreBlockPagebreaks) {
16531
+ $this->blklvl = 0;
16532
+ $this->lastblocklevelchange = 0;
16533
+ $this->blk = array();
16534
+ $this->initialiseBlock($this->blk[0]);
16535
+ $this->blk[0]['width'] =& $this->pgwidth;
16536
+ $this->blk[0]['inner_width'] =& $this->pgwidth;
16537
+ $this->blk[0]['blockContext'] = $this->blockContext;
16538
+ $properties = $this->cssmgr->MergeCSS('BLOCK','BODY','');
16539
+ $this->setCSS($properties,'','BODY');
16540
+ }
16541
+
16542
+ if ($this->restoreBlockPagebreaks) {
16543
+ $this->blk = $save_blk;
16544
+ // Re-open block tags
16545
+ $t = $this->blk[0]['tag'];
16546
+ $a = $this->blk[0]['attr'];
16547
+ $this->blklvl = 0;
16548
+ for ($b=0; $b<=$save_blklvl;$b++) {
16549
+ $tc = $t;
16550
+ $ac = $a;
16551
+ $t = $this->blk[$b+1]['tag'];
16552
+ $a = $this->blk[$b+1]['attr'];
16553
+ unset($this->blk[$b+1]);
16554
+ $this->OpenTag($tc,$ac);
16555
+ }
16556
+ $this->spanlvl = $save_spanlvl;
16557
+ $this->InlineProperties = $save_ilp;
16558
+ $this->restoreInlineProperties($save_silp);
16559
+ }
16560
+ }
16561
+
16562
+ }
16563
+
16564
+ // *********** LISTS ********************
16565
+
16566
+ if($tag=='LI') {
16567
+ $this->lastoptionaltag = '';
16568
+ unset($this->cssmgr->listcascadeCSS[$this->cssmgr->listCSSlvl]);
16569
+ $this->cssmgr->listCSSlvl--;
16570
+ if (isset($this->listoccur[$this->listlvl]) && isset($this->InlineProperties['LIST'][$this->listlvl][$this->listoccur[$this->listlvl]])) { $this->restoreInlineProperties($this->InlineProperties['LIST'][$this->listlvl][$this->listoccur[$this->listlvl]]); }
16571
+ }
16572
+
16573
+
16574
+ if(($tag=='UL') or ($tag=='OL')) {
16575
+ $this->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces
16576
+ unset($this->cssmgr->listcascadeCSS[$this->cssmgr->listCSSlvl]);
16577
+ $this->cssmgr->listCSSlvl--;
16578
+
16579
+ $this->lastoptionaltag = '';
16580
+ // A simple list for inside a table
16581
+ if($this->tableLevel) {
16582
+ $this->listlist[$this->listlvl]['MAXNUM'] = $this->listnum; //save previous lvl's maxnum
16583
+ unset($this->listlist[$this->listlvl]);
16584
+ $this->listlvl--;
16585
+ if (isset($this->listlist[$this->listlvl]['MAXNUM'])) { $this->listnum = $this->listlist[$this->listlvl]['MAXNUM']; } // restore previous levels
16586
+ if ($this->listlvl == 0) { $this->listjustfinished = true; }
16587
+ return;
16588
+ }
16589
+
16590
+ if ($this->listlvl > 1) { // returning one level
16591
+ $this->listjustfinished=true;
16592
+ if (!empty($this->textbuffer)) {
16593
+ $this->listitem[] = array($this->listlvl,$this->listnum,$this->textbuffer,$this->listoccur[$this->listlvl],$this->listitemtype);
16594
+ }
16595
+ else {
16596
+ $this->listnum--;
16597
+ }
16598
+
16599
+ $this->textbuffer = array();
16600
+ $occur = $this->listoccur[$this->listlvl];
16601
+ $this->listlist[$this->listlvl][$occur]['MAXNUM'] = $this->listnum; //save previous lvl's maxnum
16602
+ $this->listlvl--;
16603
+ $occur = $this->listoccur[$this->listlvl];
16604
+ $this->listnum = $this->listlist[$this->listlvl][$occur]['MAXNUM']; // recover previous level's number
16605
+ $this->listtype = $this->listlist[$this->listlvl][$occur]['TYPE']; // recover previous level's type
16606
+ if ($this->InlineProperties['LIST'][$this->listlvl][$occur]) { $this->restoreInlineProperties($this->InlineProperties['LIST'][$this->listlvl][$occur]); }
16607
+
16608
+ }
16609
+ else { // We are closing the last OL/UL tag
16610
+ if (!empty($this->textbuffer)) {
16611
+ $this->listitem[] = array($this->listlvl,$this->listnum,$this->textbuffer,$this->listoccur[$this->listlvl],$this->listitemtype);
16612
+ }
16613
+ else {
16614
+ $this->listnum--;
16615
+ }
16616
+
16617
+ $occur = $this->listoccur[$this->listlvl];
16618
+ $this->listlist[$this->listlvl][$occur]['MAXNUM'] = $this->listnum;
16619
+ $this->textbuffer = array();
16620
+ $this->listlvl--;
16621
+
16622
+ $this->printlistbuffer();
16623
+ unset($this->InlineProperties['LIST']);
16624
+ // SPACING AFTER LIST (Top level only)
16625
+ $this->Ln(0);
16626
+ if ($this->list_margin_bottom) {
16627
+ $this->DivLn($this->list_margin_bottom,$this->blklvl,true,1); // collapsible
16628
+ }
16629
+ if (isset($this->blk[$this->blklvl]['InlineProperties'])) { $this->restoreInlineProperties($this->blk[$this->blklvl]['InlineProperties']);}
16630
+ $this->listjustfinished = true;
16631
+ $this->cssmgr->listCSSlvl = 0;
16632
+ $this->cssmgr->listcascadeCSS = array();
16633
+ $this->blockjustfinished=true;
16634
+ $this->lastblockbottommargin = $this->list_margin_bottom;
16635
+ }
16636
+ }
16637
+
16638
+
16639
+ }
16640
+
16641
+
16642
+ // This function determines the shrink factor when resizing tables
16643
+ // val is the table_height / page_height_available
16644
+ // returns a scaling factor used as $shrin_k to resize the table
16645
+ // Overcompensating will be quicker but may unnecessarily shrink table too much
16646
+ // Undercompensating means it will reiterate more times (taking more processing time)
16647
+ function tbsqrt($val, $iteration=3) {
16648
+ $k = 4; // Alters number of iterations until it returns $val itself - Must be > 2
16649
+ // Probably best guess and most accurate
16650
+ if ($iteration==1) return sqrt($val);
16651
+ // Faster than using sqrt (because it won't undercompensate), and gives reasonable results
16652
+ //return 1+(($val-1)/2);
16653
+ $x = 2-(($iteration-2)/($k-2));
16654
+ if ($x == 0) { $ret = $val+0.00001; }
16655
+ else if ($x < 0) { $ret = 1 + ( pow(2, ($iteration-2-$k))/1000 ); }
16656
+ else { $ret = 1+(($val-1)/$x); }
16657
+ return $ret;
16658
+ }
16659
+
16660
+
16661
+ function printlistbuffer() {
16662
+ //Save x coordinate
16663
+ $x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'];
16664
+ $this->cMarginL = 0;
16665
+ $this->cMarginR = 0;
16666
+ $currIndentLvl = -1;
16667
+ $lastIndent = array();
16668
+ $bak_page = $this->page;
16669
+ $indent = 0;
16670
+ foreach($this->listitem as $item)
16671
+ {
16672
+ // COLS
16673
+ $oldcolumn = $this->CurrCol;
16674
+
16675
+ $this->bulletarray = array();
16676
+ //Get list's buffered data
16677
+ $this->listlvl = $lvl = $item[0];
16678
+ $num = $item[1];
16679
+ $this->textbuffer = $item[2];
16680
+ $occur = $item[3];
16681
+ if ($item[4]) { $type = $item[4]; } // listitemtype
16682
+ else { $type = $this->listlist[$lvl][$occur]['TYPE']; }
16683
+ $maxnum = $this->listlist[$lvl][$occur]['MAXNUM'];
16684
+ $this->restoreInlineProperties($this->InlineProperties['LIST'][$lvl][$occur]);
16685
+ $this->SetFont($this->FontFamily,$this->FontStyle,$this->FontSizePt,true,true); // force to write
16686
+ $clh = $this->FontSize;
16687
+
16688
+ $this->SetLineHeight($this->FontSizePt,$this->list_lineheight[$lvl][$occur]);
16689
+ $this->listOcc = $occur;
16690
+ $this->listnum = $num;
16691
+
16692
+ if (isset($this->list_align[$this->listlvl][$occur])) { $this->divalign = $this->list_align[$this->listlvl][$occur]; }
16693
+ else {
16694
+ if (isset($this->blk[$this->blklvl]['direction']) && $this->blk[$this->blklvl]['direction']=='rtl') { $this->divalign = 'R'; }
16695
+ else { $this->divalign = 'L'; }
16696
+ }
16697
+
16698
+ // Set the bullet fontsize
16699
+ $bullfs = $this->InlineProperties['LISTITEM'][$lvl][$occur][$num]['size'];
16700
+
16701
+ $space_width = $this->GetCharWidth(' ',false) * 1.5;
16702
+
16703
+ //Set default width & height values
16704
+ $this->divwidth = $this->blk[$this->blklvl]['inner_width'];
16705
+ $this->divheight = $this->lineheight;
16706
+ $typefont = $this->FontFamily;
16707
+ if (preg_match('/U\+([a-fA-F0-9]+)/i',$type,$m)) {
16708
+ if ($this->_charDefined($this->CurrentFont['cw'],hexdec($m[1]))) { $list_item_marker = codeHex2utf($m[1]); }
16709
+ else { $list_item_marker = '-'; }
16710
+ $blt_width = $this->GetStringWidth($list_item_marker);
16711
+ $typefont = '';
16712
+ if (preg_match('/rgb\(.*?\)/',$type,$m)) {
16713
+ $list_item_color = $this->ConvertColor($m[0]);
16714
+ }
16715
+ }
16716
+ else {
16717
+ $list_item_color = false;
16718
+
16719
+ switch($type) //Format type
16720
+ {
16721
+ case '1':
16722
+ if ($this->listDir == 'rtl') { $list_item_marker = $this->list_number_suffix . $num; }
16723
+ else { $list_item_marker = $num . $this->list_number_suffix; }
16724
+ $blt_width = $this->GetStringWidth(str_repeat('5',strlen($maxnum)).$this->list_number_suffix);
16725
+ break;
16726
+ case 'none':
16727
+ $list_item_marker = '';
16728
+ $blt_width = 0;
16729
+ break;
16730
+ case 'A':
16731
+ $anum = $this->dec2alpha($num,true);
16732
+ $maxnum = $this->dec2alpha($maxnum,true);
16733
+ if ($this->listDir == 'rtl') { $list_item_marker = $this->list_number_suffix . $anum; }
16734
+ else { $list_item_marker = $anum . $this->list_number_suffix; }
16735
+ $blt_width = $this->GetStringWidth(str_repeat('W',strlen($maxnum)).$this->list_number_suffix);
16736
+ break;
16737
+ case 'a':
16738
+ $anum = $this->dec2alpha($num,false);
16739
+ $maxnum = $this->dec2alpha($maxnum,false);
16740
+ if ($this->listDir == 'rtl') { $list_item_marker = $this->list_number_suffix . $anum; }
16741
+ else { $list_item_marker = $anum . $this->list_number_suffix; }
16742
+ $blt_width = $this->GetStringWidth(str_repeat('m',strlen($maxnum)).$this->list_number_suffix);
16743
+ break;
16744
+ case 'I':
16745
+ $anum = $this->dec2roman($num,true);
16746
+ if ($this->listDir == 'rtl') { $list_item_marker = $this->list_number_suffix . $anum; }
16747
+ else { $list_item_marker = $anum . $this->list_number_suffix; }
16748
+
16749
+ if ($maxnum>87) { $bbit = 87; }
16750
+ else if ($maxnum>86) { $bbit = 86; }
16751
+ else if ($maxnum>37) { $bbit = 38; }
16752
+ else if ($maxnum>36) { $bbit = 37; }
16753
+ else if ($maxnum>27) { $bbit = 28; }
16754
+ else if ($maxnum>26) { $bbit = 27; }
16755
+ else if ($maxnum>17) { $bbit = 18; }
16756
+ else if ($maxnum>16) { $bbit = 17; }
16757
+ else if ($maxnum>7) { $bbit = 8; }
16758
+ else if ($maxnum>6) { $bbit = 7; }
16759
+ else if ($maxnum>3) { $bbit = 4; }
16760
+ else { $bbit = $maxnum; }
16761
+ $maxlnum = $this->dec2roman($bbit,true);
16762
+ $blt_width = $this->GetStringWidth($maxlnum.$this->list_number_suffix);
16763
+ break;
16764
+ case 'i':
16765
+ $anum = $this->dec2roman($num,false);
16766
+ if ($this->listDir == 'rtl') { $list_item_marker = $this->list_number_suffix . $anum; }
16767
+ else { $list_item_marker = $anum . $this->list_number_suffix; }
16768
+
16769
+ if ($maxnum>87) { $bbit = 87; }
16770
+ else if ($maxnum>86) { $bbit = 86; }
16771
+ else if ($maxnum>37) { $bbit = 38; }
16772
+ else if ($maxnum>36) { $bbit = 37; }
16773
+ else if ($maxnum>27) { $bbit = 28; }
16774
+ else if ($maxnum>26) { $bbit = 27; }
16775
+ else if ($maxnum>17) { $bbit = 18; }
16776
+ else if ($maxnum>16) { $bbit = 17; }
16777
+ else if ($maxnum>7) { $bbit = 8; }
16778
+ else if ($maxnum>6) { $bbit = 7; }
16779
+ else if ($maxnum>3) { $bbit = 4; }
16780
+ else { $bbit = $maxnum; }
16781
+ $maxlnum = $this->dec2roman($bbit,false);
16782
+
16783
+ $blt_width = $this->GetStringWidth($maxlnum.$this->list_number_suffix);
16784
+ break;
16785
+ case 'disc':
16786
+ if ($this->PDFA || $this->PDFX) {
16787
+ if ($this->_charDefined($this->CurrentFont['cw'],8226)) { $list_item_marker = "\xe2\x80\xa2"; } // &#8226;
16788
+ else { $list_item_marker = '-'; }
16789
+ $blt_width = $this->GetCharWidth($list_item_marker);
16790
+ break;
16791
+ }
16792
+ $list_item_marker = chr(108); // bullet disc in Zapfdingbats 'l'
16793
+ $typefont = 'czapfdingbats';
16794
+ $blt_width = (0.791 * $this->FontSize/2.5);
16795
+ break;
16796
+ case 'circle':
16797
+ if ($this->PDFA || $this->PDFX) {
16798
+ if ($this->_charDefined($this->CurrentFont['cw'],9900)) { $list_item_marker = "\xe2\x9a\xac"; } // &#9900;
16799
+ else { $list_item_marker = '-'; }
16800
+ $blt_width = $this->GetCharWidth($list_item_marker);
16801
+ break;
16802
+ }
16803
+ $list_item_marker = chr(109); // circle in Zapfdingbats 'm'
16804
+ $typefont = 'czapfdingbats';
16805
+ $blt_width = (0.873 * $this->FontSize/2.5);
16806
+ break;
16807
+ case 'square':
16808
+ if ($this->PDFA || $this->PDFX) {
16809
+ if ($this->_charDefined($this->CurrentFont['cw'],9642)) { $list_item_marker = "\xe2\x96\xaa"; } // &#9642;
16810
+ else { $list_item_marker = '-'; }
16811
+ $blt_width = $this->GetCharWidth($list_item_marker);
16812
+ break;
16813
+ }
16814
+ $list_item_marker = chr(110); //black square in Zapfdingbats fon