Projet

Général

Profil

Paste
Télécharger (104 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / libraries / tcpdf-version / include / tcpdf_static.php @ 9d13637e

1
<?php
2
//============================================================+
3
// File name   : tcpdf_static.php
4
// Version     : 1.0.002
5
// Begin       : 2002-08-03
6
// Last Update : 2013-09-14
7
// Author      : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com
8
// License     : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html)
9
// -------------------------------------------------------------------
10
// Copyright (C) 2002-2013 Nicola Asuni - Tecnick.com LTD
11
//
12
// This file is part of TCPDF software library.
13
//
14
// TCPDF is free software: you can redistribute it and/or modify it
15
// under the terms of the GNU Lesser General Public License as
16
// published by the Free Software Foundation, either version 3 of the
17
// License, or (at your option) any later version.
18
//
19
// TCPDF is distributed in the hope that it will be useful, but
20
// WITHOUT ANY WARRANTY; without even the implied warranty of
21
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
22
// See the GNU Lesser General Public License for more details.
23
//
24
// You should have received a copy of the License
25
// along with TCPDF. If not, see
26
// <http://www.tecnick.com/pagefiles/tcpdf/LICENSE.TXT>.
27
//
28
// See LICENSE.TXT file for more information.
29
// -------------------------------------------------------------------
30
//
31
// Description :
32
//   Static methods used by the TCPDF class.
33
//
34
//============================================================+
35

    
36
/**
37
 * @file
38
 * This is a PHP class that contains static methods for the TCPDF class.<br>
39
 * @package com.tecnick.tcpdf
40
 * @author Nicola Asuni
41
 * @version 1.0.002
42
 */
43

    
44
/**
45
 * @class TCPDF_STATIC
46
 * Static methods used by the TCPDF class.
47
 * @package com.tecnick.tcpdf
48
 * @brief PHP class for generating PDF documents without requiring external extensions.
49
 * @version 1.0.002
50
 * @author Nicola Asuni - info@tecnick.com
51
 */
52
class TCPDF_STATIC {
53

    
54
        /**
55
         * Current TCPDF version.
56
         * @private static
57
         */
58
        private static $tcpdf_version = '6.0.038';
59

    
60
        /**
61
         * String alias for total number of pages.
62
         * @public static
63
         */
64
        public static $alias_tot_pages = '{:ptp:}';
65

    
66
        /**
67
         * String alias for page number.
68
         * @public static
69
         */
70
        public static $alias_num_page = '{:pnp:}';
71

    
72
        /**
73
         * String alias for total number of pages in a single group.
74
         * @public static
75
         */
76
        public static $alias_group_tot_pages = '{:ptg:}';
77

    
78
        /**
79
         * String alias for group page number.
80
         * @public static
81
         */
82
        public static $alias_group_num_page = '{:png:}';
83

    
84
        /**
85
         * String alias for right shift compensation used to correctly align page numbers on the right.
86
         * @public static
87
         */
88
        public static $alias_right_shift = '{rsc:';
89

    
90
        /**
91
         * Encryption padding string.
92
         * @public static
93
         */
94
        public static $enc_padding = "\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A";
95

    
96
        /**
97
         * ByteRange placemark used during digital signature process.
98
         * @since 4.6.028 (2009-08-25)
99
         * @public static
100
         */
101
        public static $byterange_string = '/ByteRange[0 ********** ********** **********]';
102

    
103
        /**
104
         * Array page boxes names
105
         * @public static
106
         */
107
        public static $pageboxes = array('MediaBox', 'CropBox', 'BleedBox', 'TrimBox', 'ArtBox');
108

    
109
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
110

    
111
        /**
112
         * Return the current TCPDF version.
113
         * @return TCPDF version string
114
         * @since 5.9.012 (2010-11-10)
115
         * @public static
116
         */
117
        public static function getTCPDFVersion() {
118
                return self::$tcpdf_version;
119
        }
120

    
121
        /**
122
         * Return the current TCPDF producer.
123
         * @return TCPDF producer string
124
         * @since 6.0.000 (2013-03-16)
125
         * @public static
126
         */
127
        public static function getTCPDFProducer() {
128
                return "\x54\x43\x50\x44\x46\x20".self::getTCPDFVersion()."\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x74\x63\x70\x64\x66\x2e\x6f\x72\x67\x29";
129
        }
130

    
131
        /**
132
         * Sets the current active configuration setting of magic_quotes_runtime (if the set_magic_quotes_runtime function exist)
133
         * @param $mqr (boolean) FALSE for off, TRUE for on.
134
         * @since 4.6.025 (2009-08-17)
135
         * @public static
136
         */
137
        public static function set_mqr($mqr) {
138
                if (!defined('PHP_VERSION_ID')) {
139
                        $version = PHP_VERSION;
140
                        define('PHP_VERSION_ID', (($version{0} * 10000) + ($version{2} * 100) + $version{4}));
141
                }
142
                if (PHP_VERSION_ID < 50300) {
143
                        @set_magic_quotes_runtime($mqr);
144
                }
145
        }
146

    
147
        /**
148
         * Gets the current active configuration setting of magic_quotes_runtime (if the get_magic_quotes_runtime function exist)
149
         * @return Returns 0 if magic quotes runtime is off or get_magic_quotes_runtime doesn't exist, 1 otherwise.
150
         * @since 4.6.025 (2009-08-17)
151
         * @public static
152
         */
153
        public static function get_mqr() {
154
                if (!defined('PHP_VERSION_ID')) {
155
                        $version = PHP_VERSION;
156
                        define('PHP_VERSION_ID', (($version{0} * 10000) + ($version{2} * 100) + $version{4}));
157
                }
158
                if (PHP_VERSION_ID < 50300) {
159
                        return @get_magic_quotes_runtime();
160
                }
161
                return 0;
162
        }
163

    
164
        /**
165
         * Get page dimensions from format name.
166
         * @param $format (mixed) The format name. It can be: <ul>
167
         * <li><b>ISO 216 A Series + 2 SIS 014711 extensions</b></li>
168
         * <li>A0 (841x1189 mm ; 33.11x46.81 in)</li>
169
         * <li>A1 (594x841 mm ; 23.39x33.11 in)</li>
170
         * <li>A2 (420x594 mm ; 16.54x23.39 in)</li>
171
         * <li>A3 (297x420 mm ; 11.69x16.54 in)</li>
172
         * <li>A4 (210x297 mm ; 8.27x11.69 in)</li>
173
         * <li>A5 (148x210 mm ; 5.83x8.27 in)</li>
174
         * <li>A6 (105x148 mm ; 4.13x5.83 in)</li>
175
         * <li>A7 (74x105 mm ; 2.91x4.13 in)</li>
176
         * <li>A8 (52x74 mm ; 2.05x2.91 in)</li>
177
         * <li>A9 (37x52 mm ; 1.46x2.05 in)</li>
178
         * <li>A10 (26x37 mm ; 1.02x1.46 in)</li>
179
         * <li>A11 (18x26 mm ; 0.71x1.02 in)</li>
180
         * <li>A12 (13x18 mm ; 0.51x0.71 in)</li>
181
         * <li><b>ISO 216 B Series + 2 SIS 014711 extensions</b></li>
182
         * <li>B0 (1000x1414 mm ; 39.37x55.67 in)</li>
183
         * <li>B1 (707x1000 mm ; 27.83x39.37 in)</li>
184
         * <li>B2 (500x707 mm ; 19.69x27.83 in)</li>
185
         * <li>B3 (353x500 mm ; 13.90x19.69 in)</li>
186
         * <li>B4 (250x353 mm ; 9.84x13.90 in)</li>
187
         * <li>B5 (176x250 mm ; 6.93x9.84 in)</li>
188
         * <li>B6 (125x176 mm ; 4.92x6.93 in)</li>
189
         * <li>B7 (88x125 mm ; 3.46x4.92 in)</li>
190
         * <li>B8 (62x88 mm ; 2.44x3.46 in)</li>
191
         * <li>B9 (44x62 mm ; 1.73x2.44 in)</li>
192
         * <li>B10 (31x44 mm ; 1.22x1.73 in)</li>
193
         * <li>B11 (22x31 mm ; 0.87x1.22 in)</li>
194
         * <li>B12 (15x22 mm ; 0.59x0.87 in)</li>
195
         * <li><b>ISO 216 C Series + 2 SIS 014711 extensions + 2 EXTENSION</b></li>
196
         * <li>C0 (917x1297 mm ; 36.10x51.06 in)</li>
197
         * <li>C1 (648x917 mm ; 25.51x36.10 in)</li>
198
         * <li>C2 (458x648 mm ; 18.03x25.51 in)</li>
199
         * <li>C3 (324x458 mm ; 12.76x18.03 in)</li>
200
         * <li>C4 (229x324 mm ; 9.02x12.76 in)</li>
201
         * <li>C5 (162x229 mm ; 6.38x9.02 in)</li>
202
         * <li>C6 (114x162 mm ; 4.49x6.38 in)</li>
203
         * <li>C7 (81x114 mm ; 3.19x4.49 in)</li>
204
         * <li>C8 (57x81 mm ; 2.24x3.19 in)</li>
205
         * <li>C9 (40x57 mm ; 1.57x2.24 in)</li>
206
         * <li>C10 (28x40 mm ; 1.10x1.57 in)</li>
207
         * <li>C11 (20x28 mm ; 0.79x1.10 in)</li>
208
         * <li>C12 (14x20 mm ; 0.55x0.79 in)</li>
209
         * <li>C76 (81x162 mm ; 3.19x6.38 in)</li>
210
         * <li>DL (110x220 mm ; 4.33x8.66 in)</li>
211
         * <li><b>SIS 014711 E Series</b></li>
212
         * <li>E0 (879x1241 mm ; 34.61x48.86 in)</li>
213
         * <li>E1 (620x879 mm ; 24.41x34.61 in)</li>
214
         * <li>E2 (440x620 mm ; 17.32x24.41 in)</li>
215
         * <li>E3 (310x440 mm ; 12.20x17.32 in)</li>
216
         * <li>E4 (220x310 mm ; 8.66x12.20 in)</li>
217
         * <li>E5 (155x220 mm ; 6.10x8.66 in)</li>
218
         * <li>E6 (110x155 mm ; 4.33x6.10 in)</li>
219
         * <li>E7 (78x110 mm ; 3.07x4.33 in)</li>
220
         * <li>E8 (55x78 mm ; 2.17x3.07 in)</li>
221
         * <li>E9 (39x55 mm ; 1.54x2.17 in)</li>
222
         * <li>E10 (27x39 mm ; 1.06x1.54 in)</li>
223
         * <li>E11 (19x27 mm ; 0.75x1.06 in)</li>
224
         * <li>E12 (13x19 mm ; 0.51x0.75 in)</li>
225
         * <li><b>SIS 014711 G Series</b></li>
226
         * <li>G0 (958x1354 mm ; 37.72x53.31 in)</li>
227
         * <li>G1 (677x958 mm ; 26.65x37.72 in)</li>
228
         * <li>G2 (479x677 mm ; 18.86x26.65 in)</li>
229
         * <li>G3 (338x479 mm ; 13.31x18.86 in)</li>
230
         * <li>G4 (239x338 mm ; 9.41x13.31 in)</li>
231
         * <li>G5 (169x239 mm ; 6.65x9.41 in)</li>
232
         * <li>G6 (119x169 mm ; 4.69x6.65 in)</li>
233
         * <li>G7 (84x119 mm ; 3.31x4.69 in)</li>
234
         * <li>G8 (59x84 mm ; 2.32x3.31 in)</li>
235
         * <li>G9 (42x59 mm ; 1.65x2.32 in)</li>
236
         * <li>G10 (29x42 mm ; 1.14x1.65 in)</li>
237
         * <li>G11 (21x29 mm ; 0.83x1.14 in)</li>
238
         * <li>G12 (14x21 mm ; 0.55x0.83 in)</li>
239
         * <li><b>ISO Press</b></li>
240
         * <li>RA0 (860x1220 mm ; 33.86x48.03 in)</li>
241
         * <li>RA1 (610x860 mm ; 24.02x33.86 in)</li>
242
         * <li>RA2 (430x610 mm ; 16.93x24.02 in)</li>
243
         * <li>RA3 (305x430 mm ; 12.01x16.93 in)</li>
244
         * <li>RA4 (215x305 mm ; 8.46x12.01 in)</li>
245
         * <li>SRA0 (900x1280 mm ; 35.43x50.39 in)</li>
246
         * <li>SRA1 (640x900 mm ; 25.20x35.43 in)</li>
247
         * <li>SRA2 (450x640 mm ; 17.72x25.20 in)</li>
248
         * <li>SRA3 (320x450 mm ; 12.60x17.72 in)</li>
249
         * <li>SRA4 (225x320 mm ; 8.86x12.60 in)</li>
250
         * <li><b>German DIN 476</b></li>
251
         * <li>4A0 (1682x2378 mm ; 66.22x93.62 in)</li>
252
         * <li>2A0 (1189x1682 mm ; 46.81x66.22 in)</li>
253
         * <li><b>Variations on the ISO Standard</b></li>
254
         * <li>A2_EXTRA (445x619 mm ; 17.52x24.37 in)</li>
255
         * <li>A3+ (329x483 mm ; 12.95x19.02 in)</li>
256
         * <li>A3_EXTRA (322x445 mm ; 12.68x17.52 in)</li>
257
         * <li>A3_SUPER (305x508 mm ; 12.01x20.00 in)</li>
258
         * <li>SUPER_A3 (305x487 mm ; 12.01x19.17 in)</li>
259
         * <li>A4_EXTRA (235x322 mm ; 9.25x12.68 in)</li>
260
         * <li>A4_SUPER (229x322 mm ; 9.02x12.68 in)</li>
261
         * <li>SUPER_A4 (227x356 mm ; 8.94x14.02 in)</li>
262
         * <li>A4_LONG (210x348 mm ; 8.27x13.70 in)</li>
263
         * <li>F4 (210x330 mm ; 8.27x12.99 in)</li>
264
         * <li>SO_B5_EXTRA (202x276 mm ; 7.95x10.87 in)</li>
265
         * <li>A5_EXTRA (173x235 mm ; 6.81x9.25 in)</li>
266
         * <li><b>ANSI Series</b></li>
267
         * <li>ANSI_E (864x1118 mm ; 34.00x44.00 in)</li>
268
         * <li>ANSI_D (559x864 mm ; 22.00x34.00 in)</li>
269
         * <li>ANSI_C (432x559 mm ; 17.00x22.00 in)</li>
270
         * <li>ANSI_B (279x432 mm ; 11.00x17.00 in)</li>
271
         * <li>ANSI_A (216x279 mm ; 8.50x11.00 in)</li>
272
         * <li><b>Traditional 'Loose' North American Paper Sizes</b></li>
273
         * <li>LEDGER, USLEDGER (432x279 mm ; 17.00x11.00 in)</li>
274
         * <li>TABLOID, USTABLOID, BIBLE, ORGANIZERK (279x432 mm ; 11.00x17.00 in)</li>
275
         * <li>LETTER, USLETTER, ORGANIZERM (216x279 mm ; 8.50x11.00 in)</li>
276
         * <li>LEGAL, USLEGAL (216x356 mm ; 8.50x14.00 in)</li>
277
         * <li>GLETTER, GOVERNMENTLETTER (203x267 mm ; 8.00x10.50 in)</li>
278
         * <li>JLEGAL, JUNIORLEGAL (203x127 mm ; 8.00x5.00 in)</li>
279
         * <li><b>Other North American Paper Sizes</b></li>
280
         * <li>QUADDEMY (889x1143 mm ; 35.00x45.00 in)</li>
281
         * <li>SUPER_B (330x483 mm ; 13.00x19.00 in)</li>
282
         * <li>QUARTO (229x279 mm ; 9.00x11.00 in)</li>
283
         * <li>FOLIO, GOVERNMENTLEGAL (216x330 mm ; 8.50x13.00 in)</li>
284
         * <li>EXECUTIVE, MONARCH (184x267 mm ; 7.25x10.50 in)</li>
285
         * <li>MEMO, STATEMENT, ORGANIZERL (140x216 mm ; 5.50x8.50 in)</li>
286
         * <li>FOOLSCAP (210x330 mm ; 8.27x13.00 in)</li>
287
         * <li>COMPACT (108x171 mm ; 4.25x6.75 in)</li>
288
         * <li>ORGANIZERJ (70x127 mm ; 2.75x5.00 in)</li>
289
         * <li><b>Canadian standard CAN 2-9.60M</b></li>
290
         * <li>P1 (560x860 mm ; 22.05x33.86 in)</li>
291
         * <li>P2 (430x560 mm ; 16.93x22.05 in)</li>
292
         * <li>P3 (280x430 mm ; 11.02x16.93 in)</li>
293
         * <li>P4 (215x280 mm ; 8.46x11.02 in)</li>
294
         * <li>P5 (140x215 mm ; 5.51x8.46 in)</li>
295
         * <li>P6 (107x140 mm ; 4.21x5.51 in)</li>
296
         * <li><b>North American Architectural Sizes</b></li>
297
         * <li>ARCH_E (914x1219 mm ; 36.00x48.00 in)</li>
298
         * <li>ARCH_E1 (762x1067 mm ; 30.00x42.00 in)</li>
299
         * <li>ARCH_D (610x914 mm ; 24.00x36.00 in)</li>
300
         * <li>ARCH_C, BROADSHEET (457x610 mm ; 18.00x24.00 in)</li>
301
         * <li>ARCH_B (305x457 mm ; 12.00x18.00 in)</li>
302
         * <li>ARCH_A (229x305 mm ; 9.00x12.00 in)</li>
303
         * <li><b>Announcement Envelopes</b></li>
304
         * <li>ANNENV_A2 (111x146 mm ; 4.37x5.75 in)</li>
305
         * <li>ANNENV_A6 (121x165 mm ; 4.75x6.50 in)</li>
306
         * <li>ANNENV_A7 (133x184 mm ; 5.25x7.25 in)</li>
307
         * <li>ANNENV_A8 (140x206 mm ; 5.50x8.12 in)</li>
308
         * <li>ANNENV_A10 (159x244 mm ; 6.25x9.62 in)</li>
309
         * <li>ANNENV_SLIM (98x225 mm ; 3.87x8.87 in)</li>
310
         * <li><b>Commercial Envelopes</b></li>
311
         * <li>COMMENV_N6_1/4 (89x152 mm ; 3.50x6.00 in)</li>
312
         * <li>COMMENV_N6_3/4 (92x165 mm ; 3.62x6.50 in)</li>
313
         * <li>COMMENV_N8 (98x191 mm ; 3.87x7.50 in)</li>
314
         * <li>COMMENV_N9 (98x225 mm ; 3.87x8.87 in)</li>
315
         * <li>COMMENV_N10 (105x241 mm ; 4.12x9.50 in)</li>
316
         * <li>COMMENV_N11 (114x263 mm ; 4.50x10.37 in)</li>
317
         * <li>COMMENV_N12 (121x279 mm ; 4.75x11.00 in)</li>
318
         * <li>COMMENV_N14 (127x292 mm ; 5.00x11.50 in)</li>
319
         * <li><b>Catalogue Envelopes</b></li>
320
         * <li>CATENV_N1 (152x229 mm ; 6.00x9.00 in)</li>
321
         * <li>CATENV_N1_3/4 (165x241 mm ; 6.50x9.50 in)</li>
322
         * <li>CATENV_N2 (165x254 mm ; 6.50x10.00 in)</li>
323
         * <li>CATENV_N3 (178x254 mm ; 7.00x10.00 in)</li>
324
         * <li>CATENV_N6 (191x267 mm ; 7.50x10.50 in)</li>
325
         * <li>CATENV_N7 (203x279 mm ; 8.00x11.00 in)</li>
326
         * <li>CATENV_N8 (210x286 mm ; 8.25x11.25 in)</li>
327
         * <li>CATENV_N9_1/2 (216x267 mm ; 8.50x10.50 in)</li>
328
         * <li>CATENV_N9_3/4 (222x286 mm ; 8.75x11.25 in)</li>
329
         * <li>CATENV_N10_1/2 (229x305 mm ; 9.00x12.00 in)</li>
330
         * <li>CATENV_N12_1/2 (241x318 mm ; 9.50x12.50 in)</li>
331
         * <li>CATENV_N13_1/2 (254x330 mm ; 10.00x13.00 in)</li>
332
         * <li>CATENV_N14_1/4 (286x311 mm ; 11.25x12.25 in)</li>
333
         * <li>CATENV_N14_1/2 (292x368 mm ; 11.50x14.50 in)</li>
334
         * <li><b>Japanese (JIS P 0138-61) Standard B-Series</b></li>
335
         * <li>JIS_B0 (1030x1456 mm ; 40.55x57.32 in)</li>
336
         * <li>JIS_B1 (728x1030 mm ; 28.66x40.55 in)</li>
337
         * <li>JIS_B2 (515x728 mm ; 20.28x28.66 in)</li>
338
         * <li>JIS_B3 (364x515 mm ; 14.33x20.28 in)</li>
339
         * <li>JIS_B4 (257x364 mm ; 10.12x14.33 in)</li>
340
         * <li>JIS_B5 (182x257 mm ; 7.17x10.12 in)</li>
341
         * <li>JIS_B6 (128x182 mm ; 5.04x7.17 in)</li>
342
         * <li>JIS_B7 (91x128 mm ; 3.58x5.04 in)</li>
343
         * <li>JIS_B8 (64x91 mm ; 2.52x3.58 in)</li>
344
         * <li>JIS_B9 (45x64 mm ; 1.77x2.52 in)</li>
345
         * <li>JIS_B10 (32x45 mm ; 1.26x1.77 in)</li>
346
         * <li>JIS_B11 (22x32 mm ; 0.87x1.26 in)</li>
347
         * <li>JIS_B12 (16x22 mm ; 0.63x0.87 in)</li>
348
         * <li><b>PA Series</b></li>
349
         * <li>PA0 (840x1120 mm ; 33.07x44.09 in)</li>
350
         * <li>PA1 (560x840 mm ; 22.05x33.07 in)</li>
351
         * <li>PA2 (420x560 mm ; 16.54x22.05 in)</li>
352
         * <li>PA3 (280x420 mm ; 11.02x16.54 in)</li>
353
         * <li>PA4 (210x280 mm ; 8.27x11.02 in)</li>
354
         * <li>PA5 (140x210 mm ; 5.51x8.27 in)</li>
355
         * <li>PA6 (105x140 mm ; 4.13x5.51 in)</li>
356
         * <li>PA7 (70x105 mm ; 2.76x4.13 in)</li>
357
         * <li>PA8 (52x70 mm ; 2.05x2.76 in)</li>
358
         * <li>PA9 (35x52 mm ; 1.38x2.05 in)</li>
359
         * <li>PA10 (26x35 mm ; 1.02x1.38 in)</li>
360
         * <li><b>Standard Photographic Print Sizes</b></li>
361
         * <li>PASSPORT_PHOTO (35x45 mm ; 1.38x1.77 in)</li>
362
         * <li>E (82x120 mm ; 3.25x4.72 in)</li>
363
         * <li>3R, L (89x127 mm ; 3.50x5.00 in)</li>
364
         * <li>4R, KG (102x152 mm ; 4.02x5.98 in)</li>
365
         * <li>4D (120x152 mm ; 4.72x5.98 in)</li>
366
         * <li>5R, 2L (127x178 mm ; 5.00x7.01 in)</li>
367
         * <li>6R, 8P (152x203 mm ; 5.98x7.99 in)</li>
368
         * <li>8R, 6P (203x254 mm ; 7.99x10.00 in)</li>
369
         * <li>S8R, 6PW (203x305 mm ; 7.99x12.01 in)</li>
370
         * <li>10R, 4P (254x305 mm ; 10.00x12.01 in)</li>
371
         * <li>S10R, 4PW (254x381 mm ; 10.00x15.00 in)</li>
372
         * <li>11R (279x356 mm ; 10.98x14.02 in)</li>
373
         * <li>S11R (279x432 mm ; 10.98x17.01 in)</li>
374
         * <li>12R (305x381 mm ; 12.01x15.00 in)</li>
375
         * <li>S12R (305x456 mm ; 12.01x17.95 in)</li>
376
         * <li><b>Common Newspaper Sizes</b></li>
377
         * <li>NEWSPAPER_BROADSHEET (750x600 mm ; 29.53x23.62 in)</li>
378
         * <li>NEWSPAPER_BERLINER (470x315 mm ; 18.50x12.40 in)</li>
379
         * <li>NEWSPAPER_COMPACT, NEWSPAPER_TABLOID (430x280 mm ; 16.93x11.02 in)</li>
380
         * <li><b>Business Cards</b></li>
381
         * <li>CREDIT_CARD, BUSINESS_CARD, BUSINESS_CARD_ISO7810 (54x86 mm ; 2.13x3.37 in)</li>
382
         * <li>BUSINESS_CARD_ISO216 (52x74 mm ; 2.05x2.91 in)</li>
383
         * <li>BUSINESS_CARD_IT, BUSINESS_CARD_UK, BUSINESS_CARD_FR, BUSINESS_CARD_DE, BUSINESS_CARD_ES (55x85 mm ; 2.17x3.35 in)</li>
384
         * <li>BUSINESS_CARD_US, BUSINESS_CARD_CA (51x89 mm ; 2.01x3.50 in)</li>
385
         * <li>BUSINESS_CARD_JP (55x91 mm ; 2.17x3.58 in)</li>
386
         * <li>BUSINESS_CARD_HK (54x90 mm ; 2.13x3.54 in)</li>
387
         * <li>BUSINESS_CARD_AU, BUSINESS_CARD_DK, BUSINESS_CARD_SE (55x90 mm ; 2.17x3.54 in)</li>
388
         * <li>BUSINESS_CARD_RU, BUSINESS_CARD_CZ, BUSINESS_CARD_FI, BUSINESS_CARD_HU, BUSINESS_CARD_IL (50x90 mm ; 1.97x3.54 in)</li>
389
         * <li><b>Billboards</b></li>
390
         * <li>4SHEET (1016x1524 mm ; 40.00x60.00 in)</li>
391
         * <li>6SHEET (1200x1800 mm ; 47.24x70.87 in)</li>
392
         * <li>12SHEET (3048x1524 mm ; 120.00x60.00 in)</li>
393
         * <li>16SHEET (2032x3048 mm ; 80.00x120.00 in)</li>
394
         * <li>32SHEET (4064x3048 mm ; 160.00x120.00 in)</li>
395
         * <li>48SHEET (6096x3048 mm ; 240.00x120.00 in)</li>
396
         * <li>64SHEET (8128x3048 mm ; 320.00x120.00 in)</li>
397
         * <li>96SHEET (12192x3048 mm ; 480.00x120.00 in)</li>
398
         * <li><b>Old Imperial English (some are still used in USA)</b></li>
399
         * <li>EN_EMPEROR (1219x1829 mm ; 48.00x72.00 in)</li>
400
         * <li>EN_ANTIQUARIAN (787x1346 mm ; 31.00x53.00 in)</li>
401
         * <li>EN_GRAND_EAGLE (730x1067 mm ; 28.75x42.00 in)</li>
402
         * <li>EN_DOUBLE_ELEPHANT (679x1016 mm ; 26.75x40.00 in)</li>
403
         * <li>EN_ATLAS (660x864 mm ; 26.00x34.00 in)</li>
404
         * <li>EN_COLOMBIER (597x876 mm ; 23.50x34.50 in)</li>
405
         * <li>EN_ELEPHANT (584x711 mm ; 23.00x28.00 in)</li>
406
         * <li>EN_DOUBLE_DEMY (572x902 mm ; 22.50x35.50 in)</li>
407
         * <li>EN_IMPERIAL (559x762 mm ; 22.00x30.00 in)</li>
408
         * <li>EN_PRINCESS (546x711 mm ; 21.50x28.00 in)</li>
409
         * <li>EN_CARTRIDGE (533x660 mm ; 21.00x26.00 in)</li>
410
         * <li>EN_DOUBLE_LARGE_POST (533x838 mm ; 21.00x33.00 in)</li>
411
         * <li>EN_ROYAL (508x635 mm ; 20.00x25.00 in)</li>
412
         * <li>EN_SHEET, EN_HALF_POST (495x597 mm ; 19.50x23.50 in)</li>
413
         * <li>EN_SUPER_ROYAL (483x686 mm ; 19.00x27.00 in)</li>
414
         * <li>EN_DOUBLE_POST (483x775 mm ; 19.00x30.50 in)</li>
415
         * <li>EN_MEDIUM (445x584 mm ; 17.50x23.00 in)</li>
416
         * <li>EN_DEMY (445x572 mm ; 17.50x22.50 in)</li>
417
         * <li>EN_LARGE_POST (419x533 mm ; 16.50x21.00 in)</li>
418
         * <li>EN_COPY_DRAUGHT (406x508 mm ; 16.00x20.00 in)</li>
419
         * <li>EN_POST (394x489 mm ; 15.50x19.25 in)</li>
420
         * <li>EN_CROWN (381x508 mm ; 15.00x20.00 in)</li>
421
         * <li>EN_PINCHED_POST (375x470 mm ; 14.75x18.50 in)</li>
422
         * <li>EN_BRIEF (343x406 mm ; 13.50x16.00 in)</li>
423
         * <li>EN_FOOLSCAP (343x432 mm ; 13.50x17.00 in)</li>
424
         * <li>EN_SMALL_FOOLSCAP (337x419 mm ; 13.25x16.50 in)</li>
425
         * <li>EN_POTT (318x381 mm ; 12.50x15.00 in)</li>
426
         * <li><b>Old Imperial Belgian</b></li>
427
         * <li>BE_GRAND_AIGLE (700x1040 mm ; 27.56x40.94 in)</li>
428
         * <li>BE_COLOMBIER (620x850 mm ; 24.41x33.46 in)</li>
429
         * <li>BE_DOUBLE_CARRE (620x920 mm ; 24.41x36.22 in)</li>
430
         * <li>BE_ELEPHANT (616x770 mm ; 24.25x30.31 in)</li>
431
         * <li>BE_PETIT_AIGLE (600x840 mm ; 23.62x33.07 in)</li>
432
         * <li>BE_GRAND_JESUS (550x730 mm ; 21.65x28.74 in)</li>
433
         * <li>BE_JESUS (540x730 mm ; 21.26x28.74 in)</li>
434
         * <li>BE_RAISIN (500x650 mm ; 19.69x25.59 in)</li>
435
         * <li>BE_GRAND_MEDIAN (460x605 mm ; 18.11x23.82 in)</li>
436
         * <li>BE_DOUBLE_POSTE (435x565 mm ; 17.13x22.24 in)</li>
437
         * <li>BE_COQUILLE (430x560 mm ; 16.93x22.05 in)</li>
438
         * <li>BE_PETIT_MEDIAN (415x530 mm ; 16.34x20.87 in)</li>
439
         * <li>BE_RUCHE (360x460 mm ; 14.17x18.11 in)</li>
440
         * <li>BE_PROPATRIA (345x430 mm ; 13.58x16.93 in)</li>
441
         * <li>BE_LYS (317x397 mm ; 12.48x15.63 in)</li>
442
         * <li>BE_POT (307x384 mm ; 12.09x15.12 in)</li>
443
         * <li>BE_ROSETTE (270x347 mm ; 10.63x13.66 in)</li>
444
         * <li><b>Old Imperial French</b></li>
445
         * <li>FR_UNIVERS (1000x1300 mm ; 39.37x51.18 in)</li>
446
         * <li>FR_DOUBLE_COLOMBIER (900x1260 mm ; 35.43x49.61 in)</li>
447
         * <li>FR_GRANDE_MONDE (900x1260 mm ; 35.43x49.61 in)</li>
448
         * <li>FR_DOUBLE_SOLEIL (800x1200 mm ; 31.50x47.24 in)</li>
449
         * <li>FR_DOUBLE_JESUS (760x1120 mm ; 29.92x44.09 in)</li>
450
         * <li>FR_GRAND_AIGLE (750x1060 mm ; 29.53x41.73 in)</li>
451
         * <li>FR_PETIT_AIGLE (700x940 mm ; 27.56x37.01 in)</li>
452
         * <li>FR_DOUBLE_RAISIN (650x1000 mm ; 25.59x39.37 in)</li>
453
         * <li>FR_JOURNAL (650x940 mm ; 25.59x37.01 in)</li>
454
         * <li>FR_COLOMBIER_AFFICHE (630x900 mm ; 24.80x35.43 in)</li>
455
         * <li>FR_DOUBLE_CAVALIER (620x920 mm ; 24.41x36.22 in)</li>
456
         * <li>FR_CLOCHE (600x800 mm ; 23.62x31.50 in)</li>
457
         * <li>FR_SOLEIL (600x800 mm ; 23.62x31.50 in)</li>
458
         * <li>FR_DOUBLE_CARRE (560x900 mm ; 22.05x35.43 in)</li>
459
         * <li>FR_DOUBLE_COQUILLE (560x880 mm ; 22.05x34.65 in)</li>
460
         * <li>FR_JESUS (560x760 mm ; 22.05x29.92 in)</li>
461
         * <li>FR_RAISIN (500x650 mm ; 19.69x25.59 in)</li>
462
         * <li>FR_CAVALIER (460x620 mm ; 18.11x24.41 in)</li>
463
         * <li>FR_DOUBLE_COURONNE (460x720 mm ; 18.11x28.35 in)</li>
464
         * <li>FR_CARRE (450x560 mm ; 17.72x22.05 in)</li>
465
         * <li>FR_COQUILLE (440x560 mm ; 17.32x22.05 in)</li>
466
         * <li>FR_DOUBLE_TELLIERE (440x680 mm ; 17.32x26.77 in)</li>
467
         * <li>FR_DOUBLE_CLOCHE (400x600 mm ; 15.75x23.62 in)</li>
468
         * <li>FR_DOUBLE_POT (400x620 mm ; 15.75x24.41 in)</li>
469
         * <li>FR_ECU (400x520 mm ; 15.75x20.47 in)</li>
470
         * <li>FR_COURONNE (360x460 mm ; 14.17x18.11 in)</li>
471
         * <li>FR_TELLIERE (340x440 mm ; 13.39x17.32 in)</li>
472
         * <li>FR_POT (310x400 mm ; 12.20x15.75 in)</li>
473
         * </ul>
474
         * @return array containing page width and height in points
475
         * @since 5.0.010 (2010-05-17)
476
         * @public static
477
         */
478
        public static function getPageSizeFromFormat($format) {
479
                // Paper cordinates are calculated in this way: (inches * 72) where (1 inch = 25.4 mm)
480
                switch (strtoupper($format)) {
481
                        // ISO 216 A Series + 2 SIS 014711 extensions
482
                        case 'A0' : {$pf = array( 2383.937, 3370.394); break;}
483
                        case 'A1' : {$pf = array( 1683.780, 2383.937); break;}
484
                        case 'A2' : {$pf = array( 1190.551, 1683.780); break;}
485
                        case 'A3' : {$pf = array(  841.890, 1190.551); break;}
486
                        case 'A4' : {$pf = array(  595.276,  841.890); break;}
487
                        case 'A5' : {$pf = array(  419.528,  595.276); break;}
488
                        case 'A6' : {$pf = array(  297.638,  419.528); break;}
489
                        case 'A7' : {$pf = array(  209.764,  297.638); break;}
490
                        case 'A8' : {$pf = array(  147.402,  209.764); break;}
491
                        case 'A9' : {$pf = array(  104.882,  147.402); break;}
492
                        case 'A10': {$pf = array(   73.701,  104.882); break;}
493
                        case 'A11': {$pf = array(   51.024,   73.701); break;}
494
                        case 'A12': {$pf = array(   36.850,   51.024); break;}
495
                        // ISO 216 B Series + 2 SIS 014711 extensions
496
                        case 'B0' : {$pf = array( 2834.646, 4008.189); break;}
497
                        case 'B1' : {$pf = array( 2004.094, 2834.646); break;}
498
                        case 'B2' : {$pf = array( 1417.323, 2004.094); break;}
499
                        case 'B3' : {$pf = array( 1000.630, 1417.323); break;}
500
                        case 'B4' : {$pf = array(  708.661, 1000.630); break;}
501
                        case 'B5' : {$pf = array(  498.898,  708.661); break;}
502
                        case 'B6' : {$pf = array(  354.331,  498.898); break;}
503
                        case 'B7' : {$pf = array(  249.449,  354.331); break;}
504
                        case 'B8' : {$pf = array(  175.748,  249.449); break;}
505
                        case 'B9' : {$pf = array(  124.724,  175.748); break;}
506
                        case 'B10': {$pf = array(   87.874,  124.724); break;}
507
                        case 'B11': {$pf = array(   62.362,   87.874); break;}
508
                        case 'B12': {$pf = array(   42.520,   62.362); break;}
509
                        // ISO 216 C Series + 2 SIS 014711 extensions + 2 EXTENSION
510
                        case 'C0' : {$pf = array( 2599.370, 3676.535); break;}
511
                        case 'C1' : {$pf = array( 1836.850, 2599.370); break;}
512
                        case 'C2' : {$pf = array( 1298.268, 1836.850); break;}
513
                        case 'C3' : {$pf = array(  918.425, 1298.268); break;}
514
                        case 'C4' : {$pf = array(  649.134,  918.425); break;}
515
                        case 'C5' : {$pf = array(  459.213,  649.134); break;}
516
                        case 'C6' : {$pf = array(  323.150,  459.213); break;}
517
                        case 'C7' : {$pf = array(  229.606,  323.150); break;}
518
                        case 'C8' : {$pf = array(  161.575,  229.606); break;}
519
                        case 'C9' : {$pf = array(  113.386,  161.575); break;}
520
                        case 'C10': {$pf = array(   79.370,  113.386); break;}
521
                        case 'C11': {$pf = array(   56.693,   79.370); break;}
522
                        case 'C12': {$pf = array(   39.685,   56.693); break;}
523
                        case 'C76': {$pf = array(  229.606,  459.213); break;}
524
                        case 'DL' : {$pf = array(  311.811,  623.622); break;}
525
                        // SIS 014711 E Series
526
                        case 'E0' : {$pf = array( 2491.654, 3517.795); break;}
527
                        case 'E1' : {$pf = array( 1757.480, 2491.654); break;}
528
                        case 'E2' : {$pf = array( 1247.244, 1757.480); break;}
529
                        case 'E3' : {$pf = array(  878.740, 1247.244); break;}
530
                        case 'E4' : {$pf = array(  623.622,  878.740); break;}
531
                        case 'E5' : {$pf = array(  439.370,  623.622); break;}
532
                        case 'E6' : {$pf = array(  311.811,  439.370); break;}
533
                        case 'E7' : {$pf = array(  221.102,  311.811); break;}
534
                        case 'E8' : {$pf = array(  155.906,  221.102); break;}
535
                        case 'E9' : {$pf = array(  110.551,  155.906); break;}
536
                        case 'E10': {$pf = array(   76.535,  110.551); break;}
537
                        case 'E11': {$pf = array(   53.858,   76.535); break;}
538
                        case 'E12': {$pf = array(   36.850,   53.858); break;}
539
                        // SIS 014711 G Series
540
                        case 'G0' : {$pf = array( 2715.591, 3838.110); break;}
541
                        case 'G1' : {$pf = array( 1919.055, 2715.591); break;}
542
                        case 'G2' : {$pf = array( 1357.795, 1919.055); break;}
543
                        case 'G3' : {$pf = array(  958.110, 1357.795); break;}
544
                        case 'G4' : {$pf = array(  677.480,  958.110); break;}
545
                        case 'G5' : {$pf = array(  479.055,  677.480); break;}
546
                        case 'G6' : {$pf = array(  337.323,  479.055); break;}
547
                        case 'G7' : {$pf = array(  238.110,  337.323); break;}
548
                        case 'G8' : {$pf = array(  167.244,  238.110); break;}
549
                        case 'G9' : {$pf = array(  119.055,  167.244); break;}
550
                        case 'G10': {$pf = array(   82.205,  119.055); break;}
551
                        case 'G11': {$pf = array(   59.528,   82.205); break;}
552
                        case 'G12': {$pf = array(   39.685,   59.528); break;}
553
                        // ISO Press
554
                        case 'RA0': {$pf = array( 2437.795, 3458.268); break;}
555
                        case 'RA1': {$pf = array( 1729.134, 2437.795); break;}
556
                        case 'RA2': {$pf = array( 1218.898, 1729.134); break;}
557
                        case 'RA3': {$pf = array(  864.567, 1218.898); break;}
558
                        case 'RA4': {$pf = array(  609.449,  864.567); break;}
559
                        case 'SRA0': {$pf = array( 2551.181, 3628.346); break;}
560
                        case 'SRA1': {$pf = array( 1814.173, 2551.181); break;}
561
                        case 'SRA2': {$pf = array( 1275.591, 1814.173); break;}
562
                        case 'SRA3': {$pf = array(  907.087, 1275.591); break;}
563
                        case 'SRA4': {$pf = array(  637.795,  907.087); break;}
564
                        // German  DIN 476
565
                        case '4A0': {$pf = array( 4767.874, 6740.787); break;}
566
                        case '2A0': {$pf = array( 3370.394, 4767.874); break;}
567
                        // Variations on the ISO Standard
568
                        case 'A2_EXTRA'   : {$pf = array( 1261.417, 1754.646); break;}
569
                        case 'A3+'        : {$pf = array(  932.598, 1369.134); break;}
570
                        case 'A3_EXTRA'   : {$pf = array(  912.756, 1261.417); break;}
571
                        case 'A3_SUPER'   : {$pf = array(  864.567, 1440.000); break;}
572
                        case 'SUPER_A3'   : {$pf = array(  864.567, 1380.472); break;}
573
                        case 'A4_EXTRA'   : {$pf = array(  666.142,  912.756); break;}
574
                        case 'A4_SUPER'   : {$pf = array(  649.134,  912.756); break;}
575
                        case 'SUPER_A4'   : {$pf = array(  643.465, 1009.134); break;}
576
                        case 'A4_LONG'    : {$pf = array(  595.276,  986.457); break;}
577
                        case 'F4'         : {$pf = array(  595.276,  935.433); break;}
578
                        case 'SO_B5_EXTRA': {$pf = array(  572.598,  782.362); break;}
579
                        case 'A5_EXTRA'   : {$pf = array(  490.394,  666.142); break;}
580
                        // ANSI Series
581
                        case 'ANSI_E': {$pf = array( 2448.000, 3168.000); break;}
582
                        case 'ANSI_D': {$pf = array( 1584.000, 2448.000); break;}
583
                        case 'ANSI_C': {$pf = array( 1224.000, 1584.000); break;}
584
                        case 'ANSI_B': {$pf = array(  792.000, 1224.000); break;}
585
                        case 'ANSI_A': {$pf = array(  612.000,  792.000); break;}
586
                        // Traditional 'Loose' North American Paper Sizes
587
                        case 'USLEDGER':
588
                        case 'LEDGER' : {$pf = array( 1224.000,  792.000); break;}
589
                        case 'ORGANIZERK':
590
                        case 'BIBLE':
591
                        case 'USTABLOID':
592
                        case 'TABLOID': {$pf = array(  792.000, 1224.000); break;}
593
                        case 'ORGANIZERM':
594
                        case 'USLETTER':
595
                        case 'LETTER' : {$pf = array(  612.000,  792.000); break;}
596
                        case 'USLEGAL':
597
                        case 'LEGAL'  : {$pf = array(  612.000, 1008.000); break;}
598
                        case 'GOVERNMENTLETTER':
599
                        case 'GLETTER': {$pf = array(  576.000,  756.000); break;}
600
                        case 'JUNIORLEGAL':
601
                        case 'JLEGAL' : {$pf = array(  576.000,  360.000); break;}
602
                        // Other North American Paper Sizes
603
                        case 'QUADDEMY': {$pf = array( 2520.000, 3240.000); break;}
604
                        case 'SUPER_B': {$pf = array(  936.000, 1368.000); break;}
605
                        case 'QUARTO': {$pf = array(  648.000,  792.000); break;}
606
                        case 'GOVERNMENTLEGAL':
607
                        case 'FOLIO': {$pf = array(  612.000,  936.000); break;}
608
                        case 'MONARCH':
609
                        case 'EXECUTIVE': {$pf = array(  522.000,  756.000); break;}
610
                        case 'ORGANIZERL':
611
                        case 'STATEMENT':
612
                        case 'MEMO': {$pf = array(  396.000,  612.000); break;}
613
                        case 'FOOLSCAP': {$pf = array(  595.440,  936.000); break;}
614
                        case 'COMPACT': {$pf = array(  306.000,  486.000); break;}
615
                        case 'ORGANIZERJ': {$pf = array(  198.000,  360.000); break;}
616
                        // Canadian standard CAN 2-9.60M
617
                        case 'P1': {$pf = array( 1587.402, 2437.795); break;}
618
                        case 'P2': {$pf = array( 1218.898, 1587.402); break;}
619
                        case 'P3': {$pf = array(  793.701, 1218.898); break;}
620
                        case 'P4': {$pf = array(  609.449,  793.701); break;}
621
                        case 'P5': {$pf = array(  396.850,  609.449); break;}
622
                        case 'P6': {$pf = array(  303.307,  396.850); break;}
623
                        // North American Architectural Sizes
624
                        case 'ARCH_E' : {$pf = array( 2592.000, 3456.000); break;}
625
                        case 'ARCH_E1': {$pf = array( 2160.000, 3024.000); break;}
626
                        case 'ARCH_D' : {$pf = array( 1728.000, 2592.000); break;}
627
                        case 'BROADSHEET':
628
                        case 'ARCH_C' : {$pf = array( 1296.000, 1728.000); break;}
629
                        case 'ARCH_B' : {$pf = array(  864.000, 1296.000); break;}
630
                        case 'ARCH_A' : {$pf = array(  648.000,  864.000); break;}
631
                        // --- North American Envelope Sizes ---
632
                        //   - Announcement Envelopes
633
                        case 'ANNENV_A2'  : {$pf = array(  314.640,  414.000); break;}
634
                        case 'ANNENV_A6'  : {$pf = array(  342.000,  468.000); break;}
635
                        case 'ANNENV_A7'  : {$pf = array(  378.000,  522.000); break;}
636
                        case 'ANNENV_A8'  : {$pf = array(  396.000,  584.640); break;}
637
                        case 'ANNENV_A10' : {$pf = array(  450.000,  692.640); break;}
638
                        case 'ANNENV_SLIM': {$pf = array(  278.640,  638.640); break;}
639
                        //   - Commercial Envelopes
640
                        case 'COMMENV_N6_1/4': {$pf = array(  252.000,  432.000); break;}
641
                        case 'COMMENV_N6_3/4': {$pf = array(  260.640,  468.000); break;}
642
                        case 'COMMENV_N8'    : {$pf = array(  278.640,  540.000); break;}
643
                        case 'COMMENV_N9'    : {$pf = array(  278.640,  638.640); break;}
644
                        case 'COMMENV_N10'   : {$pf = array(  296.640,  684.000); break;}
645
                        case 'COMMENV_N11'   : {$pf = array(  324.000,  746.640); break;}
646
                        case 'COMMENV_N12'   : {$pf = array(  342.000,  792.000); break;}
647
                        case 'COMMENV_N14'   : {$pf = array(  360.000,  828.000); break;}
648
                        //   - Catalogue Envelopes
649
                        case 'CATENV_N1'     : {$pf = array(  432.000,  648.000); break;}
650
                        case 'CATENV_N1_3/4' : {$pf = array(  468.000,  684.000); break;}
651
                        case 'CATENV_N2'     : {$pf = array(  468.000,  720.000); break;}
652
                        case 'CATENV_N3'     : {$pf = array(  504.000,  720.000); break;}
653
                        case 'CATENV_N6'     : {$pf = array(  540.000,  756.000); break;}
654
                        case 'CATENV_N7'     : {$pf = array(  576.000,  792.000); break;}
655
                        case 'CATENV_N8'     : {$pf = array(  594.000,  810.000); break;}
656
                        case 'CATENV_N9_1/2' : {$pf = array(  612.000,  756.000); break;}
657
                        case 'CATENV_N9_3/4' : {$pf = array(  630.000,  810.000); break;}
658
                        case 'CATENV_N10_1/2': {$pf = array(  648.000,  864.000); break;}
659
                        case 'CATENV_N12_1/2': {$pf = array(  684.000,  900.000); break;}
660
                        case 'CATENV_N13_1/2': {$pf = array(  720.000,  936.000); break;}
661
                        case 'CATENV_N14_1/4': {$pf = array(  810.000,  882.000); break;}
662
                        case 'CATENV_N14_1/2': {$pf = array(  828.000, 1044.000); break;}
663
                        // Japanese (JIS P 0138-61) Standard B-Series
664
                        case 'JIS_B0' : {$pf = array( 2919.685, 4127.244); break;}
665
                        case 'JIS_B1' : {$pf = array( 2063.622, 2919.685); break;}
666
                        case 'JIS_B2' : {$pf = array( 1459.843, 2063.622); break;}
667
                        case 'JIS_B3' : {$pf = array( 1031.811, 1459.843); break;}
668
                        case 'JIS_B4' : {$pf = array(  728.504, 1031.811); break;}
669
                        case 'JIS_B5' : {$pf = array(  515.906,  728.504); break;}
670
                        case 'JIS_B6' : {$pf = array(  362.835,  515.906); break;}
671
                        case 'JIS_B7' : {$pf = array(  257.953,  362.835); break;}
672
                        case 'JIS_B8' : {$pf = array(  181.417,  257.953); break;}
673
                        case 'JIS_B9' : {$pf = array(  127.559,  181.417); break;}
674
                        case 'JIS_B10': {$pf = array(   90.709,  127.559); break;}
675
                        case 'JIS_B11': {$pf = array(   62.362,   90.709); break;}
676
                        case 'JIS_B12': {$pf = array(   45.354,   62.362); break;}
677
                        // PA Series
678
                        case 'PA0' : {$pf = array( 2381.102, 3174.803,); break;}
679
                        case 'PA1' : {$pf = array( 1587.402, 2381.102); break;}
680
                        case 'PA2' : {$pf = array( 1190.551, 1587.402); break;}
681
                        case 'PA3' : {$pf = array(  793.701, 1190.551); break;}
682
                        case 'PA4' : {$pf = array(  595.276,  793.701); break;}
683
                        case 'PA5' : {$pf = array(  396.850,  595.276); break;}
684
                        case 'PA6' : {$pf = array(  297.638,  396.850); break;}
685
                        case 'PA7' : {$pf = array(  198.425,  297.638); break;}
686
                        case 'PA8' : {$pf = array(  147.402,  198.425); break;}
687
                        case 'PA9' : {$pf = array(   99.213,  147.402); break;}
688
                        case 'PA10': {$pf = array(   73.701,   99.213); break;}
689
                        // Standard Photographic Print Sizes
690
                        case 'PASSPORT_PHOTO': {$pf = array(   99.213,  127.559); break;}
691
                        case 'E'   : {$pf = array(  233.858,  340.157); break;}
692
                        case 'L':
693
                        case '3R'  : {$pf = array(  252.283,  360.000); break;}
694
                        case 'KG':
695
                        case '4R'  : {$pf = array(  289.134,  430.866); break;}
696
                        case '4D'  : {$pf = array(  340.157,  430.866); break;}
697
                        case '2L':
698
                        case '5R'  : {$pf = array(  360.000,  504.567); break;}
699
                        case '8P':
700
                        case '6R'  : {$pf = array(  430.866,  575.433); break;}
701
                        case '6P':
702
                        case '8R'  : {$pf = array(  575.433,  720.000); break;}
703
                        case '6PW':
704
                        case 'S8R' : {$pf = array(  575.433,  864.567); break;}
705
                        case '4P':
706
                        case '10R' : {$pf = array(  720.000,  864.567); break;}
707
                        case '4PW':
708
                        case 'S10R': {$pf = array(  720.000, 1080.000); break;}
709
                        case '11R' : {$pf = array(  790.866, 1009.134); break;}
710
                        case 'S11R': {$pf = array(  790.866, 1224.567); break;}
711
                        case '12R' : {$pf = array(  864.567, 1080.000); break;}
712
                        case 'S12R': {$pf = array(  864.567, 1292.598); break;}
713
                        // Common Newspaper Sizes
714
                        case 'NEWSPAPER_BROADSHEET': {$pf = array( 2125.984, 1700.787); break;}
715
                        case 'NEWSPAPER_BERLINER'  : {$pf = array( 1332.283,  892.913); break;}
716
                        case 'NEWSPAPER_TABLOID':
717
                        case 'NEWSPAPER_COMPACT'   : {$pf = array( 1218.898,  793.701); break;}
718
                        // Business Cards
719
                        case 'CREDIT_CARD':
720
                        case 'BUSINESS_CARD':
721
                        case 'BUSINESS_CARD_ISO7810': {$pf = array(  153.014,  242.646); break;}
722
                        case 'BUSINESS_CARD_ISO216' : {$pf = array(  147.402,  209.764); break;}
723
                        case 'BUSINESS_CARD_IT':
724
                        case 'BUSINESS_CARD_UK':
725
                        case 'BUSINESS_CARD_FR':
726
                        case 'BUSINESS_CARD_DE':
727
                        case 'BUSINESS_CARD_ES'     : {$pf = array(  155.906,  240.945); break;}
728
                        case 'BUSINESS_CARD_CA':
729
                        case 'BUSINESS_CARD_US'     : {$pf = array(  144.567,  252.283); break;}
730
                        case 'BUSINESS_CARD_JP'     : {$pf = array(  155.906,  257.953); break;}
731
                        case 'BUSINESS_CARD_HK'     : {$pf = array(  153.071,  255.118); break;}
732
                        case 'BUSINESS_CARD_AU':
733
                        case 'BUSINESS_CARD_DK':
734
                        case 'BUSINESS_CARD_SE'     : {$pf = array(  155.906,  255.118); break;}
735
                        case 'BUSINESS_CARD_RU':
736
                        case 'BUSINESS_CARD_CZ':
737
                        case 'BUSINESS_CARD_FI':
738
                        case 'BUSINESS_CARD_HU':
739
                        case 'BUSINESS_CARD_IL'     : {$pf = array(  141.732,  255.118); break;}
740
                        // Billboards
741
                        case '4SHEET' : {$pf = array( 2880.000, 4320.000); break;}
742
                        case '6SHEET' : {$pf = array( 3401.575, 5102.362); break;}
743
                        case '12SHEET': {$pf = array( 8640.000, 4320.000); break;}
744
                        case '16SHEET': {$pf = array( 5760.000, 8640.000); break;}
745
                        case '32SHEET': {$pf = array(11520.000, 8640.000); break;}
746
                        case '48SHEET': {$pf = array(17280.000, 8640.000); break;}
747
                        case '64SHEET': {$pf = array(23040.000, 8640.000); break;}
748
                        case '96SHEET': {$pf = array(34560.000, 8640.000); break;}
749
                        // Old European Sizes
750
                        //   - Old Imperial English Sizes
751
                        case 'EN_EMPEROR'          : {$pf = array( 3456.000, 5184.000); break;}
752
                        case 'EN_ANTIQUARIAN'      : {$pf = array( 2232.000, 3816.000); break;}
753
                        case 'EN_GRAND_EAGLE'      : {$pf = array( 2070.000, 3024.000); break;}
754
                        case 'EN_DOUBLE_ELEPHANT'  : {$pf = array( 1926.000, 2880.000); break;}
755
                        case 'EN_ATLAS'            : {$pf = array( 1872.000, 2448.000); break;}
756
                        case 'EN_COLOMBIER'        : {$pf = array( 1692.000, 2484.000); break;}
757
                        case 'EN_ELEPHANT'         : {$pf = array( 1656.000, 2016.000); break;}
758
                        case 'EN_DOUBLE_DEMY'      : {$pf = array( 1620.000, 2556.000); break;}
759
                        case 'EN_IMPERIAL'         : {$pf = array( 1584.000, 2160.000); break;}
760
                        case 'EN_PRINCESS'         : {$pf = array( 1548.000, 2016.000); break;}
761
                        case 'EN_CARTRIDGE'        : {$pf = array( 1512.000, 1872.000); break;}
762
                        case 'EN_DOUBLE_LARGE_POST': {$pf = array( 1512.000, 2376.000); break;}
763
                        case 'EN_ROYAL'            : {$pf = array( 1440.000, 1800.000); break;}
764
                        case 'EN_SHEET':
765
                        case 'EN_HALF_POST'        : {$pf = array( 1404.000, 1692.000); break;}
766
                        case 'EN_SUPER_ROYAL'      : {$pf = array( 1368.000, 1944.000); break;}
767
                        case 'EN_DOUBLE_POST'      : {$pf = array( 1368.000, 2196.000); break;}
768
                        case 'EN_MEDIUM'           : {$pf = array( 1260.000, 1656.000); break;}
769
                        case 'EN_DEMY'             : {$pf = array( 1260.000, 1620.000); break;}
770
                        case 'EN_LARGE_POST'       : {$pf = array( 1188.000, 1512.000); break;}
771
                        case 'EN_COPY_DRAUGHT'     : {$pf = array( 1152.000, 1440.000); break;}
772
                        case 'EN_POST'             : {$pf = array( 1116.000, 1386.000); break;}
773
                        case 'EN_CROWN'            : {$pf = array( 1080.000, 1440.000); break;}
774
                        case 'EN_PINCHED_POST'     : {$pf = array( 1062.000, 1332.000); break;}
775
                        case 'EN_BRIEF'            : {$pf = array(  972.000, 1152.000); break;}
776
                        case 'EN_FOOLSCAP'         : {$pf = array(  972.000, 1224.000); break;}
777
                        case 'EN_SMALL_FOOLSCAP'   : {$pf = array(  954.000, 1188.000); break;}
778
                        case 'EN_POTT'             : {$pf = array(  900.000, 1080.000); break;}
779
                        //   - Old Imperial Belgian Sizes
780
                        case 'BE_GRAND_AIGLE' : {$pf = array( 1984.252, 2948.031); break;}
781
                        case 'BE_COLOMBIER'   : {$pf = array( 1757.480, 2409.449); break;}
782
                        case 'BE_DOUBLE_CARRE': {$pf = array( 1757.480, 2607.874); break;}
783
                        case 'BE_ELEPHANT'    : {$pf = array( 1746.142, 2182.677); break;}
784
                        case 'BE_PETIT_AIGLE' : {$pf = array( 1700.787, 2381.102); break;}
785
                        case 'BE_GRAND_JESUS' : {$pf = array( 1559.055, 2069.291); break;}
786
                        case 'BE_JESUS'       : {$pf = array( 1530.709, 2069.291); break;}
787
                        case 'BE_RAISIN'      : {$pf = array( 1417.323, 1842.520); break;}
788
                        case 'BE_GRAND_MEDIAN': {$pf = array( 1303.937, 1714.961); break;}
789
                        case 'BE_DOUBLE_POSTE': {$pf = array( 1233.071, 1601.575); break;}
790
                        case 'BE_COQUILLE'    : {$pf = array( 1218.898, 1587.402); break;}
791
                        case 'BE_PETIT_MEDIAN': {$pf = array( 1176.378, 1502.362); break;}
792
                        case 'BE_RUCHE'       : {$pf = array( 1020.472, 1303.937); break;}
793
                        case 'BE_PROPATRIA'   : {$pf = array(  977.953, 1218.898); break;}
794
                        case 'BE_LYS'         : {$pf = array(  898.583, 1125.354); break;}
795
                        case 'BE_POT'         : {$pf = array(  870.236, 1088.504); break;}
796
                        case 'BE_ROSETTE'     : {$pf = array(  765.354,  983.622); break;}
797
                        //   - Old Imperial French Sizes
798
                        case 'FR_UNIVERS'          : {$pf = array( 2834.646, 3685.039); break;}
799
                        case 'FR_DOUBLE_COLOMBIER' : {$pf = array( 2551.181, 3571.654); break;}
800
                        case 'FR_GRANDE_MONDE'     : {$pf = array( 2551.181, 3571.654); break;}
801
                        case 'FR_DOUBLE_SOLEIL'    : {$pf = array( 2267.717, 3401.575); break;}
802
                        case 'FR_DOUBLE_JESUS'     : {$pf = array( 2154.331, 3174.803); break;}
803
                        case 'FR_GRAND_AIGLE'      : {$pf = array( 2125.984, 3004.724); break;}
804
                        case 'FR_PETIT_AIGLE'      : {$pf = array( 1984.252, 2664.567); break;}
805
                        case 'FR_DOUBLE_RAISIN'    : {$pf = array( 1842.520, 2834.646); break;}
806
                        case 'FR_JOURNAL'          : {$pf = array( 1842.520, 2664.567); break;}
807
                        case 'FR_COLOMBIER_AFFICHE': {$pf = array( 1785.827, 2551.181); break;}
808
                        case 'FR_DOUBLE_CAVALIER'  : {$pf = array( 1757.480, 2607.874); break;}
809
                        case 'FR_CLOCHE'           : {$pf = array( 1700.787, 2267.717); break;}
810
                        case 'FR_SOLEIL'           : {$pf = array( 1700.787, 2267.717); break;}
811
                        case 'FR_DOUBLE_CARRE'     : {$pf = array( 1587.402, 2551.181); break;}
812
                        case 'FR_DOUBLE_COQUILLE'  : {$pf = array( 1587.402, 2494.488); break;}
813
                        case 'FR_JESUS'            : {$pf = array( 1587.402, 2154.331); break;}
814
                        case 'FR_RAISIN'           : {$pf = array( 1417.323, 1842.520); break;}
815
                        case 'FR_CAVALIER'         : {$pf = array( 1303.937, 1757.480); break;}
816
                        case 'FR_DOUBLE_COURONNE'  : {$pf = array( 1303.937, 2040.945); break;}
817
                        case 'FR_CARRE'            : {$pf = array( 1275.591, 1587.402); break;}
818
                        case 'FR_COQUILLE'         : {$pf = array( 1247.244, 1587.402); break;}
819
                        case 'FR_DOUBLE_TELLIERE'  : {$pf = array( 1247.244, 1927.559); break;}
820
                        case 'FR_DOUBLE_CLOCHE'    : {$pf = array( 1133.858, 1700.787); break;}
821
                        case 'FR_DOUBLE_POT'       : {$pf = array( 1133.858, 1757.480); break;}
822
                        case 'FR_ECU'              : {$pf = array( 1133.858, 1474.016); break;}
823
                        case 'FR_COURONNE'         : {$pf = array( 1020.472, 1303.937); break;}
824
                        case 'FR_TELLIERE'         : {$pf = array(  963.780, 1247.244); break;}
825
                        case 'FR_POT'              : {$pf = array(  878.740, 1133.858); break;}
826
                        // DEFAULT ISO A4
827
                        default: {$pf = array(  595.276,  841.890); break;}
828
                }
829
                return $pf;
830
        }
831

    
832
        /**
833
         * Set page boundaries.
834
         * @param $page (int) page number
835
         * @param $type (string) valid values are: <ul><li>'MediaBox' : the boundaries of the physical medium on which the page shall be displayed or printed;</li><li>'CropBox' : the visible region of default user space;</li><li>'BleedBox' : the region to which the contents of the page shall be clipped when output in a production environment;</li><li>'TrimBox' : the intended dimensions of the finished page after trimming;</li><li>'ArtBox' : the page's meaningful content (including potential white space).</li></ul>
836
         * @param $llx (float) lower-left x coordinate in user units.
837
         * @param $lly (float) lower-left y coordinate in user units.
838
         * @param $urx (float) upper-right x coordinate in user units.
839
         * @param $ury (float) upper-right y coordinate in user units.
840
         * @param $points (boolean) If true uses user units as unit of measure, otherwise uses PDF points.
841
         * @param $k (float) Scale factor (number of points in user unit).
842
         * @param $pagedim (array) Array of page dimensions.
843
         * @return pagedim array of page dimensions.
844
         * @since 5.0.010 (2010-05-17)
845
         * @public static
846
         */
847
        public static function setPageBoxes($page, $type, $llx, $lly, $urx, $ury, $points=false, $k, $pagedim=array()) {
848
                if (!isset($pagedim[$page])) {
849
                        // initialize array
850
                        $pagedim[$page] = array();
851
                }
852
                if (!in_array($type, self::$pageboxes)) {
853
                        return;
854
                }
855
                if ($points) {
856
                        $k = 1;
857
                }
858
                $pagedim[$page][$type]['llx'] = ($llx * $k);
859
                $pagedim[$page][$type]['lly'] = ($lly * $k);
860
                $pagedim[$page][$type]['urx'] = ($urx * $k);
861
                $pagedim[$page][$type]['ury'] = ($ury * $k);
862
                return $pagedim;
863
        }
864

    
865
        /**
866
         * Swap X and Y coordinates of page boxes (change page boxes orientation).
867
         * @param $page (int) page number
868
         * @param $pagedim (array) Array of page dimensions.
869
         * @return pagedim array of page dimensions.
870
         * @since 5.0.010 (2010-05-17)
871
         * @public static
872
         */
873
        public static function swapPageBoxCoordinates($page, $pagedim) {
874
                foreach (self::$pageboxes as $type) {
875
                        // swap X and Y coordinates
876
                        if (isset($pagedim[$page][$type])) {
877
                                $tmp = $pagedim[$page][$type]['llx'];
878
                                $pagedim[$page][$type]['llx'] = $pagedim[$page][$type]['lly'];
879
                                $pagedim[$page][$type]['lly'] = $tmp;
880
                                $tmp = $pagedim[$page][$type]['urx'];
881
                                $pagedim[$page][$type]['urx'] = $pagedim[$page][$type]['ury'];
882
                                $pagedim[$page][$type]['ury'] = $tmp;
883
                        }
884
                }
885
                return $pagedim;
886
        }
887

    
888
        /**
889
         * Get the canonical page layout mode.
890
         * @param $layout (string) The page layout. Possible values are:<ul><li>SinglePage Display one page at a time</li><li>OneColumn Display the pages in one column</li><li>TwoColumnLeft Display the pages in two columns, with odd-numbered pages on the left</li><li>TwoColumnRight Display the pages in two columns, with odd-numbered pages on the right</li><li>TwoPageLeft (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the left</li><li>TwoPageRight (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the right</li></ul>
891
         * @return (string) Canonical page layout name.
892
         * @public static
893
         */
894
        public static function getPageLayoutMode($layout='SinglePage') {
895
                switch ($layout) {
896
                        case 'default':
897
                        case 'single':
898
                        case 'SinglePage': {
899
                                $layout_mode = 'SinglePage';
900
                                break;
901
                        }
902
                        case 'continuous':
903
                        case 'OneColumn': {
904
                                $layout_mode = 'OneColumn';
905
                                break;
906
                        }
907
                        case 'two':
908
                        case 'TwoColumnLeft': {
909
                                $layout_mode = 'TwoColumnLeft';
910
                                break;
911
                        }
912
                        case 'TwoColumnRight': {
913
                                $layout_mode = 'TwoColumnRight';
914
                                break;
915
                        }
916
                        case 'TwoPageLeft': {
917
                                $layout_mode = 'TwoPageLeft';
918
                                break;
919
                        }
920
                        case 'TwoPageRight': {
921
                                $layout_mode = 'TwoPageRight';
922
                                break;
923
                        }
924
                        default: {
925
                                $layout_mode = 'SinglePage';
926
                        }
927
                }
928
                return $layout_mode;
929
        }
930

    
931
        /**
932
         * Get the canonical page layout mode.
933
         * @param $mode (string) A name object specifying how the document should be displayed when opened:<ul><li>UseNone Neither document outline nor thumbnail images visible</li><li>UseOutlines Document outline visible</li><li>UseThumbs Thumbnail images visible</li><li>FullScreen Full-screen mode, with no menu bar, window controls, or any other window visible</li><li>UseOC (PDF 1.5) Optional content group panel visible</li><li>UseAttachments (PDF 1.6) Attachments panel visible</li></ul>
934
         * @return (string) Canonical page mode name.
935
         * @public static
936
         */
937
        public static function getPageMode($mode='UseNone') {
938
                switch ($mode) {
939
                        case 'UseNone': {
940
                                $page_mode = 'UseNone';
941
                                break;
942
                        }
943
                        case 'UseOutlines': {
944
                                $page_mode = 'UseOutlines';
945
                                break;
946
                        }
947
                        case 'UseThumbs': {
948
                                $page_mode = 'UseThumbs';
949
                                break;
950
                        }
951
                        case 'FullScreen': {
952
                                $page_mode = 'FullScreen';
953
                                break;
954
                        }
955
                        case 'UseOC': {
956
                                $page_mode = 'UseOC';
957
                                break;
958
                        }
959
                        case '': {
960
                                $page_mode = 'UseAttachments';
961
                                break;
962
                        }
963
                        default: {
964
                                $page_mode = 'UseNone';
965
                        }
966
                }
967
                return $page_mode;
968
        }
969

    
970
        /**
971
         * Check if the URL exist.
972
         * @param $url (string) URL to check.
973
         * @return Boolean true if the URl exist, false otherwise.
974
         * @since 5.9.204 (2013-01-28)
975
         * @public static
976
         */
977
        public static function isValidURL($url) {
978
                $headers = @get_headers($url);
979
            return (strpos($headers[0], '200') !== false);
980
        }
981

    
982
        /**
983
         * Removes SHY characters from text.
984
         * Unicode Data:<ul>
985
         * <li>Name : SOFT HYPHEN, commonly abbreviated as SHY</li>
986
         * <li>HTML Entity (decimal): "&amp;#173;"</li>
987
         * <li>HTML Entity (hex): "&amp;#xad;"</li>
988
         * <li>HTML Entity (named): "&amp;shy;"</li>
989
         * <li>How to type in Microsoft Windows: [Alt +00AD] or [Alt 0173]</li>
990
         * <li>UTF-8 (hex): 0xC2 0xAD (c2ad)</li>
991
         * <li>UTF-8 character: chr(194).chr(173)</li>
992
         * </ul>
993
         * @param $txt (string) input string
994
         * @param $unicode (boolean) True if we are in unicode mode, false otherwise.
995
         * @return string without SHY characters.
996
         * @since (4.5.019) 2009-02-28
997
         * @public static
998
         */
999
        public static function removeSHY($txt='', $unicode=true) {
1000
                $txt = preg_replace('/([\\xc2]{1}[\\xad]{1})/', '', $txt);
1001
                if (!$unicode) {
1002
                        $txt = preg_replace('/([\\xad]{1})/', '', $txt);
1003
                }
1004
                return $txt;
1005
        }
1006

    
1007

    
1008
        /**
1009
         * Get the border mode accounting for multicell position (opens bottom side of multicell crossing pages)
1010
         * @param $brd (mixed) Indicates if borders must be drawn around the cell block. The value can be a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul>or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul> or an array of line styles for each border group: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0)))
1011
         * @param $position (string) multicell position: 'start', 'middle', 'end'
1012
         * @param $opencell (boolean) True when the cell is left open at the page bottom, false otherwise.
1013
         * @return border mode array
1014
         * @since 4.4.002 (2008-12-09)
1015
         * @public static
1016
         */
1017
        public static function getBorderMode($brd, $position='start', $opencell=true) {
1018
                if ((!$opencell) OR empty($brd)) {
1019
                        return $brd;
1020
                }
1021
                if ($brd == 1) {
1022
                        $brd = 'LTRB';
1023
                }
1024
                if (is_string($brd)) {
1025
                        // convert string to array
1026
                        $slen = strlen($brd);
1027
                        $newbrd = array();
1028
                        for ($i = 0; $i < $slen; ++$i) {
1029
                                $newbrd[$brd[$i]] = array('cap' => 'square', 'join' => 'miter');
1030
                        }
1031
                        $brd = $newbrd;
1032
                }
1033
                foreach ($brd as $border => $style) {
1034
                        switch ($position) {
1035
                                case 'start': {
1036
                                        if (strpos($border, 'B') !== false) {
1037
                                                // remove bottom line
1038
                                                $newkey = str_replace('B', '', $border);
1039
                                                if (strlen($newkey) > 0) {
1040
                                                        $brd[$newkey] = $style;
1041
                                                }
1042
                                                unset($brd[$border]);
1043
                                        }
1044
                                        break;
1045
                                }
1046
                                case 'middle': {
1047
                                        if (strpos($border, 'B') !== false) {
1048
                                                // remove bottom line
1049
                                                $newkey = str_replace('B', '', $border);
1050
                                                if (strlen($newkey) > 0) {
1051
                                                        $brd[$newkey] = $style;
1052
                                                }
1053
                                                unset($brd[$border]);
1054
                                                $border = $newkey;
1055
                                        }
1056
                                        if (strpos($border, 'T') !== false) {
1057
                                                // remove bottom line
1058
                                                $newkey = str_replace('T', '', $border);
1059
                                                if (strlen($newkey) > 0) {
1060
                                                        $brd[$newkey] = $style;
1061
                                                }
1062
                                                unset($brd[$border]);
1063
                                        }
1064
                                        break;
1065
                                }
1066
                                case 'end': {
1067
                                        if (strpos($border, 'T') !== false) {
1068
                                                // remove bottom line
1069
                                                $newkey = str_replace('T', '', $border);
1070
                                                if (strlen($newkey) > 0) {
1071
                                                        $brd[$newkey] = $style;
1072
                                                }
1073
                                                unset($brd[$border]);
1074
                                        }
1075
                                        break;
1076
                                }
1077
                        }
1078
                }
1079
                return $brd;
1080
        }
1081

    
1082
        /**
1083
         * Determine whether a string is empty.
1084
         * @param $str (string) string to be checked
1085
         * @return boolean true if string is empty
1086
         * @since 4.5.044 (2009-04-16)
1087
         * @public static
1088
         */
1089
        public static function empty_string($str) {
1090
                return (is_null($str) OR (is_string($str) AND (strlen($str) == 0)));
1091
        }
1092

    
1093
        /**
1094
         * Returns a temporary filename for caching object on filesystem.
1095
         * @param $name (string) Prefix to add to the file name.
1096
         * @return string filename.
1097
         * @since 4.5.000 (2008-12-31)
1098
         * @public static
1099
         */
1100
        public static function getObjFilename($name) {
1101
                return tempnam(K_PATH_CACHE, $name.'_');
1102
        }
1103

    
1104
        /**
1105
         * Add "\" before "\", "(" and ")"
1106
         * @param $s (string) string to escape.
1107
         * @return string escaped string.
1108
         * @public static
1109
         */
1110
        public static function _escape($s) {
1111
                // the chr(13) substitution fixes the Bugs item #1421290.
1112
                return strtr($s, array(')' => '\\)', '(' => '\\(', '\\' => '\\\\', chr(13) => '\r'));
1113
        }
1114

    
1115
        /**
1116
        * Escape some special characters (&lt; &gt; &amp;) for XML output.
1117
        * @param $str (string) Input string to convert.
1118
        * @return converted string
1119
        * @since 5.9.121 (2011-09-28)
1120
         * @public static
1121
         */
1122
        public static function _escapeXML($str) {
1123
                $replaceTable = array("\0" => '', '&' => '&amp;', '<' => '&lt;', '>' => '&gt;');
1124
                $str = strtr($str, $replaceTable);
1125
                return $str;
1126
        }
1127

    
1128
        /**
1129
         * Creates a copy of a class object
1130
         * @param $object (object) class object to be cloned
1131
         * @return cloned object
1132
         * @since 4.5.029 (2009-03-19)
1133
         * @public static
1134
         */
1135
        public static function objclone($object) {
1136
                if (($object instanceof Imagick) AND (version_compare(phpversion('imagick'), '3.0.1') !== 1)) {
1137
                        // on the versions after 3.0.1 the clone() method was deprecated in favour of clone keyword
1138
                        return @$object->clone();
1139
                }
1140
                return @clone($object);
1141
        }
1142

    
1143
        /**
1144
         * Ouput input data and compress it if possible.
1145
         * @param $data (string) Data to output.
1146
         * @param $length (int) Data length in bytes.
1147
         * @since 5.9.086
1148
         * @public static
1149
         */
1150
        public static function sendOutputData($data, $length) {
1151
                if (!isset($_SERVER['HTTP_ACCEPT_ENCODING']) OR empty($_SERVER['HTTP_ACCEPT_ENCODING'])) {
1152
                        // the content length may vary if the server is using compression
1153
                        header('Content-Length: '.$length);
1154
                }
1155
                echo $data;
1156
        }
1157

    
1158
        /**
1159
         * Replace page number aliases with number.
1160
         * @param $page (string) Page content.
1161
         * @param $replace (array) Array of replacements (array keys are replacement strings, values are alias arrays).
1162
         * @param $diff (int) If passed, this will be set to the total char number difference between alias and replacements.
1163
         * @return replaced page content and updated $diff parameter as array.
1164
         * @public static
1165
         */
1166
        public static function replacePageNumAliases($page, $replace, $diff=0) {
1167
                foreach ($replace as $rep) {
1168
                        foreach ($rep[3] as $a) {
1169
                                if (strpos($page, $a) !== false) {
1170
                                        $page = str_replace($a, $rep[0], $page);
1171
                                        $diff += ($rep[2] - $rep[1]);
1172
                                }
1173
                        }
1174
                }
1175
                return array($page, $diff);
1176
        }
1177

    
1178
        /**
1179
         * Returns timestamp in seconds from formatted date-time.
1180
         * @param $date (string) Formatted date-time.
1181
         * @return int seconds.
1182
         * @since 5.9.152 (2012-03-23)
1183
         * @public static
1184
         */
1185
        public static function getTimestamp($date) {
1186
                if (($date[0] == 'D') AND ($date[1] == ':')) {
1187
                        // remove date prefix if present
1188
                        $date = substr($date, 2);
1189
                }
1190
                return strtotime($date);
1191
        }
1192

    
1193
        /**
1194
         * Returns a formatted date-time.
1195
         * @param $time (int) Time in seconds.
1196
         * @return string escaped date string.
1197
         * @since 5.9.152 (2012-03-23)
1198
         * @public static
1199
         */
1200
        public static function getFormattedDate($time) {
1201
                return substr_replace(date('YmdHisO', intval($time)), '\'', (0 - 2), 0).'\'';
1202
        }
1203

    
1204
        /**
1205
         * Get ULONG from string (Big Endian 32-bit unsigned integer).
1206
         * @param $str (string) string from where to extract value
1207
         * @param $offset (int) point from where to read the data
1208
         * @return int 32 bit value
1209
         * @author Nicola Asuni
1210
         * @since 5.2.000 (2010-06-02)
1211
         * @public static
1212
         */
1213
        public static function _getULONG($str, $offset) {
1214
                $v = unpack('Ni', substr($str, $offset, 4));
1215
                return $v['i'];
1216
        }
1217

    
1218
        /**
1219
         * Get USHORT from string (Big Endian 16-bit unsigned integer).
1220
         * @param $str (string) string from where to extract value
1221
         * @param $offset (int) point from where to read the data
1222
         * @return int 16 bit value
1223
         * @author Nicola Asuni
1224
         * @since 5.2.000 (2010-06-02)
1225
         * @public static
1226
         */
1227
        public static function _getUSHORT($str, $offset) {
1228
                $v = unpack('ni', substr($str, $offset, 2));
1229
                return $v['i'];
1230
        }
1231

    
1232
        /**
1233
         * Get SHORT from string (Big Endian 16-bit signed integer).
1234
         * @param $str (string) String from where to extract value.
1235
         * @param $offset (int) Point from where to read the data.
1236
         * @return int 16 bit value
1237
         * @author Nicola Asuni
1238
         * @since 5.2.000 (2010-06-02)
1239
         * @public static
1240
         */
1241
        public static function _getSHORT($str, $offset) {
1242
                $v = unpack('si', substr($str, $offset, 2));
1243
                return $v['i'];
1244
        }
1245

    
1246
        /**
1247
         * Get FWORD from string (Big Endian 16-bit signed integer).
1248
         * @param $str (string) String from where to extract value.
1249
         * @param $offset (int) Point from where to read the data.
1250
         * @return int 16 bit value
1251
         * @author Nicola Asuni
1252
         * @since 5.9.123 (2011-09-30)
1253
         * @public static
1254
         */
1255
        public static function _getFWORD($str, $offset) {
1256
                $v = self::_getUSHORT($str, $offset);
1257
                if ($v > 0x7fff) {
1258
                        $v -= 0x10000;
1259
                }
1260
                return $v;
1261
        }
1262

    
1263
        /**
1264
         * Get UFWORD from string (Big Endian 16-bit unsigned integer).
1265
         * @param $str (string) string from where to extract value
1266
         * @param $offset (int) point from where to read the data
1267
         * @return int 16 bit value
1268
         * @author Nicola Asuni
1269
         * @since 5.9.123 (2011-09-30)
1270
         * @public static
1271
         */
1272
        public static function _getUFWORD($str, $offset) {
1273
                $v = self::_getUSHORT($str, $offset);
1274
                return $v;
1275
        }
1276

    
1277
        /**
1278
         * Get FIXED from string (32-bit signed fixed-point number (16.16).
1279
         * @param $str (string) string from where to extract value
1280
         * @param $offset (int) point from where to read the data
1281
         * @return int 16 bit value
1282
         * @author Nicola Asuni
1283
         * @since 5.9.123 (2011-09-30)
1284
         * @public static
1285
         */
1286
        public static function _getFIXED($str, $offset) {
1287
                // mantissa
1288
                $m = self::_getFWORD($str, $offset);
1289
                // fraction
1290
                $f = self::_getUSHORT($str, ($offset + 2));
1291
                $v = floatval(''.$m.'.'.$f.'');
1292
                return $v;
1293
        }
1294

    
1295
        /**
1296
         * Get BYTE from string (8-bit unsigned integer).
1297
         * @param $str (string) String from where to extract value.
1298
         * @param $offset (int) Point from where to read the data.
1299
         * @return int 8 bit value
1300
         * @author Nicola Asuni
1301
         * @since 5.2.000 (2010-06-02)
1302
         * @public static
1303
         */
1304
        public static function _getBYTE($str, $offset) {
1305
                $v = unpack('Ci', substr($str, $offset, 1));
1306
                return $v['i'];
1307
        }
1308
        /**
1309
         * Binary-safe and URL-safe file read.
1310
         * Reads up to length bytes from the file pointer referenced by handle. Reading stops as soon as one of the following conditions is met: length bytes have been read; EOF (end of file) is reached.
1311
         * @param $handle (resource)
1312
         * @param $length (int)
1313
         * @return Returns the read string or FALSE in case of error.
1314
         * @author Nicola Asuni
1315
         * @since 4.5.027 (2009-03-16)
1316
         * @public static
1317
         */
1318
        public static function rfread($handle, $length) {
1319
                $data = fread($handle, $length);
1320
                if ($data === false) {
1321
                        return false;
1322
                }
1323
                $rest = ($length - strlen($data));
1324
                if ($rest > 0) {
1325
                        $data .= self::rfread($handle, $rest);
1326
                }
1327
                return $data;
1328
        }
1329

    
1330
        /**
1331
         * Read a 4-byte (32 bit) integer from file.
1332
         * @param $f (string) file name.
1333
         * @return 4-byte integer
1334
         * @public static
1335
         */
1336
        public static function _freadint($f) {
1337
                $a = unpack('Ni', fread($f, 4));
1338
                return $a['i'];
1339
        }
1340

    
1341
        /**
1342
         * Returns a string containing random data to be used as a seed for encryption methods.
1343
         * @param $seed (string) starting seed value
1344
         * @return string containing random data
1345
         * @author Nicola Asuni
1346
         * @since 5.9.006 (2010-10-19)
1347
         * @public static
1348
         */
1349
        public static function getRandomSeed($seed='') {
1350
                $seed .= microtime();
1351
                if (function_exists('openssl_random_pseudo_bytes') AND (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) {
1352
                        // this is not used on windows systems because it is very slow for a know bug
1353
                        $seed .= openssl_random_pseudo_bytes(512);
1354
                } else {
1355
                        for ($i = 0; $i < 23; ++$i) {
1356
                                $seed .= uniqid('', true);
1357
                        }
1358
                }
1359
                $seed .= uniqid('', true);
1360
                $seed .= rand();
1361
                $seed .= getmypid();
1362
                $seed .= __FILE__;
1363
                if (isset($_SERVER['REMOTE_ADDR'])) {
1364
                        $seed .= $_SERVER['REMOTE_ADDR'];
1365
                }
1366
                if (isset($_SERVER['HTTP_USER_AGENT'])) {
1367
                        $seed .= $_SERVER['HTTP_USER_AGENT'];
1368
                }
1369
                if (isset($_SERVER['HTTP_ACCEPT'])) {
1370
                        $seed .= $_SERVER['HTTP_ACCEPT'];
1371
                }
1372
                if (isset($_SERVER['HTTP_ACCEPT_ENCODING'])) {
1373
                        $seed .= $_SERVER['HTTP_ACCEPT_ENCODING'];
1374
                }
1375
                if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
1376
                        $seed .= $_SERVER['HTTP_ACCEPT_LANGUAGE'];
1377
                }
1378
                if (isset($_SERVER['HTTP_ACCEPT_CHARSET'])) {
1379
                        $seed .= $_SERVER['HTTP_ACCEPT_CHARSET'];
1380
                }
1381
                $seed .= rand();
1382
                $seed .= uniqid('', true);
1383
                $seed .= microtime();
1384
                return $seed;
1385
        }
1386

    
1387
        /**
1388
         * Encrypts a string using MD5 and returns it's value as a binary string.
1389
         * @param $str (string) input string
1390
         * @return String MD5 encrypted binary string
1391
         * @since 2.0.000 (2008-01-02)
1392
         * @public static
1393
         */
1394
        public static function _md5_16($str) {
1395
                return pack('H*', md5($str));
1396
        }
1397

    
1398
        /**
1399
         * Returns the input text exrypted using AES algorithm and the specified key.
1400
         * This method requires mcrypt.
1401
         * @param $key (string) encryption key
1402
         * @param $text (String) input text to be encrypted
1403
         * @return String encrypted text
1404
         * @author Nicola Asuni
1405
         * @since 5.0.005 (2010-05-11)
1406
         * @public static
1407
         */
1408
        public static function _AES($key, $text) {
1409
                // padding (RFC 2898, PKCS #5: Password-Based Cryptography Specification Version 2.0)
1410
                $padding = 16 - (strlen($text) % 16);
1411
                $text .= str_repeat(chr($padding), $padding);
1412
                $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND);
1413
                $text = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv);
1414
                $text = $iv.$text;
1415
                return $text;
1416
        }
1417

    
1418
        /**
1419
         * Returns the input text encrypted using RC4 algorithm and the specified key.
1420
         * RC4 is the standard encryption algorithm used in PDF format
1421
         * @param $key (string) Encryption key.
1422
         * @param $text (String) Input text to be encrypted.
1423
         * @param $last_enc_key (String) Reference to last RC4 key encrypted.
1424
         * @param $last_enc_key_c (String) Reference to last RC4 computed key.
1425
         * @return String encrypted text
1426
         * @since 2.0.000 (2008-01-02)
1427
         * @author Klemen Vodopivec, Nicola Asuni
1428
         * @public static
1429
         */
1430
        public static function _RC4($key, $text, &$last_enc_key, &$last_enc_key_c) {
1431
                if (function_exists('mcrypt_encrypt') AND ($out = @mcrypt_encrypt(MCRYPT_ARCFOUR, $key, $text, MCRYPT_MODE_STREAM, ''))) {
1432
                        // try to use mcrypt function if exist
1433
                        return $out;
1434
                }
1435
                if ($last_enc_key != $key) {
1436
                        $k = str_repeat($key, ((256 / strlen($key)) + 1));
1437
                        $rc4 = range(0, 255);
1438
                        $j = 0;
1439
                        for ($i = 0; $i < 256; ++$i) {
1440
                                $t = $rc4[$i];
1441
                                $j = ($j + $t + ord($k[$i])) % 256;
1442
                                $rc4[$i] = $rc4[$j];
1443
                                $rc4[$j] = $t;
1444
                        }
1445
                        $last_enc_key = $key;
1446
                        $last_enc_key_c = $rc4;
1447
                } else {
1448
                        $rc4 = $last_enc_key_c;
1449
                }
1450
                $len = strlen($text);
1451
                $a = 0;
1452
                $b = 0;
1453
                $out = '';
1454
                for ($i = 0; $i < $len; ++$i) {
1455
                        $a = ($a + 1) % 256;
1456
                        $t = $rc4[$a];
1457
                        $b = ($b + $t) % 256;
1458
                        $rc4[$a] = $rc4[$b];
1459
                        $rc4[$b] = $t;
1460
                        $k = $rc4[($rc4[$a] + $rc4[$b]) % 256];
1461
                        $out .= chr(ord($text[$i]) ^ $k);
1462
                }
1463
                return $out;
1464
        }
1465

    
1466
        /**
1467
         * Return the premission code used on encryption (P value).
1468
         * @param $permissions (Array) the set of permissions (specify the ones you want to block).
1469
         * @param $mode (int) encryption strength: 0 = RC4 40 bit; 1 = RC4 128 bit; 2 = AES 128 bit; 3 = AES 256 bit.
1470
         * @since 5.0.005 (2010-05-12)
1471
         * @author Nicola Asuni
1472
         * @public static
1473
         */
1474
        public static function getUserPermissionCode($permissions, $mode=0) {
1475
                $options = array(
1476
                        'owner' => 2, // bit 2 -- inverted logic: cleared by default
1477
                        'print' => 4, // bit 3
1478
                        'modify' => 8, // bit 4
1479
                        'copy' => 16, // bit 5
1480
                        'annot-forms' => 32, // bit 6
1481
                        'fill-forms' => 256, // bit 9
1482
                        'extract' => 512, // bit 10
1483
                        'assemble' => 1024,// bit 11
1484
                        'print-high' => 2048 // bit 12
1485
                        );
1486
                $protection = 2147422012; // 32 bit: (01111111 11111111 00001111 00111100)
1487
                foreach ($permissions as $permission) {
1488
                        if (isset($options[$permission])) {
1489
                                if (($mode > 0) OR ($options[$permission] <= 32)) {
1490
                                        // set only valid permissions
1491
                                        if ($options[$permission] == 2) {
1492
                                                // the logic for bit 2 is inverted (cleared by default)
1493
                                                $protection += $options[$permission];
1494
                                        } else {
1495
                                                $protection -= $options[$permission];
1496
                                        }
1497
                                }
1498
                        }
1499
                }
1500
                return $protection;
1501
        }
1502

    
1503
        /**
1504
         * Convert hexadecimal string to string
1505
         * @param $bs (string) byte-string to convert
1506
         * @return String
1507
         * @since 5.0.005 (2010-05-12)
1508
         * @author Nicola Asuni
1509
         * @public static
1510
         */
1511
        public static function convertHexStringToString($bs) {
1512
                $string = ''; // string to be returned
1513
                $bslength = strlen($bs);
1514
                if (($bslength % 2) != 0) {
1515
                        // padding
1516
                        $bs .= '0';
1517
                        ++$bslength;
1518
                }
1519
                for ($i = 0; $i < $bslength; $i += 2) {
1520
                        $string .= chr(hexdec($bs[$i].$bs[($i + 1)]));
1521
                }
1522
                return $string;
1523
        }
1524

    
1525
        /**
1526
         * Convert string to hexadecimal string (byte string)
1527
         * @param $s (string) string to convert
1528
         * @return byte string
1529
         * @since 5.0.010 (2010-05-17)
1530
         * @author Nicola Asuni
1531
         * @public static
1532
         */
1533
        public static function convertStringToHexString($s) {
1534
                $bs = '';
1535
                $chars = preg_split('//', $s, -1, PREG_SPLIT_NO_EMPTY);
1536
                foreach ($chars as $c) {
1537
                        $bs .= sprintf('%02s', dechex(ord($c)));
1538
                }
1539
                return $bs;
1540
        }
1541

    
1542
        /**
1543
         * Convert encryption P value to a string of bytes, low-order byte first.
1544
         * @param $protection (string) 32bit encryption permission value (P value)
1545
         * @return String
1546
         * @since 5.0.005 (2010-05-12)
1547
         * @author Nicola Asuni
1548
         * @public static
1549
         */
1550
        public static function getEncPermissionsString($protection) {
1551
                $binprot = sprintf('%032b', $protection);
1552
                $str = chr(bindec(substr($binprot, 24, 8)));
1553
                $str .= chr(bindec(substr($binprot, 16, 8)));
1554
                $str .= chr(bindec(substr($binprot, 8, 8)));
1555
                $str .= chr(bindec(substr($binprot, 0, 8)));
1556
                return $str;
1557
        }
1558

    
1559
        /**
1560
         * Encode a name object.
1561
         * @param $name (string) Name object to encode.
1562
         * @return (string) Encoded name object.
1563
         * @author Nicola Asuni
1564
         * @since 5.9.097 (2011-06-23)
1565
         * @public static
1566
         */
1567
        public static function encodeNameObject($name) {
1568
                $escname = '';
1569
                $length = strlen($name);
1570
                for ($i = 0; $i < $length; ++$i) {
1571
                        $chr = $name[$i];
1572
                        if (preg_match('/[0-9a-zA-Z]/', $chr) == 1) {
1573
                                $escname .= $chr;
1574
                        } else {
1575
                                $escname .= sprintf('#%02X', ord($chr));
1576
                        }
1577
                }
1578
                return $escname;
1579
        }
1580

    
1581
        /**
1582
         * Convert JavaScript form fields properties array to Annotation Properties array.
1583
         * @param $prop (array) javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
1584
         * @param $spot_colors (array) Reference to spot colors array.
1585
         * @param $rtl (boolean) True if in Right-To-Left text direction mode, false otherwise.
1586
         * @return array of annotation properties
1587
         * @author Nicola Asuni
1588
         * @since 4.8.000 (2009-09-06)
1589
         * @public static
1590
         */
1591
        public static function getAnnotOptFromJSProp($prop, &$spot_colors, $rtl=false) {
1592
                if (isset($prop['aopt']) AND is_array($prop['aopt'])) {
1593
                        // the annotation options area lready defined
1594
                        return $prop['aopt'];
1595
                }
1596
                $opt = array(); // value to be returned
1597
                // alignment: Controls how the text is laid out within the text field.
1598
                if (isset($prop['alignment'])) {
1599
                        switch ($prop['alignment']) {
1600
                                case 'left': {
1601
                                        $opt['q'] = 0;
1602
                                        break;
1603
                                }
1604
                                case 'center': {
1605
                                        $opt['q'] = 1;
1606
                                        break;
1607
                                }
1608
                                case 'right': {
1609
                                        $opt['q'] = 2;
1610
                                        break;
1611
                                }
1612
                                default: {
1613
                                        $opt['q'] = ($rtl)?2:0;
1614
                                        break;
1615
                                }
1616
                        }
1617
                }
1618
                // lineWidth: Specifies the thickness of the border when stroking the perimeter of a field's rectangle.
1619
                if (isset($prop['lineWidth'])) {
1620
                        $linewidth = intval($prop['lineWidth']);
1621
                } else {
1622
                        $linewidth = 1;
1623
                }
1624
                // borderStyle: The border style for a field.
1625
                if (isset($prop['borderStyle'])) {
1626
                        switch ($prop['borderStyle']) {
1627
                                case 'border.d':
1628
                                case 'dashed': {
1629
                                        $opt['border'] = array(0, 0, $linewidth, array(3, 2));
1630
                                        $opt['bs'] = array('w'=>$linewidth, 's'=>'D', 'd'=>array(3, 2));
1631
                                        break;
1632
                                }
1633
                                case 'border.b':
1634
                                case 'beveled': {
1635
                                        $opt['border'] = array(0, 0, $linewidth);
1636
                                        $opt['bs'] = array('w'=>$linewidth, 's'=>'B');
1637
                                        break;
1638
                                }
1639
                                case 'border.i':
1640
                                case 'inset': {
1641
                                        $opt['border'] = array(0, 0, $linewidth);
1642
                                        $opt['bs'] = array('w'=>$linewidth, 's'=>'I');
1643
                                        break;
1644
                                }
1645
                                case 'border.u':
1646
                                case 'underline': {
1647
                                        $opt['border'] = array(0, 0, $linewidth);
1648
                                        $opt['bs'] = array('w'=>$linewidth, 's'=>'U');
1649
                                        break;
1650
                                }
1651
                                case 'border.s':
1652
                                case 'solid': {
1653
                                        $opt['border'] = array(0, 0, $linewidth);
1654
                                        $opt['bs'] = array('w'=>$linewidth, 's'=>'S');
1655
                                        break;
1656
                                }
1657
                                default: {
1658
                                        break;
1659
                                }
1660
                        }
1661
                }
1662
                if (isset($prop['border']) AND is_array($prop['border'])) {
1663
                        $opt['border'] = $prop['border'];
1664
                }
1665
                if (!isset($opt['mk'])) {
1666
                        $opt['mk'] = array();
1667
                }
1668
                if (!isset($opt['mk']['if'])) {
1669
                        $opt['mk']['if'] = array();
1670
                }
1671
                $opt['mk']['if']['a'] = array(0.5, 0.5);
1672
                // buttonAlignX: Controls how space is distributed from the left of the button face with respect to the icon.
1673
                if (isset($prop['buttonAlignX'])) {
1674
                        $opt['mk']['if']['a'][0] = $prop['buttonAlignX'];
1675
                }
1676
                // buttonAlignY: Controls how unused space is distributed from the bottom of the button face with respect to the icon.
1677
                if (isset($prop['buttonAlignY'])) {
1678
                        $opt['mk']['if']['a'][1] = $prop['buttonAlignY'];
1679
                }
1680
                // buttonFitBounds: If true, the extent to which the icon may be scaled is set to the bounds of the button field.
1681
                if (isset($prop['buttonFitBounds']) AND ($prop['buttonFitBounds'] == 'true')) {
1682
                        $opt['mk']['if']['fb'] = true;
1683
                }
1684
                // buttonScaleHow: Controls how the icon is scaled (if necessary) to fit inside the button face.
1685
                if (isset($prop['buttonScaleHow'])) {
1686
                        switch ($prop['buttonScaleHow']) {
1687
                                case 'scaleHow.proportional': {
1688
                                        $opt['mk']['if']['s'] = 'P';
1689
                                        break;
1690
                                }
1691
                                case 'scaleHow.anamorphic': {
1692
                                        $opt['mk']['if']['s'] = 'A';
1693
                                        break;
1694
                                }
1695
                        }
1696
                }
1697
                // buttonScaleWhen: Controls when an icon is scaled to fit inside the button face.
1698
                if (isset($prop['buttonScaleWhen'])) {
1699
                        switch ($prop['buttonScaleWhen']) {
1700
                                case 'scaleWhen.always': {
1701
                                        $opt['mk']['if']['sw'] = 'A';
1702
                                        break;
1703
                                }
1704
                                case 'scaleWhen.never': {
1705
                                        $opt['mk']['if']['sw'] = 'N';
1706
                                        break;
1707
                                }
1708
                                case 'scaleWhen.tooBig': {
1709
                                        $opt['mk']['if']['sw'] = 'B';
1710
                                        break;
1711
                                }
1712
                                case 'scaleWhen.tooSmall': {
1713
                                        $opt['mk']['if']['sw'] = 'S';
1714
                                        break;
1715
                                }
1716
                        }
1717
                }
1718
                // buttonPosition: Controls how the text and the icon of the button are positioned with respect to each other within the button face.
1719
                if (isset($prop['buttonPosition'])) {
1720
                        switch ($prop['buttonPosition']) {
1721
                                case 0:
1722
                                case 'position.textOnly': {
1723
                                        $opt['mk']['tp'] = 0;
1724
                                        break;
1725
                                }
1726
                                case 1:
1727
                                case 'position.iconOnly': {
1728
                                        $opt['mk']['tp'] = 1;
1729
                                        break;
1730
                                }
1731
                                case 2:
1732
                                case 'position.iconTextV': {
1733
                                        $opt['mk']['tp'] = 2;
1734
                                        break;
1735
                                }
1736
                                case 3:
1737
                                case 'position.textIconV': {
1738
                                        $opt['mk']['tp'] = 3;
1739
                                        break;
1740
                                }
1741
                                case 4:
1742
                                case 'position.iconTextH': {
1743
                                        $opt['mk']['tp'] = 4;
1744
                                        break;
1745
                                }
1746
                                case 5:
1747
                                case 'position.textIconH': {
1748
                                        $opt['mk']['tp'] = 5;
1749
                                        break;
1750
                                }
1751
                                case 6:
1752
                                case 'position.overlay': {
1753
                                        $opt['mk']['tp'] = 6;
1754
                                        break;
1755
                                }
1756
                        }
1757
                }
1758
                // fillColor: Specifies the background color for a field.
1759
                if (isset($prop['fillColor'])) {
1760
                        if (is_array($prop['fillColor'])) {
1761
                                $opt['mk']['bg'] = $prop['fillColor'];
1762
                        } else {
1763
                                $opt['mk']['bg'] = TCPDF_COLORS::convertHTMLColorToDec($prop['fillColor'], $spot_colors);
1764
                        }
1765
                }
1766
                // strokeColor: Specifies the stroke color for a field that is used to stroke the rectangle of the field with a line as large as the line width.
1767
                if (isset($prop['strokeColor'])) {
1768
                        if (is_array($prop['strokeColor'])) {
1769
                                $opt['mk']['bc'] = $prop['strokeColor'];
1770
                        } else {
1771
                                $opt['mk']['bc'] = TCPDF_COLORS::convertHTMLColorToDec($prop['strokeColor'], $spot_colors);
1772
                        }
1773
                }
1774
                // rotation: The rotation of a widget in counterclockwise increments.
1775
                if (isset($prop['rotation'])) {
1776
                        $opt['mk']['r'] = $prop['rotation'];
1777
                }
1778
                // charLimit: Limits the number of characters that a user can type into a text field.
1779
                if (isset($prop['charLimit'])) {
1780
                        $opt['maxlen'] = intval($prop['charLimit']);
1781
                }
1782
                if (!isset($ff)) {
1783
                        $ff = 0; // default value
1784
                }
1785
                // readonly: The read-only characteristic of a field. If a field is read-only, the user can see the field but cannot change it.
1786
                if (isset($prop['readonly']) AND ($prop['readonly'] == 'true')) {
1787
                        $ff += 1 << 0;
1788
                }
1789
                // required: Specifies whether a field requires a value.
1790
                if (isset($prop['required']) AND ($prop['required'] == 'true')) {
1791
                        $ff += 1 << 1;
1792
                }
1793
                // multiline: Controls how text is wrapped within the field.
1794
                if (isset($prop['multiline']) AND ($prop['multiline'] == 'true')) {
1795
                        $ff += 1 << 12;
1796
                }
1797
                // password: Specifies whether the field should display asterisks when data is entered in the field.
1798
                if (isset($prop['password']) AND ($prop['password'] == 'true')) {
1799
                        $ff += 1 << 13;
1800
                }
1801
                // NoToggleToOff: If set, exactly one radio button shall be selected at all times; selecting the currently selected button has no effect.
1802
                if (isset($prop['NoToggleToOff']) AND ($prop['NoToggleToOff'] == 'true')) {
1803
                        $ff += 1 << 14;
1804
                }
1805
                // Radio: If set, the field is a set of radio buttons.
1806
                if (isset($prop['Radio']) AND ($prop['Radio'] == 'true')) {
1807
                        $ff += 1 << 15;
1808
                }
1809
                // Pushbutton: If set, the field is a pushbutton that does not retain a permanent value.
1810
                if (isset($prop['Pushbutton']) AND ($prop['Pushbutton'] == 'true')) {
1811
                        $ff += 1 << 16;
1812
                }
1813
                // Combo: If set, the field is a combo box; if clear, the field is a list box.
1814
                if (isset($prop['Combo']) AND ($prop['Combo'] == 'true')) {
1815
                        $ff += 1 << 17;
1816
                }
1817
                // editable: Controls whether a combo box is editable.
1818
                if (isset($prop['editable']) AND ($prop['editable'] == 'true')) {
1819
                        $ff += 1 << 18;
1820
                }
1821
                // Sort: If set, the field's option items shall be sorted alphabetically.
1822
                if (isset($prop['Sort']) AND ($prop['Sort'] == 'true')) {
1823
                        $ff += 1 << 19;
1824
                }
1825
                // fileSelect: If true, sets the file-select flag in the Options tab of the text field (Field is Used for File Selection).
1826
                if (isset($prop['fileSelect']) AND ($prop['fileSelect'] == 'true')) {
1827
                        $ff += 1 << 20;
1828
                }
1829
                // multipleSelection: If true, indicates that a list box allows a multiple selection of items.
1830
                if (isset($prop['multipleSelection']) AND ($prop['multipleSelection'] == 'true')) {
1831
                        $ff += 1 << 21;
1832
                }
1833
                // doNotSpellCheck: If true, spell checking is not performed on this editable text field.
1834
                if (isset($prop['doNotSpellCheck']) AND ($prop['doNotSpellCheck'] == 'true')) {
1835
                        $ff += 1 << 22;
1836
                }
1837
                // doNotScroll: If true, the text field does not scroll and the user, therefore, is limited by the rectangular region designed for the field.
1838
                if (isset($prop['doNotScroll']) AND ($prop['doNotScroll'] == 'true')) {
1839
                        $ff += 1 << 23;
1840
                }
1841
                // comb: If set to true, the field background is drawn as series of boxes (one for each character in the value of the field) and each character of the content is drawn within those boxes. The number of boxes drawn is determined from the charLimit property. It applies only to text fields. The setter will also raise if any of the following field properties are also set multiline, password, and fileSelect. A side-effect of setting this property is that the doNotScroll property is also set.
1842
                if (isset($prop['comb']) AND ($prop['comb'] == 'true')) {
1843
                        $ff += 1 << 24;
1844
                }
1845
                // radiosInUnison: If false, even if a group of radio buttons have the same name and export value, they behave in a mutually exclusive fashion, like HTML radio buttons.
1846
                if (isset($prop['radiosInUnison']) AND ($prop['radiosInUnison'] == 'true')) {
1847
                        $ff += 1 << 25;
1848
                }
1849
                // richText: If true, the field allows rich text formatting.
1850
                if (isset($prop['richText']) AND ($prop['richText'] == 'true')) {
1851
                        $ff += 1 << 25;
1852
                }
1853
                // commitOnSelChange: Controls whether a field value is committed after a selection change.
1854
                if (isset($prop['commitOnSelChange']) AND ($prop['commitOnSelChange'] == 'true')) {
1855
                        $ff += 1 << 26;
1856
                }
1857
                $opt['ff'] = $ff;
1858
                // defaultValue: The default value of a field - that is, the value that the field is set to when the form is reset.
1859
                if (isset($prop['defaultValue'])) {
1860
                        $opt['dv'] = $prop['defaultValue'];
1861
                }
1862
                $f = 4; // default value for annotation flags
1863
                // readonly: The read-only characteristic of a field. If a field is read-only, the user can see the field but cannot change it.
1864
                if (isset($prop['readonly']) AND ($prop['readonly'] == 'true')) {
1865
                        $f += 1 << 6;
1866
                }
1867
                // display: Controls whether the field is hidden or visible on screen and in print.
1868
                if (isset($prop['display'])) {
1869
                        if ($prop['display'] == 'display.visible') {
1870
                                //
1871
                        } elseif ($prop['display'] == 'display.hidden') {
1872
                                $f += 1 << 1;
1873
                        } elseif ($prop['display'] == 'display.noPrint') {
1874
                                $f -= 1 << 2;
1875
                        } elseif ($prop['display'] == 'display.noView') {
1876
                                $f += 1 << 5;
1877
                        }
1878
                }
1879
                $opt['f'] = $f;
1880
                // currentValueIndices: Reads and writes single or multiple values of a list box or combo box.
1881
                if (isset($prop['currentValueIndices']) AND is_array($prop['currentValueIndices'])) {
1882
                        $opt['i'] = $prop['currentValueIndices'];
1883
                }
1884
                // value: The value of the field data that the user has entered.
1885
                if (isset($prop['value'])) {
1886
                        if (is_array($prop['value'])) {
1887
                                $opt['opt'] = array();
1888
                                foreach ($prop['value'] AS $key => $optval) {
1889
                                        // exportValues: An array of strings representing the export values for the field.
1890
                                        if (isset($prop['exportValues'][$key])) {
1891
                                                $opt['opt'][$key] = array($prop['exportValues'][$key], $prop['value'][$key]);
1892
                                        } else {
1893
                                                $opt['opt'][$key] = $prop['value'][$key];
1894
                                        }
1895
                                }
1896
                        } else {
1897
                                $opt['v'] = $prop['value'];
1898
                        }
1899
                }
1900
                // richValue: This property specifies the text contents and formatting of a rich text field.
1901
                if (isset($prop['richValue'])) {
1902
                        $opt['rv'] = $prop['richValue'];
1903
                }
1904
                // submitName: If nonempty, used during form submission instead of name. Only applicable if submitting in HTML format (that is, URL-encoded).
1905
                if (isset($prop['submitName'])) {
1906
                        $opt['tm'] = $prop['submitName'];
1907
                }
1908
                // name: Fully qualified field name.
1909
                if (isset($prop['name'])) {
1910
                        $opt['t'] = $prop['name'];
1911
                }
1912
                // userName: The user name (short description string) of the field.
1913
                if (isset($prop['userName'])) {
1914
                        $opt['tu'] = $prop['userName'];
1915
                }
1916
                // highlight: Defines how a button reacts when a user clicks it.
1917
                if (isset($prop['highlight'])) {
1918
                        switch ($prop['highlight']) {
1919
                                case 'none':
1920
                                case 'highlight.n': {
1921
                                        $opt['h'] = 'N';
1922
                                        break;
1923
                                }
1924
                                case 'invert':
1925
                                case 'highlight.i': {
1926
                                        $opt['h'] = 'i';
1927
                                        break;
1928
                                }
1929
                                case 'push':
1930
                                case 'highlight.p': {
1931
                                        $opt['h'] = 'P';
1932
                                        break;
1933
                                }
1934
                                case 'outline':
1935
                                case 'highlight.o': {
1936
                                        $opt['h'] = 'O';
1937
                                        break;
1938
                                }
1939
                        }
1940
                }
1941
                // Unsupported options:
1942
                // - calcOrderIndex: Changes the calculation order of fields in the document.
1943
                // - delay: Delays the redrawing of a field's appearance.
1944
                // - defaultStyle: This property defines the default style attributes for the form field.
1945
                // - style: Allows the user to set the glyph style of a check box or radio button.
1946
                // - textColor, textFont, textSize
1947
                return $opt;
1948
        }
1949

    
1950
        /**
1951
         * Format the page numbers.
1952
         * This method can be overriden for custom formats.
1953
         * @param $num (int) page number
1954
         * @since 4.2.005 (2008-11-06)
1955
         * @public static
1956
         */
1957
        public static function formatPageNumber($num) {
1958
                return number_format((float)$num, 0, '', '.');
1959
        }
1960

    
1961
        /**
1962
         * Format the page numbers on the Table Of Content.
1963
         * This method can be overriden for custom formats.
1964
         * @param $num (int) page number
1965
         * @since 4.5.001 (2009-01-04)
1966
         * @see addTOC(), addHTMLTOC()
1967
         * @public static
1968
         */
1969
        public static function formatTOCPageNumber($num) {
1970
                return number_format((float)$num, 0, '', '.');
1971
        }
1972

    
1973
        /**
1974
         * Extracts the CSS properties from a CSS string.
1975
         * @param $cssdata (string) string containing CSS definitions.
1976
         * @return An array where the keys are the CSS selectors and the values are the CSS properties.
1977
         * @author Nicola Asuni
1978
         * @since 5.1.000 (2010-05-25)
1979
         * @public static
1980
         */
1981
        public static function extractCSSproperties($cssdata) {
1982
                if (empty($cssdata)) {
1983
                        return array();
1984
                }
1985
                // remove comments
1986
                $cssdata = preg_replace('/\/\*[^\*]*\*\//', '', $cssdata);
1987
                // remove newlines and multiple spaces
1988
                $cssdata = preg_replace('/[\s]+/', ' ', $cssdata);
1989
                // remove some spaces
1990
                $cssdata = preg_replace('/[\s]*([;:\{\}]{1})[\s]*/', '\\1', $cssdata);
1991
                // remove empty blocks
1992
                $cssdata = preg_replace('/([^\}\{]+)\{\}/', '', $cssdata);
1993
                // replace media type parenthesis
1994
                $cssdata = preg_replace('/@media[\s]+([^\{]*)\{/i', '@media \\', $cssdata);
1995
                $cssdata = preg_replace('/\}\}/si', '', $cssdata);
1996
                // trim string
1997
                $cssdata = trim($cssdata);
1998
                // find media blocks (all, braille, embossed, handheld, print, projection, screen, speech, tty, tv)
1999
                $cssblocks = array();
2000
                $matches = array();
2001
                if (preg_match_all('/@media[\s]+([^]*)§([^§]*)§/i', $cssdata, $matches) > 0) {
2002
                        foreach ($matches[1] as $key => $type) {
2003
                                $cssblocks[$type] = $matches[2][$key];
2004
                        }
2005
                        // remove media blocks
2006
                        $cssdata = preg_replace('/@media[\s]+([^]*)§([^§]*)§/i', '', $cssdata);
2007
                }
2008
                // keep 'all' and 'print' media, other media types are discarded
2009
                if (isset($cssblocks['all']) AND !empty($cssblocks['all'])) {
2010
                        $cssdata .= $cssblocks['all'];
2011
                }
2012
                if (isset($cssblocks['print']) AND !empty($cssblocks['print'])) {
2013
                        $cssdata .= $cssblocks['print'];
2014
                }
2015
                // reset css blocks array
2016
                $cssblocks = array();
2017
                $matches = array();
2018
                // explode css data string into array
2019
                if (substr($cssdata, -1) == '}') {
2020
                        // remove last parethesis
2021
                        $cssdata = substr($cssdata, 0, -1);
2022
                }
2023
                $matches = explode('}', $cssdata);
2024
                foreach ($matches as $key => $block) {
2025
                        // index 0 contains the CSS selector, index 1 contains CSS properties
2026
                        $cssblocks[$key] = explode('{', $block);
2027
                        if (!isset($cssblocks[$key][1])) {
2028
                                // remove empty definitions
2029
                                unset($cssblocks[$key]);
2030
                        }
2031
                }
2032
                // split groups of selectors (comma-separated list of selectors)
2033
                foreach ($cssblocks as $key => $block) {
2034
                        if (strpos($block[0], ',') > 0) {
2035
                                $selectors = explode(',', $block[0]);
2036
                                foreach ($selectors as $sel) {
2037
                                        $cssblocks[] = array(0 => trim($sel), 1 => $block[1]);
2038
                                }
2039
                                unset($cssblocks[$key]);
2040
                        }
2041
                }
2042
                // covert array to selector => properties
2043
                $cssdata = array();
2044
                foreach ($cssblocks as $block) {
2045
                        $selector = $block[0];
2046
                        // calculate selector's specificity
2047
                        $matches = array();
2048
                        $a = 0; // the declaration is not from is a 'style' attribute
2049
                        $b = intval(preg_match_all('/[\#]/', $selector, $matches)); // number of ID attributes
2050
                        $c = intval(preg_match_all('/[\[\.]/', $selector, $matches)); // number of other attributes
2051
                        $c += intval(preg_match_all('/[\:]link|visited|hover|active|focus|target|lang|enabled|disabled|checked|indeterminate|root|nth|first|last|only|empty|contains|not/i', $selector, $matches)); // number of pseudo-classes
2052
                        $d = intval(preg_match_all('/[\>\+\~\s]{1}[a-zA-Z0-9]+/', ' '.$selector, $matches)); // number of element names
2053
                        $d += intval(preg_match_all('/[\:][\:]/', $selector, $matches)); // number of pseudo-elements
2054
                        $specificity = $a.$b.$c.$d;
2055
                        // add specificity to the beginning of the selector
2056
                        $cssdata[$specificity.' '.$selector] = $block[1];
2057
                }
2058
                // sort selectors alphabetically to account for specificity
2059
                ksort($cssdata, SORT_STRING);
2060
                // return array
2061
                return $cssdata;
2062
        }
2063

    
2064
        /**
2065
         * Cleanup HTML code (requires HTML Tidy library).
2066
         * @param $html (string) htmlcode to fix
2067
         * @param $default_css (string) CSS commands to add
2068
         * @param $tagvs (array) parameters for setHtmlVSpace method
2069
         * @param $tidy_options (array) options for tidy_parse_string function
2070
         * @param $tagvspaces (array) Array of vertical spaces for tags.
2071
         * @return string XHTML code cleaned up
2072
         * @author Nicola Asuni
2073
         * @since 5.9.017 (2010-11-16)
2074
         * @see setHtmlVSpace()
2075
         * @public static
2076
         */
2077
        public static function fixHTMLCode($html, $default_css='', $tagvs='', $tidy_options='', &$tagvspaces) {
2078
                // configure parameters for HTML Tidy
2079
                if ($tidy_options === '') {
2080
                        $tidy_options = array (
2081
                                'clean' => 1,
2082
                                'drop-empty-paras' => 0,
2083
                                'drop-proprietary-attributes' => 1,
2084
                                'fix-backslash' => 1,
2085
                                'hide-comments' => 1,
2086
                                'join-styles' => 1,
2087
                                'lower-literals' => 1,
2088
                                'merge-divs' => 1,
2089
                                'merge-spans' => 1,
2090
                                'output-xhtml' => 1,
2091
                                'word-2000' => 1,
2092
                                'wrap' => 0,
2093
                                'output-bom' => 0,
2094
                                //'char-encoding' => 'utf8',
2095
                                //'input-encoding' => 'utf8',
2096
                                //'output-encoding' => 'utf8'
2097
                        );
2098
                }
2099
                // clean up the HTML code
2100
                $tidy = tidy_parse_string($html, $tidy_options);
2101
                // fix the HTML
2102
                $tidy->cleanRepair();
2103
                // get the CSS part
2104
                $tidy_head = tidy_get_head($tidy);
2105
                $css = $tidy_head->value;
2106
                $css = preg_replace('/<style([^>]+)>/ims', '<style>', $css);
2107
                $css = preg_replace('/<\/style>(.*)<style>/ims', "\n", $css);
2108
                $css = str_replace('/*<![CDATA[*/', '', $css);
2109
                $css = str_replace('/*]]>*/', '', $css);
2110
                preg_match('/<style>(.*)<\/style>/ims', $css, $matches);
2111
                if (isset($matches[1])) {
2112
                        $css = strtolower($matches[1]);
2113
                } else {
2114
                        $css = '';
2115
                }
2116
                // include default css
2117
                $css = '<style>'.$default_css.$css.'</style>';
2118
                // get the body part
2119
                $tidy_body = tidy_get_body($tidy);
2120
                $html = $tidy_body->value;
2121
                // fix some self-closing tags
2122
                $html = str_replace('<br>', '<br />', $html);
2123
                // remove some empty tag blocks
2124
                $html = preg_replace('/<div([^\>]*)><\/div>/', '', $html);
2125
                $html = preg_replace('/<p([^\>]*)><\/p>/', '', $html);
2126
                if ($tagvs !== '') {
2127
                        // set vertical space for some XHTML tags
2128
                        $tagvspaces = $tagvs;
2129
                }
2130
                // return the cleaned XHTML code + CSS
2131
                return $css.$html;
2132
        }
2133

    
2134
        /**
2135
         * Returns true if the CSS selector is valid for the selected HTML tag
2136
         * @param $dom (array) array of HTML tags and properties
2137
         * @param $key (int) key of the current HTML tag
2138
         * @param $selector (string) CSS selector string
2139
         * @return true if the selector is valid, false otherwise
2140
         * @since 5.1.000 (2010-05-25)
2141
         * @public static
2142
         */
2143
        public static function isValidCSSSelectorForTag($dom, $key, $selector) {
2144
                $valid = false; // value to be returned
2145
                $tag = $dom[$key]['value'];
2146
                $class = array();
2147
                if (isset($dom[$key]['attribute']['class']) AND !empty($dom[$key]['attribute']['class'])) {
2148
                        $class = explode(' ', strtolower($dom[$key]['attribute']['class']));
2149
                }
2150
                $id = '';
2151
                if (isset($dom[$key]['attribute']['id']) AND !empty($dom[$key]['attribute']['id'])) {
2152
                        $id = strtolower($dom[$key]['attribute']['id']);
2153
                }
2154
                $selector = preg_replace('/([\>\+\~\s]{1})([\.]{1})([^\>\+\~\s]*)/si', '\\1*.\\3', $selector);
2155
                $matches = array();
2156
                if (preg_match_all('/([\>\+\~\s]{1})([a-zA-Z0-9\*]+)([^\>\+\~\s]*)/si', $selector, $matches, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE) > 0) {
2157
                        $parentop = array_pop($matches[1]);
2158
                        $operator = $parentop[0];
2159
                        $offset = $parentop[1];
2160
                        $lasttag = array_pop($matches[2]);
2161
                        $lasttag = strtolower(trim($lasttag[0]));
2162
                        if (($lasttag == '*') OR ($lasttag == $tag)) {
2163
                                // the last element on selector is our tag or 'any tag'
2164
                                $attrib = array_pop($matches[3]);
2165
                                $attrib = strtolower(trim($attrib[0]));
2166
                                if (!empty($attrib)) {
2167
                                        // check if matches class, id, attribute, pseudo-class or pseudo-element
2168
                                        switch ($attrib{0}) {
2169
                                                case '.': { // class
2170
                                                        if (in_array(substr($attrib, 1), $class)) {
2171
                                                                $valid = true;
2172
                                                        }
2173
                                                        break;
2174
                                                }
2175
                                                case '#': { // ID
2176
                                                        if (substr($attrib, 1) == $id) {
2177
                                                                $valid = true;
2178
                                                        }
2179
                                                        break;
2180
                                                }
2181
                                                case '[': { // attribute
2182
                                                        $attrmatch = array();
2183
                                                        if (preg_match('/\[([a-zA-Z0-9]*)[\s]*([\~\^\$\*\|\=]*)[\s]*["]?([^"\]]*)["]?\]/i', $attrib, $attrmatch) > 0) {
2184
                                                                $att = strtolower($attrmatch[1]);
2185
                                                                $val = $attrmatch[3];
2186
                                                                if (isset($dom[$key]['attribute'][$att])) {
2187
                                                                        switch ($attrmatch[2]) {
2188
                                                                                case '=': {
2189
                                                                                        if ($dom[$key]['attribute'][$att] == $val) {
2190
                                                                                                $valid = true;
2191
                                                                                        }
2192
                                                                                        break;
2193
                                                                                }
2194
                                                                                case '~=': {
2195
                                                                                        if (in_array($val, explode(' ', $dom[$key]['attribute'][$att]))) {
2196
                                                                                                $valid = true;
2197
                                                                                        }
2198
                                                                                        break;
2199
                                                                                }
2200
                                                                                case '^=': {
2201
                                                                                        if ($val == substr($dom[$key]['attribute'][$att], 0, strlen($val))) {
2202
                                                                                                $valid = true;
2203
                                                                                        }
2204
                                                                                        break;
2205
                                                                                }
2206
                                                                                case '$=': {
2207
                                                                                        if ($val == substr($dom[$key]['attribute'][$att], -strlen($val))) {
2208
                                                                                                $valid = true;
2209
                                                                                        }
2210
                                                                                        break;
2211
                                                                                }
2212
                                                                                case '*=': {
2213
                                                                                        if (strpos($dom[$key]['attribute'][$att], $val) !== false) {
2214
                                                                                                $valid = true;
2215
                                                                                        }
2216
                                                                                        break;
2217
                                                                                }
2218
                                                                                case '|=': {
2219
                                                                                        if ($dom[$key]['attribute'][$att] == $val) {
2220
                                                                                                $valid = true;
2221
                                                                                        } elseif (preg_match('/'.$val.'[\-]{1}/i', $dom[$key]['attribute'][$att]) > 0) {
2222
                                                                                                $valid = true;
2223
                                                                                        }
2224
                                                                                        break;
2225
                                                                                }
2226
                                                                                default: {
2227
                                                                                        $valid = true;
2228
                                                                                }
2229
                                                                        }
2230
                                                                }
2231
                                                        }
2232
                                                        break;
2233
                                                }
2234
                                                case ':': { // pseudo-class or pseudo-element
2235
                                                        if ($attrib{1} == ':') { // pseudo-element
2236
                                                                // pseudo-elements are not supported!
2237
                                                                // (::first-line, ::first-letter, ::before, ::after)
2238
                                                        } else { // pseudo-class
2239
                                                                // pseudo-classes are not supported!
2240
                                                                // (:root, :nth-child(n), :nth-last-child(n), :nth-of-type(n), :nth-last-of-type(n), :first-child, :last-child, :first-of-type, :last-of-type, :only-child, :only-of-type, :empty, :link, :visited, :active, :hover, :focus, :target, :lang(fr), :enabled, :disabled, :checked)
2241
                                                        }
2242
                                                        break;
2243
                                                }
2244
                                        } // end of switch
2245
                                } else {
2246
                                        $valid = true;
2247
                                }
2248
                                if ($valid AND ($offset > 0)) {
2249
                                        $valid = false;
2250
                                        // check remaining selector part
2251
                                        $selector = substr($selector, 0, $offset);
2252
                                        switch ($operator) {
2253
                                                case ' ': { // descendant of an element
2254
                                                        while ($dom[$key]['parent'] > 0) {
2255
                                                                if (self::isValidCSSSelectorForTag($dom, $dom[$key]['parent'], $selector)) {
2256
                                                                        $valid = true;
2257
                                                                        break;
2258
                                                                } else {
2259
                                                                        $key = $dom[$key]['parent'];
2260
                                                                }
2261
                                                        }
2262
                                                        break;
2263
                                                }
2264
                                                case '>': { // child of an element
2265
                                                        $valid = self::isValidCSSSelectorForTag($dom, $dom[$key]['parent'], $selector);
2266
                                                        break;
2267
                                                }
2268
                                                case '+': { // immediately preceded by an element
2269
                                                        for ($i = ($key - 1); $i > $dom[$key]['parent']; --$i) {
2270
                                                                if ($dom[$i]['tag'] AND $dom[$i]['opening']) {
2271
                                                                        $valid = self::isValidCSSSelectorForTag($dom, $i, $selector);
2272
                                                                        break;
2273
                                                                }
2274
                                                        }
2275
                                                        break;
2276
                                                }
2277
                                                case '~': { // preceded by an element
2278
                                                        for ($i = ($key - 1); $i > $dom[$key]['parent']; --$i) {
2279
                                                                if ($dom[$i]['tag'] AND $dom[$i]['opening']) {
2280
                                                                        if (self::isValidCSSSelectorForTag($dom, $i, $selector)) {
2281
                                                                                break;
2282
                                                                        }
2283
                                                                }
2284
                                                        }
2285
                                                        break;
2286
                                                }
2287
                                        }
2288
                                }
2289
                        }
2290
                }
2291
                return $valid;
2292
        }
2293

    
2294
        /**
2295
         * Returns the styles array that apply for the selected HTML tag.
2296
         * @param $dom (array) array of HTML tags and properties
2297
         * @param $key (int) key of the current HTML tag
2298
         * @param $css (array) array of CSS properties
2299
         * @return array containing CSS properties
2300
         * @since 5.1.000 (2010-05-25)
2301
         * @public static
2302
         */
2303
        public static function getCSSdataArray($dom, $key, $css) {
2304
                $cssarray = array(); // style to be returned
2305
                // get parent CSS selectors
2306
                $selectors = array();
2307
                if (isset($dom[($dom[$key]['parent'])]['csssel'])) {
2308
                        $selectors = $dom[($dom[$key]['parent'])]['csssel'];
2309
                }
2310
                // get all styles that apply
2311
                foreach($css as $selector => $style) {
2312
                        $pos = strpos($selector, ' ');
2313
                        // get specificity
2314
                        $specificity = substr($selector, 0, $pos);
2315
                        // remove specificity
2316
                        $selector = substr($selector, $pos);
2317
                        // check if this selector apply to current tag
2318
                        if (self::isValidCSSSelectorForTag($dom, $key, $selector)) {
2319
                                if (!in_array($selector, $selectors)) {
2320
                                        // add style if not already added on parent selector
2321
                                        $cssarray[] = array('k' => $selector, 's' => $specificity, 'c' => $style);
2322
                                        $selectors[] = $selector;
2323
                                }
2324
                        }
2325
                }
2326
                if (isset($dom[$key]['attribute']['style'])) {
2327
                        // attach inline style (latest properties have high priority)
2328
                        $cssarray[] = array('k' => '', 's' => '1000', 'c' => $dom[$key]['attribute']['style']);
2329
                }
2330
                // order the css array to account for specificity
2331
                $cssordered = array();
2332
                foreach ($cssarray as $key => $val) {
2333
                        $skey = sprintf('%04d', $key);
2334
                        $cssordered[$val['s'].'_'.$skey] = $val;
2335
                }
2336
                // sort selectors alphabetically to account for specificity
2337
                ksort($cssordered, SORT_STRING);
2338
                return array($selectors, $cssordered);
2339
        }
2340

    
2341
        /**
2342
         * Compact CSS data array into single string.
2343
         * @param $css (array) array of CSS properties
2344
         * @return string containing merged CSS properties
2345
         * @since 5.9.070 (2011-04-19)
2346
         * @public static
2347
         */
2348
        public static function getTagStyleFromCSSarray($css) {
2349
                $tagstyle = ''; // value to be returned
2350
                foreach ($css as $style) {
2351
                        // split single css commands
2352
                        $csscmds = explode(';', $style['c']);
2353
                        foreach ($csscmds as $cmd) {
2354
                                if (!empty($cmd)) {
2355
                                        $pos = strpos($cmd, ':');
2356
                                        if ($pos !== false) {
2357
                                                $cmd = substr($cmd, 0, ($pos + 1));
2358
                                                if (strpos($tagstyle, $cmd) !== false) {
2359
                                                        // remove duplicate commands (last commands have high priority)
2360
                                                        $tagstyle = preg_replace('/'.$cmd.'[^;]+/i', '', $tagstyle);
2361
                                                }
2362
                                        }
2363
                                }
2364
                        }
2365
                        $tagstyle .= ';'.$style['c'];
2366
                }
2367
                // remove multiple semicolons
2368
                $tagstyle = preg_replace('/[;]+/', ';', $tagstyle);
2369
                return $tagstyle;
2370
        }
2371

    
2372
        /**
2373
         * Returns the Roman representation of an integer number
2374
         * @param $number (int) number to convert
2375
         * @return string roman representation of the specified number
2376
         * @since 4.4.004 (2008-12-10)
2377
         * @public static
2378
         */
2379
        public static function intToRoman($number) {
2380
                $roman = '';
2381
                while ($number >= 1000) {
2382
                        $roman .= 'M';
2383
                        $number -= 1000;
2384
                }
2385
                while ($number >= 900) {
2386
                        $roman .= 'CM';
2387
                        $number -= 900;
2388
                }
2389
                while ($number >= 500) {
2390
                        $roman .= 'D';
2391
                        $number -= 500;
2392
                }
2393
                while ($number >= 400) {
2394
                        $roman .= 'CD';
2395
                        $number -= 400;
2396
                }
2397
                while ($number >= 100) {
2398
                        $roman .= 'C';
2399
                        $number -= 100;
2400
                }
2401
                while ($number >= 90) {
2402
                        $roman .= 'XC';
2403
                        $number -= 90;
2404
                }
2405
                while ($number >= 50) {
2406
                        $roman .= 'L';
2407
                        $number -= 50;
2408
                }
2409
                while ($number >= 40) {
2410
                        $roman .= 'XL';
2411
                        $number -= 40;
2412
                }
2413
                while ($number >= 10) {
2414
                        $roman .= 'X';
2415
                        $number -= 10;
2416
                }
2417
                while ($number >= 9) {
2418
                        $roman .= 'IX';
2419
                        $number -= 9;
2420
                }
2421
                while ($number >= 5) {
2422
                        $roman .= 'V';
2423
                        $number -= 5;
2424
                }
2425
                while ($number >= 4) {
2426
                        $roman .= 'IV';
2427
                        $number -= 4;
2428
                }
2429
                while ($number >= 1) {
2430
                        $roman .= 'I';
2431
                        --$number;
2432
                }
2433
                return $roman;
2434
        }
2435

    
2436
        /**
2437
         * Find position of last occurrence of a substring in a string
2438
         * @param $haystack (string) The string to search in.
2439
         * @param $needle (string) substring to search.
2440
         * @param $offset (int) May be specified to begin searching an arbitrary number of characters into the string.
2441
         * @return Returns the position where the needle exists. Returns FALSE if the needle was not found.
2442
         * @since 4.8.038 (2010-03-13)
2443
         * @public static
2444
         */
2445
        public static function revstrpos($haystack, $needle, $offset = 0) {
2446
                $length = strlen($haystack);
2447
                $offset = ($offset > 0)?($length - $offset):abs($offset);
2448
                $pos = strpos(strrev($haystack), strrev($needle), $offset);
2449
                return ($pos === false)?false:($length - $pos - strlen($needle));
2450
        }
2451

    
2452
        /**
2453
         * Serialize an array of parameters to be used with TCPDF tag in HTML code.
2454
         * @param $pararray (array) parameters array
2455
         * @return sting containing serialized data
2456
         * @since 4.9.006 (2010-04-02)
2457
         * @public static
2458
         */
2459
        public static function serializeTCPDFtagParameters($pararray) {
2460
                return urlencode(serialize($pararray));
2461
        }
2462

    
2463
        /**
2464
         * Returns an array of hyphenation patterns.
2465
         * @param $file (string) TEX file containing hypenation patterns. TEX pattrns can be downloaded from http://www.ctan.org/tex-archive/language/hyph-utf8/tex/generic/hyph-utf8/patterns/
2466
         * @return array of hyphenation patterns
2467
         * @author Nicola Asuni
2468
         * @since 4.9.012 (2010-04-12)
2469
         * @public static
2470
         */
2471
        public static function getHyphenPatternsFromTEX($file) {
2472
                // TEX patterns are available at:
2473
                // http://www.ctan.org/tex-archive/language/hyph-utf8/tex/generic/hyph-utf8/patterns/
2474
                $data = file_get_contents($file);
2475
                $patterns = array();
2476
                // remove comments
2477
                $data = preg_replace('/\%[^\n]*/', '', $data);
2478
                // extract the patterns part
2479
                preg_match('/\\\\patterns\{([^\}]*)\}/i', $data, $matches);
2480
                $data = trim(substr($matches[0], 10, -1));
2481
                // extract each pattern
2482
                $patterns_array = preg_split('/[\s]+/', $data);
2483
                // create new language array of patterns
2484
                $patterns = array();
2485
                foreach($patterns_array as $val) {
2486
                        if (!TCPDF_STATIC::empty_string($val)) {
2487
                                $val = trim($val);
2488
                                $val = str_replace('\'', '\\\'', $val);
2489
                                $key = preg_replace('/[0-9]+/', '', $val);
2490
                                $patterns[$key] = $val;
2491
                        }
2492
                }
2493
                return $patterns;
2494
        }
2495

    
2496
        /**
2497
         * Get the Path-Painting Operators.
2498
         * @param $style (string) Style of rendering. Possible values are:
2499
         * <ul>
2500
         *   <li>S or D: Stroke the path.</li>
2501
         *   <li>s or d: Close and stroke the path.</li>
2502
         *   <li>f or F: Fill the path, using the nonzero winding number rule to determine the region to fill.</li>
2503
         *   <li>f* or F*: Fill the path, using the even-odd rule to determine the region to fill.</li>
2504
         *   <li>B or FD or DF: Fill and then stroke the path, using the nonzero winding number rule to determine the region to fill.</li>
2505
         *   <li>B* or F*D or DF*: Fill and then stroke the path, using the even-odd rule to determine the region to fill.</li>
2506
         *   <li>b or fd or df: Close, fill, and then stroke the path, using the nonzero winding number rule to determine the region to fill.</li>
2507
         *   <li>b or f*d or df*: Close, fill, and then stroke the path, using the even-odd rule to determine the region to fill.</li>
2508
         *   <li>CNZ: Clipping mode using the even-odd rule to determine which regions lie inside the clipping path.</li>
2509
         *   <li>CEO: Clipping mode using the nonzero winding number rule to determine which regions lie inside the clipping path</li>
2510
         *   <li>n: End the path object without filling or stroking it.</li>
2511
         * </ul>
2512
         * @param $default (string) default style
2513
         * @author Nicola Asuni
2514
         * @since 5.0.000 (2010-04-30)
2515
         * @public static
2516
         */
2517
        public static function getPathPaintOperator($style, $default='S') {
2518
                $op = '';
2519
                switch($style) {
2520
                        case 'S':
2521
                        case 'D': {
2522
                                $op = 'S';
2523
                                break;
2524
                        }
2525
                        case 's':
2526
                        case 'd': {
2527
                                $op = 's';
2528
                                break;
2529
                        }
2530
                        case 'f':
2531
                        case 'F': {
2532
                                $op = 'f';
2533
                                break;
2534
                        }
2535
                        case 'f*':
2536
                        case 'F*': {
2537
                                $op = 'f*';
2538
                                break;
2539
                        }
2540
                        case 'B':
2541
                        case 'FD':
2542
                        case 'DF': {
2543
                                $op = 'B';
2544
                                break;
2545
                        }
2546
                        case 'B*':
2547
                        case 'F*D':
2548
                        case 'DF*': {
2549
                                $op = 'B*';
2550
                                break;
2551
                        }
2552
                        case 'b':
2553
                        case 'fd':
2554
                        case 'df': {
2555
                                $op = 'b';
2556
                                break;
2557
                        }
2558
                        case 'b*':
2559
                        case 'f*d':
2560
                        case 'df*': {
2561
                                $op = 'b*';
2562
                                break;
2563
                        }
2564
                        case 'CNZ': {
2565
                                $op = 'W n';
2566
                                break;
2567
                        }
2568
                        case 'CEO': {
2569
                                $op = 'W* n';
2570
                                break;
2571
                        }
2572
                        case 'n': {
2573
                                $op = 'n';
2574
                                break;
2575
                        }
2576
                        default: {
2577
                                if (!empty($default)) {
2578
                                        $op = self::getPathPaintOperator($default, '');
2579
                                } else {
2580
                                        $op = '';
2581
                                }
2582
                        }
2583
                }
2584
                return $op;
2585
        }
2586

    
2587
        /**
2588
         * Get the product of two SVG tranformation matrices
2589
         * @param $ta (array) first SVG tranformation matrix
2590
         * @param $tb (array) second SVG tranformation matrix
2591
         * @return transformation array
2592
         * @author Nicola Asuni
2593
         * @since 5.0.000 (2010-05-02)
2594
         * @public static
2595
         */
2596
        public static function getTransformationMatrixProduct($ta, $tb) {
2597
                $tm = array();
2598
                $tm[0] = ($ta[0] * $tb[0]) + ($ta[2] * $tb[1]);
2599
                $tm[1] = ($ta[1] * $tb[0]) + ($ta[3] * $tb[1]);
2600
                $tm[2] = ($ta[0] * $tb[2]) + ($ta[2] * $tb[3]);
2601
                $tm[3] = ($ta[1] * $tb[2]) + ($ta[3] * $tb[3]);
2602
                $tm[4] = ($ta[0] * $tb[4]) + ($ta[2] * $tb[5]) + $ta[4];
2603
                $tm[5] = ($ta[1] * $tb[4]) + ($ta[3] * $tb[5]) + $ta[5];
2604
                return $tm;
2605
        }
2606

    
2607
        /**
2608
         * Get the tranformation matrix from SVG transform attribute
2609
         * @param $attribute (string) transformation
2610
         * @return array of transformations
2611
         * @author Nicola Asuni
2612
         * @since 5.0.000 (2010-05-02)
2613
         * @public static
2614
         */
2615
        public static function getSVGTransformMatrix($attribute) {
2616
                // identity matrix
2617
                $tm = array(1, 0, 0, 1, 0, 0);
2618
                $transform = array();
2619
                if (preg_match_all('/(matrix|translate|scale|rotate|skewX|skewY)[\s]*\(([^\)]+)\)/si', $attribute, $transform, PREG_SET_ORDER) > 0) {
2620
                        foreach ($transform as $key => $data) {
2621
                                if (!empty($data[2])) {
2622
                                        $a = 1;
2623
                                        $b = 0;
2624
                                        $c = 0;
2625
                                        $d = 1;
2626
                                        $e = 0;
2627
                                        $f = 0;
2628
                                        $regs = array();
2629
                                        switch ($data[1]) {
2630
                                                case 'matrix': {
2631
                                                        if (preg_match('/([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)/si', $data[2], $regs)) {
2632
                                                                $a = $regs[1];
2633
                                                                $b = $regs[2];
2634
                                                                $c = $regs[3];
2635
                                                                $d = $regs[4];
2636
                                                                $e = $regs[5];
2637
                                                                $f = $regs[6];
2638
                                                        }
2639
                                                        break;
2640
                                                }
2641
                                                case 'translate': {
2642
                                                        if (preg_match('/([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)/si', $data[2], $regs)) {
2643
                                                                $e = $regs[1];
2644
                                                                $f = $regs[2];
2645
                                                        } elseif (preg_match('/([a-z0-9\-\.]+)/si', $data[2], $regs)) {
2646
                                                                $e = $regs[1];
2647
                                                        }
2648
                                                        break;
2649
                                                }
2650
                                                case 'scale': {
2651
                                                        if (preg_match('/([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)/si', $data[2], $regs)) {
2652
                                                                $a = $regs[1];
2653
                                                                $d = $regs[2];
2654
                                                        } elseif (preg_match('/([a-z0-9\-\.]+)/si', $data[2], $regs)) {
2655
                                                                $a = $regs[1];
2656
                                                                $d = $a;
2657
                                                        }
2658
                                                        break;
2659
                                                }
2660
                                                case 'rotate': {
2661
                                                        if (preg_match('/([0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)/si', $data[2], $regs)) {
2662
                                                                $ang = deg2rad($regs[1]);
2663
                                                                $x = $regs[2];
2664
                                                                $y = $regs[3];
2665
                                                                $a = cos($ang);
2666
                                                                $b = sin($ang);
2667
                                                                $c = -$b;
2668
                                                                $d = $a;
2669
                                                                $e = ($x * (1 - $a)) - ($y * $c);
2670
                                                                $f = ($y * (1 - $d)) - ($x * $b);
2671
                                                        } elseif (preg_match('/([0-9\-\.]+)/si', $data[2], $regs)) {
2672
                                                                $ang = deg2rad($regs[1]);
2673
                                                                $a = cos($ang);
2674
                                                                $b = sin($ang);
2675
                                                                $c = -$b;
2676
                                                                $d = $a;
2677
                                                                $e = 0;
2678
                                                                $f = 0;
2679
                                                        }
2680
                                                        break;
2681
                                                }
2682
                                                case 'skewX': {
2683
                                                        if (preg_match('/([0-9\-\.]+)/si', $data[2], $regs)) {
2684
                                                                $c = tan(deg2rad($regs[1]));
2685
                                                        }
2686
                                                        break;
2687
                                                }
2688
                                                case 'skewY': {
2689
                                                        if (preg_match('/([0-9\-\.]+)/si', $data[2], $regs)) {
2690
                                                                $b = tan(deg2rad($regs[1]));
2691
                                                        }
2692
                                                        break;
2693
                                                }
2694
                                        }
2695
                                        $tm = self::getTransformationMatrixProduct($tm, array($a, $b, $c, $d, $e, $f));
2696
                                }
2697
                        }
2698
                }
2699
                return $tm;
2700
        }
2701

    
2702
        /**
2703
         * Returns the angle in radiants between two vectors
2704
         * @param $x1 (int) X coordinate of first vector point
2705
         * @param $y1 (int) Y coordinate of first vector point
2706
         * @param $x2 (int) X coordinate of second vector point
2707
         * @param $y2 (int) Y coordinate of second vector point
2708
         * @author Nicola Asuni
2709
         * @since 5.0.000 (2010-05-04)
2710
         * @public static
2711
         */
2712
        public static function getVectorsAngle($x1, $y1, $x2, $y2) {
2713
                $dprod = ($x1 * $x2) + ($y1 * $y2);
2714
                $dist1 = sqrt(($x1 * $x1) + ($y1 * $y1));
2715
                $dist2 = sqrt(($x2 * $x2) + ($y2 * $y2));
2716
                $angle = acos($dprod / ($dist1 * $dist2));
2717
                if (is_nan($angle)) {
2718
                        $angle = M_PI;
2719
                }
2720
                if ((($x1 * $y2) - ($x2 * $y1)) < 0) {
2721
                        $angle *= -1;
2722
                }
2723
                return $angle;
2724
        }
2725

    
2726
        /**
2727
         * Split string by a regular expression.
2728
         * This is a wrapper for the preg_split function to avoid the bug: https://bugs.php.net/bug.php?id=45850
2729
         * @param $pattern (string) The regular expression pattern to search for without the modifiers, as a string.
2730
         * @param $modifiers (string) The modifiers part of the pattern,
2731
         * @param $subject (string) The input string.
2732
         * @param $limit (int) If specified, then only substrings up to limit are returned with the rest of the string being placed in the last substring. A limit of -1, 0 or NULL means "no limit" and, as is standard across PHP, you can use NULL to skip to the flags parameter.
2733
         * @param $flags (int) The flags as specified on the preg_split PHP function.
2734
         * @return Returns an array containing substrings of subject split along boundaries matched by pattern.modifier
2735
         * @author Nicola Asuni
2736
         * @since 6.0.023
2737
         * @public static
2738
         */
2739
        public static function pregSplit($pattern, $modifiers, $subject, $limit=NULL, $flags=NULL) {
2740
                // the bug only happens on PHP 5.2 when using the u modifier
2741
                if ((strpos($modifiers, 'u') === FALSE) OR (count(preg_split('//u', "\n\t", -1, PREG_SPLIT_NO_EMPTY)) == 2)) {
2742
                        return preg_split($pattern.$modifiers, $subject, $limit, $flags);
2743
                }
2744
                // preg_split is bugged - try alternative solution
2745
                $ret = array();
2746
                while (($nl = strpos($subject, "\n")) !== FALSE) {
2747
                        $ret = array_merge($ret, preg_split($pattern.$modifiers, substr($subject, 0, $nl), $limit, $flags));
2748
                        $ret[] = "\n";
2749
                        $subject = substr($subject, ($nl + 1));
2750
                }
2751
                if (strlen($subject) > 0) {
2752
                        $ret = array_merge($ret, preg_split($pattern.$modifiers, $subject, $limit, $flags));
2753
                }
2754
                return $ret;
2755
        }
2756

    
2757
        /**
2758
         * Reads entire file into a string.
2759
         * The file can be also an URL.
2760
         * @param $file (string) Name of the file or URL to read.
2761
         * @return The function returns the read data or FALSE on failure. 
2762
         * @author Nicola Asuni
2763
         * @since 6.0.025
2764
         * @public static
2765
         */
2766
        public static function fileGetContents($file) {
2767
                // array of possible alternative paths/URLs
2768
                $alt = array($file);
2769
                // replace URL relative path with full real server path
2770
                if ((strlen($file) > 1)
2771
                        AND ($file[0] == '/')
2772
                        AND ($file[1] != '/')
2773
                        AND !empty($_SERVER['DOCUMENT_ROOT'])
2774
                        AND ($_SERVER['DOCUMENT_ROOT'] != '/')) {
2775
                        $findroot = strpos($file, $_SERVER['DOCUMENT_ROOT']);
2776
                        if (($findroot === false) OR ($findroot > 1)) {
2777
                                if (substr($_SERVER['DOCUMENT_ROOT'], -1) == '/') {
2778
                                        $tmp = substr($_SERVER['DOCUMENT_ROOT'], 0, -1).$file;
2779
                                } else {
2780
                                        $tmp = $_SERVER['DOCUMENT_ROOT'].$file;
2781
                                }
2782
                                $alt[] = htmlspecialchars_decode(urldecode($tmp));
2783
                        }
2784
                }
2785
                // URL mode
2786
                $url = $file;
2787
                // check for missing protocol
2788
                if (preg_match('%^/{2}%', $url)) {
2789
                        if (preg_match('%^([^:]+:)//%i', K_PATH_URL, $match)) {
2790
                                $url = $match[1].str_replace(' ', '%20', $url);
2791
                                $alt[] = $url;
2792
                        }
2793
                }
2794
                $urldata = @parse_url($url);
2795
                if (!isset($urldata['query']) OR (strlen($urldata['query']) <= 0)) {
2796
                        if (strpos($url, K_PATH_URL) === 0) {
2797
                                // convert URL to full server path
2798
                                $tmp = str_replace(K_PATH_URL, K_PATH_MAIN, $url);
2799
                                $tmp = htmlspecialchars_decode(urldecode($tmp));
2800
                                $alt[] = $tmp;
2801
                        }
2802
                }
2803
                foreach ($alt as $f) {
2804
                        $ret = @file_get_contents($f);
2805
                        if (($ret === FALSE)
2806
                                AND !ini_get('allow_url_fopen')
2807
                                AND function_exists('curl_init')
2808
                                AND preg_match('%^(https?|ftp)://%', $f)) {
2809
                                // try to get remote file data using cURL
2810
                                $cs = curl_init(); // curl session
2811
                                curl_setopt($cs, CURLOPT_URL, $file);
2812
                                curl_setopt($cs, CURLOPT_BINARYTRANSFER, true);
2813
                                curl_setopt($cs, CURLOPT_FAILONERROR, true);
2814
                                curl_setopt($cs, CURLOPT_RETURNTRANSFER, true);
2815
                                if ((ini_get('open_basedir') == '') AND (!ini_get('safe_mode'))) {
2816
                                        curl_setopt($cs, CURLOPT_FOLLOWLOCATION, true);
2817
                                }
2818
                                curl_setopt($cs, CURLOPT_CONNECTTIMEOUT, 5);
2819
                                curl_setopt($cs, CURLOPT_TIMEOUT, 30);
2820
                                curl_setopt($cs, CURLOPT_SSL_VERIFYPEER, false);
2821
                                curl_setopt($cs, CURLOPT_SSL_VERIFYHOST, false);
2822
                                curl_setopt($cs, CURLOPT_USERAGENT, 'TCPDF');
2823
                                $ret = curl_exec($cs);
2824
                                curl_close($cs);
2825
                        }
2826
                        if ($ret !== FALSE) {
2827
                                break;
2828
                        }
2829
                }
2830
                return $ret;
2831
        }
2832

    
2833
} // END OF TCPDF_STATIC CLASS
2834

    
2835
//============================================================+
2836
// END OF FILE
2837
//============================================================+