~ubuntu-branches/ubuntu/trusty/phpmyadmin/trusty

« back to all changes in this revision

Viewing changes to libraries/tcpdf/tcpdf.php

  • Committer: Bazaar Package Importer
  • Author(s): Thijs Kinkhorst
  • Date: 2009-02-16 17:58:28 UTC
  • mfrom: (13.1.4 jaunty)
  • Revision ID: james.westby@ubuntu.com-20090216175828-d2dllrukk9kecv4k
Tags: 4:3.1.2-2
* Upload to unstable.
* [INTL:es] Spanish debconf template update (Closes: #513690).

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
//============================================================+
3
3
// File name   : tcpdf.php
4
4
// Begin       : 2002-08-03
5
 
// Last Update : 2006-10-27
 
5
// Last Update : 2008-02-28
6
6
// Author      : Nicola Asuni
7
 
// Version     : 1.53.0.TC026_PHP4
 
7
// Version     : 2.2.002
8
8
// License     : GNU LGPL (http://www.gnu.org/copyleft/lesser.html)
9
9
//
10
 
// Description : This is a PHP4 class for generating PDF files 
 
10
// Description : This is a PHP5 class for generating PDF files 
11
11
//               on-the-fly without requiring external 
12
12
//               extensions.
13
13
//
14
14
// IMPORTANT:
15
 
// This class is an extension and improvement of the public Domain 
16
 
// FPDF class by Olivier Plathey (http://www.fpdf.org).
17
 
//
18
 
// Main changes by Nicola Asuni:
19
 
//    PHP4 porting;
20
 
//    UTF-8 Unicode support;
21
 
//    code refactoring;
22
 
//    source code clean up;
23
 
//    code style and formatting;
24
 
//    source code documentation using phpDocumentor (www.phpdoc.org);
25
 
//    All ISO page formats were included;
26
 
//    image scale factor;
27
 
//    includes methods to parse and printsome XHTML code, supporting the following elements: h1, h2, h3, h4, h5, h6, b, u, i, a, img, p, br, strong, em, font, blockquote, li, ul, ol, hr, td, th, tr, table, sup, sub, small;
28
 
//    includes a method to print various barcode formats using an improved version of "Generic Barcode Render Class" by Karim Mribti (http://www.mribti.com/barcode/) (require GD library: http://www.boutell.com/gd/);
29
 
//    defines standard Header() and Footer() methods.
 
15
// This class was originally derived in 2002 from the Public 
 
16
// Domain FPDF class by Olivier Plathey (http://www.fpdf.org).
 
17
//
 
18
// Main features:
 
19
//  - supports all ISO page formats; 
 
20
//  - supports UTF-8 Unicode and Right-To-Left languages; 
 
21
//  - supports document encryption; 
 
22
//  - includes methods to publish some xhtml code; 
 
23
//  - includes graphic and transformation methods;
 
24
//  - includes bookmarks;
 
25
//  - includes Javascript and forms support;
 
26
//  - includes a method to print various barcode formats using an improved version of "Generic Barcode Render Class" by Karim Mribti (http://www.mribti.com/barcode/) (require GD library: http://www.boutell.com/gd/) 
 
27
//  - supports TrueTypeUnicode, TrueType, Type1 and encoding; 
 
28
//  - supports custom page formats, margins and units of measure; 
 
29
//  - includes methods for page header and footer management; 
 
30
//  - supports automatic page break; 
 
31
//  - supports automatic page numbering; 
 
32
//  - supports automatic line break and text justification; 
 
33
//  - supports JPEG, PNG anf GIF images; 
 
34
//  - supports colors; 
 
35
//  - supports links; 
 
36
//  - support page compression (require zlib extension: http://www.gzip.org/zlib/); 
 
37
//  - the source code is full documented in PhpDocumentor Style (http://www.phpdoc.org). 
 
38
//
 
39
// -----------------------------------------------------------
 
40
// THANKS TO:
 
41
// 
 
42
// Olivier Plathey (http://www.fpdf.org) for original FPDF.
 
43
// Efthimios Mavrogeorgiadis (emavro@yahoo.com) for suggestions on RTL language support.
 
44
// Klemen Vodopivec (http://www.fpdf.de/downloads/addons/37/) for Encryption algorithm.
 
45
// Warren Sherliker (wsherliker@gmail.com) for better image handling.
 
46
// dullus for text Justification.
 
47
// Bob Vincent (pillarsdotnet@users.sourceforge.net) for <li> value attribute.
 
48
// Patrick Benny for text stretch suggestion on Cell().
 
49
// Johannes G�ntert for JavaScript support.
 
50
// Denis Van Nuffelen for Dynamic Form.
 
51
// Jacek Czekaj for multibyte justification
 
52
// Anthony Ferrara for the reintroduction of legacy image methods.
 
53
// Anyone that has reported a bug or sent a suggestion.
30
54
//============================================================+
31
55
 
32
 
/**
33
 
 * include configuration file
34
 
 */
35
 
// Disabled in phpMyAdmin
36
 
//require_once(dirname(__FILE__).'/config/tcpdf_config.php');
37
 
 
38
 
 
39
 
/**
40
 
 * TCPDF Class.
41
 
 * @package com.tecnick.tcpdf
42
 
 */
43
 
 
44
 
/**
45
 
 * This is a PHP4 class for generating PDF files on-the-fly without requiring external extensions.<br>
46
 
 * TCPDF project (http://tcpdf.sourceforge.net) is based on the public Domain FPDF class by Olivier Plathey (http://www.fpdf.org).<br>
47
 
 * <h3>TCPDF main changes from FPDF are:</h3><ul>
48
 
 * <li>PHP4 porting</li>
49
 
 * <li>UTF-8 Unicode support</li>
50
 
 * <li>source code clean up</li>
51
 
 * <li>code style and formatting</li>
52
 
 * <li>source code documentation using phpDocumentor (www.phpdoc.org)</li>
53
 
 * <li>All ISO page formats were included</li>
54
 
 * <li>image scale factor</li>
55
 
 * <li>includes methods to parse and printsome XHTML code, supporting the following elements: h1, h2, h3, h4, h5, h6, b, u, i, a, img, p, br, strong, em, font, blockquote, li, ul, ol, hr, td, th, tr, table, sup, sub, small;</li>
56
 
 * <li>includes a method to print various barcode formats using an improved version of "Generic Barcode Render Class" by Karim Mribti (http://www.mribti.com/barcode/) (require GD library: http://www.boutell.com/gd/)</li>
57
 
 * <li>defines standard Header() and Footer() methods.</li>
 
56
 
 
57
 
 
58
/**
 
59
 * This is a PHP5 class for generating PDF files on-the-fly without requiring external extensions.<br>
 
60
 * TCPDF project (http://tcpdf.sourceforge.net) has been originally derived from the Public Domain FPDF class by Olivier Plathey (http://www.fpdf.org).<br>
 
61
 * <h3>TCPDF main features are:</h3>
 
62
 * <ul>
 
63
 * <li>supports all ISO page formats;</li>
 
64
 * <li>supports UTF-8 Unicode and Right-To-Left languages;</li>
 
65
 * <li>supports document encryption;</li>
 
66
 * <li>includes methods to publish some xhtml code, supporting the following elements: h1, h2, h3, h4, h5, h6, b, u, i, a, img, p, br, strong, em, font, blockquote, li, ul, ol, hr, td, th, tr, table, sup, sub, small;</li>
 
67
 * <li>includes a method to print various barcode formats using an improved version of "Generic Barcode Render Class" by Karim Mribti (<a href="http://www.mribti.com/barcode/" target="_blank" title="Generic Barcode Render Class by Karim Mribti">http://www.mribti.com/barcode/</a>) (require GD library: <a href="http://www.boutell.com/gd/" target="_blank" title="GD library">http://www.boutell.com/gd/</a>)</li>
 
68
 * <li>supports TrueTypeUnicode, TrueType, Type1 and encoding; </li>
 
69
 * <li>supports custom page formats, margins and units of measure;</li>
 
70
 * <li>includes methods for page header and footer management;</li>
 
71
 * <li>supports automatic page break;</li>
 
72
 * <li>supports automatic page numbering;</li>
 
73
 * <li>supports automatic line break and text justification;</li>
 
74
 * <li>supports JPEG, PNG anf GIF images;</li>
 
75
 * <li>supports colors;</li>
 
76
 * <li>supports links;</li>
 
77
 * <li>support page compression (require zlib extension: <a href="http://www.gzip.org/zlib/" target="_blank" title="zlib">http://www.gzip.org/zlib/</a>);</li>
 
78
 * <li>the source code is full documented in PhpDocumentor Style (<a href="http://www.phpdoc.org" target="_blank" title="phpDocumentor">http://www.phpdoc.org</a>).</li>
58
79
 * </ul>
59
80
 * Tools to encode your unicode fonts are on fonts/ttf2ufm directory.</p>
60
81
 * @name TCPDF
61
82
 * @package com.tecnick.tcpdf
62
83
 * @abstract Class for generating PDF files on-the-fly without requiring external extensions.
63
84
 * @author Nicola Asuni
64
 
 * @copyright 2004-2006 Tecnick.com S.r.l (www.tecnick.com) Via Ugo Foscolo n.19 - 09045 Quartu Sant'Elena (CA) - ITALY - www.tecnick.com - info@tecnick.com
 
85
 * @copyright 2004-2008 Nicola Asuni - Tecnick.com S.r.l (www.tecnick.com) Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com
65
86
 * @link http://tcpdf.sourceforge.net
66
87
 * @license http://www.gnu.org/copyleft/lesser.html LGPL
67
 
 @version 1.53.0.TC026_PHP4
68
 
 */
69
 
 
70
 
if(!class_exists('TCPDF')) {
 
88
 * @version 2.2.002
 
89
 */
 
90
 
 
91
/**
 
92
 * include configuration file
 
93
 * (Disabled in phpMyAdmin)
 
94
 */
 
95
//require_once(dirname(__FILE__).'/config/tcpdf_config.php');
 
96
 
 
97
if(!class_exists('TCPDF', false)) {
71
98
        /**
72
99
         * define default PDF document producer
73
100
         */ 
74
 
        define('PDF_PRODUCER','TCPDF 1.53.0.TC026_PHP4 (http://tcpdf.sourceforge.net)');
 
101
        define('PDF_PRODUCER','TCPDF 2.2.002 (http://tcpdf.sf.net)');
75
102
        
76
103
        /**
77
 
        * This is a PHP4 class for generating PDF files on-the-fly without requiring external extensions.<br>
78
 
        * This class is an extension and improvement of the FPDF class by Olivier Plathey (http://www.fpdf.org).<br>
79
 
        * This version contains some changes: [porting to PHP4, support for UTF-8 Unicode, code style and formatting, php documentation (www.phpdoc.org), ISO page formats, minor improvements, image scale factor]<br>
80
 
        * TCPDF project (http://tcpdf.sourceforge.net) is based on the public Domain FPDF class by Olivier Plathey (http://www.fpdf.org).<br>
 
104
        * This is a PHP5 class for generating PDF files on-the-fly without requiring external extensions.<br>
 
105
        * TCPDF project (http://tcpdf.sourceforge.net) has been originally derived from the Public Domain FPDF class by Olivier Plathey (http://www.fpdf.org).<br>
81
106
        * To add your own TTF fonts please read /fonts/README.TXT
82
107
        * @name TCPDF
83
108
        * @package com.tecnick.tcpdf
84
 
        * @version 1.53.0.TC026_PHP4
 
109
        * @version 2.2.002
85
110
        * @author Nicola Asuni
86
111
        * @link http://tcpdf.sourceforge.net
87
112
        * @license http://www.gnu.org/copyleft/lesser.html LGPL
88
113
        */
89
114
        class TCPDF {
90
 
                //var properties
 
115
                
 
116
                // Private or Protected properties
91
117
 
92
118
                /**
93
119
                * @var current page number
94
120
                * @access protected
95
121
                */
96
 
                var $page;
97
 
 
 
122
                protected $page;
 
123
                
98
124
                /**
99
125
                * @var current object number
100
126
                * @access protected
101
127
                */
102
 
                var $n;
 
128
                protected $n;
103
129
 
104
130
                /**
105
131
                * @var array of object offsets
106
132
                * @access protected
107
133
                */
108
 
                var $offsets;
 
134
                protected $offsets;
109
135
 
110
136
                /**
111
137
                * @var buffer holding in-memory PDF
112
138
                * @access protected
113
139
                */
114
 
                var $buffer;
 
140
                protected $buffer;
115
141
 
116
142
                /**
117
143
                * @var array containing pages
118
144
                * @access protected
119
145
                */
120
 
                var $pages;
 
146
                protected $pages;
121
147
 
122
148
                /**
123
149
                * @var current document state
124
150
                * @access protected
125
151
                */
126
 
                var $state;
 
152
                protected $state;
127
153
 
128
154
                /**
129
155
                * @var compression flag
130
156
                * @access protected
131
157
                */
132
 
                var $compress;
133
 
 
134
 
                /**
135
 
                * @var default orientation
136
 
                * @access protected
137
 
                */
138
 
                var $DefOrientation;
139
 
 
140
 
                /**
141
 
                * @var current orientation
142
 
                * @access protected
143
 
                */
144
 
                var $CurOrientation;
145
 
 
146
 
                /**
147
 
                * @var array indicating orientation changes
148
 
                * @access protected
149
 
                */
150
 
                var $OrientationChanges;
 
158
                protected $compress;
 
159
 
 
160
                /**
 
161
                * @var default page orientation (P = Portrait, L = Landscape)
 
162
                * @access protected
 
163
                */
 
164
                protected $DefOrientation;
 
165
 
 
166
                /**
 
167
                * @var current page orientation (P = Portrait, L = Landscape)
 
168
                * @access protected
 
169
                */
 
170
                protected $CurOrientation;
 
171
 
 
172
                /**
 
173
                * @var array indicating page orientation changes
 
174
                * @access protected
 
175
                */
 
176
                protected $OrientationChanges;
151
177
 
152
178
                /**
153
179
                * @var scale factor (number of points in user unit)
154
180
                * @access protected
155
181
                */
156
 
                var $k;
 
182
                protected $k;
157
183
 
158
184
                /**
159
185
                * @var width of page format in points
160
186
                * @access protected
161
187
                */
162
 
                var $fwPt;
 
188
                protected $fwPt;
163
189
 
164
190
                /**
165
191
                * @var height of page format in points
166
192
                * @access protected
167
193
                */
168
 
                var $fhPt;
 
194
                protected $fhPt;
169
195
 
170
196
                /**
171
197
                * @var width of page format in user unit
172
198
                * @access protected
173
199
                */
174
 
                var $fw;
 
200
                protected $fw;
175
201
 
176
202
                /**
177
203
                * @var height of page format in user unit
178
204
                * @access protected
179
205
                */
180
 
                var $fh;
 
206
                protected $fh;
181
207
 
182
208
                /**
183
209
                * @var current width of page in points
184
210
                * @access protected
185
211
                */
186
 
                var $wPt;
 
212
                protected $wPt;
187
213
 
188
214
                /**
189
215
                * @var current height of page in points
190
216
                * @access protected
191
217
                */
192
 
                var $hPt;
 
218
                protected $hPt;
193
219
 
194
220
                /**
195
221
                * @var current width of page in user unit
196
222
                * @access protected
197
223
                */
198
 
                var $w;
 
224
                protected $w;
199
225
 
200
226
                /**
201
227
                * @var current height of page in user unit
202
228
                * @access protected
203
229
                */
204
 
                var $h;
 
230
                protected $h;
205
231
 
206
232
                /**
207
233
                * @var left margin
208
234
                * @access protected
209
235
                */
210
 
                var $lMargin;
 
236
                protected $lMargin;
211
237
 
212
238
                /**
213
239
                * @var top margin
214
240
                * @access protected
215
241
                */
216
 
                var $tMargin;
 
242
                protected $tMargin;
217
243
 
218
244
                /**
219
245
                * @var right margin
220
246
                * @access protected
221
247
                */
222
 
                var $rMargin;
 
248
                protected $rMargin;
223
249
 
224
250
                /**
225
251
                * @var page break margin
226
252
                * @access protected
227
253
                */
228
 
                var $bMargin;
 
254
                protected $bMargin;
229
255
 
230
256
                /**
231
 
                * @var cell margin
 
257
                * @var cell internal padding
232
258
                * @access protected
233
259
                */
234
 
                var $cMargin;
 
260
                protected $cMargin;
235
261
 
236
262
                /**
237
263
                * @var current horizontal position in user unit for cell positioning
238
264
                * @access protected
239
265
                */
240
 
                var $x;
 
266
                protected $x;
241
267
 
242
268
                /**
243
269
                * @var current vertical position in user unit for cell positioning
244
270
                * @access protected
245
271
                */
246
 
                var $y;
 
272
                protected $y;
247
273
 
248
274
                /**
249
275
                * @var height of last cell printed
250
276
                * @access protected
251
277
                */
252
 
                var $lasth;
 
278
                protected $lasth;
253
279
 
254
280
                /**
255
281
                * @var line width in user unit
256
282
                * @access protected
257
283
                */
258
 
                var $LineWidth;
 
284
                protected $LineWidth;
259
285
 
260
286
                /**
261
287
                * @var array of standard font names
262
288
                * @access protected
263
289
                */
264
 
                var $CoreFonts;
 
290
                protected $CoreFonts;
265
291
 
266
292
                /**
267
293
                * @var array of used fonts
268
294
                * @access protected
269
295
                */
270
 
                var $fonts;
 
296
                protected $fonts;
271
297
 
272
298
                /**
273
299
                * @var array of font files
274
300
                * @access protected
275
301
                */
276
 
                var $FontFiles;
 
302
                protected $FontFiles;
277
303
 
278
304
                /**
279
305
                * @var array of encoding differences
280
306
                * @access protected
281
307
                */
282
 
                var $diffs;
 
308
                protected $diffs;
283
309
 
284
310
                /**
285
311
                * @var array of used images
286
312
                * @access protected
287
313
                */
288
 
                var $images;
 
314
                protected $images;
289
315
 
290
316
                /**
291
317
                * @var array of links in pages
292
318
                * @access protected
293
319
                */
294
 
                var $PageLinks;
 
320
                protected $PageLinks;
295
321
 
296
322
                /**
297
323
                * @var array of internal links
298
324
                * @access protected
299
325
                */
300
 
                var $links;
 
326
                protected $links;
301
327
 
302
328
                /**
303
329
                * @var current font family
304
330
                * @access protected
305
331
                */
306
 
                var $FontFamily;
 
332
                protected $FontFamily;
307
333
 
308
334
                /**
309
335
                * @var current font style
310
336
                * @access protected
311
337
                */
312
 
                var $FontStyle;
 
338
                protected $FontStyle;
313
339
 
314
340
                /**
315
341
                * @var underlining flag
316
342
                * @access protected
317
343
                */
318
 
                var $underline;
 
344
                protected $underline;
319
345
 
320
346
                /**
321
347
                * @var current font info
322
348
                * @access protected
323
349
                */
324
 
                var $CurrentFont;
 
350
                protected $CurrentFont;
325
351
 
326
352
                /**
327
353
                * @var current font size in points
328
354
                * @access protected
329
355
                */
330
 
                var $FontSizePt;
 
356
                protected $FontSizePt;
331
357
 
332
358
                /**
333
359
                * @var current font size in user unit
334
360
                * @access protected
335
361
                */
336
 
                var $FontSize;
 
362
                protected $FontSize;
337
363
 
338
364
                /**
339
365
                * @var commands for drawing color
340
366
                * @access protected
341
367
                */
342
 
                var $DrawColor;
 
368
                protected $DrawColor;
343
369
 
344
370
                /**
345
371
                * @var commands for filling color
346
372
                * @access protected
347
373
                */
348
 
                var $FillColor;
 
374
                protected $FillColor;
349
375
 
350
376
                /**
351
377
                * @var commands for text color
352
378
                * @access protected
353
379
                */
354
 
                var $TextColor;
 
380
                protected $TextColor;
355
381
 
356
382
                /**
357
383
                * @var indicates whether fill and text colors are different
358
384
                * @access protected
359
385
                */
360
 
                var $ColorFlag;
 
386
                protected $ColorFlag;
361
387
 
362
388
                /**
363
389
                * @var word spacing
364
390
                * @access protected
365
391
                */
366
 
                var $ws;
 
392
                protected $ws;
367
393
 
368
394
                /**
369
395
                * @var automatic page breaking
370
396
                * @access protected
371
397
                */
372
 
                var $AutoPageBreak;
 
398
                protected $AutoPageBreak;
373
399
 
374
400
                /**
375
401
                * @var threshold used to trigger page breaks
376
402
                * @access protected
377
403
                */
378
 
                var $PageBreakTrigger;
 
404
                protected $PageBreakTrigger;
379
405
 
380
406
                /**
381
407
                * @var flag set when processing footer
382
408
                * @access protected
383
409
                */
384
 
                var $InFooter;
 
410
                protected $InFooter;
385
411
 
386
412
                /**
387
413
                * @var zoom display mode
388
414
                * @access protected
389
415
                */
390
 
                var $ZoomMode;
 
416
                protected $ZoomMode;
391
417
 
392
418
                /**
393
419
                * @var layout display mode
394
420
                * @access protected
395
421
                */
396
 
                var $LayoutMode;
 
422
                protected $LayoutMode;
397
423
 
398
424
                /**
399
425
                * @var title
400
426
                * @access protected
401
427
                */
402
 
                var $title;
 
428
                protected $title;
403
429
 
404
430
                /**
405
431
                * @var subject
406
432
                * @access protected
407
433
                */
408
 
                var $subject;
 
434
                protected $subject;
409
435
 
410
436
                /**
411
437
                * @var author
412
438
                * @access protected
413
439
                */
414
 
                var $author;
 
440
                protected $author;
415
441
 
416
442
                /**
417
443
                * @var keywords
418
444
                * @access protected
419
445
                */
420
 
                var $keywords;
 
446
                protected $keywords;
421
447
 
422
448
                /**
423
449
                * @var creator
424
450
                * @access protected
425
451
                */
426
 
                var $creator;
 
452
                protected $creator;
427
453
 
428
454
                /**
429
455
                * @var alias for total number of pages
430
456
                * @access protected
431
457
                */
432
 
                var $AliasNbPages;
 
458
                protected $AliasNbPages;
433
459
 
434
460
                /**
435
461
                * @var right-bottom corner X coordinate of inserted image
437
463
                * @author Nicola Asuni
438
464
                * @access protected
439
465
                */
440
 
                var $img_rb_x;
 
466
                protected $img_rb_x;
441
467
 
442
468
                /**
443
469
                * @var right-bottom corner Y coordinate of inserted image
445
471
                * @author Nicola Asuni
446
472
                * @access protected
447
473
                */
448
 
                var $img_rb_y;
 
474
                protected $img_rb_y;
449
475
 
450
476
                /**
451
477
                * @var image scale factor
453
479
                * @author Nicola Asuni
454
480
                * @access protected
455
481
                */
456
 
                var $imgscale = 1;
 
482
                protected $imgscale = 1;
457
483
 
458
484
                /**
459
485
                * @var boolean set to true when the input text is unicode (require unicode fonts)
461
487
                * @author Nicola Asuni
462
488
                * @access protected
463
489
                */
464
 
                var $isunicode = false;
 
490
                protected $isunicode = false;
465
491
 
466
492
                /**
467
493
                * @var PDF version
468
494
                * @since 1.5.3
469
495
                * @access protected
470
496
                */
471
 
                var $PDFVersion = "1.3";
 
497
                protected $PDFVersion = "1.5";
472
498
                
473
499
                
474
500
                // ----------------------
477
503
                 * @var Minimum distance between header and top page margin.
478
504
                 * @access private
479
505
                 */
480
 
                var $header_margin;
 
506
                private $header_margin;
481
507
                
482
508
                /**
483
509
                 * @var Minimum distance between footer and bottom page margin.
484
510
                 * @access private
485
511
                 */
486
 
                var $footer_margin;
 
512
                private $footer_margin;
487
513
                
488
514
                /**
489
515
                 * @var original left margin value
490
516
                 * @access private
491
517
                 * @since 1.53.0.TC013
492
518
                 */
493
 
                var $original_lMargin;
 
519
                private $original_lMargin;
494
520
                
495
521
                /**
496
522
                 * @var original right margin value
497
523
                 * @access private
498
524
                 * @since 1.53.0.TC013
499
525
                 */
500
 
                var $original_rMargin;
 
526
                private $original_rMargin;
501
527
                        
502
528
                /**
503
529
                 * @var Header font.
504
530
                 * @access private
505
531
                 */
506
 
                var $header_font;
 
532
                private $header_font;
507
533
                
508
534
                /**
509
535
                 * @var Footer font.
510
536
                 * @access private
511
537
                 */
512
 
                var $footer_font;
 
538
                private $footer_font;
513
539
                
514
540
                /**
515
541
                 * @var Language templates.
516
542
                 * @access private
517
543
                 */
518
 
                var $l;
 
544
                private $l;
519
545
                
520
546
                /**
521
547
                 * @var Barcode to print on page footer (only if set).
522
548
                 * @access private
523
549
                 */
524
 
                var $barcode = false;
 
550
                private $barcode = false;
525
551
                
526
552
                /**
527
553
                 * @var If true prints header
528
554
                 * @access private
529
555
                 */
530
 
                var $print_header = true;
 
556
                private $print_header = true;
531
557
                
532
558
                /**
533
559
                 * @var If true prints footer.
534
560
                 * @access private
535
561
                 */
536
 
                var $print_footer = true;
 
562
                private $print_footer = true;
537
563
                
538
564
                /**
539
565
                 * @var Header width (0 = full page width).
540
566
                 * @access private
541
567
                 */
542
 
                var $header_width = 0;
 
568
                private $header_width = 0;
543
569
                
544
570
                /**
545
571
                 * @var Header image logo.
546
572
                 * @access private
547
573
                 */
548
 
                var $header_logo = "";
 
574
                private $header_logo = "";
549
575
                
550
576
                /**
551
577
                 * @var Header image logo width in mm.
552
578
                 * @access private
553
579
                 */
554
 
                var $header_logo_width = 30;
 
580
                private $header_logo_width = 30;
555
581
                
556
582
                /**
557
583
                 * @var String to print as title on document header.
558
584
                 * @access private
559
585
                 */
560
 
                var $header_title = "";
 
586
                private $header_title = "";
561
587
                
562
588
                /**
563
589
                 * @var String to print on document header.
564
590
                 * @access private
565
591
                 */
566
 
                var $header_string = "";
 
592
                private $header_string = "";
567
593
                
568
594
                /**
569
595
                 * @var Default number of columns for html table.
570
596
                 * @access private
571
597
                 */
572
 
                var $default_table_columns = 4;
 
598
                private $default_table_columns = 4;
573
599
                
574
600
                
575
601
                // variables for html parser
578
604
                 * @var HTML PARSER: store current link.
579
605
                 * @access private
580
606
                 */
581
 
                var $HREF;
 
607
                private $HREF;
582
608
                
583
609
                /**
584
610
                 * @var HTML PARSER: store font list.
585
611
                 * @access private
586
612
                 */
587
 
                var $fontList;
 
613
                private $fontList;
588
614
                
589
615
                /**
590
616
                 * @var HTML PARSER: true when font attribute is set.
591
617
                 * @access private
592
618
                 */
593
 
                var $issetfont;
 
619
                private $issetfont;
594
620
                
595
621
                /**
596
622
                 * @var HTML PARSER: true when color attribute is set.
597
623
                 * @access private
598
624
                 */
599
 
                var $issetcolor;
 
625
                private $issetcolor;
600
626
                
601
627
                /**
602
628
                 * @var HTML PARSER: true in case of ordered list (OL), false otherwise.
603
629
                 * @access private
604
630
                 */
605
 
                var $listordered = false;
 
631
                private $listordered = false;
606
632
                
607
633
                /**
608
634
                 * @var HTML PARSER: count list items.
609
635
                 * @access private
610
636
                 */
611
 
                var $listcount = 0;
 
637
                private $listcount = 0;
612
638
                
613
639
                /**
614
640
                 * @var HTML PARSER: size of table border.
615
641
                 * @access private
616
642
                 */
617
 
                var $tableborder = 0;
 
643
                private $tableborder = 0;
618
644
                
619
645
                /**
620
646
                 * @var HTML PARSER: true at the beginning of table.
621
647
                 * @access private
622
648
                 */
623
 
                var $tdbegin = false;
 
649
                private $tdbegin = false;
624
650
                
625
651
                /**
626
652
                 * @var HTML PARSER: table width.
627
653
                 * @access private
628
654
                 */
629
 
                var $tdwidth = 0;
 
655
                private $tdwidth = 0;
630
656
                
631
657
                /**
632
658
                 * @var HTML PARSER: table height.
633
659
                 * @access private
634
660
                 */
635
 
                var $tdheight = 0;
 
661
                private $tdheight = 0;
636
662
                
637
663
                /**
638
664
                 * @var HTML PARSER: table align.
639
665
                 * @access private
640
666
                 */
641
 
                var $tdalign = "L";
 
667
                private $tdalign = "L";
642
668
                
643
669
                /**
644
670
                 * @var HTML PARSER: table background color.
645
671
                 * @access private
646
672
                 */
647
 
                var $tdbgcolor = false;
 
673
                private $tdbgcolor = false;
648
674
                
649
675
                /**
650
676
                 * @var Store temporary font size in points.
651
677
                 * @access private
652
678
                 */
653
 
                var $tempfontsize = 10;
 
679
                private $tempfontsize = 10;
654
680
                
655
681
                /**
656
682
                 * @var Bold font style status.
657
683
                 * @access private
658
684
                 */
659
 
                var $b;
 
685
                private $b;
660
686
                
661
687
                /**
662
688
                 * @var Underlined font style status.
663
689
                 * @access private
664
690
                 */
665
 
                var $u;
 
691
                private $u;
666
692
                
667
693
                /**
668
694
                 * @var Italic font style status.
669
695
                 * @access private
670
696
                 */
671
 
                var $i;
 
697
                private $i;
672
698
                
673
699
                /**
674
700
                 * @var spacer for LI tags.
675
701
                 * @access private
676
702
                 */
677
 
                var $lispacer = "";
 
703
                private $lispacer = "";
678
704
                
679
705
                /**
680
706
                 * @var default encoding
681
707
                 * @access private
682
708
                 * @since 1.53.0.TC010
683
709
                 */
684
 
                var $encoding = "UTF-8";
 
710
                private $encoding = "UTF-8";
685
711
                
686
712
                /**
687
713
                 * @var PHP internal encoding
688
714
                 * @access private
689
715
                 * @since 1.53.0.TC016
690
716
                 */
691
 
                var $internal_encoding;
 
717
                private $internal_encoding;
692
718
                
693
719
                /**
694
720
                 * @var store previous fill color as RGB array
695
721
                 * @access private
696
722
                 * @since 1.53.0.TC017
697
723
                 */
698
 
                var $prevFillColor = array(255,255,255);
 
724
                private $prevFillColor = array(255,255,255);
699
725
                
700
726
                /**
701
727
                 * @var store previous text color as RGB array
702
728
                 * @access private
703
729
                 * @since 1.53.0.TC017
704
730
                 */
705
 
                var $prevTextColor = array(0,0,0);
 
731
                private $prevTextColor = array(0,0,0);
706
732
                
707
733
                /**
708
734
                 * @var store previous font family
709
735
                 * @access private
710
736
                 * @since 1.53.0.TC017
711
737
                 */
712
 
                var $prevFontFamily;
 
738
                private $prevFontFamily;
713
739
                
714
740
                /**
715
741
                 * @var store previous font style
716
742
                 * @access private
717
743
                 * @since 1.53.0.TC017
718
744
                 */
719
 
                var $prevFontStyle;
720
 
 
 
745
                private $prevFontStyle;
 
746
                
 
747
                /**
 
748
                 * @var indicates if the document language is Right-To-Left
 
749
                 * @access private
 
750
                 * @since 2.0.000
 
751
                 */
 
752
                private $rtl = false;
 
753
                
 
754
                /**
 
755
                 * @var used to force RTL or LTR string inversion
 
756
                 * @access private
 
757
                 * @since 2.0.000
 
758
                 */
 
759
                private $tmprtl = false;
 
760
                
 
761
                // --- Variables used for document encryption:
 
762
                
 
763
                /**
 
764
                 * Indicates whether document is protected
 
765
                 * @access private
 
766
                 * @since 2.0.000 (2008-01-02)
 
767
                 */
 
768
                private $encrypted;
 
769
                
 
770
                /**
 
771
                 * U entry in pdf document
 
772
                 * @access private
 
773
                 * @since 2.0.000 (2008-01-02)
 
774
                 */
 
775
                private $Uvalue;
 
776
                
 
777
                /**
 
778
                 * O entry in pdf document
 
779
                 * @access private
 
780
                 * @since 2.0.000 (2008-01-02)
 
781
                 */
 
782
                private $Ovalue;
 
783
                
 
784
                /**
 
785
                 * P entry in pdf document
 
786
                 * @access private
 
787
                 * @since 2.0.000 (2008-01-02)
 
788
                 */
 
789
                private $Pvalue;
 
790
                
 
791
                /**
 
792
                 * encryption object id
 
793
                 * @access private
 
794
                 * @since 2.0.000 (2008-01-02)
 
795
                 */
 
796
                private $enc_obj_id;
 
797
                
 
798
                /**
 
799
                 * last RC4 key encrypted (cached for optimisation)
 
800
                 * @access private
 
801
                 * @since 2.0.000 (2008-01-02)
 
802
                 */
 
803
                private $last_rc4_key;
 
804
                
 
805
                /**
 
806
                 * last RC4 computed key
 
807
                 * @access private
 
808
                 * @since 2.0.000 (2008-01-02)
 
809
                 */
 
810
                private $last_rc4_key_c;
 
811
                
 
812
                // --- bookmark ---
 
813
                
 
814
                /**
 
815
                 * Outlines for bookmark
 
816
                 * @access private
 
817
                 * @since 2.1.002 (2008-02-12)
 
818
                 */
 
819
                private $outlines = array();
 
820
                
 
821
                /**
 
822
                 * Outline root for bookmark
 
823
                 * @access private
 
824
                 * @since 2.1.002 (2008-02-12)
 
825
                 */
 
826
                private $OutlineRoot;
 
827
                
 
828
                
 
829
                // --- javascript and form ---
 
830
                
 
831
                /**
 
832
                 * javascript code
 
833
                 * @access private
 
834
                 * @since 2.1.002 (2008-02-12)
 
835
                 */
 
836
                private $javascript = "";
 
837
                
 
838
                /**
 
839
                 * javascript counter
 
840
                 * @access private
 
841
                 * @since 2.1.002 (2008-02-12)
 
842
                 */
 
843
    private $n_js;
 
844
    
721
845
                //------------------------------------------------------------
722
 
                // var methods
 
846
                // Public methods
723
847
                //------------------------------------------------------------
724
848
 
725
849
                /**
733
857
                 * @param boolean $unicode TRUE means that the input text is unicode (default = true)
734
858
                 * @param String $encoding charset encoding; default is UTF-8
735
859
                 */
736
 
                function TCPDF($orientation='P', $unit='mm', $format='A4', $unicode=true, $encoding="UTF-8") {
 
860
                public function __construct($orientation='P', $unit='mm', $format='A4', $unicode=true, $encoding="UTF-8") {
737
861
                        
738
862
                        /* Set internal character encoding to ASCII */
739
863
                        if (function_exists("mb_internal_encoding") AND mb_internal_encoding()) {
740
864
                                $this->internal_encoding = mb_internal_encoding();
741
865
                                mb_internal_encoding("ASCII");
742
866
                        }
743
 
                                
 
867
                        
 
868
                        // set language direction
 
869
                        $this->rtl = $this->l['a_meta_dir']=='rtl' ? true : false;
 
870
                        $this->tmprtl = false;
 
871
                        
744
872
                        //Some checks
745
873
                        $this->_dochecks();
 
874
                        
746
875
                        //Initialization of properties
747
876
                        $this->isunicode=$unicode;
748
877
                        $this->page=0;
767
896
                        $this->TextColor='0 g';
768
897
                        $this->ColorFlag=false;
769
898
                        $this->ws=0;
 
899
                        // encryption values
 
900
                        $this->encrypted=false;
 
901
                        $this->last_rc4_key='';
 
902
                        $this->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";
 
903
                        
770
904
                        //Standard Unicode fonts
771
905
                        $this->CoreFonts=array(
772
906
                        'courier'=>'Courier',
786
920
                        );
787
921
 
788
922
                        //Scale factor
789
 
                        // 2003-06-11 - Nicola Asuni : changed if/else with switch statement
790
923
                        switch (strtolower($unit)){
791
924
                                case 'pt': {$this->k=1; break;}
792
925
                                case 'mm': {$this->k=72/25.4; break;}
797
930
 
798
931
                        //Page format
799
932
                        if(is_string($format)) {
800
 
                                // 2002-07-24 - Nicola Asuni (info@tecnick.com)
801
 
                                // Added new page formats (45 standard ISO paper formats and 4 american common formats).
 
933
                                // Page formats (45 standard ISO paper formats and 4 american common formats).
802
934
                                // Paper cordinates are calculated in this way: (inches * 72) where (1 inch = 2.54 cm)
803
935
                                switch (strtoupper($format)){
804
936
                                        case '4A0': {$format = array(4767.87,6740.79); break;}
851
983
                                        case 'EXECUTIVE': {$format = array(521.86,756.00); break;}
852
984
                                        case 'FOLIO': {$format = array(612.00,936.00); break;}
853
985
                                        // default: {$this->Error('Unknown page format: '.$format); break;}
854
 
                                        // END CHANGES Nicola Asuni
855
986
                                }
856
987
                                $this->fwPt=$format[0];
857
988
                                $this->fhPt=$format[1];
897
1028
                        //Compression
898
1029
                        $this->SetCompression(true);
899
1030
                        //Set default PDF version number
900
 
                        $this->PDFVersion = "1.3";
 
1031
                        $this->PDFVersion = "1.5";
901
1032
                        
902
1033
                        $this->encoding = $encoding;
903
1034
                        $this->b = 0;
911
1042
                        $this->tdbegin = false;
912
1043
                        $this->tdwidth=  0;
913
1044
                        $this->tdheight = 0;
914
 
                        $this->tdalign = "L";
 
1045
                        if($this->rtl) {
 
1046
                                $this->tdalign = "R";
 
1047
                        } else {
 
1048
                                $this->tdalign = "L";
 
1049
                        }
915
1050
                        $this->tdbgcolor = false;
916
1051
                        
917
1052
                        $this->SetFillColor(200, 200, 200, true);
918
1053
                        $this->SetTextColor(0, 0, 0, true);
919
1054
                }
920
 
 
 
1055
                
 
1056
                /**
 
1057
                 * Default destructor.
 
1058
                 * @since 1.53.0.TC016
 
1059
                 */
 
1060
                public function __destruct() {
 
1061
                        // restore internal encoding
 
1062
                        if (isset($this->internal_encoding) AND !empty($this->internal_encoding)) {
 
1063
                                mb_internal_encoding($this->internal_encoding);
 
1064
                        }
 
1065
                }
 
1066
                
 
1067
                /**
 
1068
                * Enable or disable Right-To-Left language mode
 
1069
                * @param Boolean $enable if true enable Right-To-Left language mode.
 
1070
                * @since 2.0.000 (2008-01-03)
 
1071
                */
 
1072
                public function setRTL($enable) {
 
1073
                        $this->rtl = $enable ? true : false;
 
1074
                        $this->tmprtl = false;
 
1075
                }
 
1076
                
 
1077
                /**
 
1078
                * Force temporary RTL language direction
 
1079
                * @param mixed $mode can be false, 'L' for LTR or 'R' for RTL
 
1080
                * @since 2.1.000 (2008-01-09)
 
1081
                */
 
1082
                public function setTempRTL($mode) {
 
1083
                        switch ($mode) {
 
1084
                                case false:
 
1085
                                case 'L':
 
1086
                                case 'R': {
 
1087
                                        $this->tmprtl = $mode;
 
1088
                                }
 
1089
                        }
 
1090
                }
 
1091
                
 
1092
                /**
 
1093
                * Set the last cell height.
 
1094
                * @param float $h cell height.
 
1095
                * @author Nicola Asuni
 
1096
                * @since 1.53.0.TC034
 
1097
                */
 
1098
                public function setLastH($h) {
 
1099
                        $this->lasth=$h;
 
1100
                }
 
1101
                
921
1102
                /**
922
1103
                * Set the image scale.
923
1104
                * @param float $scale image scale.
924
1105
                * @author Nicola Asuni
925
1106
                * @since 1.5.2
926
1107
                */
927
 
                function setImageScale($scale) {
 
1108
                public function setImageScale($scale) {
928
1109
                        $this->imgscale=$scale;
929
1110
                }
930
1111
 
934
1115
                * @author Nicola Asuni
935
1116
                * @since 1.5.2
936
1117
                */
937
 
                function getImageScale() {
 
1118
                public function getImageScale() {
938
1119
                        return $this->imgscale;
939
1120
                }
940
1121
 
944
1125
                * @author Nicola Asuni
945
1126
                * @since 1.5.2
946
1127
                */
947
 
                function getPageWidth() {
 
1128
                public function getPageWidth() {
948
1129
                        return $this->w;
949
1130
                }
950
1131
 
954
1135
                * @author Nicola Asuni
955
1136
                * @since 1.5.2
956
1137
                */
957
 
                function getPageHeight() {
 
1138
                public function getPageHeight() {
958
1139
                        return $this->h;
959
1140
                }
960
1141
 
964
1145
                * @author Nicola Asuni
965
1146
                * @since 1.5.2
966
1147
                */
967
 
                function getBreakMargin() {
 
1148
                public function getBreakMargin() {
968
1149
                        return $this->bMargin;
969
1150
                }
970
1151
 
974
1155
                * @author Nicola Asuni
975
1156
                * @since 1.5.2
976
1157
                */
977
 
                function getScaleFactor() {
 
1158
                public function getScaleFactor() {
978
1159
                        return $this->k;
979
1160
                }
980
1161
 
986
1167
                * @since 1.0
987
1168
                * @see SetLeftMargin(), SetTopMargin(), SetRightMargin(), SetAutoPageBreak()
988
1169
                */
989
 
                function SetMargins($left, $top, $right=-1) {
 
1170
                public function SetMargins($left, $top, $right=-1) {
990
1171
                        //Set left, top and right margins
991
1172
                        $this->lMargin=$left;
992
1173
                        $this->tMargin=$top;
1002
1183
                * @since 1.4
1003
1184
                * @see SetTopMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins()
1004
1185
                */
1005
 
                function SetLeftMargin($margin) {
 
1186
                public function SetLeftMargin($margin) {
1006
1187
                        //Set left margin
1007
1188
                        $this->lMargin=$margin;
1008
 
                        if(($this->page>0) and ($this->x<$margin)) {
1009
 
                                $this->x=$margin;
 
1189
                        if(($this->page > 0) AND ($this->x < $margin)) {
 
1190
                                $this->x = $margin;
1010
1191
                        }
1011
1192
                }
1012
1193
 
1016
1197
                * @since 1.5
1017
1198
                * @see SetLeftMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins()
1018
1199
                */
1019
 
                function SetTopMargin($margin) {
 
1200
                public function SetTopMargin($margin) {
1020
1201
                        //Set top margin
1021
1202
                        $this->tMargin=$margin;
 
1203
                        if(($this->page > 0) AND ($this->y < $margin)) {
 
1204
                                $this->y = $margin;
 
1205
                        }
1022
1206
                }
1023
1207
 
1024
1208
                /**
1027
1211
                * @since 1.5
1028
1212
                * @see SetLeftMargin(), SetTopMargin(), SetAutoPageBreak(), SetMargins()
1029
1213
                */
1030
 
                function SetRightMargin($margin) {
1031
 
                        //Set right margin
 
1214
                public function SetRightMargin($margin) {
1032
1215
                        $this->rMargin=$margin;
 
1216
                        if(($this->page > 0) AND ($this->x > ($this->w - $margin))) {
 
1217
                                $this->x = $this->w - $margin;
 
1218
                        }
 
1219
                }
 
1220
 
 
1221
                /**
 
1222
                * Set the internal Cell padding.
 
1223
                * @param float $pad internal padding.
 
1224
                * @since 2.1.000 (2008-01-09)
 
1225
                * @see Cell(), SetLeftMargin(), SetTopMargin(), SetAutoPageBreak(), SetMargins()
 
1226
                */
 
1227
                public function SetCellPadding($pad) {
 
1228
                        $this->cMargin=$pad;
1033
1229
                }
1034
1230
 
1035
1231
                /**
1039
1235
                * @since 1.0
1040
1236
                * @see Cell(), MultiCell(), AcceptPageBreak()
1041
1237
                */
1042
 
                function SetAutoPageBreak($auto, $margin=0) {
 
1238
                public function SetAutoPageBreak($auto, $margin=0) {
1043
1239
                        //Set auto page break mode and triggering margin
1044
 
                        $this->AutoPageBreak=$auto;
1045
 
                        $this->bMargin=$margin;
1046
 
                        $this->PageBreakTrigger=$this->h-$margin;
 
1240
                        $this->AutoPageBreak = $auto;
 
1241
                        $this->bMargin = $margin;
 
1242
                        $this->PageBreakTrigger = $this->h - $margin;
1047
1243
                }
1048
1244
 
1049
1245
                /**
1052
1248
                * @param string $layout The page layout. Possible values are:<ul><li>single: displays one page at once</li><li>continuous: displays pages continuously (default)</li><li>two: displays two pages on two columns</li><li>default: uses viewer default mode</li></ul>
1053
1249
                * @since 1.2
1054
1250
                */
1055
 
                function SetDisplayMode($zoom, $layout='continuous') {
 
1251
                public function SetDisplayMode($zoom, $layout='continuous') {
1056
1252
                        //Set display mode in viewer
1057
1253
                        if($zoom=='fullpage' or $zoom=='fullwidth' or $zoom=='real' or $zoom=='default' or !is_string($zoom)) {
1058
1254
                                $this->ZoomMode=$zoom;
1074
1270
                * @param boolean $compress Boolean indicating if compression must be enabled.
1075
1271
                * @since 1.4
1076
1272
                */
1077
 
                function SetCompression($compress) {
 
1273
                public function SetCompression($compress) {
1078
1274
                        //Set page compression
1079
1275
                        if(function_exists('gzcompress')) {
1080
1276
                                $this->compress=$compress;
1090
1286
                * @since 1.2
1091
1287
                * @see SetAuthor(), SetCreator(), SetKeywords(), SetSubject()
1092
1288
                */
1093
 
                function SetTitle($title) {
 
1289
                public function SetTitle($title) {
1094
1290
                        //Title of document
1095
1291
                        $this->title=$title;
1096
1292
                }
1101
1297
                * @since 1.2
1102
1298
                * @see SetAuthor(), SetCreator(), SetKeywords(), SetTitle()
1103
1299
                */
1104
 
                function SetSubject($subject) {
 
1300
                public function SetSubject($subject) {
1105
1301
                        //Subject of document
1106
1302
                        $this->subject=$subject;
1107
1303
                }
1112
1308
                * @since 1.2
1113
1309
                * @see SetCreator(), SetKeywords(), SetSubject(), SetTitle()
1114
1310
                */
1115
 
                function SetAuthor($author) {
 
1311
                public function SetAuthor($author) {
1116
1312
                        //Author of document
1117
1313
                        $this->author=$author;
1118
1314
                }
1123
1319
                * @since 1.2
1124
1320
                * @see SetAuthor(), SetCreator(), SetSubject(), SetTitle()
1125
1321
                */
1126
 
                function SetKeywords($keywords) {
 
1322
                public function SetKeywords($keywords) {
1127
1323
                        //Keywords of document
1128
1324
                        $this->keywords=$keywords;
1129
1325
                }
1134
1330
                * @since 1.2
1135
1331
                * @see SetAuthor(), SetKeywords(), SetSubject(), SetTitle()
1136
1332
                */
1137
 
                function SetCreator($creator) {
 
1333
                public function SetCreator($creator) {
1138
1334
                        //Creator of document
1139
1335
                        $this->creator=$creator;
1140
1336
                }
1144
1340
                * <b>Example:</b><br />
1145
1341
                * <pre>
1146
1342
                * class PDF extends TCPDF {
1147
 
                *       function Footer() {
 
1343
                *       public function Footer() {
1148
1344
                *               //Go to 1.5 cm from bottom
1149
1345
                *               $this->SetY(-15);
1150
1346
                *               //Select Arial italic 8
1160
1356
                * @since 1.4
1161
1357
                * @see PageNo(), Footer()
1162
1358
                */
1163
 
                function AliasNbPages($alias='{nb}') {
 
1359
                public function AliasNbPages($alias='{nb}') {
1164
1360
                        //Define an alias for total number of pages
1165
1361
                        $this->AliasNbPages = $this->_escapetext($alias);
1166
1362
                }
1171
1367
                * @param string $msg The error message
1172
1368
                * @since 1.0
1173
1369
                */
1174
 
                function Error($msg) {
 
1370
                public function Error($msg) {
1175
1371
                        //Fatal error
1176
1372
                        die('<strong>TCPDF error: </strong>'.$msg);
1177
1373
                }
1182
1378
                * @since 1.0
1183
1379
                * @see AddPage(), Close()
1184
1380
                */
1185
 
                function Open() {
 
1381
                public function Open() {
1186
1382
                        //Begin document
1187
1383
                        $this->state=1;
1188
1384
                }
1192
1388
                * @since 1.0
1193
1389
                * @see Open(), Output()
1194
1390
                */
1195
 
                function Close() {
 
1391
                public function Close() {
1196
1392
                        //Terminate document
1197
1393
                        if($this->state==3) {
1198
1394
                                return;
1211
1407
                }
1212
1408
 
1213
1409
                /**
 
1410
                * Reset pointer to the last document page.
 
1411
                * @since 2.0.000 (2008-01-04)
 
1412
                * @see setPage(), getPage(), getNumPages()
 
1413
                */
 
1414
                public function lastPage() {
 
1415
                        $this->page = count($this->pages);
 
1416
                }
 
1417
                
 
1418
                /**
 
1419
                * Move pointer to the apecified document page.
 
1420
                * @param int $pnum page number
 
1421
                * @since 2.1.000 (2008-01-07)
 
1422
                * @see getPage(), lastpage(), getNumPages()
 
1423
                */
 
1424
                public function setPage($pnum) {
 
1425
                        if(($pnum > 0) AND ($pnum <= count($this->pages))) {
 
1426
                                $this->page = $pnum;
 
1427
                        }
 
1428
                }
 
1429
                
 
1430
                /**
 
1431
                * Get current document page number.
 
1432
                * @return int page number
 
1433
                * @since 2.1.000 (2008-01-07)
 
1434
                * @see setPage(), lastpage(), getNumPages()
 
1435
                */
 
1436
                public function getPage() {
 
1437
                        return $this->page;
 
1438
                }
 
1439
                
 
1440
                
 
1441
                /**
 
1442
                * Get the total number of insered pages.
 
1443
                * @return int number of pages
 
1444
                * @since 2.1.000 (2008-01-07)
 
1445
                * @see setPage(), getPage(), lastpage()
 
1446
                */
 
1447
                public function getNumPages() {
 
1448
                        return count($this->pages);
 
1449
                }
 
1450
 
 
1451
                /**
1214
1452
                * Adds a new page to the document. If a page is already present, the Footer() method is called first to output the footer. Then the page is added, the current position set to the top-left corner according to the left and top margins, and Header() is called to display the header.
1215
1453
                * The font which was set before calling is automatically restored. There is no need to call SetFont() again if you want to continue with the same font. The same is true for colors and line width.
1216
1454
                * The origin of the coordinate system is at the top-left corner and increasing ordinates go downwards.
1218
1456
                * @since 1.0
1219
1457
                * @see TCPDF(), Header(), Footer(), SetMargins()
1220
1458
                */
1221
 
                function AddPage($orientation='') {
 
1459
                public function AddPage($orientation='') {
 
1460
                        if (count($this->pages) > ($this->page + 1)) {
 
1461
                                // this page has been already added
 
1462
                                $this->page++;
 
1463
                                return;
 
1464
                        }
1222
1465
                        //Start a new page
1223
1466
                        if($this->state==0) {
1224
1467
                                $this->Open();
1285
1528
                        $this->ColorFlag=$cf;
1286
1529
                }
1287
1530
                
1288
 
                
1289
 
                
1290
1531
                /**
1291
1532
                 * Set header data.
1292
1533
                 * @param string $ln header image logo
1294
1535
                 * @param string $ht string to print as title on document header
1295
1536
                 * @param string $hs string to print on document header
1296
1537
                */
1297
 
                function setHeaderData($ln="", $lw=0, $ht="", $hs="") {
 
1538
                public function setHeaderData($ln="", $lw=0, $ht="", $hs="") {
1298
1539
                        $this->header_logo = $ln;
1299
1540
                        $this->header_logo_width = $lw;
1300
1541
                        $this->header_title = $ht;
1306
1547
                 * (minimum distance between header and top page margin)
1307
1548
                 * @param int $hm distance in millimeters
1308
1549
                */
1309
 
                function setHeaderMargin($hm=10) {
 
1550
                public function setHeaderMargin($hm=10) {
1310
1551
                        $this->header_margin = $hm;
1311
1552
                }
1312
1553
                
1315
1556
                 * (minimum distance between footer and bottom page margin)
1316
1557
                 * @param int $fm distance in millimeters
1317
1558
                */
1318
 
                function setFooterMargin($fm=10) {
 
1559
                public function setFooterMargin($fm=10) {
1319
1560
                        $this->footer_margin = $fm;
1320
1561
                }
1321
1562
                
1322
1563
                /**
 
1564
                 * Set a flag to print page header.
 
1565
                 * @param boolean $val set to true to print the page header (default), false otherwise. 
 
1566
                */
 
1567
                public function setPrintHeader($val=true) {
 
1568
                        $this->print_header = $val;
 
1569
                }
 
1570
                
 
1571
                /**
 
1572
                 * Set a flag to print page footer.
 
1573
                 * @param boolean $value set to true to print the page footer (default), false otherwise. 
 
1574
                */
 
1575
                public function setPrintFooter($val=true) {
 
1576
                        $this->print_footer = $val;
 
1577
                }
 
1578
                
 
1579
                /**
1323
1580
                 * This method is used to render the page header.
1324
1581
                 * It is automatically called by AddPage() and could be overwritten in your own inherited class.
1325
1582
                 */
1326
 
                function Header() {
 
1583
                public function Header() {
1327
1584
                        if ($this->print_header) {
1328
1585
                                
1329
1586
                                if (!isset($this->original_lMargin)) {
1334
1591
                                }
1335
1592
                                
1336
1593
                                //set current position
1337
 
                                $this->SetXY($this->original_lMargin, $this->header_margin);
 
1594
                                if ($this->rtl) {
 
1595
                                        $this->SetXY($this->original_rMargin, $this->header_margin);
 
1596
                                } else {
 
1597
                                        $this->SetXY($this->original_lMargin, $this->header_margin);
 
1598
                                }
1338
1599
                                
1339
1600
                                if (($this->header_logo) AND ($this->header_logo != K_BLANK_IMAGE)) {
1340
 
                                        $this->Image(K_PATH_IMAGES.$this->header_logo, $this->original_lMargin, $this->header_margin, $this->header_logo_width);
1341
 
                                }
1342
 
                                else {
 
1601
                                        $this->Image(K_PATH_IMAGES.$this->header_logo, $this->GetX(), $this->header_margin, $this->header_logo_width);
 
1602
                                } else {
 
1603
                                        $this->img_rb_x = $this->GetX();
1343
1604
                                        $this->img_rb_y = $this->GetY();
1344
1605
                                }
1345
1606
                                
1346
1607
                                $cell_height = round((K_CELL_HEIGHT_RATIO * $this->header_font[2]) / $this->k, 2);
1347
 
                                
1348
 
                                $header_x = $this->original_lMargin + ($this->header_logo_width * 1.05); //set left margin for text data cell
 
1608
                                // set starting margin for text data cell
 
1609
                                if ($this->rtl) {
 
1610
                                        $header_x = $this->original_rMargin + ($this->header_logo_width * 1.1);
 
1611
                                } else {
 
1612
                                        $header_x = $this->original_lMargin + ($this->header_logo_width * 1.1);
 
1613
                                }
1349
1614
                                
1350
1615
                                // header title
1351
1616
                                $this->SetFont($this->header_font[0], 'B', $this->header_font[2] + 1);
1352
1617
                                $this->SetX($header_x);
1353
 
                                $this->Cell($this->header_width, $cell_height, $this->header_title, 0, 1, 'L'); 
 
1618
                                $this->Cell($this->header_width, $cell_height, $this->header_title, 0, 1, ''); 
1354
1619
                                
1355
1620
                                // header string
1356
1621
                                $this->SetFont($this->header_font[0], $this->header_font[1], $this->header_font[2]);
1357
1622
                                $this->SetX($header_x);
1358
 
                                $this->MultiCell($this->header_width, $cell_height, $this->header_string, 0, 'L', 0);
 
1623
                                $this->MultiCell($this->header_width, $cell_height, $this->header_string, 0, '', 0);
1359
1624
                                
1360
1625
                                // print an ending header line
1361
1626
                                if (empty($this->header_width)) {
1362
1627
                                        //set style for cell border
1363
 
                                        $this->SetLineWidth(0.3);
 
1628
                                        $prevlinewidth = $this->GetLineWidth();
 
1629
                                        $line_width = 0.3;
 
1630
                                        $this->SetLineWidth($line_width);
1364
1631
                                        $this->SetDrawColor(0, 0, 0);
1365
1632
                                        $this->SetY(1 + max($this->img_rb_y, $this->GetY()));
1366
 
                                        $this->SetX($this->original_lMargin);
1367
 
                                        $this->Cell(0, 0, '', 'T', 0, 'C'); 
 
1633
                                        if ($this->rtl) {
 
1634
                                                $this->SetX($this->original_rMargin);
 
1635
                                        } else {
 
1636
                                                $this->SetX($this->original_lMargin);
 
1637
                                        }
 
1638
                                        $this->Cell(0, 0, '', 'T', 0, 'C');
 
1639
                                        $this->SetLineWidth($prevlinewidth);
1368
1640
                                }
1369
1641
                                
1370
1642
                                //restore position
1371
 
                                $this->SetXY($this->original_lMargin, $this->tMargin);
 
1643
                                if ($this->rtl) {
 
1644
                                        $this->SetXY($this->original_rMargin, $this->tMargin);
 
1645
                                } else {
 
1646
                                        $this->SetXY($this->original_lMargin, $this->tMargin);
 
1647
                                }
1372
1648
                        }
1373
1649
                }
1374
1650
                
1376
1652
                 * This method is used to render the page footer. 
1377
1653
                 * It is automatically called by AddPage() and could be overwritten in your own inherited class.
1378
1654
                 */
1379
 
                function Footer() {
 
1655
                public function Footer() {
1380
1656
                        if ($this->print_footer) {
1381
1657
                                
1382
1658
                                if (!isset($this->original_lMargin)) {
1389
1665
                                //set font
1390
1666
                                $this->SetFont($this->footer_font[0], $this->footer_font[1] , $this->footer_font[2]);
1391
1667
                                //set style for cell border
 
1668
                                $prevlinewidth = $this->GetLineWidth();
1392
1669
                                $line_width = 0.3;
1393
1670
                                $this->SetLineWidth($line_width);
1394
1671
                                $this->SetDrawColor(0, 0, 0);
1397
1674
                                //get footer y position
1398
1675
                                $footer_y = $this->h - $this->footer_margin - $footer_height;
1399
1676
                                //set current position
1400
 
                                $this->SetXY($this->original_lMargin, $footer_y); 
 
1677
                                if ($this->rtl) {
 
1678
                                        $this->SetXY($this->original_rMargin, $footer_y);
 
1679
                                } else {
 
1680
                                        $this->SetXY($this->original_lMargin, $footer_y);
 
1681
                                }
1401
1682
                                
1402
1683
                                //print document barcode
1403
1684
                                if ($this->barcode) {
1404
1685
                                        $this->Ln();
1405
 
                                        $barcode_width = round(($this->w - $this->original_lMargin - $this->original_rMargin)); //max width
1406
 
                                        $this->writeBarcode($this->original_lMargin, $footer_y + $line_width, $barcode_width, $footer_height - $line_width, "C128B", false, false, 2, $this->barcode);
 
1686
                                        $barcode_width = round(($this->w - $this->original_lMargin - $this->original_rMargin)/3); //max width
 
1687
                                        $this->writeBarcode($this->GetX(), $footer_y + $line_width, $barcode_width, $footer_height - $line_width, "C128B", false, false, 2, $this->barcode);
1407
1688
                                }
1408
1689
                                
1409
 
                                $this->SetXY($this->original_lMargin, $footer_y); 
 
1690
                                $pagenumtxt = $this->l['w_page']." ".$this->PageNo().' / {nb}';
 
1691
                                
 
1692
                                $this->SetY($footer_y); 
1410
1693
                                
1411
1694
                                //Print page number
1412
 
                                $this->Cell(0, $footer_height, $this->l['w_page']." ".$this->PageNo().' / {nb}', 'T', 0, 'R'); 
 
1695
                                if ($this->rtl) {
 
1696
                                        $this->SetX($this->original_rMargin);
 
1697
                                        $this->Cell(0, $footer_height, $pagenumtxt, 'T', 0, 'L');
 
1698
                                } else {
 
1699
                                        $this->SetX($this->original_lMargin);
 
1700
                                        $this->Cell(0, $footer_height, $pagenumtxt, 'T', 0, 'R');
 
1701
                                }
 
1702
                                // restore line width
 
1703
                                $this->SetLineWidth($prevlinewidth);
1413
1704
                        }
1414
1705
                }
1415
1706
                
1419
1710
                * @since 1.0
1420
1711
                * @see AliasNbPages()
1421
1712
                */
1422
 
                function PageNo() {
 
1713
                public function PageNo() {
1423
1714
                        //Get current page number
1424
1715
                        return $this->page;
1425
1716
                }
1432
1723
                * @since 1.3
1433
1724
                * @see SetFillColor(), SetTextColor(), Line(), Rect(), Cell(), MultiCell()
1434
1725
                */
1435
 
                function SetDrawColor($r, $g=-1, $b=-1) {
 
1726
                public function SetDrawColor($r, $g=-1, $b=-1) {
1436
1727
                        //Set color for all stroking operations
1437
1728
                        if(($r==0 and $g==0 and $b==0) or $g==-1) {
1438
1729
                                $this->DrawColor=sprintf('%.3f G',$r/255);
1454
1745
                * @since 1.3
1455
1746
                * @see SetDrawColor(), SetTextColor(), Rect(), Cell(), MultiCell()
1456
1747
                */
1457
 
                function SetFillColor($r, $g=-1, $b=-1, $storeprev=false) {
 
1748
                public function SetFillColor($r, $g=-1, $b=-1, $storeprev=false) {
1458
1749
                        //Set color for all filling operations
1459
1750
                        if(($r==0 and $g==0 and $b==0) or $g==-1) {
1460
1751
                                $this->FillColor=sprintf('%.3f g',$r/255);
1481
1772
                * @since 1.3
1482
1773
                * @see SetDrawColor(), SetFillColor(), Text(), Cell(), MultiCell()
1483
1774
                */
1484
 
                function SetTextColor($r, $g=-1, $b=-1, $storeprev=false) {
 
1775
                public function SetTextColor($r, $g=-1, $b=-1, $storeprev=false) {
1485
1776
                        //Set color for text
1486
1777
                        if(($r==0 and $g==0 and $b==0) or $g==-1) {
1487
1778
                                $this->TextColor=sprintf('%.3f g',$r/255);
1503
1794
                * @return int
1504
1795
                * @since 1.2
1505
1796
                */
1506
 
                function GetStringWidth($s) {
 
1797
                public function GetStringWidth($s) {
1507
1798
                        //Get width of a string in the current font
1508
1799
                        $s = (string)$s;
1509
1800
                        $cw = &$this->CurrentFont['cw'];
1525
1816
                                }
1526
1817
                        } else {
1527
1818
                                $l = strlen($s);
1528
 
                                for($i=0; $i<$l; $i++) {
 
1819
                                for($i=0; $i < $l; $i++) {
1529
1820
                                        if (isset($cw[$s{$i}])) {
1530
1821
                                                $w += $cw[$s{$i}];
1531
1822
                                        } else if (isset($cw[ord($s{$i})])) {
1535
1826
                        }
1536
1827
                        return ($w * $this->FontSize / 1000);
1537
1828
                }
1538
 
 
1539
 
                /**
1540
 
                * Defines the line width. By default, the value equals 0.2 mm. The method can be called before the first page is created and the value is retained from page to page.
1541
 
                * @param float $width The width.
1542
 
                * @since 1.0
1543
 
                * @see Line(), Rect(), Cell(), MultiCell()
1544
 
                */
1545
 
                function SetLineWidth($width) {
1546
 
                        //Set line width
1547
 
                        $this->LineWidth=$width;
1548
 
                        if($this->page>0) {
1549
 
                                $this->_out(sprintf('%.2f w',$width*$this->k));
1550
 
                        }
1551
 
                }
1552
 
 
1553
 
                /**
1554
 
                * Draws a line between two points.
1555
 
                * @param float $x1 Abscissa of first point
1556
 
                * @param float $y1 Ordinate of first point
1557
 
                * @param float $x2 Abscissa of second point
1558
 
                * @param float $y2 Ordinate of second point
1559
 
                * @since 1.0
1560
 
                * @see SetLineWidth(), SetDrawColor()
1561
 
                */
1562
 
                function Line($x1, $y1, $x2, $y2) {
1563
 
                        //Draw a line
1564
 
                        $this->_out(sprintf('%.2f %.2f m %.2f %.2f l S', $x1*$this->k, ($this->h-$y1)*$this->k, $x2*$this->k, ($this->h-$y2)*$this->k));
1565
 
                }
1566
 
 
1567
 
                /**
1568
 
                * Outputs a rectangle. It can be drawn (border only), filled (with no border) or both.
1569
 
                * @param float $x Abscissa of upper-left corner
1570
 
                * @param float $y Ordinate of upper-left corner
1571
 
                * @param float $w Width
1572
 
                * @param float $h Height
1573
 
                * @param string $style Style of rendering. Possible values are:<ul><li>D or empty string: draw (default)</li><li>F: fill</li><li>DF or FD: draw and fill</li></ul>
1574
 
                * @since 1.0
1575
 
                * @see SetLineWidth(), SetDrawColor(), SetFillColor()
1576
 
                */
1577
 
                function Rect($x, $y, $w, $h, $style='') {
1578
 
                        //Draw a rectangle
1579
 
                        if($style=='F') {
1580
 
                                $op='f';
1581
 
                        }
1582
 
                        elseif($style=='FD' or $style=='DF') {
1583
 
                                $op='B';
1584
 
                        }
1585
 
                        else {
1586
 
                                $op='S';
1587
 
                        }
1588
 
                        $this->_out(sprintf('%.2f %.2f %.2f %.2f re %s',$x*$this->k,($this->h-$y)*$this->k,$w*$this->k,-$h*$this->k,$op));
1589
 
                }
1590
 
 
1591
 
                /**
1592
 
                * Imports a TrueType or Type1 font and makes it available. It is necessary to generate a font definition file first with the makefont.php utility. The definition file (and the font file itself when embedding) must be present either in the current directory or in the one indicated by FPDF_FONTPATH if the constant is defined. If it could not be found, the error "Could not include font definition file" is generated.
 
1829
                
 
1830
                /**
 
1831
                * Returns the numbero of characters in a string.
 
1832
                * @param string $s The input string.
 
1833
                * @return int number of characters
 
1834
                * @since 2.0.0001 (2008-01-07)
 
1835
                */
 
1836
                public function GetNumChars($s) {
 
1837
                        if($this->isunicode) {
 
1838
                                return count($this->UTF8StringToArray($s));
 
1839
                        } 
 
1840
                        return strlen($s);
 
1841
                }
 
1842
                
 
1843
                /**
 
1844
                * Imports a TrueType or Type1 font and makes it available. It is necessary to generate a font definition file first with the makefont.php utility. The definition file (and the font file itself when embedding) must be present either in the current directory or in the one indicated by K_PATH_FONTS if the constant is defined. If it could not be found, the error "Could not include font definition file" is generated.
1593
1845
                * Support UTF-8 Unicode [Nicola Asuni, 2005-01-02].
1594
1846
                * <b>Example</b>:<br />
1595
1847
                * <pre>
1603
1855
                * @since 1.5
1604
1856
                * @see SetFont()
1605
1857
                */
1606
 
                function AddFont($family, $style='', $file='') {
 
1858
                public function AddFont($family, $style='', $file='') {
1607
1859
                        if(empty($family)) {
1608
1860
                                return;
1609
1861
                        }
1680
1932
                * The font can be either a standard one or a font added via the AddFont() method. Standard fonts use Windows encoding cp1252 (Western Europe).
1681
1933
                * The method can be called before the first page is created and the font is retained from page to page.
1682
1934
                If you just wish to change the current font size, it is simpler to call SetFontSize().
1683
 
                * Note: for the standard fonts, the font metric files must be accessible. There are three possibilities for this:<ul><li>They are in the current directory (the one where the running script lies)</li><li>They are in one of the directories defined by the include_path parameter</li><li>They are in the directory defined by the FPDF_FONTPATH constant</li></ul><br />
 
1935
                * Note: for the standard fonts, the font metric files must be accessible. There are three possibilities for this:<ul><li>They are in the current directory (the one where the running script lies)</li><li>They are in one of the directories defined by the include_path parameter</li><li>They are in the directory defined by the K_PATH_FONTS constant</li></ul><br />
1684
1936
                * Example for the last case (note the trailing slash):<br />
1685
1937
                * <pre>
1686
 
                * define('FPDF_FONTPATH','/home/www/font/');
 
1938
                * define('K_PATH_FONTS','/home/www/font/');
1687
1939
                * require('tcpdf.php');
1688
1940
                *
1689
1941
                * //Times regular 12
1702
1954
                * @since 1.0
1703
1955
                * @see AddFont(), SetFontSize(), Cell(), MultiCell(), Write()
1704
1956
                */
1705
 
                function SetFont($family, $style='', $size=0) {
 
1957
                public function SetFont($family, $style='', $size=0) {
1706
1958
                        // save previous values
1707
1959
                        $this->prevFontFamily = $this->FontFamily;
1708
1960
                        $this->prevFontStyle = $this->FontStyle;
1801
2053
                * @since 1.0
1802
2054
                * @see SetFont()
1803
2055
                */
1804
 
                function SetFontSize($size) {
 
2056
                public function SetFontSize($size) {
1805
2057
                        //Set font size in points
1806
2058
                        if($this->FontSizePt==$size) {
1807
2059
                                return;
1819
2071
                * @since 1.5
1820
2072
                * @see Cell(), Write(), Image(), Link(), SetLink()
1821
2073
                */
1822
 
                function AddLink() {
 
2074
                public function AddLink() {
1823
2075
                        //Create a new internal link
1824
2076
                        $n=count($this->links)+1;
1825
2077
                        $this->links[$n]=array(0,0);
1834
2086
                * @since 1.5
1835
2087
                * @see AddLink()
1836
2088
                */
1837
 
                function SetLink($link, $y=0, $page=-1) {
 
2089
                public function SetLink($link, $y=0, $page=-1) {
1838
2090
                        //Set destination of internal link
1839
2091
                        if($y==-1) {
1840
2092
                                $y=$this->y;
1847
2099
 
1848
2100
                /**
1849
2101
                * Puts a link on a rectangular area of the page. Text or image links are generally put via Cell(), Write() or Image(), but this method can be useful for instance to define a clickable area inside an image.
1850
 
                * @param float $x Abscissa of the upper-left corner of the rectangle
1851
 
                * @param float $y Ordinate of the upper-left corner of the rectangle
 
2102
                * @param float $x Abscissa of the upper-left corner of the rectangle (or upper-right for RTL languages)
 
2103
                * @param float $y Ordinate of the upper-left corner of the rectangle (or upper-right for RTL languages)
1852
2104
                * @param float $w Width of the rectangle
1853
2105
                * @param float $h Height of the rectangle
1854
2106
                * @param mixed $link URL or identifier returned by AddLink()
1855
2107
                * @since 1.5
1856
2108
                * @see AddLink(), Cell(), Write(), Image()
1857
2109
                */
1858
 
                function Link($x, $y, $w, $h, $link) {
1859
 
                        //Put a link on the page
 
2110
                public function Link($x, $y, $w, $h, $link) {
1860
2111
                        $this->PageLinks[$this->page][] = array($x * $this->k, $this->hPt - $y * $this->k, $w * $this->k, $h*$this->k, $link);
1861
2112
                }
1862
 
 
 
2113
                
1863
2114
                /**
1864
2115
                * Prints a character string. The origin is on the left of the first charcter, on the baseline. This method allows to place a string precisely on the page, but it is usually easier to use Cell(), MultiCell() or Write() which are the standard methods to print text.
1865
2116
                * @param float $x Abscissa of the origin
1868
2119
                * @since 1.0
1869
2120
                * @see SetFont(), SetTextColor(), Cell(), MultiCell(), Write()
1870
2121
                */
1871
 
                function Text($x, $y, $txt) {
 
2122
                public function Text($x, $y, $txt) {
1872
2123
                        //Output a string
1873
 
                        $s=sprintf('BT %.2f %.2f Td (%s) Tj ET', $x * $this->k, ($this->h-$y) * $this->k, $this->_escapetext($txt));
 
2124
                        if($this->rtl) {
 
2125
                                $xr = $this->w - $x - $this->GetStringWidth($txt);
 
2126
                        } else {
 
2127
                                $xr = $x;
 
2128
                        }
 
2129
                        $s = sprintf('BT %.2f %.2f Td (%s) Tj ET', $xr * $this->k, ($this->h-$y) * $this->k, $this->_escapetext($txt));
1874
2130
                        if($this->underline AND ($txt!='')) {
1875
 
                                $s .= ' '.$this->_dounderline($x,$y,$txt);
 
2131
                                $s .= ' '.$this->_dounderline($xr, $y, $txt);
1876
2132
                        }
1877
2133
                        if($this->ColorFlag) {
1878
2134
                                $s='q '.$this->TextColor.' '.$s.' Q';
1889
2145
                * class PDF extends TCPDF {
1890
2146
                *       var $col=0;
1891
2147
                *
1892
 
                *       function SetCol($col) {
 
2148
                *       public function SetCol($col) {
1893
2149
                *               //Move position to a column
1894
2150
                *               $this->col=$col;
1895
2151
                *               $x=10+$col*65;
1897
2153
                *               $this->SetX($x);
1898
2154
                *       }
1899
2155
                *
1900
 
                *       function AcceptPageBreak() {
 
2156
                *       public function AcceptPageBreak() {
1901
2157
                *               if($this->col<2) {
1902
2158
                *                       //Go to next column
1903
2159
                *                       $this->SetCol($this->col+1);
1925
2181
                * @since 1.4
1926
2182
                * @see SetAutoPageBreak()
1927
2183
                */
1928
 
                function AcceptPageBreak() {
 
2184
                public function AcceptPageBreak() {
1929
2185
                        //Accept automatic page break or not
1930
2186
                        return $this->AutoPageBreak;
1931
2187
                }
1937
2193
                * @param float $h Cell height. Default value: 0.
1938
2194
                * @param string $txt String to print. Default value: empty string.
1939
2195
                * @param mixed $border Indicates if borders must be drawn around the cell. The value can be either 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>
1940
 
                * @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right</li><li>1: to the beginning of the next line</li><li>2: below</li></ul>
 
2196
                * @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right (or left for RTL languages)</li><li>1: to the beginning of the next line</li><li>2: below</li></ul>
1941
2197
                Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.
1942
 
                * @param string $align Allows to center or align the text. Possible values are:<ul><li>L or empty string: left align (default value)</li><li>C: center</li><li>R: right align</li></ul>
 
2198
                * @param string $align Allows to center or align the text. Possible values are:<ul><li>L or empty string: left align (default value)</li><li>C: center</li><li>R: right align</li><li>J: justify</li></ul>
1943
2199
                * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.
1944
2200
                * @param mixed $link URL or identifier returned by AddLink().
 
2201
                * @param int $stretch stretch carachter mode: <ul><li>0 = disabled</li><li>1 = horizontal scaling only if necessary</li><li>2 = forced horizontal scaling</li><li>3 = character spacing only if necessary</li><li>4 = forced character spacing</li></ul>
1945
2202
                * @since 1.0
1946
2203
                * @see SetFont(), SetDrawColor(), SetFillColor(), SetTextColor(), SetLineWidth(), AddLink(), Ln(), MultiCell(), Write(), SetAutoPageBreak()
1947
2204
                */
1948
 
                function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=0, $link='') {
 
2205
                public function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=0, $link='', $stretch=0) {
1949
2206
                        //Output a cell
1950
2207
                        $k=$this->k;
1951
2208
                        if(($this->y + $h) > $this->PageBreakTrigger AND empty($this->InFooter) AND $this->AcceptPageBreak()) {
1964
2221
                                }
1965
2222
                        }
1966
2223
                        if($w == 0) {
1967
 
                                $w = $this->w - $this->rMargin - $this->x;
 
2224
                                if ($this->rtl) {
 
2225
                                        $w = $this->x - $this->lMargin;
 
2226
                                } else {
 
2227
                                        $w = $this->w - $this->rMargin - $this->x;
 
2228
                                }
1968
2229
                        }
1969
2230
                        $s = '';
1970
2231
                        if(($fill == 1) OR ($border == 1)) {
1971
2232
                                if($fill == 1) {
1972
2233
                                        $op = ($border == 1) ? 'B' : 'f';
1973
 
                                }
1974
 
                                else {
 
2234
                                } else {
1975
2235
                                        $op = 'S';
1976
2236
                                }
1977
 
                                $s = sprintf('%.2f %.2f %.2f %.2f re %s ', $this->x * $k, ($this->h - $this->y) * $k, $w * $k, -$h * $k, $op);
 
2237
                                if ($this->rtl) {
 
2238
                                        $xk = ($this->x - $w) * $k;
 
2239
                                } else {
 
2240
                                        $xk = $this->x * $k;
 
2241
                                }
 
2242
                                $s .= sprintf('%.2f %.2f %.2f %.2f re %s ', $xk, ($this->h - $this->y) * $k, $w * $k, -$h * $k, $op);
1978
2243
                        }
1979
2244
                        if(is_string($border)) {
1980
2245
                                $x=$this->x;
1981
2246
                                $y=$this->y;
1982
2247
                                if(strpos($border,'L')!==false) {
1983
 
                                        $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-$y)*$k,$x*$k,($this->h-($y+$h))*$k);
 
2248
                                        if ($this->rtl) {
 
2249
                                                $xk = ($x - $w) * $k;
 
2250
                                        } else {
 
2251
                                                $xk = $x * $k;
 
2252
                                        }
 
2253
                                        $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$xk,($this->h-$y)*$k,$xk,($this->h-($y+$h))*$k);
1984
2254
                                }
1985
2255
                                if(strpos($border,'T')!==false) {
1986
 
                                        $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-$y)*$k);
 
2256
                                        if ($this->rtl) {
 
2257
                                                $xk = ($x - $w) * $k;
 
2258
                                                $xwk = $x * $k;
 
2259
                                        } else {
 
2260
                                                $xk = $x * $k;
 
2261
                                                $xwk = ($x + $w) * $k;
 
2262
                                        }
 
2263
                                        $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$xk,($this->h-$y)*$k,$xwk,($this->h-$y)*$k);
1987
2264
                                }
1988
2265
                                if(strpos($border,'R')!==false) {
1989
 
                                        $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',($x+$w)*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-($y+$h))*$k);
 
2266
                                        if ($this->rtl) {
 
2267
                                                $xk = $x * $k;
 
2268
                                        } else {
 
2269
                                                $xk = ($x + $w) * $k;
 
2270
                                        }
 
2271
                                        $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$xk,($this->h-$y)*$k,$xk,($this->h-($y+$h))*$k);
1990
2272
                                }
1991
2273
                                if(strpos($border,'B')!==false) {
1992
 
                                        $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-($y+$h))*$k,($x+$w)*$k,($this->h-($y+$h))*$k);
 
2274
                                        if ($this->rtl) {
 
2275
                                                $xk = ($x - $w) * $k;
 
2276
                                                $xwk = $x * $k;
 
2277
                                        } else {
 
2278
                                                $xk = $x * $k;
 
2279
                                                $xwk = ($x + $w) * $k;
 
2280
                                        }
 
2281
                                        $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$xk,($this->h-($y+$h))*$k,$xwk,($this->h-($y+$h))*$k);
1993
2282
                                }
1994
2283
                        }
1995
2284
                        if($txt != '') {
 
2285
                                // text lenght
1996
2286
                                $width = $this->GetStringWidth($txt);
1997
 
                                if($align == 'R') {
1998
 
                                        $dx = $w - $this->cMargin - $width;
 
2287
                                // ratio between cell lenght and text lenght
 
2288
                                $ratio = ($w - (2 * $this->cMargin)) / $width;
 
2289
                                
 
2290
                                // stretch text if requested
 
2291
                                if (($stretch > 0) AND (($ratio < 1) OR (($ratio > 1) AND (($stretch % 2) == 0)))) {
 
2292
                                        if ($stretch > 2) {
 
2293
                                                // spacing
 
2294
                                                //Calculate character spacing in points
 
2295
                                                $char_space = ($w - (2 * $this->cMargin) - $width) / max($this->GetNumChars($s)-1,1) * $this->k;
 
2296
                                                //Set character spacing
 
2297
                                                $this->_out(sprintf('BT %.2f Tc ET', $char_space));
 
2298
                                        } else {
 
2299
                                                // scaling
 
2300
                                                //Calculate horizontal scaling
 
2301
                                                $horiz_scale = $ratio*100.0;
 
2302
                                                //Set horizontal scaling
 
2303
                                                $this->_out(sprintf('BT %.2f Tz ET', $horiz_scale));
 
2304
                                        }
 
2305
                                        $align = '';
 
2306
                                        $width = $w - (2 * $this->cMargin);
 
2307
                                } else {
 
2308
                                        $stretch == 0;
1999
2309
                                }
2000
 
                                elseif($align=='C') {
 
2310
                                
 
2311
                                if($align == 'L') {
 
2312
                                        if ($this->rtl) {
 
2313
                                                $dx = $w - $this->cMargin - $width;
 
2314
                                        } else {
 
2315
                                                $dx = $this->cMargin;
 
2316
                                        }
 
2317
                                } elseif($align == 'R') {
 
2318
                                        if ($this->rtl) {
 
2319
                                                $dx = $this->cMargin;
 
2320
                                        } else {
 
2321
                                                $dx = $w - $this->cMargin - $width;
 
2322
                                        }
 
2323
                                } elseif($align=='C') {
2001
2324
                                        $dx = ($w - $width)/2;
2002
 
                                }
2003
 
                                else {
 
2325
                                } elseif($align=='J') {
 
2326
                                        if ($this->rtl) {
 
2327
                                                $dx = $w - $this->cMargin - $width;
 
2328
                                        } else {
 
2329
                                                $dx = $this->cMargin;
 
2330
                                        }
 
2331
                                } else {
2004
2332
                                        $dx = $this->cMargin;
2005
2333
                                }
2006
2334
                                if($this->ColorFlag) {
2007
2335
                                        $s .= 'q '.$this->TextColor.' ';
2008
2336
                                }
2009
2337
                                $txt2 = $this->_escapetext($txt);
2010
 
                                $s.=sprintf('BT %.2f %.2f Td (%s) Tj ET', ($this->x + $dx) * $k, ($this->h - ($this->y + 0.5 * $h + 0.3 * $this->FontSize)) * $k, $txt2);
 
2338
                                if ($this->rtl) {
 
2339
                                        $xdk = ($this->x - $dx - $width) * $k;
 
2340
                                } else {
 
2341
                                        $xdk = ($this->x + $dx) * $k;
 
2342
                                }
 
2343
                                // 2008-02-16 Jacek Czekaj - multibyte justification
 
2344
                                if ($align == 'J') {
 
2345
                                        // count number of spaces
 
2346
                                        $ns = substr_count($txt, ' ');
 
2347
                                        // get string width without spaces
 
2348
                                        $width = $this->GetStringWidth(str_replace(' ', '', $txt));
 
2349
                                        // set word position to be used with TJ operator
 
2350
                                        $txt2 = str_replace(chr(0).' ', ') '. -2830*($w-$width-2)/($ns?$ns:1)/$this->FontSize/$this->k . ' (', $txt2);
 
2351
                                }
 
2352
                                $s.=sprintf('BT %.2f %.2f Td [(%s)] TJ ET', $xdk, ($this->h - ($this->y + 0.5 * $h + 0.3 * $this->FontSize)) * $k, $txt2);
 
2353
                                //$s.=sprintf('BT %.2f %.2f Td (%s) Tj ET', $xdk, ($this->h - ($this->y + 0.5 * $h + 0.3 * $this->FontSize)) * $k, $txt2);
2011
2354
                                if($this->underline) {
2012
 
                                        $s.=' '.$this->_dounderline($this->x + $dx, $this->y + 0.5 * $h + 0.3 * $this->FontSize, $txt);
 
2355
                                        if ($this->rtl) {
 
2356
                                                $xdx = $this->x - $dx - $width;
 
2357
                                        } else {
 
2358
                                                $xdx = $this->x + $dx;
 
2359
                                        }
 
2360
                                        $s.=' '.$this->_dounderline($xdx, $this->y + 0.5 * $h + 0.3 * $this->FontSize, $txt);
2013
2361
                                }
2014
2362
                                if($this->ColorFlag) {
2015
2363
                                        $s.=' Q';
2016
2364
                                }
2017
2365
                                if($link) {
2018
 
                                        $this->Link($this->x + $dx, $this->y + 0.5 * $h - 0.5 * $this->FontSize, $width, $this->FontSize, $link);
 
2366
                                        if ($this->rtl) {
 
2367
                                                $xdx = $this->x - $dx - $width;
 
2368
                                        } else {
 
2369
                                                $xdx = $this->x + $dx;
 
2370
                                        }
 
2371
                                        $this->Link($xdx, $this->y + 0.5 * $h - 0.5 * $this->FontSize, $width, $this->FontSize, $link);
2019
2372
                                }
2020
2373
                        }
 
2374
                        
 
2375
                        // output cell
2021
2376
                        if($s) {
 
2377
                                // output cell
2022
2378
                                $this->_out($s);
 
2379
                                // reset text stretching
 
2380
                                if($stretch > 2) {
 
2381
                                        //Reset character horizontal spacing
 
2382
                                        $this->_out('BT 0 Tc ET');
 
2383
                                } elseif($stretch > 0) {
 
2384
                                        //Reset character horizontal scaling
 
2385
                                        $this->_out('BT 100 Tz ET');
 
2386
                                }
2023
2387
                        }
 
2388
                        
2024
2389
                        $this->lasth = $h;
2025
2390
                        if($ln>0) {
2026
 
                                //Go to next line
 
2391
                                //Go to the beginning of the next line
2027
2392
                                $this->y += $h;
2028
2393
                                if($ln == 1) {
2029
 
                                        $this->x = $this->lMargin;
2030
 
                                }
2031
 
                        }
2032
 
                        else {
2033
 
                                $this->x += $w;
 
2394
                                        if ($this->rtl) {
 
2395
                                                $this->x = $this->w - $this->rMargin;
 
2396
                                        } else {
 
2397
                                                $this->x = $this->lMargin;
 
2398
                                        }
 
2399
                                }
 
2400
                        } else {
 
2401
                                // go left or right by case
 
2402
                                if ($this->rtl) {
 
2403
                                        $this->x -= $w;
 
2404
                                } else {
 
2405
                                        $this->x += $w;
 
2406
                                }
2034
2407
                        }
2035
2408
                }
2036
2409
 
2043
2416
                * @param mixed $border Indicates if borders must be drawn around the cell block. The value can be either 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>
2044
2417
                * @param string $align Allows to center or align the text. Possible values are:<ul><li>L or empty string: left align</li><li>C: center</li><li>R: right align</li><li>J: justification (default value)</li></ul>
2045
2418
                * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.
 
2419
                * @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right</li><li>1: to the beginning of the next line [DEFAULT]</li><li>2: below</li></ul>
 
2420
                * @return int number of cells (number of lines)
2046
2421
                * @since 1.3
2047
2422
                * @see SetFont(), SetDrawColor(), SetFillColor(), SetTextColor(), SetLineWidth(), Cell(), Write(), SetAutoPageBreak()
2048
2423
                */
2049
 
                function MultiCell($w, $h, $txt, $border=0, $align='J', $fill=0) {
 
2424
                public function MultiCell($w, $h, $txt, $border=0, $align='J', $fill=0, $ln=1) {
 
2425
                        
 
2426
                        // save current position
 
2427
                        $prevx = $this->x;
 
2428
                        $prevy = $this->y;
 
2429
                        
 
2430
                        // get current page number
 
2431
                        $startpage = $this->page;
 
2432
                        
 
2433
                        // calculate remaining vertical space on first page ($startpage)
 
2434
                        $restspace = $this->getPageHeight() - $this->GetY() - $this->getBreakMargin();
 
2435
                         
2050
2436
                        //Output text with automatic or explicit line breaks
2051
2437
                        $cw = &$this->CurrentFont['cw'];
2052
 
 
 
2438
                        
2053
2439
                        if($w == 0) {
2054
 
                                $w = $this->w - $this->rMargin - $this->x;
 
2440
                                if ($this->rtl) {
 
2441
                                        $w = $this->x - $this->lMargin;
 
2442
                                } else {
 
2443
                                        $w = $this->w - $this->rMargin - $this->x;
 
2444
                                }
2055
2445
                        }
2056
 
 
 
2446
                        
2057
2447
                        $wmax = ($w - 2 * $this->cMargin);
2058
 
 
 
2448
                        
2059
2449
                        $s = str_replace("\r", '', $txt); // remove carriage returns
2060
2450
                        $nb = strlen($s);
2061
 
 
2062
 
                        $b=0;
2063
 
                        if($border) {
2064
 
                                if($border==1) {
2065
 
                                        $border='LTRB';
2066
 
                                        $b='LRT';
2067
 
                                        $b2='LR';
2068
 
                                }
2069
 
                                else {
2070
 
                                        $b2='';
2071
 
                                        if(strpos($border,'L')!==false) {
2072
 
                                                $b2.='L';
2073
 
                                        }
2074
 
                                        if(strpos($border,'R')!==false) {
2075
 
                                                $b2.='R';
2076
 
                                        }
2077
 
                                        $b=(strpos($border,'T')!==false) ? $b2.'T' : $b2;
2078
 
                                }
2079
 
                        }
 
2451
                        
2080
2452
                        $sep=-1;
2081
2453
                        $i=0;
2082
2454
                        $j=0;
2083
2455
                        $l=0;
2084
2456
                        $ns=0;
2085
2457
                        $nl=1;
2086
 
                        while($i<$nb) {
 
2458
                        while($i < $nb) {
2087
2459
                                //Get next character
2088
2460
                                $c = $s{$i};
2089
2461
                                if(preg_match("/[\n]/u", $c)) {
2092
2464
                                                $this->ws = 0;
2093
2465
                                                $this->_out('0 Tw');
2094
2466
                                        }
2095
 
                                        $this->Cell($w, $h, substr($s, $j, $i-$j), $b, 2, $align, $fill);
 
2467
                                        $this->Cell($w, $h, substr($s, $j, $i-$j), 0, 2, $align, $fill, '');
2096
2468
                                        $i++;
2097
2469
                                        $sep=-1;
2098
2470
                                        $j=$i;
2099
2471
                                        $l=0;
2100
2472
                                        $ns=0;
2101
2473
                                        $nl++;
2102
 
                                        if($border and $nl==2) {
2103
 
                                                $b = $b2;
2104
 
                                        }
2105
2474
                                        continue;
2106
2475
                                }
2107
2476
                                if(preg_match("/[ ]/u", $c)) {
2109
2478
                                        $ls = $l;
2110
2479
                                        $ns++;
2111
2480
                                }
2112
 
 
 
2481
                                
2113
2482
                                $l = $this->GetStringWidth(substr($s, $j, $i-$j));
2114
 
 
 
2483
                                
2115
2484
                                if($l > $wmax) {
2116
2485
                                        //Automatic line break
2117
2486
                                        if($sep == -1) {
2122
2491
                                                        $this->ws = 0;
2123
2492
                                                        $this->_out('0 Tw');
2124
2493
                                                }
2125
 
                                                $this->Cell($w, $h, substr($s, $j, $i-$j), $b, 2, $align, $fill);
 
2494
                                                $this->Cell($w, $h, substr($s, $j, $i-$j), 0, 2, $align, $fill, '');
2126
2495
                                        }
2127
2496
                                        else {
2128
2497
                                                if($align=='J') {
2129
 
                                                        $this->ws = ($ns>1) ? ($wmax-$ls)/($ns-1) : 0;
 
2498
                                                        $this->ws = ($ns>1) ? ($wmax-$ls)/1000*$this->FontSize/($ns-1) : 0;
2130
2499
                                                        $this->_out(sprintf('%.3f Tw', $this->ws * $this->k));
2131
2500
                                                }
2132
 
                                                $this->Cell($w, $h, substr($s, $j, $sep-$j), $b, 2, $align, $fill);
 
2501
                                                $this->Cell($w, $h, substr($s, $j, $sep-$j), 0, 2, $align, $fill, '');
2133
2502
                                                $i = $sep + 1;
2134
2503
                                        }
2135
2504
                                        $sep=-1;
2137
2506
                                        $l=0;
2138
2507
                                        $ns=0;
2139
2508
                                        $nl++;
2140
 
                                        if($border AND ($nl==2)) {
2141
 
                                                $b=$b2;
2142
 
                                        }
2143
2509
                                }
2144
2510
                                else {
2145
2511
                                        $i++;
2150
2516
                                $this->ws=0;
2151
2517
                                $this->_out('0 Tw');
2152
2518
                        }
2153
 
                        if($border and is_int(strpos($border,'B'))) {
2154
 
                                $b.='B';
2155
 
                        }
2156
 
                        $this->Cell($w, $h, substr($s, $j, $i-$j), $b, 2, $align, $fill);
2157
 
                        $this->x=$this->lMargin;
 
2519
                        if($align == "J") {
 
2520
                                $align = "L";
 
2521
                        }
 
2522
                        $this->Cell($w, $h, substr($s, $j, $i-$j), 0, 2, $align, $fill, '');
 
2523
                        
 
2524
                        // Get end-of-text Y position
 
2525
                        $currentY = $this->GetY();
 
2526
                        // get latest page number
 
2527
                        $endpage = $this->page;
 
2528
                        
 
2529
                        if (!empty($border)) {
 
2530
                                // check if a new page has been created
 
2531
                                if ($endpage > $startpage) {
 
2532
                                        // design borders around HTML cells.
 
2533
                                        for ($page=$startpage; $page<=$endpage; $page++) {
 
2534
                                                $this->page = $page;
 
2535
                                                if ($page==$startpage) {
 
2536
                                                        $this->y = $this->getPageHeight() - $restspace - $this->getBreakMargin();
 
2537
                                                        $h = $restspace - 1;
 
2538
                                                } elseif ($page==$endpage) {
 
2539
                                                        $this->y = $this->tMargin; // put cursor at the beginning of text
 
2540
                                                        $h = $currentY - $this->tMargin;
 
2541
                                                } else {
 
2542
                                                        $this->y = $this->tMargin; // put cursor at the beginning of text
 
2543
                                                        $h = $this->getPageHeight() - $this->tMargin - $this->getBreakMargin();
 
2544
                                                }
 
2545
                                                $this->Cell($w, $h, "", $border, 1, '', 0);
 
2546
                                        }
 
2547
                                } else {
 
2548
                                        $h = max($h, ($currentY - $prevy));
 
2549
                                        $this->y = $prevy; // put cursor at the beginning of text
 
2550
                                        // design a cell around the text
 
2551
                                        $this->Cell($w, $h, "", $border, 1, '', 0);
 
2552
                                }
 
2553
                        }
 
2554
                        
 
2555
                        // move cursor to specified position
 
2556
                        if($ln>0) {
 
2557
                                //Go to the beginning of the next line
 
2558
                                $this->SetY($currentY);
 
2559
                                if($ln == 2) {
 
2560
                                        $this->SetX($prevx + $w);
 
2561
                                }
 
2562
                        } else {
 
2563
                                // go left or right by case
 
2564
                                $this->page = $startpage;
 
2565
                                $this->y = $prevy;
 
2566
                                $this->SetX($prevx + $w);
 
2567
                        }
 
2568
                                                
 
2569
                        return $nl;
2158
2570
                }
2159
2571
 
2160
2572
                /**
2176
2588
                * @since 1.5
2177
2589
                * @see SetFont(), SetTextColor(), AddLink(), MultiCell(), SetAutoPageBreak()
2178
2590
                */
2179
 
                function Write($h, $txt, $link='', $fill=0) {
2180
 
 
 
2591
                public function Write($h, $txt, $link='', $fill=0) {
2181
2592
                        //Output text in flowing mode
2182
2593
                        $cw = &$this->CurrentFont['cw'];
2183
 
                        $w = $this->w - $this->rMargin - $this->x;
2184
 
                        $wmax = ($w - 2 * $this->cMargin);
2185
 
 
 
2594
                        // calculating remaining line width ($w)
 
2595
                        if ($this->rtl) {
 
2596
                                $w = $this->x - $this->lMargin;
 
2597
                        } else {
 
2598
                                $w = $this->w - $this->rMargin - $this->x;
 
2599
                        }
 
2600
                        $wmax = $w - 2 * $this->cMargin;
2186
2601
                        $s = str_replace("\r", '', $txt);
2187
2602
                        $nb = strlen($s);
2188
 
 
2189
2603
                        // handle single space character
2190
2604
                        if(($nb==1) AND preg_match("/[ ]/u", $s)) {
2191
 
                                $this->x += $this->GetStringWidth($s);
 
2605
                                if ($this->rtl) {
 
2606
                                        $this->x -= $this->GetStringWidth($s);
 
2607
                                } else {
 
2608
                                        $this->x += $this->GetStringWidth($s);
 
2609
                                }
2192
2610
                                return;
2193
2611
                        }
2194
 
 
2195
2612
                        $sep=-1;
2196
2613
                        $i=0;
2197
2614
                        $j=0;
2208
2625
                                        $j = $i;
2209
2626
                                        $l = 0;
2210
2627
                                        if($nl == 1) {
2211
 
                                                $this->x = $this->lMargin;
2212
 
                                                $w = $this->w - $this->rMargin - $this->x;
 
2628
                                                if ($this->rtl) {
 
2629
                                                        $this->x = $this->w - $this->rMargin;
 
2630
                                                        $w = $this->x - $this->lMargin;
 
2631
                                                }
 
2632
                                                else {
 
2633
                                                        $this->x = $this->lMargin;
 
2634
                                                        $w = $this->w - $this->rMargin - $this->x;
 
2635
                                                }
2213
2636
                                                $wmax = ($w - 2 * $this->cMargin);
2214
2637
                                        }
2215
2638
                                        $nl++;
2218
2641
                                if(preg_match("/[ ]/u", $c)) {
2219
2642
                                        $sep= $i;
2220
2643
                                }
2221
 
 
2222
2644
                                $l = $this->GetStringWidth(substr($s, $j, $i-$j));
2223
 
 
2224
2645
                                if($l > $wmax) {
2225
2646
                                        //Automatic line break (word wrapping)
2226
2647
                                        if($sep == -1) {
2227
 
                                                if($this->x > $this->lMargin) {
 
2648
                                                if((!$this->rtl) AND ($this->x > $this->lMargin)) {
2228
2649
                                                        //Move to next line
2229
2650
                                                        $this->x = $this->lMargin;
2230
2651
                                                        $this->y += $h;
2234
2655
                                                        $nl++;
2235
2656
                                                        continue;
2236
2657
                                                }
 
2658
                                                if($this->rtl AND ($this->x < $this->rMargin)) {
 
2659
                                                        //Move to next line
 
2660
                                                        $this->x = $this->w - $this->rMargin;
 
2661
                                                        $this->y += $h;
 
2662
                                                        $w=$this->x - $this->lMargin;
 
2663
                                                        $wmax=($w - 2 * $this->cMargin);
 
2664
                                                        $i++;
 
2665
                                                        $nl++;
 
2666
                                                        continue;
 
2667
                                                }
2237
2668
                                                if($i==$j) {
2238
2669
                                                        $i++;
2239
2670
                                                }
2247
2678
                                        $j = $i;
2248
2679
                                        $l = 0;
2249
2680
                                        if($nl==1) {
2250
 
                                                $this->x = $this->lMargin;
2251
 
                                                $w = $this->w - $this->rMargin - $this->x;
 
2681
                                                if ($this->rtl) {
 
2682
                                                        $this->x = $this->w - $this->rMargin;
 
2683
                                                        $w = $this->x - $this->lMargin;
 
2684
                                                } else {
 
2685
                                                        $this->x = $this->lMargin;
 
2686
                                                        $w = $this->w - $this->rMargin - $this->x;
 
2687
                                                }
2252
2688
                                                $wmax = ($w - 2 * $this->cMargin);
2253
2689
                                        }
2254
2690
                                        $nl++;
2260
2696
                        
2261
2697
                        //Last chunk
2262
2698
                        if($i!=$j) {
2263
 
                                $this->Cell($this->GetStringWidth(substr($s, $j)), $h, substr($s, $j), 0, 0, '', $fill, $link);
 
2699
                                $this->Cell($this->GetStringWidth(substr($s, $j)) + 2 * $this->cMargin, $h, substr($s, $j), 0, 0, '', $fill, $link);
2264
2700
                        }
2265
2701
                }
2266
 
 
 
2702
                
2267
2703
                /**
2268
2704
                * Puts an image in the page. The upper-left corner must be given. The dimensions can be specified in different ways:<ul><li>explicit width and height (expressed in user unit)</li><li>one explicit dimension, the other being calculated automatically in order to keep the original proportions</li><li>no explicit dimension, in which case the image is put at 72 dpi</li></ul>
2269
2705
                * Supported formats are JPEG and PNG.
2270
2706
                * For JPEG, all flavors are allowed:<ul><li>gray scales</li><li>true colors (24 bits)</li><li>CMYK (32 bits)</li></ul>
2271
2707
                * For PNG, are allowed:<ul><li>gray scales on at most 8 bits (256 levels)</li><li>indexed colors</li><li>true colors (24 bits)</li></ul>
2272
 
                * but are not supported:<ul><li>Interlacing</li><li>Alpha channel</li></ul>
2273
2708
                * If a transparent color is defined, it will be taken into account (but will be only interpreted by Acrobat 4 and above).<br />
2274
2709
                * The format can be specified explicitly or inferred from the file extension.<br />
2275
2710
                * It is possible to put a link on the image.<br />
2281
2716
                * @param float $h Height of the image in the page. If not specified or equal to zero, it is automatically calculated.
2282
2717
                * @param string $type Image format. Possible values are (case insensitive): JPG, JPEG, PNG. If not specified, the type is inferred from the file extension.
2283
2718
                * @param mixed $link URL or identifier returned by AddLink().
 
2719
                * @param string $align Indicates the alignment of the pointer next to image insertion relative to image height. The value can be:<ul><li>T: top-right for LTR or top-left for RTL</li><li>M: middle-right for LTR or middle-left for RTL</li><li>B: bottom-right for LTR or bottom-left for RTL</li><li>N: next line</li></ul>
2284
2720
                * @since 1.1
2285
2721
                * @see AddLink()
2286
2722
                */
2287
 
                function Image($file, $x, $y, $w=0, $h=0, $type='', $link='') {
 
2723
                public function Image($file, $x, $y, $w=0, $h=0, $type='', $link='', $align='') {
2288
2724
                        //Put an image on the page
2289
2725
                        if(!isset($this->images[$file])) {
2290
2726
                                //First use of image, get info
2300
2736
                                set_magic_quotes_runtime(0);
2301
2737
                                if($type == 'jpg' or $type == 'jpeg') {
2302
2738
                                        $info=$this->_parsejpg($file);
2303
 
                                }
2304
 
                                elseif($type == 'png') {
 
2739
                                } elseif($type == 'gif') {
 
2740
                                        $info=$this->_parsegif($file);
 
2741
                                } elseif($type == 'png') {
2305
2742
                                        $info=$this->_parsepng($file);
2306
 
                                }
2307
 
                                else {
 
2743
                                }else {
2308
2744
                                        //Allow for additional formats
2309
2745
                                        $mtd='_parse'.$type;
2310
2746
                                        if(!method_exists($this,$mtd)) {
2312
2748
                                        }
2313
2749
                                        $info=$this->$mtd($file);
2314
2750
                                }
 
2751
                                if($info === false) {
 
2752
                                        //If false, we cannot process image
 
2753
                                        return;
 
2754
                                }
2315
2755
                                set_magic_quotes_runtime($mqr);
2316
2756
                                $info['i']=count($this->images)+1;
2317
2757
                                $this->images[$file]=$info;
2332
2772
                        if($h == 0) {
2333
2773
                                $h = $w * $info['h'] / $info['w'];
2334
2774
                        }
2335
 
                        $this->_out(sprintf('q %.2f 0 0 %.2f %.2f %.2f cm /I%d Do Q', $w*$this->k, $h*$this->k, $x*$this->k, ($this->h-($y+$h))*$this->k, $info['i']));
 
2775
                        
 
2776
                        // 2007-10-19 Warren Sherliker
 
2777
                        // Check whether we need a new page first as this does not fit
 
2778
                        // Copied from Cell()
 
2779
                        if((($this->y + $h) > $this->PageBreakTrigger) AND empty($this->InFooter) AND $this->AcceptPageBreak()) {
 
2780
                                // Automatic page break
 
2781
                                $this->AddPage($this->CurOrientation);
 
2782
                                // Reset coordinates to top fo next page
 
2783
                                $x = $this->GetX();
 
2784
                                $y = $this->GetY();
 
2785
                        }
 
2786
                        // 2007-10-19 Warren Sherliker: End Edit
 
2787
                        
 
2788
                        // set bottomcoordinates
 
2789
                        $this->img_rb_y = $y + $h;
 
2790
                        if ($this->rtl) {
 
2791
                                $ximg = ($this->w - $x -$w);
 
2792
                                // set left side coordinate
 
2793
                                $this->img_rb_x = $ximg;
 
2794
                        } else {
 
2795
                                $ximg = $x;
 
2796
                                // set right side coordinate
 
2797
                                $this->img_rb_x = $ximg + $w;
 
2798
                        }
 
2799
                        $xkimg = $ximg * $this->k;
 
2800
                        $this->_out(sprintf('q %.2f 0 0 %.2f %.2f %.2f cm /I%d Do Q', $w*$this->k, $h*$this->k, $xkimg, ($this->h-($y+$h))*$this->k, $info['i']));
 
2801
                        
2336
2802
                        if($link) {
2337
 
                                $this->Link($x, $y, $w, $h, $link);
2338
 
                        }
2339
 
 
2340
 
                        //2002-07-31 - Nicola Asuni
2341
 
                        // set right-bottom corner coordinates
2342
 
                        $this->img_rb_x = $x + $w;
2343
 
                        $this->img_rb_y = $y + $h;
 
2803
                                $this->Link($ximg, $y, $w, $h, $link);
 
2804
                        }
 
2805
                        
 
2806
                        // set pointer to align the successive text/objects
 
2807
                        switch($align) {
 
2808
                                case 'T':{
 
2809
                                        $this->y = $y;
 
2810
                                        $this->x = $this->img_rb_x;
 
2811
                                        break;
 
2812
                                }
 
2813
                                case 'M':{
 
2814
                                        $this->y = $y + round($h/2);
 
2815
                                        $this->x = $this->img_rb_x;
 
2816
                                        break;
 
2817
                                }
 
2818
                                case 'B':{
 
2819
                                        $this->y = $this->img_rb_y;
 
2820
                                        $this->x = $this->img_rb_x;
 
2821
                                        break;
 
2822
                                }
 
2823
                                case 'N':{
 
2824
                                        $this->SetY($this->img_rb_y);
 
2825
                                        break;
 
2826
                                }
 
2827
                                default:{
 
2828
                                        break;
 
2829
                                }
 
2830
                        }
2344
2831
                }
2345
 
 
 
2832
                
 
2833
                
2346
2834
                /**
2347
2835
                * Performs a line break. The current abscissa goes back to the left margin and the ordinate increases by the amount passed in parameter.
2348
2836
                * @param float $h The height of the break. By default, the value equals the height of the last printed cell.
2349
2837
                * @since 1.0
2350
2838
                * @see Cell()
2351
2839
                */
2352
 
                function Ln($h='') {
 
2840
                public function Ln($h='') {
2353
2841
                        //Line feed; default value is last cell height
2354
 
                        $this->x=$this->lMargin;
 
2842
                        if ($this->rtl) {
 
2843
                                $this->x = $this->w - $this->rMargin;
 
2844
                        } else {
 
2845
                                $this->x = $this->lMargin;
 
2846
                        }
2355
2847
                        if(is_string($h)) {
2356
 
                                $this->y+=$this->lasth;
2357
 
                        }
2358
 
                        else {
2359
 
                                $this->y+=$h;
 
2848
                                $this->y += $this->lasth;
 
2849
                        } else {
 
2850
                                $this->y += $h;
2360
2851
                        }
2361
2852
                }
2362
2853
 
2363
2854
                /**
2364
 
                * Returns the abscissa of the current position.
 
2855
                * Returns the relative X value of current position.
 
2856
                * The value is relative to the left border for LTR languages and to the right border for RTL languages.
2365
2857
                * @return float
2366
2858
                * @since 1.2
2367
2859
                * @see SetX(), GetY(), SetY()
2368
2860
                */
2369
 
                function GetX() {
 
2861
                public function GetX() {
2370
2862
                        //Get x position
 
2863
                        if ($this->rtl) {
 
2864
                                return ($this->w - $this->x);
 
2865
                        } else {
 
2866
                                return $this->x;
 
2867
                        }
 
2868
                }
 
2869
                
 
2870
                /**
 
2871
                * Returns the absolute X value of current position.
 
2872
                * @return float
 
2873
                * @since 1.2
 
2874
                * @see SetX(), GetY(), SetY()
 
2875
                */
 
2876
                public function GetAbsX() {
2371
2877
                        return $this->x;
2372
2878
                }
2373
 
 
2374
 
                /**
2375
 
                * Defines the abscissa of the current position. If the passed value is negative, it is relative to the right of the page.
2376
 
                * @param float $x The value of the abscissa.
2377
 
                * @since 1.2
2378
 
                * @see GetX(), GetY(), SetY(), SetXY()
2379
 
                */
2380
 
                function SetX($x) {
2381
 
                        //Set x position
2382
 
                        if($x>=0) {
2383
 
                                $this->x=$x;
2384
 
                        }
2385
 
                        else {
2386
 
                                $this->x=$this->w+$x;
2387
 
                        }
2388
 
                }
2389
 
 
 
2879
                
2390
2880
                /**
2391
2881
                * Returns the ordinate of the current position.
2392
2882
                * @return float
2393
2883
                * @since 1.0
2394
2884
                * @see SetY(), GetX(), SetX()
2395
2885
                */
2396
 
                function GetY() {
 
2886
                public function GetY() {
2397
2887
                        //Get y position
2398
2888
                        return $this->y;
2399
2889
                }
2400
 
 
2401
 
                /**
2402
 
                * Moves the current abscissa back to the left margin and sets the ordinate. If the passed value is negative, it is relative to the bottom of the page.
 
2890
                
 
2891
                /**
 
2892
                * Defines the abscissa of the current position. 
 
2893
                * If the passed value is negative, it is relative to the right of the page (or left if language is RTL).
 
2894
                * @param float $x The value of the abscissa.
 
2895
                * @since 1.2
 
2896
                * @see GetX(), GetY(), SetY(), SetXY()
 
2897
                */
 
2898
                public function SetX($x) {
 
2899
                        //Set x position
 
2900
                        if ($this->rtl) {
 
2901
                                if($x >= 0) {
 
2902
                                        $this->x = $this->w - $x;
 
2903
                                } else {
 
2904
                                        $this->x = abs($x);
 
2905
                                }
 
2906
                        } else {
 
2907
                                if($x >= 0) {
 
2908
                                        $this->x = $x;
 
2909
                                } else {
 
2910
                                        $this->x = $this->w + $x;
 
2911
                                }
 
2912
                        }
 
2913
                }
 
2914
                
 
2915
                /**
 
2916
                * Moves the current abscissa back to the left margin and sets the ordinate.
 
2917
                * If the passed value is negative, it is relative to the bottom of the page.
2403
2918
                * @param float $y The value of the ordinate.
2404
2919
                * @since 1.0
2405
2920
                * @see GetX(), GetY(), SetY(), SetXY()
2406
2921
                */
2407
 
                function SetY($y) {
 
2922
                public function SetY($y) {
2408
2923
                        //Set y position and reset x
2409
 
                        $this->x=$this->lMargin;
2410
 
                        if($y>=0) {
2411
 
                                $this->y=$y;
 
2924
                        if ($this->rtl) {
 
2925
                                $this->x = $this->w - $this->rMargin;
 
2926
                        } else {
 
2927
                                $this->x = $this->lMargin;
2412
2928
                        }
2413
 
                        else {
2414
 
                                $this->y=$this->h+$y;
 
2929
                        if($y >= 0) {
 
2930
                                $this->y = $y;
 
2931
                        } else {
 
2932
                                $this->y = $this->h + $y;
2415
2933
                        }
2416
2934
                }
 
2935
                
2417
2936
 
2418
2937
                /**
2419
2938
                * Defines the abscissa and ordinate of the current position. If the passed values are negative, they are relative respectively to the right and bottom of the page.
2422
2941
                * @since 1.2
2423
2942
                * @see SetX(), SetY()
2424
2943
                */
2425
 
                function SetXY($x, $y) {
 
2944
                public function SetXY($x, $y) {
2426
2945
                        //Set x and y positions
2427
2946
                        $this->SetY($y);
2428
2947
                        $this->SetX($x);
2436
2955
                * @since 1.0
2437
2956
                * @see Close()
2438
2957
                */
2439
 
                function Output($name='',$dest='') {
 
2958
                public function Output($name='',$dest='') {
2440
2959
                        //Output PDF to some destination
2441
2960
                        //Finish document if necessary
2442
2961
                        if($this->state < 3) {
2512
3031
                        return '';
2513
3032
                }
2514
3033
 
2515
 
                // var methods
 
3034
                // Protected methods
2516
3035
 
2517
3036
                /**
2518
3037
                * Check for locale-related bug
2519
3038
                * @access protected
2520
3039
                */
2521
 
                function _dochecks() {
 
3040
                protected function _dochecks() {
2522
3041
                        //Check for locale-related bug
2523
3042
                        if(1.1==1) {
2524
3043
                                $this->Error('Don\'t alter the locale before including class file');
2533
3052
                * Return fonts path
2534
3053
                * @access protected
2535
3054
                */
2536
 
                function _getfontpath() {
2537
 
                        if(!defined('FPDF_FONTPATH') AND is_dir(dirname(__FILE__).'/font')) {
2538
 
                                define('FPDF_FONTPATH', dirname(__FILE__).'/font/');
 
3055
                protected function _getfontpath() {
 
3056
                        if(!defined('K_PATH_FONTS') AND is_dir(dirname(__FILE__).'/font')) {
 
3057
                                define('K_PATH_FONTS', dirname(__FILE__).'/font/');
2539
3058
                        }
2540
 
                        return defined('FPDF_FONTPATH') ? FPDF_FONTPATH : '';
 
3059
                        return defined('K_PATH_FONTS') ? K_PATH_FONTS : '';
2541
3060
                }
2542
3061
 
2543
3062
                /**
2544
3063
                * Start document
2545
3064
                * @access protected
2546
3065
                */
2547
 
                function _begindoc() {
 
3066
                protected function _begindoc() {
2548
3067
                        //Start document
2549
3068
                        $this->state=1;
2550
 
                        $this->_out('%PDF-1.3');
 
3069
                        $this->_out('%PDF-'.$this->PDFVersion);
2551
3070
                }
2552
3071
 
2553
3072
                /**
2554
3073
                * _putpages
2555
3074
                * @access protected
2556
3075
                */
2557
 
                function _putpages() {
 
3076
                protected function _putpages() {
2558
3077
                        $nb = $this->page;
2559
3078
                        if(!empty($this->AliasNbPages)) {
2560
3079
                                $nbstr = $this->UTF8ToUTF16BE($nb, false);
2588
3107
                                                $rect=sprintf('%.2f %.2f %.2f %.2f',$pl[0],$pl[1],$pl[0]+$pl[2],$pl[1]-$pl[3]);
2589
3108
                                                $annots.='<</Type /Annot /Subtype /Link /Rect ['.$rect.'] /Border [0 0 0] ';
2590
3109
                                                if(is_string($pl[4])) {
2591
 
                                                        $annots.='/A <</S /URI /URI ('.$this->_escape($pl[4]).')>>>>';
 
3110
                                                        $annots.='/A <</S /URI /URI '.$this->_uristring($pl[4]).'>>>>';
2592
3111
                                                }
2593
3112
                                                else {
2594
3113
                                                        $l=$this->links[$pl[4]];
2627
3146
                * _putfonts
2628
3147
                * @access protected
2629
3148
                */
2630
 
                function _putfonts() {
 
3149
                protected function _putfonts() {
2631
3150
                        $nf=$this->n;
2632
3151
                        foreach($this->diffs as $diff) {
2633
3152
                                //Encodings
2642
3161
                                $this->_newobj();
2643
3162
                                $this->FontFiles[$file]['n']=$this->n;
2644
3163
                                $font='';
2645
 
                                $f=fopen($this->_getfontpath().$file,'rb',1);
 
3164
                                $f=fopen($this->_getfontpath().strtolower($file),'rb',1);
2646
3165
                                if(!$f) {
2647
 
                                        $this->Error('Font file not found');
 
3166
                                        $this->Error('Font file not found: '.$file);
2648
3167
                                }
2649
3168
                                while(!feof($f)) {
2650
3169
                                        $font .= fread($f, 8192);
2691
3210
                                        }
2692
3211
                                        $this->_out('>>');
2693
3212
                                        $this->_out('endobj');
2694
 
                                } elseif($type=='Type1' || $type=='TrueType') {
 
3213
                                } elseif($type=='Type1' OR $type=='TrueType') {
2695
3214
                                        //Additional Type1 or TrueType font
2696
3215
                                        $this->_newobj();
2697
3216
                                        $this->_out('<</Type /Font');
2745
3264
                * _putimages
2746
3265
                * @access protected
2747
3266
                */
2748
 
                function _putimages() {
 
3267
                protected function _putimages() {
2749
3268
                        $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
2750
3269
                        reset($this->images);
2751
3270
                        while(list($file,$info)=each($this->images)) {
2755
3274
                                $this->_out('/Subtype /Image');
2756
3275
                                $this->_out('/Width '.$info['w']);
2757
3276
                                $this->_out('/Height '.$info['h']);
 
3277
                                
 
3278
                                if (isset($info["masked"])) {
 
3279
                                        $this->_out('/SMask '.($this->n-1).' 0 R');
 
3280
                                }
 
3281
                                
2758
3282
                                if($info['cs']=='Indexed') {
2759
3283
                                        $this->_out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
2760
3284
                                }
2833
3357
                        $this->_putresourcedict();
2834
3358
                        $this->_out('>>');
2835
3359
                        $this->_out('endobj');
 
3360
                        $this->_putjavascript();
 
3361
                        $this->_putbookmarks();
 
3362
                        // encryption
 
3363
                        if ($this->encrypted) {
 
3364
                                $this->_newobj();
 
3365
                                $this->enc_obj_id = $this->n;
 
3366
                                $this->_out('<<');
 
3367
                                $this->_putencryption();
 
3368
                                $this->_out('>>');
 
3369
                                $this->_out('endobj');
 
3370
                        }
2836
3371
                }
2837
3372
                
2838
3373
                /**
2839
3374
                * _putinfo
 
3375
                * Adds some meta information
2840
3376
                * @access protected
2841
3377
                */
2842
 
                function _putinfo() {
 
3378
                protected function _putinfo() {
 
3379
                        $this->_out('/CreationDate ('.$this->_escape('D:'.date('YmdHis')).')');
 
3380
                        $this->_out('/ModDate ('.$this->_escape('D:'.date('YmdHis')).')');
2843
3381
                        $this->_out('/Producer '.$this->_textstring(PDF_PRODUCER));
2844
3382
                        if(!empty($this->title)) {
2845
3383
                                $this->_out('/Title '.$this->_textstring($this->title));
2856
3394
                        if(!empty($this->creator)) {
2857
3395
                                $this->_out('/Creator '.$this->_textstring($this->creator));
2858
3396
                        }
2859
 
                        $this->_out('/CreationDate '.$this->_textstring('D:'.date('YmdHis')));
2860
3397
                }
2861
3398
 
2862
3399
                /**
2863
3400
                * _putcatalog
2864
3401
                * @access protected
2865
3402
                */
2866
 
                function _putcatalog() {
 
3403
                protected function _putcatalog() {
2867
3404
                        $this->_out('/Type /Catalog');
2868
3405
                        $this->_out('/Pages 1 0 R');
2869
3406
                        if($this->ZoomMode=='fullpage') {
2887
3424
                        elseif($this->LayoutMode=='two') {
2888
3425
                                $this->_out('/PageLayout /TwoColumnLeft');
2889
3426
                        }
 
3427
                        if (!empty($this->javascript)) {
 
3428
                                $this->_out('/Names <</JavaScript '.($this->n_js).' 0 R>>');
 
3429
                        }
 
3430
                        if(count($this->outlines)>0) {
 
3431
                                $this->_out('/Outlines '.$this->OutlineRoot.' 0 R');
 
3432
                                $this->_out('/PageMode /UseOutlines');
 
3433
                        }
 
3434
                        if($this->rtl) {
 
3435
                                $this->_out('/ViewerPreferences << /Direction /R2L >>');
 
3436
                        }
2890
3437
                }
2891
3438
 
2892
3439
                /**
2893
3440
                * _puttrailer
2894
3441
                * @access protected
2895
3442
                */
2896
 
                function _puttrailer() {
 
3443
                protected function _puttrailer() {
2897
3444
                        $this->_out('/Size '.($this->n+1));
2898
3445
                        $this->_out('/Root '.$this->n.' 0 R');
2899
3446
                        $this->_out('/Info '.($this->n-1).' 0 R');
 
3447
                        if ($this->encrypted) {
 
3448
                                $this->_out('/Encrypt '.$this->enc_obj_id.' 0 R');
 
3449
                                $this->_out('/ID [()()]');
 
3450
                        }
2900
3451
                }
2901
3452
 
2902
3453
                /**
2911
3462
                * _enddoc
2912
3463
                * @access protected
2913
3464
                */
2914
 
                function _enddoc() {
 
3465
                protected function _enddoc() {
2915
3466
                        $this->_putheader();
2916
3467
                        $this->_putpages();
2917
3468
                        $this->_putresources();
2950
3501
                * _beginpage
2951
3502
                * @access protected
2952
3503
                */
2953
 
                function _beginpage($orientation) {
 
3504
                protected function _beginpage($orientation) {
2954
3505
                        $this->page++;
2955
3506
                        $this->pages[$this->page]='';
2956
3507
                        $this->state=2;
2957
 
                        $this->x=$this->lMargin;
2958
 
                        $this->y=$this->tMargin;
 
3508
                        if ($this->rtl) {
 
3509
                                $this->x = $this->w - $this->rMargin;
 
3510
                        } else {
 
3511
                                $this->x = $this->lMargin;
 
3512
                        }
 
3513
                        $this->y = $this->tMargin;
2959
3514
                        $this->FontFamily='';
2960
3515
                        //Page orientation
2961
3516
                        if(empty($orientation)) {
2990
3545
                * End of page contents
2991
3546
                * @access protected
2992
3547
                */
2993
 
                function _endpage() {
 
3548
                protected function _endpage() {
2994
3549
                        $this->state=1;
2995
3550
                }
2996
3551
 
2998
3553
                * Begin a new object
2999
3554
                * @access protected
3000
3555
                */
3001
 
                function _newobj() {
 
3556
                protected function _newobj() {
3002
3557
                        $this->n++;
3003
3558
                        $this->offsets[$this->n]=strlen($this->buffer);
3004
3559
                        $this->_out($this->n.' 0 obj');
3006
3561
 
3007
3562
                /**
3008
3563
                * Underline text
 
3564
                * @param int $x X coordinate
 
3565
                * @param int $y Y coordinate
 
3566
                * @param string $txt text to underline
3009
3567
                * @access protected
3010
3568
                */
3011
 
                function _dounderline($x,$y,$txt) {
 
3569
                protected function _dounderline($x, $y, $txt) {
3012
3570
                        $up = $this->CurrentFont['up'];
3013
3571
                        $ut = $this->CurrentFont['ut'];
3014
3572
                        $w = $this->GetStringWidth($txt) + $this->ws * substr_count($txt,' ');
3015
3573
                        return sprintf('%.2f %.2f %.2f %.2f re f', $x * $this->k, ($this->h - ($y - $up / 1000 * $this->FontSize)) * $this->k, $w * $this->k, -$ut / 1000 * $this->FontSizePt);
3016
3574
                }
3017
3575
 
 
3576
                
 
3577
                // REWRITTEN by Warren Sherliker wsherliker@gmail.com
 
3578
                // altered to allow compatibility with all sorts of image formats including gif. 
 
3579
                // Can easily extend to work with others
 
3580
                // such as gd xbm etc. which are all supported by php 5+
 
3581
                // (Requires GD library)
 
3582
                
3018
3583
                /**
3019
3584
                * Extract info from a JPEG file
3020
 
                * @access protected
3021
 
                */
3022
 
                function _parsejpg($file) {
 
3585
                * @param string $file image file to parse
 
3586
                * @return string
 
3587
                * @access protected
 
3588
                */
 
3589
                protected function _parsejpg($file) {
 
3590
                        if(!function_exists('imagecreatefromjpeg')) {
 
3591
                                // GD is not installed, try legacy method
 
3592
                                return $this->_legacyparsejpg($file);
 
3593
                        }
 
3594
                        $a=getimagesize($file);
 
3595
                        if(empty($a)) {
 
3596
                                $this->Error('Missing or incorrect image file: '.$file);
 
3597
                        }
 
3598
                        if($a[2]!=2) {
 
3599
                                $this->Error('Not a JPEG file: '.$file);
 
3600
                        }
 
3601
                        $jpeg = imagecreatefromjpeg($file);
 
3602
                        return $this->outputjpg($file, $jpeg);  
 
3603
                }
 
3604
 
 
3605
                /**
 
3606
                * Extract info from a GIF file
 
3607
                * @param string $file image file to parse
 
3608
                * @return string
 
3609
                * @access protected
 
3610
                */
 
3611
                protected function _parsegif($file) {
 
3612
                        if(!function_exists('imagecreatefromgif')) {
 
3613
                                // PDF doesn't support native GIF and GD is not installed
 
3614
                                return false;
 
3615
                        }
 
3616
                        $a=getimagesize($file);
 
3617
                        if(empty($a)) {
 
3618
                                $this->Error('Missing or incorrect image file: '.$file);
 
3619
                        }
 
3620
                        if($a[2]!=1) {
 
3621
                                $this->Error('Not a GIF file: '.$file);
 
3622
                        }
 
3623
                        // Temporary convert file to jpg and then delete this temp data file
 
3624
                        $gif = imagecreatefromgif($file);
 
3625
                        return $this->toJPEG($file, $gif);      
 
3626
                }
 
3627
                
 
3628
                /**
 
3629
                * Extract info from a PNG file
 
3630
                * @param string $file image file to parse
 
3631
                * @return string
 
3632
                * @access protected
 
3633
                */
 
3634
                protected function _parsepng($file) {   
 
3635
                        if(!function_exists('imagecreatefrompng')) {
 
3636
                                // GD is not installed, try legacy method
 
3637
                                return $this->_legacyparsepng($file);
 
3638
                        }
 
3639
                        $f=fopen($file,'rb');
 
3640
                        if(empty($f)) {
 
3641
                                $this->Error('Can\'t open image file: '.$file);
 
3642
                        }
 
3643
                        //Check signature
 
3644
                        if(fread($f,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) {
 
3645
                                $this->Error('Not a PNG file: '.$file);
 
3646
                        }
 
3647
                        //Read header chunk
 
3648
                        fread($f,4);
 
3649
                        if(fread($f,4)!='IHDR') {
 
3650
                                $this->Error('Incorrect PNG file: '.$file);
 
3651
                        }
 
3652
                        // Temporary convert file to jpg and then delete this temp data file
 
3653
                        $a=getimagesize($file);
 
3654
                        $png = imagecreatefrompng($file);
 
3655
                        return $this->toJPEG($file, $png);
 
3656
                }
 
3657
                
 
3658
                /**
 
3659
                * Extract info from a JPEG file without using GD
 
3660
                * @param string $file image file to parse
 
3661
                * @return string
 
3662
                * @access protected
 
3663
                */
 
3664
                protected function _legacyparsejpg($file) {
3023
3665
                        $a=GetImageSize($file);
3024
3666
                        if(empty($a)) {
3025
3667
                                $this->Error('Missing or incorrect image file: '.$file);
3048
3690
                }
3049
3691
 
3050
3692
                /**
3051
 
                * Extract info from a PNG file
 
3693
                * Extract info from a PNG file without using GD
 
3694
                * @param string $file image file to parse
 
3695
                * @return string
3052
3696
                * @access protected
3053
3697
                */
3054
 
                function _parsepng($file) {
 
3698
                protected function _legacyparsepng($file) {
3055
3699
                        $f=fopen($file,'rb');
3056
3700
                        if(empty($f)) {
3057
3701
                                $this->Error('Can\'t open image file: '.$file);
3143
3787
                        fclose($f);
3144
3788
                        return array('w'=>$w, 'h'=>$h, 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'FlateDecode', 'parms'=>$parms, 'pal'=>$pal, 'trns'=>$trns, 'data'=>$data);
3145
3789
                }
 
3790
                
 
3791
                /**
 
3792
                * Convert the loaded php image to a JPEG and then return a structure for the PDF creator.
 
3793
                * @param string $file Image file name.
 
3794
                * @param image $image Image object.
 
3795
                * return image JPEG image object.
 
3796
                * @access protected
 
3797
                */
 
3798
                protected function toJPEG($file, $image) {
 
3799
                        if ($image) {
 
3800
                                // output
 
3801
                                $tempname = tempnam(K_PATH_CACHE,'jpg');
 
3802
                                imagejpeg($image, $tempname, 100);
 
3803
                                imagedestroy($image);
 
3804
                                $retvars = $this->outputjpg($tempname);
 
3805
                                // tidy up by removing temporary image
 
3806
                                unlink($tempname);
 
3807
                                return $retvars;
 
3808
                        } else {
 
3809
                                $this->Error('Can\'t open image file: '.$file);
 
3810
                        }
 
3811
                }
 
3812
                
 
3813
                /**
 
3814
                * Get a JPEG filename and return a structure for the PDF creator.
 
3815
                * @param string $filename JPEG file name.
 
3816
                * @return array structure containing the image data
 
3817
                * @access protected
 
3818
                */
 
3819
                protected function outputjpg($filename) {
 
3820
                        $a=getimagesize($filename);
 
3821
        
 
3822
                        if(!isset($a['channels']) or $a['channels']==3) {
 
3823
                                $colspace='DeviceRGB';
 
3824
                        }
 
3825
                        elseif($a['channels']==4) {
 
3826
                                $colspace='DeviceCMYK';
 
3827
                        }
 
3828
                        else {
 
3829
                                $colspace='DeviceGray';
 
3830
                        }
 
3831
                        $bpc=isset($a['bits']) ? $a['bits'] : 8;
 
3832
                        //Read whole file
 
3833
                        
 
3834
                        $f=fopen($filename,'rb');
 
3835
                        $data='';
 
3836
                        while(!feof($f)) {
 
3837
                                $data.=fread($f,4096);
 
3838
                        }
 
3839
                        fclose($f);
 
3840
                        
 
3841
                        return array('w'=>$a[0],'h'=>$a[1],'cs'=>$colspace,'bpc'=>$bpc,'f'=>'DCTDecode','data'=>$data);                 
 
3842
                }
 
3843
                
 
3844
                /// END OF REWRITE BY Warren Sherliker wsherliker@gmail.com
3146
3845
 
3147
3846
                /**
3148
3847
                * Read a 4-byte integer from file
 
3848
                * @param string $f file name.
 
3849
                * @return 4-byte integer
3149
3850
                * @access protected
3150
3851
                */
3151
 
                function _freadint($f) {
3152
 
                        //Read a 4-byte integer from file
 
3852
                protected function _freadint($f) {
3153
3853
                        $a=unpack('Ni',fread($f,4));
3154
3854
                        return $a['i'];
3155
3855
                }
3156
3856
 
3157
3857
                /**
3158
 
                * Format a text string
 
3858
                * Format a text string for meta information
 
3859
                * @param string $s string to escape.
 
3860
                * @return string escaped string.
3159
3861
                * @access protected
3160
3862
                */
3161
 
                function _textstring($s) {
 
3863
                protected function _textstring($s) {
3162
3864
                        if($this->isunicode) {
3163
3865
                                //Convert string to UTF-16BE
3164
3866
                                $s = $this->UTF8ToUTF16BE($s, true);
3165
3867
                        }
 
3868
                        if ($this->encrypted) {
 
3869
                                $s = $this->_RC4($this->_objectkey($this->n), $s);
 
3870
                        }
3166
3871
                        return '('. $this->_escape($s).')';
3167
3872
                }
3168
 
 
 
3873
                
 
3874
                /**
 
3875
                * Format an URI string
 
3876
                * @param string $s string to escape.
 
3877
                * @return string escaped string.
 
3878
                * @access protected
 
3879
                */
 
3880
                protected function _uristring($s) {
 
3881
                        if ($this->encrypted) {
 
3882
                                $s = $this->_RC4($this->_objectkey($this->n), $s);
 
3883
                        }
 
3884
                        return '('.$this->_escape($s).')';
 
3885
                }
 
3886
                
3169
3887
                /**
3170
3888
                * Format a text string
 
3889
                * @param string $s string to escape.
 
3890
                * @return string escaped string.
3171
3891
                * @access protected
3172
3892
                */
3173
 
                function _escapetext($s) {
 
3893
                protected function _escapetext($s) {
3174
3894
                        if($this->isunicode) {
3175
 
                                //Convert string to UTF-16BE
3176
 
                                $s = $this->UTF8ToUTF16BE($s, false);
 
3895
                                //Convert string to UTF-16BE and reverse RTL language
 
3896
                                $s = $this->utf8StrRev($s, false, $this->tmprtl);
3177
3897
                        }
3178
3898
                        return $this->_escape($s);
3179
3899
                }
3180
3900
 
3181
3901
                /**
3182
3902
                * Add \ before \, ( and )
 
3903
                * @param string $s string to escape.
 
3904
                * @return string escaped string.
3183
3905
                * @access protected
3184
3906
                */
3185
 
                function _escape($s) {
 
3907
                protected function _escape($s) {
3186
3908
                        // the chr(13) substitution fixes the Bugs item #1421290.
3187
3909
                        return strtr($s, array(')' => '\\)', '(' => '\\(', '\\' => '\\\\', chr(13) => '\r'));
3188
3910
                }
3189
3911
 
3190
3912
                /**
3191
 
                *
 
3913
                * Output a stream.
 
3914
                * @param string $s string to output.
3192
3915
                * @access protected
3193
3916
                */
3194
 
                function _putstream($s) {
 
3917
                protected function _putstream($s) {
 
3918
                        if ($this->encrypted) {
 
3919
                                $s = $this->_RC4($this->_objectkey($this->n), $s);
 
3920
                        }
3195
3921
                        $this->_out('stream');
3196
3922
                        $this->_out($s);
3197
3923
                        $this->_out('endstream');
3198
3924
                }
3199
 
 
 
3925
                
3200
3926
                /**
3201
 
                * Add a line to the document
 
3927
                * Output a string to the document.
 
3928
                * @param string $s string to output.
3202
3929
                * @access protected
3203
3930
                */
3204
 
                function _out($s) {
 
3931
                protected function _out($s) {
3205
3932
                        if($this->state==2) {
3206
3933
                                $this->pages[$this->page] .= $s."\n";
3207
3934
                        }
3217
3944
                * @author Nicola Asuni
3218
3945
                * @since 1.52.0.TC005 (2005-01-05)
3219
3946
                */
3220
 
                function _puttruetypeunicode($font) {
 
3947
                protected function _puttruetypeunicode($font) {
3221
3948
                        // Type0 Font
3222
 
                        // A composite font—a font composed of other fonts, organized hierarchically
 
3949
                        // A composite font composed of other fonts, organized hierarchically
3223
3950
                        $this->_newobj();
3224
3951
                        $this->_out('<</Type /Font');
3225
3952
                        $this->_out('/Subtype /Type0');
3226
3953
                        $this->_out('/BaseFont /'.$font['name'].'');
3227
3954
                        $this->_out('/Encoding /Identity-H'); //The horizontal identity mapping for 2-byte CIDs; may be used with CIDFonts using any Registry, Ordering, and Supplement values.
3228
3955
                        $this->_out('/DescendantFonts ['.($this->n + 1).' 0 R]');
 
3956
                        $this->_out('/ToUnicode '.($this->n + 2).' 0 R');
3229
3957
                        $this->_out('>>');
3230
3958
                        $this->_out('endobj');
3231
3959
                        
3235
3963
                        $this->_out('<</Type /Font');
3236
3964
                        $this->_out('/Subtype /CIDFontType2');
3237
3965
                        $this->_out('/BaseFont /'.$font['name'].'');
3238
 
                        $this->_out('/CIDSystemInfo '.($this->n + 1).' 0 R'); 
3239
 
                        $this->_out('/FontDescriptor '.($this->n + 2).' 0 R');
 
3966
                        $this->_out('/CIDSystemInfo '.($this->n + 2).' 0 R'); 
 
3967
                        $this->_out('/FontDescriptor '.($this->n + 3).' 0 R');
3240
3968
                        if (isset($font['desc']['MissingWidth'])){
3241
3969
                                $this->_out('/DW '.$font['desc']['MissingWidth'].''); // The default width for glyphs in the CIDFont MissingWidth
3242
3970
                        }
3245
3973
                                $w .= ''.$cid.' ['.$width.'] '; // define a specific width for each individual CID
3246
3974
                        }
3247
3975
                        $this->_out('/W ['.$w.']'); // A description of the widths for the glyphs in the CIDFont
3248
 
                        $this->_out('/CIDToGIDMap '.($this->n + 3).' 0 R');
 
3976
                        $this->_out('/CIDToGIDMap '.($this->n + 4).' 0 R');
3249
3977
                        $this->_out('>>');
3250
3978
                        $this->_out('endobj');
3251
3979
                        
 
3980
                        // ToUnicode
 
3981
                        // is a stream object that contains the definition of the CMap
 
3982
                        // (PDF Reference 1.3 chap. 5.9)
 
3983
                        $this->_newobj();
 
3984
                        $this->_out('<</Length 345>>');
 
3985
                        $this->_out('stream');
 
3986
                        $this->_out('/CIDInit /ProcSet findresource begin');
 
3987
                        $this->_out('12 dict begin');
 
3988
                        $this->_out('begincmap');
 
3989
                        $this->_out('/CIDSystemInfo');
 
3990
                        $this->_out('<</Registry (Adobe)');
 
3991
                        $this->_out('/Ordering (UCS)');
 
3992
                        $this->_out('/Supplement 0');
 
3993
                        $this->_out('>> def');
 
3994
                        $this->_out('/CMapName /Adobe-Identity-UCS def');
 
3995
                        $this->_out('/CMapType 2 def');
 
3996
                        $this->_out('1 begincodespacerange');
 
3997
                        $this->_out('<0000> <FFFF>');
 
3998
                        $this->_out('endcodespacerange');
 
3999
                        $this->_out('1 beginbfrange');
 
4000
                        $this->_out('<0000> <FFFF> <0000>');
 
4001
                        $this->_out('endbfrange');
 
4002
                        $this->_out('endcmap');
 
4003
                        $this->_out('CMapName currentdict /CMap defineresource pop');
 
4004
                        $this->_out('end');
 
4005
                        $this->_out('end');
 
4006
                        $this->_out('endstream');
 
4007
                        $this->_out('endobj');
 
4008
                        
3252
4009
                        // CIDSystemInfo dictionary
3253
4010
                        // A dictionary containing entries that define the character collection of the CIDFont.
3254
4011
                        $this->_newobj();
3259
4016
                        $this->_out('endobj');
3260
4017
                        
3261
4018
                        // Font descriptor
3262
 
                        // A font descriptor describing the CIDFont’s default metrics other than its glyph widths
 
4019
                        // A font descriptor describing the CIDFont default metrics other than its glyph widths
3263
4020
                        $this->_newobj();
3264
4021
                        $this->_out('<</Type /FontDescriptor');
3265
4022
                        $this->_out('/FontName /'.$font['name']);
3276
4033
                        // Embed CIDToGIDMap
3277
4034
                        // A specification of the mapping from CIDs to glyph indices
3278
4035
                        $this->_newobj();
3279
 
                        $ctgfile = $this->_getfontpath().$font['ctg'];
 
4036
                        $ctgfile = $this->_getfontpath().strtolower($font['ctg']);
3280
4037
                        if(!file_exists($ctgfile)) {
3281
4038
                                $this->Error('Font file not found: '.$ctgfile);
3282
4039
                        }
3327
4084
                 * @author Nicola Asuni
3328
4085
                 * @since 1.53.0.TC005 (2005-01-05)
3329
4086
                 */
3330
 
                function UTF8StringToArray($str) {
 
4087
                protected function UTF8StringToArray($str) {
3331
4088
                        if(!$this->isunicode) {
3332
4089
                                return $str; // string is not in unicode
3333
4090
                        }
3393
4150
                
3394
4151
                /**
3395
4152
                 * Converts UTF-8 strings to UTF16-BE.<br>
 
4153
                 * @param string $str string to process.
 
4154
                 * @param boolean $setbom if true set the Byte Order Mark (BOM = 0xFEFF)
 
4155
                 * @return string
 
4156
                 * @access protected
 
4157
                 * @author Nicola Asuni
 
4158
                 * @since 1.53.0.TC005 (2005-01-05)
 
4159
                 * @uses UTF8StringToArray(), arrUTF8ToUTF16BE()
 
4160
                 */
 
4161
                protected function UTF8ToUTF16BE($str, $setbom=true) {
 
4162
                        if(!$this->isunicode) {
 
4163
                                return $str; // string is not in unicode
 
4164
                        }
 
4165
                        $unicode = $this->UTF8StringToArray($str); // array containing UTF-8 unicode values
 
4166
                        return $this->arrUTF8ToUTF16BE($unicode, $setbom);
 
4167
                }
 
4168
                
 
4169
                /**
 
4170
                 * Converts array of UTF-8 characters to UTF16-BE string.<br>
3396
4171
                 * Based on: http://www.faqs.org/rfcs/rfc2781.html
3397
4172
                 * <pre>
3398
4173
                 *   Encoding UTF-16:
3421
4196
                 *    W1 = 110110yyyyyyyyyy
3422
4197
                 *    W2 = 110111xxxxxxxxxx
3423
4198
                 * </pre>
3424
 
                 * @param string $str string to process.
 
4199
                 * @param array $unicode array containing UTF-8 unicode values
3425
4200
                 * @param boolean $setbom if true set the Byte Order Mark (BOM = 0xFEFF)
3426
4201
                 * @return string
3427
4202
                 * @access protected
3428
4203
                 * @author Nicola Asuni
3429
 
                 * @since 1.53.0.TC005 (2005-01-05)
3430
 
                 * @uses UTF8StringToArray
 
4204
                 * @since 2.1.000 (2008-01-08)
 
4205
                 * @see UTF8ToUTF16BE()
3431
4206
                 */
3432
 
                function UTF8ToUTF16BE($str, $setbom=true) {
3433
 
                        if(!$this->isunicode) {
3434
 
                                return $str; // string is not in unicode
3435
 
                        }
 
4207
                protected function arrUTF8ToUTF16BE($unicode, $setbom=true) {
3436
4208
                        $outstr = ""; // string to be returned
3437
 
                        $unicode = $this->UTF8StringToArray($str); // array containing UTF-8 unicode values
3438
 
                        $numitems = count($unicode);
3439
 
                        
3440
4209
                        if ($setbom) {
3441
4210
                                $outstr .= "\xFE\xFF"; // Byte Order Mark (BOM)
3442
4211
                        }
3458
4227
                        }
3459
4228
                        return $outstr;
3460
4229
                }
3461
 
                
3462
4230
                // ====================================================
3463
4231
                
3464
4232
                /**
3466
4234
                 * @param array $font font
3467
4235
                 * @since 1.1
3468
4236
                 */
3469
 
                function setHeaderFont($font) {
 
4237
                public function setHeaderFont($font) {
3470
4238
                        $this->header_font = $font;
3471
4239
                }
3472
4240
                
3475
4243
                 * @param array $font font
3476
4244
                 * @since 1.1
3477
4245
                 */
3478
 
                function setFooterFont($font) {
 
4246
                public function setFooterFont($font) {
3479
4247
                        $this->footer_font = $font;
3480
4248
                }
3481
4249
                
3484
4252
                 * @param array $language
3485
4253
                 * @since 1.1
3486
4254
                 */
3487
 
                function setLanguageArray($language) {
 
4255
                public function setLanguageArray($language) {
3488
4256
                        $this->l = $language;
 
4257
                        $this->rtl = $this->l['a_meta_dir']=='rtl' ? true : false;
3489
4258
                }
3490
4259
                
3491
4260
                /**
3492
4261
                 * Set document barcode.
3493
4262
                 * @param string $bc barcode
3494
4263
                 */
3495
 
                function setBarcode($bc="") {
 
4264
                public function setBarcode($bc="") {
3496
4265
                        $this->barcode = $bc;
3497
4266
                }
3498
4267
                
3508
4277
                 * @param int $xres x resolution
3509
4278
                 * @param string $code code to print
3510
4279
                 */
3511
 
                function writeBarcode($x, $y, $w, $h, $type, $style, $font, $xres, $code) {
 
4280
                public function writeBarcode($x, $y, $w, $h, $type, $style, $font, $xres, $code) {
3512
4281
                        require_once(dirname(__FILE__)."/barcode/barcode.php");
3513
4282
                        require_once(dirname(__FILE__)."/barcode/i25object.php");
3514
4283
                        require_once(dirname(__FILE__)."/barcode/c39object.php");
3560
4329
                                }
3561
4330
                        }
3562
4331
                        
3563
 
                        $obj->SetFont($font);   
 
4332
                        $obj->SetFont($font);
3564
4333
                        $obj->DrawObject($xres);
3565
4334
                        
3566
4335
                        //use a temporary file....
3573
4342
                }
3574
4343
                
3575
4344
                /**
3576
 
                 * Returns the PDF data.
 
4345
                 * Returns the PDF data.
3577
4346
                 */
3578
 
                function getPDFData() {
 
4347
                public function getPDFData() {
3579
4348
                        if($this->state < 3) {
3580
4349
                                $this->Close();
3581
4350
                        }
3590
4359
                 * @param string $html text to display
3591
4360
                 * @param boolean $ln if true add a new line after text (default = true)
3592
4361
                 * @param int $fill Indicates if the background must be painted (1) or transparent (0). Default value: 0.
 
4362
                 * @param boolean $reseth if true reset the last cell height (default false).
 
4363
                 * @param boolean $cell if true add the default cMargin space to each Write.
3593
4364
                 */
3594
 
                function writeHTML($html, $ln=true, $fill=0) {
3595
 
                                                
 
4365
                public function writeHTML($html, $ln=true, $fill=0, $reseth=false, $cell=false) {
 
4366
                        
3596
4367
                        // store some variables
3597
 
                        $html=strip_tags($html,"<h1><h2><h3><h4><h5><h6><b><u><i><a><img><p><br><br/><strong><em><font><blockquote><li><ul><ol><hr><td><th><tr><table><sup><sub><small>"); //remove all unsupported tags
 
4368
                $html=strip_tags($html,"<h1><h2><h3><h4><h5><h6><b><u><i><a><img><p><br><br/><strong><em><font><blockquote><li><ul><ol><hr><td><th><tr><table><sup><sub><small><span><div>"); //remove all unsupported tags
3598
4369
                        //replace carriage returns, newlines and tabs
3599
4370
                        $repTable = array("\t" => " ", "\n" => " ", "\r" => " ", "\0" => " ", "\x0B" => " "); 
3600
4371
                        $html = strtr($html, $repTable);
3601
4372
                        $pattern = '/(<[^>]+>)/Uu';
3602
4373
                        $a = preg_split($pattern, $html, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); //explodes the string
3603
4374
                        
3604
 
                        if (empty($this->lasth)) {
 
4375
                        if ((empty($this->lasth))OR ($reseth)) {
3605
4376
                                //set row height
3606
4377
                                $this->lasth = $this->FontSize * K_CELL_HEIGHT_RATIO; 
3607
4378
                        }
3611
4382
                                        //Text
3612
4383
                                        if($this->HREF) {
3613
4384
                                                $this->addHtmlLink($this->HREF, $element, $fill);
3614
 
                                        }
3615
 
                                        elseif($this->tdbegin) {
 
4385
                                        } elseif($this->tdbegin) {
3616
4386
                                                if((strlen(trim($element)) > 0) AND ($element != "&nbsp;")) {
3617
4387
                                                        $this->Cell($this->tdwidth, $this->tdheight, $this->unhtmlentities($element), $this->tableborder, '', $this->tdalign, $this->tdbgcolor);
3618
 
                                                }
3619
 
                                                elseif($element == "&nbsp;") {
 
4388
                                                } elseif($element == "&nbsp;") {
3620
4389
                                                        $this->Cell($this->tdwidth, $this->tdheight, '', $this->tableborder, '', $this->tdalign, $this->tdbgcolor);
3621
4390
                                                }
3622
 
                                        }
3623
 
                                        else {
3624
 
                                                $this->Write($this->lasth, stripslashes($this->unhtmlentities($element)), '', $fill);
3625
 
                                        }
3626
 
                                }
3627
 
                                else {
 
4391
                                        } else {
 
4392
                                                
 
4393
                                                $ctmpmargin = $this->cMargin;
 
4394
                                                if(!$cell) {
 
4395
                                                        $this->cMargin = 0;
 
4396
                                                }
 
4397
                                                $this->Write($this->lasth, stripslashes($this->unhtmlentities($element)), '', $fill, 0);
 
4398
                                                $this->cMargin = $ctmpmargin;
 
4399
                                        }
 
4400
                                } else {
3628
4401
                                        $element = substr($element, 1, -1);
3629
4402
                                        //Tag
3630
4403
                                        if($element{0}=='/') {
3659
4432
                 * @param float $y upper-left corner Y coordinate
3660
4433
                 * @param string $html html text to print. Default value: empty string.
3661
4434
                 * @param mixed $border Indicates if borders must be drawn around the cell. The value can be either 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>
3662
 
                 * @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right</li><li>1: to the beginning of the next line</li><li>2: below</li></ul>
 
4435
                 * @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right (or left for RTL language)</li><li>1: to the beginning of the next line</li><li>2: below</li></ul>
3663
4436
        Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.
3664
4437
                 * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.
 
4438
                 * @param boolean $reseth if true reset the last cell height (default false).
3665
4439
                 * @see Cell()
3666
4440
                 */
3667
 
                function writeHTMLCell($w, $h, $x, $y, $html='', $border=0, $ln=0, $fill=0) {
 
4441
                public function writeHTMLCell($w, $h, $x, $y, $html='', $border=0, $ln=0, $fill=0, $reseth=false) {
3668
4442
                        
3669
 
                        if (empty($this->lasth)) {
 
4443
                        if ((empty($this->lasth))OR ($reseth)) {
3670
4444
                                //set row height
3671
 
                                $this->lasth = $this->FontSize * K_CELL_HEIGHT_RATIO; 
3672
 
                        }
3673
 
                        
3674
 
                        if (empty($x)) {
 
4445
                                $this->lasth = $this->FontSize * K_CELL_HEIGHT_RATIO;
 
4446
                        }
 
4447
                        
 
4448
                        // get current page number
 
4449
                        $startpage = $this->page;
 
4450
                        
 
4451
                        if (!empty($y)) {
 
4452
                                $this->SetY($y);
 
4453
                        } else {
 
4454
                                $y = $this->GetY();
 
4455
                        }
 
4456
                        if (!empty($x)) {
 
4457
                                $this->SetX($x);
 
4458
                        } else {
3675
4459
                                $x = $this->GetX();
3676
4460
                        }
3677
 
                        if (empty($y)) {
3678
 
                                $y = $this->GetY();
3679
 
                        }
3680
 
                        
3681
 
                        // get current page number
3682
 
                        $pagenum = $this->page;
3683
 
                        
3684
 
                        $this->SetX($x);
3685
 
                        $this->SetY($y);
3686
 
                                        
 
4461
                        
3687
4462
                        if(empty($w)) {
3688
 
                                $w = $this->fw - $x - $this->rMargin;
 
4463
                                if ($this->rtl) {
 
4464
                                        $w = $this->x - $this->lMargin;
 
4465
                                } else {
 
4466
                                        $w = $this->w - $this->rMargin - $this->x;
 
4467
                                }
3689
4468
                        }
3690
4469
                        
3691
4470
                        // store original margin values
3693
4472
                        $rMargin = $this->rMargin;
3694
4473
                        
3695
4474
                        // set new margin values
3696
 
                        $this->SetLeftMargin($x);
3697
 
                        $this->SetRightMargin($this->fw - $x - $w);
3698
 
                                        
3699
 
                        // calculate remaining vertical space on page
 
4475
                        if ($this->rtl) {
 
4476
                                $this->SetLeftMargin($this->x - $w);
 
4477
                                $this->SetRightMargin($this->w - $this->x);
 
4478
                        } else {
 
4479
                                $this->SetLeftMargin($this->x);
 
4480
                                $this->SetRightMargin($this->w - $this->x - $w);
 
4481
                        }
 
4482
                        
 
4483
                        // calculate remaining vertical space on first page ($startpage)
3700
4484
                        $restspace = $this->getPageHeight() - $this->GetY() - $this->getBreakMargin();
3701
4485
                        
3702
 
                        $this->writeHTML($html, true, $fill); // write html text
3703
 
                        
3704
 
                        $currentY =  $this->GetY();
3705
 
                        
3706
 
                        // check if a new page has been created
3707
 
                        if ($this->page > $pagenum) {
3708
 
                                // design a cell around the text on first page
3709
 
                                $currentpage = $this->page;
3710
 
                                $this->page = $pagenum;
3711
 
                                $this->SetY($this->getPageHeight() - $restspace - $this->getBreakMargin());
3712
 
                                $h = $restspace - 1;
3713
 
                                $this->Cell($w, $h, "", $border, $ln, 'L', 0);
3714
 
                                // design a cell around the text on last page
3715
 
                                $this->page = $currentpage;
3716
 
                                $h = $currentY - $this->tMargin;
3717
 
                                $this->SetY($this->tMargin); // put cursor at the beginning of text
3718
 
                                $this->Cell($w, $h, "", $border, $ln, 'L', 0);
3719
 
                        } else {
3720
 
                                $h = max($h, ($currentY - $y));
3721
 
                                $this->SetY($y); // put cursor at the beginning of text
3722
 
                                // design a cell around the text
3723
 
                                $this->Cell($w, $h, "", $border, $ln, 'L', 0);
 
4486
                        // Write HTML text
 
4487
                        $this->writeHTML($html, true, $fill, $reseth, true); 
 
4488
                        
 
4489
                        // Get end-of-text Y position
 
4490
                        $currentY = $this->GetY();
 
4491
                        // get latest page number
 
4492
                        $endpage = $this->page;
 
4493
                        
 
4494
                        if (!empty($border)) {
 
4495
                                // check if a new page has been created
 
4496
                                if ($endpage > $startpage) {
 
4497
                                        // design borders around HTML cells.
 
4498
                                        for ($page=$startpage; $page<=$endpage; $page++) {
 
4499
                                                $this->page = $page;
 
4500
                                                if ($page==$startpage) {
 
4501
                                                        $this->SetY($this->getPageHeight() - $restspace - $this->getBreakMargin());
 
4502
                                                        $h = $restspace - 1;
 
4503
                                                } elseif ($page==$endpage) {
 
4504
                                                        $this->SetY($this->tMargin); // put cursor at the beginning of text
 
4505
                                                        $h = $currentY - $this->tMargin;
 
4506
                                                } else {
 
4507
                                                        $this->SetY($this->tMargin); // put cursor at the beginning of text
 
4508
                                                        $h = $this->getPageHeight() - $this->tMargin - $this->getBreakMargin();
 
4509
                                                }
 
4510
                                                $this->Cell($w, $h, "", $border, 1, '', 0);
 
4511
                                        }
 
4512
                                } else {
 
4513
                                        $h = max($h, ($currentY - $y));
 
4514
                                        $this->SetY($y); // put cursor at the beginning of text
 
4515
                                        // design a cell around the text
 
4516
                                        $this->Cell($w, $h, "", $border, 1, '', 0);
 
4517
                                }
3724
4518
                        }
3725
4519
                        
3726
4520
                        // restore original margin values
3727
4521
                        $this->SetLeftMargin($lMargin);
3728
4522
                        $this->SetRightMargin($rMargin);
3729
4523
                        
3730
 
                        if ($ln) {
3731
 
                                $this->Ln(0);
 
4524
                        
 
4525
                        if($ln>0) {
 
4526
                                //Go to the beginning of the next line
 
4527
                                $this->SetY($currentY);
 
4528
                                if($ln == 2) {
 
4529
                                        $this->SetX($x + $w);
 
4530
                                }
 
4531
                        } else {
 
4532
                                // go left or right by case
 
4533
                                $this->page = $startpage;
 
4534
                                $this->y = $y;
 
4535
                                $this->SetX($x + $w);
3732
4536
                        }
 
4537
                        
3733
4538
                }
3734
4539
                
3735
4540
                /**
3739
4544
                 * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.
3740
4545
                 * @access private
3741
4546
                 */
3742
 
                function openHTMLTagHandler($tag, $attr, $fill=0) {
 
4547
                private function openHTMLTagHandler($tag, $attr, $fill=0) {
 
4548
                        // check for text direction attribute
 
4549
                        if (isset($attr['dir'])) {
 
4550
                                        $this->tmprtl = $attr['dir']=='rtl' ? 'R' : 'L';
 
4551
                        } else {
 
4552
                                $this->tmprtl = false;
 
4553
                        }
3743
4554
                        //Opening tag
3744
4555
                        switch($tag) {
3745
4556
                                case 'table': {
3784
4595
                                                                break;
3785
4596
                                                        }
3786
4597
                                                }
 
4598
                                        } else {
 
4599
                                                if($this->rtl) {
 
4600
                                                        $this->tdalign = "R";
 
4601
                                                } else {
 
4602
                                                        $this->tdalign = "L";
 
4603
                                                }
3787
4604
                                        }
3788
4605
                                        if ((isset($attr['bgcolor'])) AND ($attr['bgcolor'] != '')) {
3789
4606
                                                $coul = $this->convertColorHexToDec($attr['bgcolor']);
3803
4620
                                        }
3804
4621
                                        $x = $this->GetX();
3805
4622
                                        $y = $this->GetY();
3806
 
                                        $this->SetLineWidth(0.2);
 
4623
                                        $this->GetLineWidth();
 
4624
                                        $prevlinewidth = $this->SetLineWidth(0.2);
3807
4625
                                        $this->Line($x, $y, $x + $hrWidth, $y);
3808
 
                                        $this->SetLineWidth(0.2);
 
4626
                                        $this->SetLineWidth($prevlinewidth);
3809
4627
                                        $this->Ln();
3810
4628
                                        break;
3811
4629
                                }
3830
4648
                                case 'img': {
3831
4649
                                        if(isset($attr['src'])) {
3832
4650
                                                // replace relative path with real server path
3833
 
                                                $attr['src'] = str_replace(K_PATH_URL_CACHE, K_PATH_CACHE, $attr['src']);
 
4651
                                                if ($attr['src'][0] == '/') {
 
4652
                                                        $attr['src'] = $_SERVER['DOCUMENT_ROOT'].$attr['src'];
 
4653
                                                }
 
4654
                                                $attr['src'] = str_replace(K_PATH_URL, K_PATH_MAIN, $attr['src']);
3834
4655
                                                if(!isset($attr['width'])) {
3835
4656
                                                        $attr['width'] = 0;
3836
4657
                                                }
3837
4658
                                                if(!isset($attr['height'])) {
3838
4659
                                                        $attr['height'] = 0;
3839
4660
                                                }
3840
 
                                                
3841
 
                                                $this->Image($attr['src'], $this->GetX(),$this->GetY(), $this->pixelsToMillimeters($attr['width']), $this->pixelsToMillimeters($attr['height']));
3842
 
                                                //$this->SetX($this->img_rb_x);
3843
 
                                                $this->SetY($this->img_rb_y);
 
4661
                                                if(!isset($attr['align'])) {
 
4662
                                                        $align = 'N';
 
4663
                                                } else {
 
4664
                                                        switch($attr['align']) {
 
4665
                                                                case 'top':{
 
4666
                                                                        $align = 'T';
 
4667
                                                                        break;
 
4668
                                                                }
 
4669
                                                                case 'middle':{
 
4670
                                                                        $align = 'M';
 
4671
                                                                        break;
 
4672
                                                                }
 
4673
                                                                case 'bottom':{
 
4674
                                                                        $align = 'B';
 
4675
                                                                        break;
 
4676
                                                                }
 
4677
                                                                default:{
 
4678
                                                                        $align = 'N';
 
4679
                                                                        break;
 
4680
                                                                }
 
4681
                                                        }
 
4682
                                                }
 
4683
                                                $this->Image($attr['src'], $this->GetX(),$this->GetY(), $this->pixelsToMillimeters($attr['width']), $this->pixelsToMillimeters($attr['height']), '', '', $align);
3844
4684
                                                
3845
4685
                                        }
3846
4686
                                        break;
3858
4698
                                case 'li': {
3859
4699
                                        $this->Ln();
3860
4700
                                        if ($this->listordered) {
 
4701
                                                if (isset($attr['value'])) {
 
4702
                                                        $this->listcount = intval($attr['value']);
 
4703
                                                }
3861
4704
                                                $this->lispacer = "    ".(++$this->listcount).". ";
3862
 
                                        }
3863
 
                                        else {
 
4705
                                        } else {
3864
4706
                                                //unordered list simbol
3865
4707
                                                $this->lispacer = "    -  ";
3866
4708
                                        }
 
4709
                                        $rtldir = $this->tmprtl;
 
4710
                                        $this->tmprtl = false;
3867
4711
                                        $this->Write($this->lasth, $this->lispacer, '', $fill);
 
4712
                                        $this->tmprtl = $rtldir;
3868
4713
                                        break;
3869
4714
                                }
3870
4715
                                case 'blockquote':
3871
4716
                                case 'br': {
3872
4717
                                        $this->Ln();
3873
4718
                                        if(strlen($this->lispacer) > 0) {
3874
 
                                                $this->x += $this->GetStringWidth($this->lispacer);
 
4719
                                                if ($this->rtl) {
 
4720
                                                        $this->x -= $this->GetStringWidth($this->lispacer);
 
4721
                                                } else {
 
4722
                                                        $this->x += $this->GetStringWidth($this->lispacer);
 
4723
                                                }
3875
4724
                                        }
3876
4725
                                        break;
3877
4726
                                }
3908
4757
                                                $this->issetcolor=true;
3909
4758
                                        }
3910
4759
                                        if (isset($attr['face']) and in_array(strtolower($attr['face']), $this->fontlist)) {
3911
 
                                                $this->SetFont(strtolower($attr['FACE']));
 
4760
                                                $this->SetFont(strtolower($attr['face']));
3912
4761
                                                $this->issetfont=true;
3913
4762
                                        }
3914
4763
                                        if (isset($attr['size'])) {
3944
4793
                 * @param string $tag tag name (in uppercase)
3945
4794
                 * @access private
3946
4795
                 */
3947
 
                function closedHTMLTagHandler($tag) {
 
4796
                private function closedHTMLTagHandler($tag) {
3948
4797
                        //Closing tag
3949
4798
                        switch($tag) {
3950
4799
                                case 'td':
3952
4801
                                        $this->tdbegin = false;
3953
4802
                                        $this->tdwidth = 0;
3954
4803
                                        $this->tdheight = 0;
3955
 
                                        $this->tdalign = "L";
 
4804
                                        if($this->rtl) {
 
4805
                                                $this->tdalign = "R";
 
4806
                                        } else {
 
4807
                                                $this->tdalign = "L";
 
4808
                                        }
3956
4809
                                        $this->tdbgcolor = false;
3957
4810
                                        $this->SetFillColor($this->prevFillColor[0], $this->prevFillColor[1], $this->prevFillColor[2]);
3958
4811
                                        break;
4021
4874
                                        $this->lasth = $this->FontSize * K_CELL_HEIGHT_RATIO;
4022
4875
                                        break;
4023
4876
                                }
4024
 
                                case 'ul': {
 
4877
                                case 'p': {
 
4878
                                        $this->Ln();
4025
4879
                                        $this->Ln();
4026
4880
                                        break;
4027
4881
                                }
 
4882
                                case 'ul':
4028
4883
                                case 'ol': {
4029
4884
                                        $this->Ln();
 
4885
                                        $this->Ln();
4030
4886
                                        break;
4031
4887
                                }
4032
4888
                                case 'li': {
4051
4907
                                        break;
4052
4908
                                }
4053
4909
                        }
 
4910
                        $this->tmprtl = false;
4054
4911
                }
4055
4912
                
4056
4913
                /**
4059
4916
                 * @param boolean $enable
4060
4917
                 * @access private
4061
4918
                 */
4062
 
                function setStyle($tag, $enable) {
 
4919
                private function setStyle($tag, $enable) {
4063
4920
                        //Modify style and select corresponding font
4064
4921
                        $this->$tag += ($enable ? 1 : -1);
4065
4922
                        $style='';
4078
4935
                 * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.
4079
4936
                 * @access public
4080
4937
                 */
4081
 
                function addHtmlLink($url, $name, $fill=0) {
 
4938
                public function addHtmlLink($url, $name, $fill=0) {
4082
4939
                        //Put a hyperlink
4083
4940
                        $this->SetTextColor(0, 0, 255);
4084
4941
                        $this->setStyle('u', true);
4094
4951
                 * @return array
4095
4952
                 * @access private
4096
4953
                 */
4097
 
                function convertColorHexToDec($color = "#000000"){
 
4954
                private function convertColorHexToDec($color = "#000000"){
4098
4955
                        $tbl_color = array();
4099
4956
                        $tbl_color['R'] = hexdec(substr($color, 1, 2));
4100
4957
                        $tbl_color['G'] = hexdec(substr($color, 3, 2));
4108
4965
                 * @return float millimeters
4109
4966
                 * @access private
4110
4967
                 */
4111
 
                function pixelsToMillimeters($px){
 
4968
                private function pixelsToMillimeters($px){
4112
4969
                        return $px * 25.4 / 72;
4113
4970
                }
4114
4971
                        
4119
4976
                 * @param $text_to_convert Text to convert.
4120
4977
                 * @return string converted
4121
4978
                 */
4122
 
                function unhtmlentities($text_to_convert) {
4123
 
                        require_once(dirname(__FILE__).'/html_entity_decode_php4.php');
4124
 
                        return html_entity_decode_php4($text_to_convert);
4125
 
                }
4126
 
        } // END OF CLASS
 
4979
                public function unhtmlentities($text_to_convert) {
 
4980
                        return html_entity_decode($text_to_convert, ENT_QUOTES, $this->encoding);
 
4981
                }
 
4982
                
 
4983
                // ENCRYPTION METHODS ----------------------------------
 
4984
                // SINCE 2.0.000 (2008-01-02)
 
4985
                /**
 
4986
                * Compute encryption key depending on object number where the encrypted data is stored
 
4987
                * @param int $n object number
 
4988
                * @since 2.0.000 (2008-01-02)
 
4989
                */
 
4990
                protected function _objectkey($n) {
 
4991
                        return substr($this->_md5_16($this->encryption_key.pack('VXxx',$n)),0,10);
 
4992
                }
 
4993
                
 
4994
                /**
 
4995
                 * Put encryption on PDF document
 
4996
                 * @since 2.0.000 (2008-01-02)
 
4997
                 */
 
4998
                protected function _putencryption() {
 
4999
                        $this->_out('/Filter /Standard');
 
5000
                        $this->_out('/V 1');
 
5001
                        $this->_out('/R 2');
 
5002
                        $this->_out('/O ('.$this->_escape($this->Ovalue).')');
 
5003
                        $this->_out('/U ('.$this->_escape($this->Uvalue).')');
 
5004
                        $this->_out('/P '.$this->Pvalue);
 
5005
                }
 
5006
                
 
5007
                /**
 
5008
                * Returns the input text exrypted using RC4 algorithm and the specified key.
 
5009
                * RC4 is the standard encryption algorithm used in PDF format
 
5010
                * @param string $key encryption key
 
5011
                * @param String $text input text to be encrypted
 
5012
                * @return String encrypted text
 
5013
                * @since 2.0.000 (2008-01-02)
 
5014
                * @author Klemen Vodopivec
 
5015
                */
 
5016
                protected function _RC4($key, $text) {
 
5017
                        if ($this->last_rc4_key != $key) {
 
5018
                                $k = str_repeat($key, 256/strlen($key)+1);
 
5019
                                $rc4 = range(0,255);
 
5020
                                $j = 0;
 
5021
                                for ($i=0; $i<256; $i++) {
 
5022
                                        $t = $rc4[$i];
 
5023
                                        $j = ($j + $t + ord($k{$i})) % 256;
 
5024
                                        $rc4[$i] = $rc4[$j];
 
5025
                                        $rc4[$j] = $t;
 
5026
                                }
 
5027
                                $this->last_rc4_key = $key;
 
5028
                                $this->last_rc4_key_c = $rc4;
 
5029
                        } else {
 
5030
                                $rc4 = $this->last_rc4_key_c;
 
5031
                        }
 
5032
                        $len = strlen($text);
 
5033
                        $a = 0;
 
5034
                        $b = 0;
 
5035
                        $out = '';
 
5036
                        for ($i=0; $i<$len; $i++) {
 
5037
                                $a = ($a+1)%256;
 
5038
                                $t= $rc4[$a];
 
5039
                                $b = ($b+$t)%256;
 
5040
                                $rc4[$a] = $rc4[$b];
 
5041
                                $rc4[$b] = $t;
 
5042
                                $k = $rc4[($rc4[$a]+$rc4[$b])%256];
 
5043
                                $out.=chr(ord($text{$i}) ^ $k);
 
5044
                        }
 
5045
                        return $out;
 
5046
                }
 
5047
                
 
5048
                /**
 
5049
                * Encrypts a string using MD5 and returns it's value as a binary string.
 
5050
                * @param string $str input string
 
5051
                * @return String MD5 encrypted binary string
 
5052
                * @since 2.0.000 (2008-01-02)
 
5053
                * @author Klemen Vodopivec
 
5054
                */
 
5055
                protected function _md5_16($str) {
 
5056
                        return pack('H*',md5($str));
 
5057
                }
 
5058
                
 
5059
                /**
 
5060
                * Compute O value (used for RC4 encryption)
 
5061
                * @param String $user_pass user password
 
5062
                * @param String $owner_pass user password
 
5063
                * @return String O value
 
5064
                * @since 2.0.000 (2008-01-02)
 
5065
                * @author Klemen Vodopivec
 
5066
                */
 
5067
                protected function _Ovalue($user_pass, $owner_pass) {
 
5068
                        $tmp = $this->_md5_16($owner_pass);
 
5069
                        $owner_RC4_key = substr($tmp,0,5);
 
5070
                        return $this->_RC4($owner_RC4_key, $user_pass);
 
5071
                }
 
5072
                
 
5073
                /**
 
5074
                * Compute U value (used for RC4 encryption)
 
5075
                * @return String U value
 
5076
                * @since 2.0.000 (2008-01-02)
 
5077
                * @author Klemen Vodopivec
 
5078
                */
 
5079
                protected function _Uvalue() {
 
5080
                        return $this->_RC4($this->encryption_key, $this->padding);
 
5081
                }
 
5082
                
 
5083
                /**
 
5084
                * Compute encryption key
 
5085
                * @param String $user_pass user password
 
5086
                * @param String $owner_pass user password
 
5087
                * @param String $protection protection type
 
5088
                * @since 2.0.000 (2008-01-02)
 
5089
                * @author Klemen Vodopivec
 
5090
                */
 
5091
                protected function _generateencryptionkey($user_pass, $owner_pass, $protection) {
 
5092
                        // Pad passwords
 
5093
                        $user_pass = substr($user_pass.$this->padding,0,32);
 
5094
                        $owner_pass = substr($owner_pass.$this->padding,0,32);
 
5095
                        // Compute O value
 
5096
                        $this->Ovalue = $this->_Ovalue($user_pass,$owner_pass);
 
5097
                        // Compute encyption key
 
5098
                        $tmp = $this->_md5_16($user_pass.$this->Ovalue.chr($protection)."\xFF\xFF\xFF");
 
5099
                        $this->encryption_key = substr($tmp,0,5);
 
5100
                        // Compute U value
 
5101
                        $this->Uvalue = $this->_Uvalue();
 
5102
                        // Compute P value
 
5103
                        $this->Pvalue = -(($protection^255)+1);
 
5104
                }
 
5105
                
 
5106
                /**
 
5107
                * Set document protection
 
5108
                * The permission array is composed of values taken from the following ones:
 
5109
                * - copy: copy text and images to the clipboard
 
5110
                * - print: print the document
 
5111
                * - modify: modify it (except for annotations and forms)
 
5112
                * - annot-forms: add annotations and forms 
 
5113
                * Remark: the protection against modification is for people who have the full Acrobat product.
 
5114
                * If you don't set any password, the document will open as usual. If you set a user password, the PDF viewer will ask for it before displaying the document. The master password, if different from the user one, can be used to get full access.
 
5115
                * Note: protecting a document requires to encrypt it, which increases the processing time a lot. This can cause a PHP time-out in some cases, especially if the document contains images or fonts.
 
5116
                * @param Array $permissions the set of permissions. Empty by default (only viewing is allowed). (print, modify, copy, annot-forms)
 
5117
                * @param String $user_pass user password. Empty by default.
 
5118
                * @param String $owner_pass owner password. If not specified, a random value is used.
 
5119
                * @since 2.0.000 (2008-01-02)
 
5120
                * @author Klemen Vodopivec
 
5121
                */
 
5122
                public function SetProtection($permissions=array(),$user_pass='',$owner_pass=null) {
 
5123
                        $options = array('print' => 4, 'modify' => 8, 'copy' => 16, 'annot-forms' => 32);
 
5124
                        $protection = 192;
 
5125
                        foreach($permissions as $permission) {
 
5126
                                if (!isset($options[$permission])) {
 
5127
                                        $this->Error('Incorrect permission: '.$permission);
 
5128
                                }
 
5129
                                $protection += $options[$permission];
 
5130
                        }
 
5131
                        if ($owner_pass === null) {
 
5132
                                $owner_pass = uniqid(rand());
 
5133
                        }
 
5134
                        $this->encrypted = true;
 
5135
                        $this->_generateencryptionkey($user_pass, $owner_pass, $protection);
 
5136
                }
 
5137
                
 
5138
                // END OF ENCRYPTION FUNCTIONS -------------------------
 
5139
                
 
5140
                // START TRANSFORMATIONS SECTION -----------------------
 
5141
                // authors: Moritz Wagner, Andreas Wurmser, Nicola Asuni
 
5142
                
 
5143
                /**
 
5144
                * Starts a 2D tranformation saving current graphic state.
 
5145
                * This function must be called before scaling, mirroring, translation, rotation and skewing.
 
5146
                * Use StartTransform() before, and StopTransform() after the transformations to restore the normal behavior.
 
5147
                * @since 2.1.000 (2008-01-07)
 
5148
                * @see StartTransform(), StopTransform()
 
5149
                */
 
5150
                public function StartTransform() {
 
5151
                        $this->_out('q');
 
5152
                }
 
5153
                
 
5154
                /**
 
5155
                * Stops a 2D tranformation restoring previous graphic state.
 
5156
                * This function must be called after scaling, mirroring, translation, rotation and skewing.
 
5157
                * Use StartTransform() before, and StopTransform() after the transformations to restore the normal behavior.
 
5158
                * @since 2.1.000 (2008-01-07)
 
5159
                * @see StartTransform(), StopTransform()
 
5160
                */
 
5161
                public function StopTransform() {
 
5162
                        $this->_out('Q');
 
5163
                }
 
5164
                /**
 
5165
                * Horizontal Scaling.
 
5166
                * @param float $s_x scaling factor for width as percent. 0 is not allowed.
 
5167
                * @param int $x abscissa of the scaling center. Default is current x position
 
5168
                * @param int $y ordinate of the scaling center. Default is current y position
 
5169
                * @since 2.1.000 (2008-01-07)
 
5170
                * @see StartTransform(), StopTransform()
 
5171
                */
 
5172
                public function ScaleX($s_x, $x='', $y=''){
 
5173
                        $this->Scale($s_x, 100, $x, $y);
 
5174
                }
 
5175
                
 
5176
                /**
 
5177
                * Vertical Scaling.
 
5178
                * @param float $s_y scaling factor for height as percent. 0 is not allowed.
 
5179
                * @param int $x abscissa of the scaling center. Default is current x position
 
5180
                * @param int $y ordinate of the scaling center. Default is current y position
 
5181
                * @since 2.1.000 (2008-01-07)
 
5182
                * @see StartTransform(), StopTransform()
 
5183
                */
 
5184
                public function ScaleY($s_y, $x='', $y=''){
 
5185
                        $this->Scale(100, $s_y, $x, $y);
 
5186
                }
 
5187
                
 
5188
                /**
 
5189
                * Vertical and horizontal proportional Scaling.
 
5190
                * @param float $s scaling factor for width and height as percent. 0 is not allowed.
 
5191
                * @param int $x abscissa of the scaling center. Default is current x position
 
5192
                * @param int $y ordinate of the scaling center. Default is current y position
 
5193
                * @since 2.1.000 (2008-01-07)
 
5194
                * @see StartTransform(), StopTransform()
 
5195
                */
 
5196
                public function ScaleXY($s, $x='', $y=''){
 
5197
                        $this->Scale($s, $s, $x, $y);
 
5198
                }
 
5199
                
 
5200
                /**
 
5201
                * Vertical and horizontal non-proportional Scaling.
 
5202
                * @param float $s_x scaling factor for width as percent. 0 is not allowed.
 
5203
                * @param float $s_y scaling factor for height as percent. 0 is not allowed.
 
5204
                * @param int $x abscissa of the scaling center. Default is current x position
 
5205
                * @param int $y ordinate of the scaling center. Default is current y position
 
5206
                * @since 2.1.000 (2008-01-07)
 
5207
                * @see StartTransform(), StopTransform()
 
5208
                */
 
5209
                public function Scale($s_x, $s_y, $x='', $y=''){
 
5210
                        if($x === '') {
 
5211
                                $x=$this->x;
 
5212
                        }
 
5213
                        if($y === '') {
 
5214
                                $y=$this->y;
 
5215
                        }
 
5216
                        if($this->rtl) {
 
5217
                                $x = $this->w - $x;
 
5218
                        }
 
5219
                        if($s_x == 0 OR $s_y == 0)
 
5220
                                $this->Error('Please use values unequal to zero for Scaling');
 
5221
                        $y=($this->h-$y)*$this->k;
 
5222
                        $x*=$this->k;
 
5223
                        //calculate elements of transformation matrix
 
5224
                        $s_x/=100;
 
5225
                        $s_y/=100;
 
5226
                        $tm[0]=$s_x;
 
5227
                        $tm[1]=0;
 
5228
                        $tm[2]=0;
 
5229
                        $tm[3]=$s_y;
 
5230
                        $tm[4]=$x*(1-$s_x);
 
5231
                        $tm[5]=$y*(1-$s_y);
 
5232
                        //scale the coordinate system
 
5233
                        $this->Transform($tm);
 
5234
                }
 
5235
                
 
5236
                /**
 
5237
                * Horizontal Mirroring.
 
5238
                * @param int $x abscissa of the point. Default is current x position
 
5239
                * @since 2.1.000 (2008-01-07)
 
5240
                * @see StartTransform(), StopTransform()
 
5241
                */
 
5242
                public function MirrorH($x=''){
 
5243
                        $this->Scale(-100, 100, $x);
 
5244
                }
 
5245
                
 
5246
                /**
 
5247
                * Verical Mirroring.
 
5248
                * @param int $y ordinate of the point. Default is current y position
 
5249
                * @since 2.1.000 (2008-01-07)
 
5250
                * @see StartTransform(), StopTransform()
 
5251
                */
 
5252
                public function MirrorV($y=''){
 
5253
                        $this->Scale(100, -100, '', $y);
 
5254
                }
 
5255
                
 
5256
                /**
 
5257
                * Point reflection mirroring.
 
5258
                * @param int $x abscissa of the point. Default is current x position
 
5259
                * @param int $y ordinate of the point. Default is current y position
 
5260
                * @since 2.1.000 (2008-01-07)
 
5261
                * @see StartTransform(), StopTransform()
 
5262
                */
 
5263
                public function MirrorP($x='',$y=''){
 
5264
                        $this->Scale(-100, -100, $x, $y);
 
5265
                }
 
5266
                
 
5267
                /**
 
5268
                * Reflection against a straight line through point (x, y) with the gradient angle (angle).
 
5269
                * @param float $angle gradient angle of the straight line. Default is 0 (horizontal line).
 
5270
                * @param int $x abscissa of the point. Default is current x position
 
5271
                * @param int $y ordinate of the point. Default is current y position
 
5272
                * @since 2.1.000 (2008-01-07)
 
5273
                * @see StartTransform(), StopTransform()
 
5274
                */
 
5275
                public function MirrorL($angle=0, $x='',$y=''){
 
5276
                        $this->Scale(-100, 100, $x, $y);
 
5277
                        $this->Rotate(-2*($angle-90),$x,$y);
 
5278
                }
 
5279
                
 
5280
                /**
 
5281
                * Translate graphic object horizontally.
 
5282
                * @param int $t_x movement to the right
 
5283
                * @since 2.1.000 (2008-01-07)
 
5284
                * @see StartTransform(), StopTransform()
 
5285
                */
 
5286
                public function TranslateX($t_x){
 
5287
                        $this->Translate($t_x, 0);
 
5288
                }
 
5289
                
 
5290
                /**
 
5291
                * Translate graphic object vertically.
 
5292
                * @param int $t_y movement to the bottom
 
5293
                * @since 2.1.000 (2008-01-07)
 
5294
                * @see StartTransform(), StopTransform()
 
5295
                */
 
5296
                public function TranslateY($t_y){
 
5297
                        $this->Translate(0, $t_y, $x, $y);
 
5298
                }
 
5299
                
 
5300
                /**
 
5301
                * Translate graphic object horizontally and vertically.
 
5302
                * @param int $t_x movement to the right
 
5303
                * @param int $t_y movement to the bottom
 
5304
                * @since 2.1.000 (2008-01-07)
 
5305
                * @see StartTransform(), StopTransform()
 
5306
                */
 
5307
                public function Translate($t_x, $t_y){
 
5308
                        if($this->rtl) {
 
5309
                                $t_x = -$t_x;
 
5310
                        }
 
5311
                        //calculate elements of transformation matrix
 
5312
                        $tm[0]=1;
 
5313
                        $tm[1]=0;
 
5314
                        $tm[2]=0;
 
5315
                        $tm[3]=1;
 
5316
                        $tm[4]=$t_x*$this->k;
 
5317
                        $tm[5]=-$t_y*$this->k;
 
5318
                        //translate the coordinate system
 
5319
                        $this->Transform($tm);
 
5320
                }
 
5321
                
 
5322
                /**
 
5323
                * Rotate object.
 
5324
                * @param float $angle angle in degrees for counter-clockwise rotation
 
5325
                * @param int $x abscissa of the rotation center. Default is current x position
 
5326
                * @param int $y ordinate of the rotation center. Default is current y position
 
5327
                * @since 2.1.000 (2008-01-07)
 
5328
                * @see StartTransform(), StopTransform()
 
5329
                */
 
5330
                public function Rotate($angle, $x='', $y=''){
 
5331
                        if($x === '') {
 
5332
                                $x=$this->x;
 
5333
                        }
 
5334
                        if($y === '') {
 
5335
                                $y=$this->y;
 
5336
                        }
 
5337
                        if($this->rtl) {
 
5338
                                $x = $this->w - $x;
 
5339
                                $angle = -$angle;
 
5340
                        }
 
5341
                        $y=($this->h-$y)*$this->k;
 
5342
                        $x*=$this->k;
 
5343
                        //calculate elements of transformation matrix
 
5344
                        $tm[0]=cos(deg2rad($angle));
 
5345
                        $tm[1]=sin(deg2rad($angle));
 
5346
                        $tm[2]=-$tm[1];
 
5347
                        $tm[3]=$tm[0];
 
5348
                        $tm[4]=$x+$tm[1]*$y-$tm[0]*$x;
 
5349
                        $tm[5]=$y-$tm[0]*$y-$tm[1]*$x;
 
5350
                        //rotate the coordinate system around ($x,$y)
 
5351
                        $this->Transform($tm);
 
5352
                }
 
5353
                
 
5354
                /**
 
5355
                * Skew horizontally.
 
5356
                * @param float $angle_x angle in degrees between -90 (skew to the left) and 90 (skew to the right)
 
5357
                * @param int $x abscissa of the skewing center. default is current x position
 
5358
                * @param int $y ordinate of the skewing center. default is current y position
 
5359
                * @since 2.1.000 (2008-01-07)
 
5360
                * @see StartTransform(), StopTransform()
 
5361
                */
 
5362
                public function SkewX($angle_x, $x='', $y=''){
 
5363
                        $this->Skew($angle_x, 0, $x, $y);
 
5364
                }
 
5365
                
 
5366
                /**
 
5367
                * Skew vertically.
 
5368
                * @param float $angle_y angle in degrees between -90 (skew to the bottom) and 90 (skew to the top)
 
5369
                * @param int $x abscissa of the skewing center. default is current x position
 
5370
                * @param int $y ordinate of the skewing center. default is current y position
 
5371
                * @since 2.1.000 (2008-01-07)
 
5372
                * @see StartTransform(), StopTransform()
 
5373
                */
 
5374
                public function SkewY($angle_y, $x='', $y=''){
 
5375
                        $this->Skew(0, $angle_y, $x, $y);
 
5376
                }
 
5377
                
 
5378
                /**
 
5379
                * Skew.
 
5380
                * @param float $angle_x angle in degrees between -90 (skew to the left) and 90 (skew to the right)
 
5381
                * @param float $angle_y angle in degrees between -90 (skew to the bottom) and 90 (skew to the top)
 
5382
                * @param int $x abscissa of the skewing center. default is current x position
 
5383
                * @param int $y ordinate of the skewing center. default is current y position
 
5384
                * @since 2.1.000 (2008-01-07)
 
5385
                * @see StartTransform(), StopTransform()
 
5386
                */
 
5387
                public function Skew($angle_x, $angle_y, $x='', $y=''){
 
5388
                        if($x === '') {
 
5389
                                $x=$this->x;
 
5390
                        }
 
5391
                        if($y === '') {
 
5392
                                $y=$this->y;
 
5393
                        }
 
5394
                        if($this->rtl) {
 
5395
                                $x = $this->w - $x;
 
5396
                                $angle_x = -$angle_x;
 
5397
                        }
 
5398
                        if($angle_x <= -90 OR $angle_x >= 90 OR $angle_y <= -90 OR $angle_y >= 90)
 
5399
                                $this->Error('Please use values between -90� and 90� for skewing');
 
5400
                        $x*=$this->k;
 
5401
                        $y=($this->h-$y)*$this->k;
 
5402
                        //calculate elements of transformation matrix
 
5403
                        $tm[0]=1;
 
5404
                        $tm[1]=tan(deg2rad($angle_y));
 
5405
                        $tm[2]=tan(deg2rad($angle_x));
 
5406
                        $tm[3]=1;
 
5407
                        $tm[4]=-$tm[2]*$y;
 
5408
                        $tm[5]=-$tm[1]*$x;
 
5409
                        //skew the coordinate system
 
5410
                        $this->Transform($tm);
 
5411
                }
 
5412
                
 
5413
                /**
 
5414
                * Apply graphic transformations.
 
5415
                * @since 2.1.000 (2008-01-07)
 
5416
                * @see StartTransform(), StopTransform()
 
5417
                */
 
5418
                protected function Transform($tm){
 
5419
                        $this->_out(sprintf('%.3f %.3f %.3f %.3f %.3f %.3f cm', $tm[0],$tm[1],$tm[2],$tm[3],$tm[4],$tm[5]));
 
5420
                }
 
5421
                
 
5422
                // END TRANSFORMATIONS SECTION -------------------------
 
5423
                
 
5424
                
 
5425
                // START GRAPHIC FUNCTIONS SECTION ---------------------
 
5426
                // The following section is based on the code provided by David Hernandez Sanz
 
5427
                
 
5428
                /**
 
5429
                * Defines the line width. By default, the value equals 0.2 mm. The method can be called before the first page is created and the value is retained from page to page.
 
5430
                * @param float $width The width.
 
5431
                * @since 1.0
 
5432
                * @see Line(), Rect(), Cell(), MultiCell()
 
5433
                */
 
5434
                public function SetLineWidth($width) {
 
5435
                        //Set line width
 
5436
                        $this->LineWidth=$width;
 
5437
                        if($this->page>0) {
 
5438
                                $this->_out(sprintf('%.2f w',$width*$this->k));
 
5439
                        }
 
5440
                }
 
5441
                
 
5442
                /**
 
5443
                * Returns the current the line width.
 
5444
                * @return int Line width 
 
5445
                * @since 2.1.000 (2008-01-07)
 
5446
                * @see Line(), SetLineWidth()
 
5447
                */
 
5448
                public function GetLineWidth() {
 
5449
                        return $this->LineWidth;
 
5450
                }
 
5451
                
 
5452
                /**
 
5453
                * Set line style.
 
5454
                *
 
5455
                * @param array $style Line style. Array with keys among the following:
 
5456
                * <ul>
 
5457
                *        <li>width (float): Width of the line in user units.</li>
 
5458
                *        <li>cap (string): Type of cap to put on the line. Possible values are:
 
5459
                * butt, round, square. The difference between "square" and "butt" is that
 
5460
                * "square" projects a flat end past the end of the line.</li>
 
5461
                *        <li>join (string): Type of join. Possible values are: miter, round,
 
5462
                * bevel.</li>
 
5463
                *        <li>dash (mixed): Dash pattern. Is 0 (without dash) or string with
 
5464
                * series of length values, which are the lengths of the on and off dashes.
 
5465
                * For example: "2" represents 2 on, 2 off, 2 on, 2 off, ...; "2,1" is 2 on,
 
5466
                * 1 off, 2 on, 1 off, ...</li>
 
5467
                *        <li>phase (integer): Modifier on the dash pattern which is used to shift
 
5468
                * the point at which the pattern starts.</li>
 
5469
                *        <li>color (array): Draw color. Format: array(red, green, blue).</li>
 
5470
                * </ul>
 
5471
                * @access public
 
5472
                * @since 2.1.000 (2008-01-08)
 
5473
                */
 
5474
                public function SetLineStyle($style) {
 
5475
                        extract($style);
 
5476
                        if (isset($width)) {
 
5477
                                $width_prev = $this->LineWidth;
 
5478
                                $this->SetLineWidth($width);
 
5479
                                $this->LineWidth = $width_prev;
 
5480
                        }
 
5481
                        if (isset($cap)) {
 
5482
                                $ca = array("butt" => 0, "round"=> 1, "square" => 2);
 
5483
                                if (isset($ca[$cap])) {
 
5484
                                        $this->_out($ca[$cap] . " J");
 
5485
                                }
 
5486
                        }
 
5487
                        if (isset($join)) {
 
5488
                                $ja = array("miter" => 0, "round" => 1, "bevel" => 2);
 
5489
                                if (isset($ja[$join])) {
 
5490
                                        $this->_out($ja[$join] . " j");
 
5491
                                }
 
5492
                        }
 
5493
                        if (isset($dash)) {
 
5494
                                $dash_string = "";
 
5495
                                if ($dash) {
 
5496
                                        // phpMyAdmin change
 
5497
                                        if (preg_match("/^.+,/", $dash)) {
 
5498
                                                $tab = explode(",", $dash);
 
5499
                                        } else {
 
5500
                                                $tab = array($dash);
 
5501
                                        }
 
5502
                                        $dash_string = "";
 
5503
                                        foreach ($tab as $i => $v) {
 
5504
                                                if ($i) {
 
5505
                                                        $dash_string .= " ";
 
5506
                                                }
 
5507
                                                $dash_string .= sprintf("%.2f", $v);
 
5508
                                        }
 
5509
                                }
 
5510
                                if (!isset($phase) OR !$dash) {
 
5511
                                        $phase = 0;
 
5512
                                }
 
5513
                                $this->_out(sprintf("[%s] %.2f d", $dash_string, $phase));
 
5514
                        }
 
5515
                        if (isset($color)) {
 
5516
                                list($r, $g, $b) = $color;
 
5517
                                $this->SetDrawColor($r, $g, $b);
 
5518
                        }
 
5519
                }
 
5520
                
 
5521
                /*
 
5522
                * Set a draw point.
 
5523
                * @param float $x Abscissa of point.
 
5524
                * @param float $y Ordinate of point.
 
5525
                * @access private
 
5526
                * @since 2.1.000 (2008-01-08)
 
5527
                */
 
5528
                protected function _outPoint($x, $y) {
 
5529
                        if($this->rtl) {
 
5530
                                $x = $this->w - $x;
 
5531
                        }
 
5532
                        $this->_out(sprintf("%.2f %.2f m", $x * $this->k, ($this->h - $y) * $this->k));
 
5533
                }
 
5534
                
 
5535
                /*
 
5536
                * Draws a line from last draw point.
 
5537
                * @param float $x Abscissa of end point.
 
5538
                * @param float $y Ordinate of end point.
 
5539
                * @access private
 
5540
                * @since 2.1.000 (2008-01-08)
 
5541
                */
 
5542
                protected function _outLine($x, $y) {
 
5543
                        if($this->rtl) {
 
5544
                                $x = $this->w - $x;
 
5545
                        }
 
5546
                        $this->_out(sprintf("%.2f %.2f l", $x * $this->k, ($this->h - $y) * $this->k));
 
5547
                }
 
5548
                
 
5549
                /**
 
5550
                * Draws a rectangle.
 
5551
                * @param float $x Abscissa of upper-left corner (or upper-right corner for RTL language).
 
5552
                * @param float $y Ordinate of upper-left corner (or upper-right corner for RTL language).
 
5553
                * @param float $w Width.
 
5554
                * @param float $h Height.
 
5555
                * @param string $op options
 
5556
                * @access protected
 
5557
                * @since 2.1.000 (2008-01-08)
 
5558
                */
 
5559
                protected function _outRect($x, $y, $w, $h, $op) {
 
5560
                        if($this->rtl) {
 
5561
                                $x = $this->w - $x - $w;
 
5562
                        }
 
5563
                        $this->_out(sprintf('%.2f %.2f %.2f %.2f re %s',$x*$this->k,($this->h-$y)*$this->k,$w*$this->k,-$h*$this->k,$op));
 
5564
                }
 
5565
                
 
5566
                /*
 
5567
                * Draws a Bezier curve from last draw point.
 
5568
                * The Bezier curve is a tangent to the line between the control points at either end of the curve.
 
5569
                * @param float $x1 Abscissa of control point 1.
 
5570
                * @param float $y1 Ordinate of control point 1.
 
5571
                * @param float $x2 Abscissa of control point 2.
 
5572
                * @param float $y2 Ordinate of control point 2.
 
5573
                * @param float $x3 Abscissa of end point.
 
5574
                * @param float $y3 Ordinate of end point.
 
5575
                * @access private
 
5576
                * @since 2.1.000 (2008-01-08)
 
5577
                */
 
5578
                protected function _outCurve($x1, $y1, $x2, $y2, $x3, $y3) {
 
5579
                        if($this->rtl) {
 
5580
                                $x1 = $this->w - $x1;
 
5581
                                $x2 = $this->w - $x2;
 
5582
                                $x3 = $this->w - $x3;
 
5583
                        }
 
5584
                        $this->_out(sprintf("%.2f %.2f %.2f %.2f %.2f %.2f c", $x1 * $this->k, ($this->h - $y1) * $this->k, $x2 * $this->k, ($this->h - $y2) * $this->k, $x3 * $this->k, ($this->h - $y3) * $this->k));
 
5585
                }
 
5586
                
 
5587
                /**
 
5588
                * Draws a line between two points.
 
5589
                * @param float $x1 Abscissa of first point.
 
5590
                * @param float $y1 Ordinate of first point.
 
5591
                * @param float $x2 Abscissa of second point.
 
5592
                * @param float $y2 Ordinate of second point.
 
5593
                * @param array $style Line style. Array like for {@link SetLineStyle SetLineStyle}. Default value: default line style (empty array).
 
5594
                * @access public
 
5595
                * @since 1.0
 
5596
                * @see SetLineWidth(), SetDrawColor(), SetLineStyle()
 
5597
                */
 
5598
                public function Line($x1, $y1, $x2, $y2, $style = array()) {
 
5599
                        if ($style) {
 
5600
                                $this->SetLineStyle($style);
 
5601
                        }
 
5602
                        $this->_outPoint($x1, $y1);
 
5603
                        $this->_outLine($x2, $y2);
 
5604
                        $this->_out(" S");
 
5605
                }
 
5606
                
 
5607
                /**
 
5608
                * Draws a rectangle.
 
5609
                * @param float $x Abscissa of upper-left corner (or upper-right corner for RTL language).
 
5610
                * @param float $y Ordinate of upper-left corner (or upper-right corner for RTL language).
 
5611
                * @param float $w Width.
 
5612
                * @param float $h Height.
 
5613
                * @param string $style Style of rendering. Possible values are:
 
5614
                * <ul>
 
5615
                *        <li>D or empty string: Draw (default).</li>
 
5616
                *        <li>F: Fill.</li>
 
5617
                *        <li>DF or FD: Draw and fill.</li>
 
5618
                * </ul>
 
5619
                * @param array $border_style Border style of rectangle. Array with keys among the following:
 
5620
                * <ul>
 
5621
                *        <li>all: Line style of all borders. Array like for {@link SetLineStyle SetLineStyle}.</li>
 
5622
                *        <li>L, T, R, B or combinations: Line style of left, top, right or bottom border. Array like for {@link SetLineStyle SetLineStyle}.</li>
 
5623
                * </ul>
 
5624
                * If a key is not present or is null, not draws the border. Default value: default line style (empty array).
 
5625
                * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array).
 
5626
                * @access public
 
5627
                * @since 1.0
 
5628
                * @see SetLineStyle()
 
5629
                */
 
5630
                public function Rect($x, $y, $w, $h, $style='', $border_style = array(), $fill_color = array()) {
 
5631
                        if (!(false === strpos($style, "F")) AND $fill_color) {
 
5632
                                list($r, $g, $b) = $fill_color;
 
5633
                                $this->SetFillColor($r, $g, $b);
 
5634
                        }
 
5635
                        switch ($style) {
 
5636
                                case "F": {
 
5637
                                        $op='f';
 
5638
                                        $border_style = array();
 
5639
                                        $this->_outRect($x, $y, $w, $h, $op);
 
5640
                                        break;
 
5641
                                }
 
5642
                                case "DF":
 
5643
                                case "FD": {
 
5644
                                        if (!$border_style OR isset($border_style["all"])) {
 
5645
                                                $op='B';
 
5646
                                                if (isset($border_style["all"])) {
 
5647
                                                        $this->SetLineStyle($border_style["all"]);
 
5648
                                                        $border_style = array();
 
5649
                                                }
 
5650
                                        } else {
 
5651
                                                $op='f';
 
5652
                                        }
 
5653
                                        $this->_outRect($x, $y, $w, $h, $op);
 
5654
                                        break;
 
5655
                                }
 
5656
                                default: {
 
5657
                                        $op='S';
 
5658
                                        if (!$border_style OR isset($border_style["all"])) {
 
5659
                                                if (isset($border_style["all"]) && $border_style["all"]) {
 
5660
                                                        $this->SetLineStyle($border_style["all"]);
 
5661
                                                        $border_style = array();
 
5662
                                                }
 
5663
                                                $this->_outRect($x, $y, $w, $h, $op);
 
5664
                                        }
 
5665
                                        break;
 
5666
                                }
 
5667
                        }
 
5668
                        if ($border_style) {
 
5669
                                $border_style2 = array();
 
5670
                                foreach ($border_style as $line => $value) {
 
5671
                                        $lenght = strlen($line);
 
5672
                                        for ($i = 0; $i < $lenght; $i++) {
 
5673
                                                $border_style2[$line[$i]] = $value;
 
5674
                                        }
 
5675
                                }
 
5676
                                $border_style = $border_style2;
 
5677
                                if (isset($border_style["L"]) && $border_style["L"]) {
 
5678
                                        $this->Line($x, $y, $x, $y + $h, $border_style["L"]);
 
5679
                                }
 
5680
                                if (isset($border_style["T"]) && $border_style["T"]) {
 
5681
                                        $this->Line($x, $y, $x + $w, $y, $border_style["T"]);
 
5682
                                }
 
5683
                                if (isset($border_style["R"]) && $border_style["R"]) {
 
5684
                                        $this->Line($x + $w, $y, $x + $w, $y + $h, $border_style["R"]);
 
5685
                                }
 
5686
                                if (isset($border_style["B"]) && $border_style["B"]) {
 
5687
                                        $this->Line($x, $y + $h, $x + $w, $y + $h, $border_style["B"]);
 
5688
                                }
 
5689
                        }
 
5690
                }
 
5691
                
 
5692
                
 
5693
                /**
 
5694
                * Draws a Bezier curve.
 
5695
                * The Bezier curve is a tangent to the line between the control points at
 
5696
                * either end of the curve.
 
5697
                * @param float $x0 Abscissa of start point.
 
5698
                * @param float $y0 Ordinate of start point.
 
5699
                * @param float $x1 Abscissa of control point 1.
 
5700
                * @param float $y1 Ordinate of control point 1.
 
5701
                * @param float $x2 Abscissa of control point 2.
 
5702
                * @param float $y2 Ordinate of control point 2.
 
5703
                * @param float $x3 Abscissa of end point.
 
5704
                * @param float $y3 Ordinate of end point.
 
5705
                * @param string $style Style of rendering. Possible values are:
 
5706
                * <ul>
 
5707
                *        <li>D or empty string: Draw (default).</li>
 
5708
                *        <li>F: Fill.</li>
 
5709
                *        <li>DF or FD: Draw and fill.</li>
 
5710
                * </ul>
 
5711
                * @param array $line_style Line style of curve. Array like for {@link SetLineStyle SetLineStyle}. Default value: default line style (empty array).
 
5712
                * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array).
 
5713
                * @access public
 
5714
                * @see SetLineStyle()
 
5715
                * @since 2.1.000 (2008-01-08)
 
5716
                */
 
5717
                public function Curve($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3, $style = "", $line_style = array(), $fill_color = array()) {
 
5718
                        if (!(false === strpos($style, "F")) AND $fill_color) {
 
5719
                                list($r, $g, $b) = $fill_color;
 
5720
                                $this->SetFillColor($r, $g, $b);
 
5721
                        }
 
5722
                        switch ($style) {
 
5723
                                case "F": {
 
5724
                                        $op = "f";
 
5725
                                        $line_style = array();
 
5726
                                        break;
 
5727
                                }
 
5728
                                case "FD": 
 
5729
                                case "DF": {
 
5730
                                        $op = "B";
 
5731
                                        break;
 
5732
                                }
 
5733
                                default: {
 
5734
                                        $op = "S";
 
5735
                                        break;
 
5736
                                }
 
5737
                        }
 
5738
                        if ($line_style) {
 
5739
                                $this->SetLineStyle($line_style);
 
5740
                        }
 
5741
                        $this->_outPoint($x0, $y0);
 
5742
                        $this->_outCurve($x1, $y1, $x2, $y2, $x3, $y3);
 
5743
                        $this->_out($op);
 
5744
                }
 
5745
                
 
5746
                /**
 
5747
                * Draws an ellipse.
 
5748
                * An ellipse is formed from n Bezier curves.
 
5749
                * @param float $x0 Abscissa of center point.
 
5750
                * @param float $y0 Ordinate of center point.
 
5751
                * @param float $rx Horizontal radius.
 
5752
                * @param float $ry Vertical radius (if ry = 0 then is a circle, see {@link Circle Circle}). Default value: 0.
 
5753
                * @param float $angle: Angle oriented (anti-clockwise). Default value: 0.
 
5754
                * @param float $astart: Angle start of draw line. Default value: 0.
 
5755
                * @param float $afinish: Angle finish of draw line. Default value: 360.
 
5756
                * @param string $style Style of rendering. Possible values are:
 
5757
                * <ul>
 
5758
                *        <li>D or empty string: Draw (default).</li>
 
5759
                *        <li>F: Fill.</li>
 
5760
                *        <li>DF or FD: Draw and fill.</li>
 
5761
                *        <li>C: Draw close.</li>
 
5762
                * </ul>
 
5763
                * @param array $line_style Line style of ellipse. Array like for {@link SetLineStyle SetLineStyle}. Default value: default line style (empty array).
 
5764
                * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array).
 
5765
                * @param integer $nc Number of curves used in ellipse. Default value: 8.
 
5766
                * @access public
 
5767
                * @since 2.1.000 (2008-01-08)
 
5768
                */
 
5769
                public function Ellipse($x0, $y0, $rx, $ry = 0, $angle = 0, $astart = 0, $afinish = 360, $style = "", $line_style = array(), $fill_color = array(), $nc = 8) {
 
5770
                        if ($angle) {
 
5771
                                $this->StartTransform();
 
5772
                                $this->Rotate($angle, $x0, $y0);
 
5773
                                $this->Ellipse($x0, $y0, $rx, $ry, 0, $astart, $afinish, $style, $line_style, $fill_color, $nc);
 
5774
                                $this->StopTransform();
 
5775
                                return;
 
5776
                        }
 
5777
                        if ($rx) {
 
5778
                                if (!(false === strpos($style, "F")) AND $fill_color) {
 
5779
                                        list($r, $g, $b) = $fill_color;
 
5780
                                        $this->SetFillColor($r, $g, $b);
 
5781
                                }
 
5782
                                switch ($style) {
 
5783
                                        case "F": {
 
5784
                                                $op = "f";
 
5785
                                                $line_style = array();
 
5786
                                                break;
 
5787
                                        }
 
5788
                                        case "FD": 
 
5789
                                        case "DF": {
 
5790
                                                $op = "B";
 
5791
                                                break;
 
5792
                                        }
 
5793
                                        case "C": {
 
5794
                                                $op = "s"; // Small "s" signifies closing the path as well
 
5795
                                                break;
 
5796
                                        }
 
5797
                                        default: {
 
5798
                                                $op = "S";
 
5799
                                                break;
 
5800
                                        }
 
5801
                                }
 
5802
                                if ($line_style) {
 
5803
                                        $this->SetLineStyle($line_style);
 
5804
                                }
 
5805
                                if (!$ry) {
 
5806
                                        $ry = $rx;
 
5807
                                }
 
5808
                                $rx *= $this->k;
 
5809
                                $ry *= $this->k;
 
5810
                                if ($nc < 2){
 
5811
                                        $nc = 2;
 
5812
                                }
 
5813
                                $astart = deg2rad((float) $astart);
 
5814
                                $afinish = deg2rad((float) $afinish);
 
5815
                                $total_angle = $afinish - $astart;
 
5816
                                $dt = $total_angle / $nc;
 
5817
                                $dtm = $dt/3;
 
5818
                                $x0 *= $this->k;
 
5819
                                $y0 = ($this->h - $y0) * $this->k;
 
5820
                                $t1 = $astart;
 
5821
                                $a0 = $x0 + ($rx * cos($t1));
 
5822
                                $b0 = $y0 + ($ry * sin($t1));
 
5823
                                $c0 = -$rx * sin($t1);
 
5824
                                $d0 = $ry * cos($t1);
 
5825
                                $this->_outPoint($a0 / $this->k, $this->h - ($b0 / $this->k));
 
5826
                                for ($i = 1; $i <= $nc; $i++) {
 
5827
                                        // Draw this bit of the total curve
 
5828
                                        $t1 = ($i * $dt) + $astart;
 
5829
                                        $a1 = $x0 + ($rx * cos($t1));
 
5830
                                        $b1 = $y0 + ($ry * sin($t1));
 
5831
                                        $c1 = -$rx * sin($t1);
 
5832
                                        $d1 = $ry * cos($t1);
 
5833
                                        $this->_outCurve(($a0 + ($c0 * $dtm)) / $this->k, $this->h - (($b0 + ($d0 * $dtm)) / $this->k), ($a1 - ($c1 * $dtm)) / $this->k, $this->h - (($b1 - ($d1 * $dtm)) / $this->k), $a1 / $this->k, $this->h - ($b1 / $this->k));
 
5834
                                        $a0 = $a1;
 
5835
                                        $b0 = $b1;
 
5836
                                        $c0 = $c1;
 
5837
                                        $d0 = $d1;
 
5838
                                }
 
5839
                                $this->_out($op);
 
5840
                        }
 
5841
                }
 
5842
                
 
5843
                /**
 
5844
                * Draws a circle.
 
5845
                * A circle is formed from n Bezier curves.
 
5846
                * @param float $x0 Abscissa of center point.
 
5847
                * @param float $y0 Ordinate of center point.
 
5848
                * @param float $r Radius.
 
5849
                * @param float $astart: Angle start of draw line. Default value: 0.
 
5850
                * @param float $afinish: Angle finish of draw line. Default value: 360.
 
5851
                * @param string $style Style of rendering. Possible values are:
 
5852
                * <ul>
 
5853
                *        <li>D or empty string: Draw (default).</li>
 
5854
                *        <li>F: Fill.</li>
 
5855
                *        <li>DF or FD: Draw and fill.</li>
 
5856
                *        <li>C: Draw close.</li>
 
5857
                * </ul>
 
5858
                * @param array $line_style Line style of circle. Array like for {@link SetLineStyle SetLineStyle}. Default value: default line style (empty array).
 
5859
                * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array).
 
5860
                * @param integer $nc Number of curves used in circle. Default value: 8.
 
5861
                * @access public
 
5862
                * @since 2.1.000 (2008-01-08)
 
5863
                */
 
5864
                public function Circle($x0, $y0, $r, $astart = 0, $afinish = 360, $style = "", $line_style = array(), $fill_color = array(), $nc = 8) {
 
5865
                        $this->Ellipse($x0, $y0, $r, 0, 0, $astart, $afinish, $style, $line_style, $fill_color, $nc);
 
5866
                }
 
5867
                
 
5868
                /**
 
5869
                * Draws a polygon.
 
5870
                * @param array $p Points 0 to ($np - 1). Array with values (x0, y0, x1, y1,..., x(np-1), y(np - 1))
 
5871
                * @param string $style Style of rendering. Possible values are:
 
5872
                * <ul>
 
5873
                *        <li>D or empty string: Draw (default).</li>
 
5874
                *        <li>F: Fill.</li>
 
5875
                *        <li>DF or FD: Draw and fill.</li>
 
5876
                * </ul>
 
5877
                * @param array $line_style Line style of polygon. Array with keys among the following:
 
5878
                * <ul>
 
5879
                *        <li>all: Line style of all lines. Array like for {@link SetLineStyle SetLineStyle}.</li>
 
5880
                *        <li>0 to ($np - 1): Line style of each line. Array like for {@link SetLineStyle SetLineStyle}.</li>
 
5881
                * </ul>
 
5882
                * If a key is not present or is null, not draws the line. Default value is default line style (empty array).
 
5883
                * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array).
 
5884
                * @access public
 
5885
                * @since 2.1.000 (2008-01-08)
 
5886
                */
 
5887
                public function Polygon($p, $style = "", $line_style = array(), $fill_color = array()) {
 
5888
                        $np = count($p) / 2;
 
5889
                        if (!(false === strpos($style, "F")) AND $fill_color) {
 
5890
                                list($r, $g, $b) = $fill_color;
 
5891
                                $this->SetFillColor($r, $g, $b);
 
5892
                        }
 
5893
                        switch ($style) {
 
5894
                                case "F": {
 
5895
                                        $line_style = array();
 
5896
                                        $op = "f";
 
5897
                                        break;
 
5898
                                }
 
5899
                                case "FD": 
 
5900
                                case "DF": {
 
5901
                                        $op = "B";
 
5902
                                        break;
 
5903
                                }
 
5904
                                default: {
 
5905
                                        $op = "S";
 
5906
                                        break;
 
5907
                                }
 
5908
                        }
 
5909
                        $draw = true;
 
5910
                        if ($line_style) {
 
5911
                                if (isset($line_style["all"])) {
 
5912
                                        $this->SetLineStyle($line_style["all"]);
 
5913
                                }
 
5914
                                else { // 0 .. (np - 1), op = {B, S}
 
5915
                                        $draw = false;
 
5916
                                        if ("B" == $op) {
 
5917
                                                $op = "f";
 
5918
                                                $this->_outPoint($p[0], $p[1]);
 
5919
                                                for ($i = 2; $i < ($np * 2); $i = $i + 2) {
 
5920
                                                        $this->_outLine($p[$i], $p[$i + 1]);
 
5921
                                                }
 
5922
                                                $this->_outLine($p[0], $p[1]);
 
5923
                                                $this->_out($op);
 
5924
                                        }
 
5925
                                        $p[$np * 2] = $p[0];
 
5926
                                        $p[($np * 2) + 1] = $p[1];
 
5927
                                        for ($i = 0; $i < $np; $i++) {
 
5928
                                                if (isset($line_style[$i])) {
 
5929
                                                        $this->Line($p[$i * 2], $p[($i * 2) + 1], $p[($i * 2) + 2], $p[($i * 2) + 3], $line_style[$i]);
 
5930
                                                }
 
5931
                                        }
 
5932
                                }
 
5933
                        }
 
5934
                        if ($draw) {
 
5935
                                $this->_outPoint($p[0], $p[1]);
 
5936
                                for ($i = 2; $i < ($np * 2); $i = $i + 2) {
 
5937
                                        $this->_outLine($p[$i], $p[$i + 1]);
 
5938
                                }
 
5939
                                $this->_outLine($p[0], $p[1]);
 
5940
                                $this->_out($op);
 
5941
                        }
 
5942
                }
 
5943
                
 
5944
                /**
 
5945
                * Draws a regular polygon.
 
5946
                * @param float $x0 Abscissa of center point.
 
5947
                * @param float $y0 Ordinate of center point.
 
5948
                * @param float $r: Radius of inscribed circle.
 
5949
                * @param integer $ns Number of sides.
 
5950
                * @param float $angle Angle oriented (anti-clockwise). Default value: 0.
 
5951
                * @param boolean $draw_circle Draw inscribed circle or not. Default value: false.
 
5952
                * @param string $style Style of rendering. Possible values are:
 
5953
                * <ul>
 
5954
                *        <li>D or empty string: Draw (default).</li>
 
5955
                *        <li>F: Fill.</li>
 
5956
                *        <li>DF or FD: Draw and fill.</li>
 
5957
                * </ul>
 
5958
                * @param array $line_style Line style of polygon sides. Array with keys among the following:
 
5959
                * <ul>
 
5960
                *        <li>all: Line style of all sides. Array like for {@link SetLineStyle SetLineStyle}.</li>
 
5961
                *        <li>0 to ($ns - 1): Line style of each side. Array like for {@link SetLineStyle SetLineStyle}.</li>
 
5962
                * </ul>
 
5963
                * If a key is not present or is null, not draws the side. Default value is default line style (empty array).
 
5964
                * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array).
 
5965
                * @param string $circle_style Style of rendering of inscribed circle (if draws). Possible values are:
 
5966
                * <ul>
 
5967
                *        <li>D or empty string: Draw (default).</li>
 
5968
                *        <li>F: Fill.</li>
 
5969
                *        <li>DF or FD: Draw and fill.</li>
 
5970
                * </ul>
 
5971
                * @param array $circle_outLine_style Line style of inscribed circle (if draws). Array like for {@link SetLineStyle SetLineStyle}. Default value: default line style (empty array).
 
5972
                * @param array $circle_fill_color Fill color of inscribed circle (if draws). Format: array(red, green, blue). Default value: default color (empty array).
 
5973
                * @access public
 
5974
                * @since 2.1.000 (2008-01-08)
 
5975
                */
 
5976
                public function RegularPolygon($x0, $y0, $r, $ns, $angle = 0, $draw_circle = false, $style = "", $line_style = array(), $fill_color = array(), $circle_style = "", $circle_outLine_style = array(), $circle_fill_color = array()) {
 
5977
                        if (3 > $ns) {
 
5978
                                $ns = 3;
 
5979
                        }
 
5980
                        if ($draw_circle) {
 
5981
                                $this->Circle($x0, $y0, $r, 0, 360, $circle_style, $circle_outLine_style, $circle_fill_color);
 
5982
                        }
 
5983
                        $p = array();
 
5984
                        for ($i = 0; $i < $ns; $i++) {
 
5985
                                $a = $angle + ($i * 360 / $ns);
 
5986
                                $a_rad = deg2rad((float) $a);
 
5987
                                $p[] = $x0 + ($r * sin($a_rad));
 
5988
                                $p[] = $y0 + ($r * cos($a_rad));
 
5989
                        }
 
5990
                        $this->Polygon($p, $style, $line_style, $fill_color);
 
5991
                }
 
5992
                
 
5993
                /**
 
5994
                * Draws a star polygon
 
5995
                * @param float $x0 Abscissa of center point.
 
5996
                * @param float $y0 Ordinate of center point.
 
5997
                * @param float $r Radius of inscribed circle.
 
5998
                * @param integer $nv Number of vertices.
 
5999
                * @param integer $ng Number of gap (if ($ng % $nv = 1) then is a regular polygon).
 
6000
                * @param float $angle: Angle oriented (anti-clockwise). Default value: 0.
 
6001
                * @param boolean $draw_circle: Draw inscribed circle or not. Default value is false.
 
6002
                * @param string $style Style of rendering. Possible values are:
 
6003
                * <ul>
 
6004
                *        <li>D or empty string: Draw (default).</li>
 
6005
                *        <li>F: Fill.</li>
 
6006
                *        <li>DF or FD: Draw and fill.</li>
 
6007
                * </ul>
 
6008
                * @param array $line_style Line style of polygon sides. Array with keys among the following:
 
6009
                * <ul>
 
6010
                *        <li>all: Line style of all sides. Array like for
 
6011
                * {@link SetLineStyle SetLineStyle}.</li>
 
6012
                *        <li>0 to (n - 1): Line style of each side. Array like for {@link SetLineStyle SetLineStyle}.</li>
 
6013
                * </ul>
 
6014
                * If a key is not present or is null, not draws the side. Default value is default line style (empty array).
 
6015
                * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array).
 
6016
                * @param string $circle_style Style of rendering of inscribed circle (if draws). Possible values are:
 
6017
                * <ul>
 
6018
                *        <li>D or empty string: Draw (default).</li>
 
6019
                *        <li>F: Fill.</li>
 
6020
                *        <li>DF or FD: Draw and fill.</li>
 
6021
                * </ul>
 
6022
                * @param array $circle_outLine_style Line style of inscribed circle (if draws). Array like for {@link SetLineStyle SetLineStyle}. Default value: default line style (empty array).
 
6023
                * @param array $circle_fill_color Fill color of inscribed circle (if draws). Format: array(red, green, blue). Default value: default color (empty array).
 
6024
                * @access public
 
6025
                * @since 2.1.000 (2008-01-08)
 
6026
                */
 
6027
                public function StarPolygon($x0, $y0, $r, $nv, $ng, $angle = 0, $draw_circle = false, $style = "", $line_style = array(), $fill_color = array(), $circle_style = "", $circle_outLine_style = array(), $circle_fill_color = array()) {
 
6028
                        if (2 > $nv) {
 
6029
                                $nv = 2;
 
6030
                        }
 
6031
                        if ($draw_circle) {
 
6032
                                $this->Circle($x0, $y0, $r, 0, 360, $circle_style, $circle_outLine_style, $circle_fill_color);
 
6033
                        }
 
6034
                        $p2 = array();
 
6035
                        $visited = array();
 
6036
                        for ($i = 0; $i < $nv; $i++) {
 
6037
                                $a = $angle + ($i * 360 / $nv);
 
6038
                                $a_rad = deg2rad((float) $a);
 
6039
                                $p2[] = $x0 + ($r * sin($a_rad));
 
6040
                                $p2[] = $y0 + ($r * cos($a_rad));
 
6041
                                $visited[] = false;
 
6042
                        }
 
6043
                        $p = array();
 
6044
                        $i = 0;
 
6045
                        do {
 
6046
                                $p[] = $p2[$i * 2];
 
6047
                                $p[] = $p2[($i * 2) + 1];
 
6048
                                $visited[$i] = true;
 
6049
                                $i += $ng;
 
6050
                                $i %= $nv;
 
6051
                        } while (!$visited[$i]);
 
6052
                        $this->Polygon($p, $style, $line_style, $fill_color);
 
6053
                }
 
6054
                
 
6055
                /**
 
6056
                * Draws a rounded rectangle.
 
6057
                * @param float $x Abscissa of upper-left corner.
 
6058
                * @param float $y Ordinate of upper-left corner.
 
6059
                * @param float $w Width.
 
6060
                * @param float $h Height.
 
6061
                * @param float $r Radius of the rounded corners.
 
6062
                * @param string $round_corner Draws rounded corner or not. String with a 0 (not rounded i-corner) or 1 (rounded i-corner) in i-position. Positions are, in order and begin to 0: top left, top right, bottom right and bottom left. Default value: all rounded corner ("1111").
 
6063
                * @param string $style Style of rendering. Possible values are:
 
6064
                * <ul>
 
6065
                *        <li>D or empty string: Draw (default).</li>
 
6066
                *        <li>F: Fill.</li>
 
6067
                *        <li>DF or FD: Draw and fill.</li>
 
6068
                * </ul>
 
6069
                * @param array $border_style Border style of rectangle. Array like for {@link SetLineStyle SetLineStyle}. Default value: default line style (empty array).
 
6070
                * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array).
 
6071
                * @access public
 
6072
                * @since 2.1.000 (2008-01-08)
 
6073
                */
 
6074
                public function RoundedRect($x, $y, $w, $h, $r, $round_corner = "1111", $style = "", $border_style = array(), $fill_color = array()) {
 
6075
                        if ("0000" == $round_corner) { // Not rounded
 
6076
                                $this->Rect($x, $y, $w, $h, $style, $border_style, $fill_color);
 
6077
                        } else { // Rounded
 
6078
                                if (!(false === strpos($style, "F")) AND $fill_color) {
 
6079
                                        list($red, $g, $b) = $fill_color;
 
6080
                                        $this->SetFillColor($red, $g, $b);
 
6081
                                }
 
6082
                                switch ($style) {
 
6083
                                        case "F": {
 
6084
                                                $border_style = array();
 
6085
                                                $op = "f";
 
6086
                                                break;
 
6087
                                        }
 
6088
                                        case "FD": 
 
6089
                                        case "DF": {
 
6090
                                                $op = "B";
 
6091
                                                break;
 
6092
                                        }
 
6093
                                        default: {
 
6094
                                                $op = "S";
 
6095
                                                break;
 
6096
                                        }
 
6097
                                }
 
6098
                                if ($border_style) {
 
6099
                                        $this->SetLineStyle($border_style);
 
6100
                                }
 
6101
                                $MyArc = 4 / 3 * (sqrt(2) - 1);
 
6102
                                $this->_outPoint($x + $r, $y);
 
6103
                                $xc = $x + $w - $r;
 
6104
                                $yc = $y + $r;
 
6105
                                $this->_outLine($xc, $y);
 
6106
                                if ($round_corner[0]) {
 
6107
                                        $this->_outCurve($xc + ($r * $MyArc), $yc - $r, $xc + $r, $yc - ($r * $MyArc), $xc + $r, $yc);
 
6108
                                } else {
 
6109
                                        $this->_outLine($x + $w, $y);
 
6110
                                }
 
6111
                                $xc = $x + $w - $r;
 
6112
                                $yc = $y + $h - $r;
 
6113
                                $this->_outLine($x + $w, $yc);
 
6114
                                if ($round_corner[1]) {
 
6115
                                        $this->_outCurve($xc + $r, $yc + ($r * $MyArc), $xc + ($r * $MyArc), $yc + $r, $xc, $yc + $r);
 
6116
                                } else {
 
6117
                                        $this->_outLine($x + $w, $y + $h);
 
6118
                                }
 
6119
                                $xc = $x + $r;
 
6120
                                $yc = $y + $h - $r;
 
6121
                                $this->_outLine($xc, $y + $h);
 
6122
                                if ($round_corner[2]) {
 
6123
                                        $this->_outCurve($xc - ($r * $MyArc), $yc + $r, $xc - $r, $yc + ($r * $MyArc), $xc - $r, $yc);
 
6124
                                } else {
 
6125
                                        $this->_outLine($x, $y + $h);
 
6126
                                }
 
6127
                                $xc = $x + $r;
 
6128
                                $yc = $y + $r;
 
6129
                                $this->_outLine($x, $yc);
 
6130
                                if ($round_corner[3]) {
 
6131
                                        $this->_outCurve($xc - $r, $yc - ($r * $MyArc), $xc - ($r * $MyArc), $yc - $r, $xc, $yc - $r);
 
6132
                                } else {
 
6133
                                        $this->_outLine($x, $y);
 
6134
                                        $this->_outLine($x + $r, $y);
 
6135
                                }
 
6136
                                $this->_out($op);
 
6137
                        }
 
6138
                }
 
6139
                
 
6140
                // END GRAPHIC FUNCTIONS SECTION -----------------------
 
6141
                
 
6142
                // BIDIRECTIONAL TEXT SECTION --------------------------
 
6143
                
 
6144
                /**
 
6145
                 * Reverse the RLT substrings using the Bidirectional Algorithm (http://unicode.org/reports/tr9/).
 
6146
                 * @param string $str string to manipulate.
 
6147
                 * @param bool $forcertl if 'R' forces RTL, if 'L' forces LTR
 
6148
                 * @return string
 
6149
                 * @author Nicola Asuni
 
6150
                 * @since 2.1.000 (2008-01-08)
 
6151
                */
 
6152
                protected function utf8StrRev($str, $setbom=false, $forcertl=false) {
 
6153
                        global $unicode,$unicode_mirror, $unicode_arlet;
 
6154
                        require_once(dirname(__FILE__).'/unicode_data.php');
 
6155
                        
 
6156
                        // paragraph embedding level
 
6157
                        $pel = 0;
 
6158
                        // max level
 
6159
                        $maxlevel = 0;
 
6160
                        
 
6161
                        // check if string contains arabic text
 
6162
                        if (preg_match(K_RE_PATTERN_ARABIC, $str)) {
 
6163
                                $arabic = true;
 
6164
                        } else {
 
6165
                                $arabic = false;
 
6166
                        }
 
6167
                        
 
6168
                        // check if string contains RTL text
 
6169
                        if (!($forcertl OR $arabic OR preg_match(K_RE_PATTERN_RTL, $str))) {
 
6170
                                return $this->UTF8ToUTF16BE($str, false);
 
6171
                        }
 
6172
                        
 
6173
                        // convert string to array of unicode chars
 
6174
                        $ta = $this->UTF8StringToArray($str);
 
6175
                        // get number of chars
 
6176
                        $numchars = count($ta);
 
6177
                        
 
6178
                        if ($forcertl == 'R') {
 
6179
                                        $pel = 1;
 
6180
                        } elseif ($forcertl == 'L') {
 
6181
                                        $pel = 0;
 
6182
                        } else {
 
6183
                                // P2. In each paragraph, find the first character of type L, AL, or R.
 
6184
                                // P3. If a character is found in P2 and it is of type AL or R, then set the paragraph embedding level to one; otherwise, set it to zero.
 
6185
                                for ($i=0; $i < $numchars; $i++) {
 
6186
                                        $type = $unicode[$ta[$i]];
 
6187
                                        if ($type == 'L') {
 
6188
                                                $pel = 0;
 
6189
                                                break;
 
6190
                                        } elseif (($type == 'AL') OR ($type == 'R')) {
 
6191
                                                $pel = 1;
 
6192
                                                break;
 
6193
                                        }
 
6194
                                }
 
6195
                        }
 
6196
                        
 
6197
                        // Current Embedding Level
 
6198
                        $cel = $pel;
 
6199
                        // directional override status
 
6200
                        $dos = 'N';
 
6201
                        $remember = array();
 
6202
                        // start-of-level-run
 
6203
                        $sor = $pel % 2 ? 'R' : 'L';
 
6204
                        $eor = $sor;
 
6205
                        
 
6206
                        //$levels = array(array('level' => $cel, 'sor' => $sor, 'eor' => '', 'chars' => array()));
 
6207
                        //$current_level = &$levels[count( $levels )-1];
 
6208
                        
 
6209
                        // Array of characters data
 
6210
                        $chardata = Array();
 
6211
                        
 
6212
                        // X1. Begin by setting the current embedding level to the paragraph embedding level. Set the directional override status to neutral. Process each character iteratively, applying rules X2 through X9. Only embedding levels from 0 to 61 are valid in this phase.
 
6213
                        //      In the resolution of levels in rules I1 and I2, the maximum embedding level of 62 can be reached.
 
6214
                        for ($i=0; $i < $numchars; $i++) {
 
6215
                                if ($ta[$i] == K_RLE) {
 
6216
                                        // X2. With each RLE, compute the least greater odd embedding level.
 
6217
                                        //      a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to neutral.
 
6218
                                        //      b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status.
 
6219
                                        $next_level = $cel + ($cel % 2) + 1;
 
6220
                                        if ($next_level < 62) {
 
6221
                                                $remember[] = array('num' => K_RLE, 'cel' => $cel, 'dos' => $dos);
 
6222
                                                $cel = $next_level;
 
6223
                                                $dos = 'N';
 
6224
                                                $sor = $eor;
 
6225
                                                $eor = $cel % 2 ? 'R' : 'L';
 
6226
                                        }
 
6227
                                } elseif ($ta[$i] == K_LRE) {
 
6228
                                        // X3. With each LRE, compute the least greater even embedding level.
 
6229
                                        //      a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to neutral.
 
6230
                                        //      b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status.
 
6231
                                        $next_level = $cel + 2 - ($cel % 2);
 
6232
                                        if ( $next_level < 62 ) {
 
6233
                                                $remember[] = array('num' => K_LRE, 'cel' => $cel, 'dos' => $dos);
 
6234
                                                $cel = $next_level;
 
6235
                                                $dos = 'N';
 
6236
                                                $sor = $eor;
 
6237
                                                $eor = $cel % 2 ? 'R' : 'L';
 
6238
                                        }
 
6239
                                } elseif ($ta[$i] == K_RLO) {
 
6240
                                        // X4. With each RLO, compute the least greater odd embedding level.
 
6241
                                        //      a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to right-to-left.
 
6242
                                        //      b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status.
 
6243
                                        $next_level = $cel + ($cel % 2) + 1;
 
6244
                                        if ($next_level < 62) {
 
6245
                                                $remember[] = array('num' => K_RLO, 'cel' => $cel, 'dos' => $dos);
 
6246
                                                $cel = $next_level;
 
6247
                                                $dos = 'R';
 
6248
                                                $sor = $eor;
 
6249
                                                $eor = $cel % 2 ? 'R' : 'L';
 
6250
                                        }
 
6251
                                } elseif ($ta[$i] == K_LRO) {
 
6252
                                        // X5. With each LRO, compute the least greater even embedding level.
 
6253
                                        //      a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to left-to-right.
 
6254
                                        //      b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status.
 
6255
                                        $next_level = $cel + 2 - ($cel % 2);
 
6256
                                        if ( $next_level < 62 ) {
 
6257
                                                $remember[] = array('num' => K_LRO, 'cel' => $cel, 'dos' => $dos);
 
6258
                                                $cel = $next_level;
 
6259
                                                $dos = 'L';
 
6260
                                                $sor = $eor;
 
6261
                                                $eor = $cel % 2 ? 'R' : 'L';
 
6262
                                        }
 
6263
                                } elseif ($ta[$i] == K_PDF) {
 
6264
                                        // X7. With each PDF, determine the matching embedding or override code. If there was a valid matching code, restore (pop) the last remembered (pushed) embedding level and directional override.
 
6265
                                        if (count($remember)) {
 
6266
                                                $last = count($remember ) - 1;
 
6267
                                                if (($remember[$last]['num'] == K_RLE) OR 
 
6268
                                                          ($remember[$last]['num'] == K_LRE) OR 
 
6269
                                                          ($remember[$last]['num'] == K_RLO) OR 
 
6270
                                                          ($remember[$last]['num'] == K_LRO)) {
 
6271
                                                        $match = array_pop($remember);
 
6272
                                                        $cel = $match['cel'];
 
6273
                                                        $dos = $match['dos'];
 
6274
                                                        $sor = $eor;
 
6275
                                                        $eor = ($cel > $match['cel'] ? $cel : $match['cel']) % 2 ? 'R' : 'L';
 
6276
                                                }
 
6277
                                        }
 
6278
                                } elseif (($ta[$i] != K_RLE) AND
 
6279
                                                                 ($ta[$i] != K_LRE) AND
 
6280
                                                                 ($ta[$i] != K_RLO) AND
 
6281
                                                                 ($ta[$i] != K_LRO) AND
 
6282
                                                                 ($ta[$i] != K_PDF)) {
 
6283
                                        // X6. For all types besides RLE, LRE, RLO, LRO, and PDF:
 
6284
                                        //      a. Set the level of the current character to the current embedding level.
 
6285
                                        //      b. Whenever the directional override status is not neutral, reset the current character type to the directional override status.
 
6286
                                        if ($dos != 'N') {
 
6287
                                                $chardir = $dos;
 
6288
                                        } else {
 
6289
                                                $chardir = $unicode[$ta[$i]];
 
6290
                                        }
 
6291
                                        // stores string characters and other information
 
6292
                                        $chardata[] = array('char' => $ta[$i], 'level' => $cel, 'type' => $chardir, 'sor' => $sor, 'eor' => $eor);
 
6293
                                }
 
6294
                        } // end for each char
 
6295
                        
 
6296
                        // X8. All explicit directional embeddings and overrides are completely terminated at the end of each paragraph. Paragraph separators are not included in the embedding.
 
6297
                        // X9. Remove all RLE, LRE, RLO, LRO, PDF, and BN codes.
 
6298
                        // X10. The remaining rules are applied to each run of characters at the same level. For each run, determine the start-of-level-run (sor) and end-of-level-run (eor) type, either L or R. This depends on the higher of the two levels on either side of the boundary (at the start or end of the paragraph, the level of the �other� run is the base embedding level). If the higher level is odd, the type is R; otherwise, it is L.
 
6299
                        
 
6300
                        // 3.3.3 Resolving Weak Types
 
6301
                        // Weak types are now resolved one level run at a time. At level run boundaries where the type of the character on the other side of the boundary is required, the type assigned to sor or eor is used.
 
6302
                        // Nonspacing marks are now resolved based on the previous characters.
 
6303
                        $numchars = count($chardata);
 
6304
                        
 
6305
                        // W1. Examine each nonspacing mark (NSM) in the level run, and change the type of the NSM to the type of the previous character. If the NSM is at the start of the level run, it will get the type of sor.
 
6306
                        $prevlevel = -1; // track level changes
 
6307
                        $levcount = 0; // counts consecutive chars at the same level
 
6308
                        for ($i=0; $i < $numchars; $i++) {
 
6309
                                if ($chardata[$i]['type'] == 'NSM') {
 
6310
                                        if ($levcount) {
 
6311
                                                $chardata[$i]['type'] = $chardata[$i]['sor'];
 
6312
                                        } elseif ($i > 0) {
 
6313
                                                $chardata[$i]['type'] = $chardata[($i-1)]['type'];
 
6314
                                        }
 
6315
                                }
 
6316
                                if ($chardata[$i]['level'] != $prevlevel) {
 
6317
                                        $levcount = 0;
 
6318
                                } else {
 
6319
                                        $levcount++;
 
6320
                                }
 
6321
                                $prevlevel = $chardata[$i]['level'];
 
6322
                        }
 
6323
                        
 
6324
                        // W2. Search backward from each instance of a European number until the first strong type (R, L, AL, or sor) is found. If an AL is found, change the type of the European number to Arabic number.
 
6325
                        $prevlevel = -1;
 
6326
                        $levcount = 0;
 
6327
                        for ($i=0; $i < $numchars; $i++) {
 
6328
                                if ($chardata[$i]['char'] == 'EN') {
 
6329
                                        for ($j=$levcount; $j >= 0; $j--) {
 
6330
                                                if ($chardata[$j]['type'] == 'AL') {
 
6331
                                                        $chardata[$i]['type'] = 'AN';
 
6332
                                                } elseif (($chardata[$j]['type'] == 'L') OR ($chardata[$j]['type'] == 'R')) {
 
6333
                                                        break;
 
6334
                                                }
 
6335
                                        }
 
6336
                                }
 
6337
                                if ($chardata[$i]['level'] != $prevlevel) {
 
6338
                                        $levcount = 0;
 
6339
                                } else {
 
6340
                                        $levcount++;
 
6341
                                }
 
6342
                                $prevlevel = $chardata[$i]['level'];
 
6343
                        }
 
6344
                        
 
6345
                        // W3. Change all ALs to R.
 
6346
                        for ($i=0; $i < $numchars; $i++) {
 
6347
                                if ($chardata[$i]['type'] == 'AL') {
 
6348
                                        $chardata[$i]['type'] = 'R';
 
6349
                                } 
 
6350
                        }
 
6351
                        
 
6352
                        // W4. A single European separator between two European numbers changes to a European number. A single common separator between two numbers of the same type changes to that type.
 
6353
                        $prevlevel = -1;
 
6354
                        $levcount = 0;
 
6355
                        for ($i=0; $i < $numchars; $i++) {
 
6356
                                if (($levcount > 0) AND (($i+1) < $numchars) AND ($chardata[($i+1)]['level'] == $prevlevel)) {
 
6357
                                        if (($chardata[$i]['type'] == 'ES') AND ($chardata[($i-1)]['type'] == 'EN') AND ($chardata[($i+1)]['type'] == 'EN')) {
 
6358
                                                $chardata[$i]['type'] = 'EN';
 
6359
                                        } elseif (($chardata[$i]['type'] == 'CS') AND ($chardata[($i-1)]['type'] == 'EN') AND ($chardata[($i+1)]['type'] == 'EN')) {
 
6360
                                                $chardata[$i]['type'] = 'EN';
 
6361
                                        } elseif (($chardata[$i]['type'] == 'CS') AND ($chardata[($i-1)]['type'] == 'AN') AND ($chardata[($i+1)]['type'] == 'AN')) {
 
6362
                                                $chardata[$i]['type'] = 'AN';
 
6363
                                        }
 
6364
                                }
 
6365
                                if ($chardata[$i]['level'] != $prevlevel) {
 
6366
                                        $levcount = 0;
 
6367
                                } else {
 
6368
                                        $levcount++;
 
6369
                                }
 
6370
                                $prevlevel = $chardata[$i]['level'];
 
6371
                        }
 
6372
                        
 
6373
                        // W5. A sequence of European terminators adjacent to European numbers changes to all European numbers.
 
6374
                        $prevlevel = -1;
 
6375
                        $levcount = 0;
 
6376
                        for ($i=0; $i < $numchars; $i++) {
 
6377
                                if($chardata[$i]['type'] == 'ET') {
 
6378
                                        if (($levcount > 0) AND ($chardata[($i-1)]['type'] == 'EN')) {
 
6379
                                                $chardata[$i]['type'] = 'EN';
 
6380
                                        } else {
 
6381
                                                $j = $i+1;
 
6382
                                                while (($j < $numchars) AND ($chardata[$j]['level'] == $prevlevel)) {
 
6383
                                                        if ($chardata[$j]['type'] == 'EN') {
 
6384
                                                                $chardata[$i]['type'] = 'EN';
 
6385
                                                                break;
 
6386
                                                        } elseif ($chardata[$j]['type'] != 'ET') {
 
6387
                                                                break;
 
6388
                                                        }
 
6389
                                                        $j++;
 
6390
                                                }
 
6391
                                        }
 
6392
                                }
 
6393
                                if ($chardata[$i]['level'] != $prevlevel) {
 
6394
                                        $levcount = 0;
 
6395
                                } else {
 
6396
                                        $levcount++;
 
6397
                                }
 
6398
                                $prevlevel = $chardata[$i]['level'];
 
6399
                        }
 
6400
                        
 
6401
                        // W6. Otherwise, separators and terminators change to Other Neutral.
 
6402
                        $prevlevel = -1;
 
6403
                        $levcount = 0;
 
6404
                        for ($i=0; $i < $numchars; $i++) {
 
6405
                                if (($chardata[$i]['type'] == 'ET') OR ($chardata[$i]['type'] == 'ES') OR ($chardata[$i]['type'] == 'CS')) {
 
6406
                                        $chardata[$i]['type'] = 'ON';
 
6407
                                }
 
6408
                                if ($chardata[$i]['level'] != $prevlevel) {
 
6409
                                        $levcount = 0;
 
6410
                                } else {
 
6411
                                        $levcount++;
 
6412
                                }
 
6413
                                $prevlevel = $chardata[$i]['level'];
 
6414
                        }
 
6415
                        
 
6416
                        //W7. Search backward from each instance of a European number until the first strong type (R, L, or sor) is found. If an L is found, then change the type of the European number to L.
 
6417
                        $prevlevel = -1;
 
6418
                        $levcount = 0;
 
6419
                        for ($i=0; $i < $numchars; $i++) {
 
6420
                                if ($chardata[$i]['char'] == 'EN') {
 
6421
                                        for ($j=$levcount; $j >= 0; $j--) {
 
6422
                                                if ($chardata[$j]['type'] == 'L') {
 
6423
                                                        $chardata[$i]['type'] = 'L';
 
6424
                                                } elseif ($chardata[$j]['type'] == 'R') {
 
6425
                                                        break;
 
6426
                                                }
 
6427
                                        }
 
6428
                                }
 
6429
                                if ($chardata[$i]['level'] != $prevlevel) {
 
6430
                                        $levcount = 0;
 
6431
                                } else {
 
6432
                                        $levcount++;
 
6433
                                }
 
6434
                                $prevlevel = $chardata[$i]['level'];
 
6435
                        }
 
6436
                        
 
6437
                        // N1. A sequence of neutrals takes the direction of the surrounding strong text if the text on both sides has the same direction. European and Arabic numbers act as if they were R in terms of their influence on neutrals. Start-of-level-run (sor) and end-of-level-run (eor) are used at level run boundaries.
 
6438
                        $prevlevel = -1;
 
6439
                        $levcount = 0;
 
6440
                        for ($i=0; $i < $numchars; $i++) {
 
6441
                                if (($levcount > 0) AND (($i+1) < $numchars) AND ($chardata[($i+1)]['level'] == $prevlevel)) {
 
6442
                                        if (($chardata[$i]['type'] == 'N') AND ($chardata[($i-1)]['type'] == 'L') AND ($chardata[($i+1)]['type'] == 'L')) {
 
6443
                                                $chardata[$i]['type'] = 'L';
 
6444
                                        } elseif (($chardata[$i]['type'] == 'N') AND
 
6445
                                         (($chardata[($i-1)]['type'] == 'R') OR ($chardata[($i-1)]['type'] == 'EN') OR ($chardata[($i-1)]['type'] == 'AN')) AND
 
6446
                                         (($chardata[($i+1)]['type'] == 'R') OR ($chardata[($i+1)]['type'] == 'EN') OR ($chardata[($i+1)]['type'] == 'AN'))) {
 
6447
                                                $chardata[$i]['type'] = 'R';
 
6448
                                        } elseif ($chardata[$i]['type'] == 'N') {
 
6449
                                                // N2. Any remaining neutrals take the embedding direction
 
6450
                                                $chardata[$i]['type'] = $chardata[$i]['sor'];
 
6451
                                        }
 
6452
                                } elseif (($levcount == 0) AND (($i+1) < $numchars) AND ($chardata[($i+1)]['level'] == $prevlevel)) {
 
6453
                                        // first char
 
6454
                                        if (($chardata[$i]['type'] == 'N') AND ($chardata[$i]['sor'] == 'L') AND ($chardata[($i+1)]['type'] == 'L')) {
 
6455
                                                $chardata[$i]['type'] = 'L';
 
6456
                                        } elseif (($chardata[$i]['type'] == 'N') AND
 
6457
                                         (($chardata[$i]['sor'] == 'R') OR ($chardata[$i]['sor'] == 'EN') OR ($chardata[$i]['sor'] == 'AN')) AND
 
6458
                                         (($chardata[($i+1)]['type'] == 'R') OR ($chardata[($i+1)]['type'] == 'EN') OR ($chardata[($i+1)]['type'] == 'AN'))) {
 
6459
                                                $chardata[$i]['type'] = 'R';
 
6460
                                        } elseif ($chardata[$i]['type'] == 'N') {
 
6461
                                                // N2. Any remaining neutrals take the embedding direction
 
6462
                                                $chardata[$i]['type'] = $chardata[$i]['sor'];
 
6463
                                        }
 
6464
                                } elseif (($levcount > 0) AND ((($i+1) == $numchars) OR (($i+1) < $numchars) AND ($chardata[($i+1)]['level'] != $prevlevel))) {
 
6465
                                        //last char
 
6466
                                        if (($chardata[$i]['type'] == 'N') AND ($chardata[($i-1)]['type'] == 'L') AND ($chardata[$i]['eor'] == 'L')) {
 
6467
                                                $chardata[$i]['type'] = 'L';
 
6468
                                        } elseif (($chardata[$i]['type'] == 'N') AND
 
6469
                                         (($chardata[($i-1)]['type'] == 'R') OR ($chardata[($i-1)]['type'] == 'EN') OR ($chardata[($i-1)]['type'] == 'AN')) AND
 
6470
                                         (($chardata[$i]['eor'] == 'R') OR ($chardata[$i]['eor'] == 'EN') OR ($chardata[$i]['eor'] == 'AN'))) {
 
6471
                                                $chardata[$i]['type'] = 'R';
 
6472
                                        } elseif ($chardata[$i]['type'] == 'N') {
 
6473
                                                // N2. Any remaining neutrals take the embedding direction
 
6474
                                                $chardata[$i]['type'] = $chardata[$i]['sor'];
 
6475
                                        }
 
6476
                                } elseif ($chardata[$i]['type'] == 'N') {
 
6477
                                        // N2. Any remaining neutrals take the embedding direction
 
6478
                                        $chardata[$i]['type'] = $chardata[$i]['sor'];
 
6479
                                }
 
6480
                                if ($chardata[$i]['level'] != $prevlevel) {
 
6481
                                        $levcount = 0;
 
6482
                                } else {
 
6483
                                        $levcount++;
 
6484
                                }
 
6485
                                $prevlevel = $chardata[$i]['level'];
 
6486
                        }
 
6487
                        
 
6488
                        // I1. For all characters with an even (left-to-right) embedding direction, those of type R go up one level and those of type AN or EN go up two levels.
 
6489
                        // I2. For all characters with an odd (right-to-left) embedding direction, those of type L, EN or AN go up one level.
 
6490
                        for ($i=0; $i < $numchars; $i++) {
 
6491
                                $odd = $chardata[$i]['level'] % 2;
 
6492
                                if ($odd) {
 
6493
                                        if (($chardata[$i]['type'] == 'L') OR ($chardata[$i]['type'] == 'AN') OR ($chardata[$i]['type'] == 'EN')){
 
6494
                                                $chardata[$i]['level'] += 1;
 
6495
                                        }
 
6496
                                } else {
 
6497
                                        if ($chardata[$i]['type'] == 'R') {
 
6498
                                                $chardata[$i]['level'] += 1;
 
6499
                                        } elseif (($chardata[$i]['type'] == 'AN') OR ($chardata[$i]['type'] == 'EN')){
 
6500
                                                $chardata[$i]['level'] += 2;
 
6501
                                        }
 
6502
                                }
 
6503
                                $maxlevel = max($chardata[$i]['level'],$maxlevel);
 
6504
                        }
 
6505
                        
 
6506
                        // L1. On each line, reset the embedding level of the following characters to the paragraph embedding level:
 
6507
                        //      1. Segment separators,
 
6508
                        //      2. Paragraph separators,
 
6509
                        //      3. Any sequence of whitespace characters preceding a segment separator or paragraph separator, and
 
6510
                        //      4. Any sequence of white space characters at the end of the line.
 
6511
                        for ($i=0; $i < $numchars; $i++) {
 
6512
                                if (($chardata[$i]['type'] == 'B') OR ($chardata[$i]['type'] == 'S')) {
 
6513
                                        $chardata[$i]['level'] = $pel;
 
6514
                                } elseif ($chardata[$i]['type'] == 'WS') {
 
6515
                                        $j = $i+1;
 
6516
                                        while ($j < $numchars) {
 
6517
                                                if ((($chardata[$j]['type'] == 'B') OR ($chardata[$j]['type'] == 'S')) OR
 
6518
                                                        (($j == ($numchars-1)) AND ($chardata[$j]['type'] == 'WS'))) {
 
6519
                                                        $chardata[$i]['level'] = $pel;;
 
6520
                                                        break;
 
6521
                                                } elseif ($chardata[$j]['type'] != 'WS') {
 
6522
                                                        break;
 
6523
                                                }
 
6524
                                                $j++;
 
6525
                                        }
 
6526
                                }
 
6527
                        }
 
6528
                        
 
6529
                        // Arabic Shaping
 
6530
                        // Cursively connected scripts, such as Arabic or Syriac, require the selection of positional character shapes that depend on adjacent characters. Shaping is logically applied after the Bidirectional Algorithm is used and is limited to characters within the same directional run. 
 
6531
                        if ($arabic) {
 
6532
                                for ($i=0; $i < $numchars; $i++) {
 
6533
                                        if ($unicode[$chardata[$i]['char']] == 'AL') {
 
6534
                                                if (($i > 0) AND (($i+1) < $numchars) AND 
 
6535
                                                                ($unicode[$chardata[($i-1)]['char']] == 'AL') AND 
 
6536
                                                                ($unicode[$chardata[($i+1)]['char']] == 'AL') AND
 
6537
                                                                ($chardata[($i-1)]['type'] == $chardata[$i]['type']) AND
 
6538
                                                                ($chardata[($i+1)]['type'] == $chardata[$i]['type'])) {
 
6539
                                                        // medial
 
6540
                                                        if (isset($unicode_arlet[$chardata[$i]['char']][3])) {
 
6541
                                                                $chardata[$i]['char'] = $unicode_arlet[$chardata[$i]['char']][3];
 
6542
                                                        }
 
6543
                                                } elseif ((($i+1) < $numchars) AND 
 
6544
                                                                ($unicode[$chardata[($i+1)]['char']] == 'AL') AND 
 
6545
                                                                ($chardata[($i+1)]['type'] == $chardata[$i]['type'])) {
 
6546
                                                        // initial
 
6547
                                                        if (isset($unicode_arlet[$chardata[$i]['char']][2])) {
 
6548
                                                                $chardata[$i]['char'] = $unicode_arlet[$chardata[$i]['char']][2];
 
6549
                                                        }
 
6550
                                                } elseif (($i > 0) AND 
 
6551
                                                                ($unicode[$chardata[($i-1)]['char']] == 'AL') AND 
 
6552
                                                                ($chardata[($i-1)]['type'] == $chardata[$i]['type'])) {
 
6553
                                                        // final
 
6554
                                                        if (isset($unicode_arlet[$chardata[$i]['char']][1])) {
 
6555
                                                                $chardata[$i]['char'] = $unicode_arlet[$chardata[$i]['char']][1];
 
6556
                                                        }
 
6557
                                                } elseif (isset($unicode_arlet[$chardata[$i]['char']][0])) {
 
6558
                                                        // isolated
 
6559
                                                        $chardata[$i]['char'] = $unicode_arlet[$chardata[$i]['char']][0];
 
6560
                                                }
 
6561
                                        }
 
6562
                                }
 
6563
                        }
 
6564
                        
 
6565
                        // L2. From the highest level found in the text to the lowest odd level on each line, including intermediate levels not actually present in the text, reverse any contiguous sequence of characters that are at that level or higher.
 
6566
                        for ($j=$maxlevel; $j > 0; $j--) {
 
6567
                                $ordarray = Array();
 
6568
                                $revarr = Array();
 
6569
                                $onlevel = false;
 
6570
                                for ($i=0; $i < $numchars; $i++) {
 
6571
                                        if ($chardata[$i]['level'] >= $j) {
 
6572
                                                $onlevel = true;
 
6573
                                                if (isset($unicode_mirror[$chardata[$i]['char']])) {
 
6574
                                                        // L4. A character is depicted by a mirrored glyph if and only if (a) the resolved directionality of that character is R, and (b) the Bidi_Mirrored property value of that character is true.
 
6575
                                                        $chardata[$i]['char'] = $unicode_mirror[$chardata[$i]['char']];
 
6576
                                                }
 
6577
                                                $revarr[] = $chardata[$i];
 
6578
                                        } else {
 
6579
                                                if($onlevel) {
 
6580
                                                        $revarr = array_reverse($revarr);
 
6581
                                                        $ordarray = array_merge($ordarray, $revarr);
 
6582
                                                        $revarr = Array();
 
6583
                                                        $onlevel = false;
 
6584
                                                }
 
6585
                                                $ordarray[] = $chardata[$i];
 
6586
                                        }
 
6587
                                }
 
6588
                                if($onlevel) {
 
6589
                                        $revarr = array_reverse($revarr);
 
6590
                                        $ordarray = array_merge($ordarray, $revarr);
 
6591
                                }
 
6592
                                $chardata = $ordarray;
 
6593
                        }
 
6594
                        
 
6595
                        $ordarray = array();
 
6596
                        for ($i=0; $i < $numchars; $i++) {
 
6597
                                $ordarray[] = $chardata[$i]['char'];
 
6598
                        }
 
6599
                        
 
6600
                        return $this->arrUTF8ToUTF16BE($ordarray, $setbom);
 
6601
                }
 
6602
                
 
6603
                // END OF BIDIRECTIONAL TEXT SECTION -------------------
 
6604
                
 
6605
                /*
 
6606
                * Adds a bookmark.
 
6607
                * @param string $txt bookmark description.
 
6608
                * @param int $level bookmark level.
 
6609
                * @param float $y Ordinate of the boorkmark position (default = -1 = current position).
 
6610
                * @access public
 
6611
                * @author Olivier Plathey, Nicola Asuni
 
6612
                * @since 2.1.002 (2008-02-12)
 
6613
                */
 
6614
                public function Bookmark($txt, $level=0, $y=-1) {
 
6615
        if($y == -1) {
 
6616
                                $y = $this->GetY();
 
6617
                        }
 
6618
                        $this->outlines[]=array('t'=>$txt,'l'=>$level,'y'=>$y,'p'=>$this->PageNo());
 
6619
                }
 
6620
                
 
6621
                /*
 
6622
                * Create a bookmark PDF string.
 
6623
                * @access private
 
6624
                * @author Olivier Plathey, Nicola Asuni
 
6625
                * @since 2.1.002 (2008-02-12)
 
6626
                */
 
6627
                private function _putbookmarks() {
 
6628
                        $nb = count($this->outlines);
 
6629
                        if($nb == 0) {
 
6630
                                return;
 
6631
                        }
 
6632
                        $lru = array();
 
6633
                        $level = 0;
 
6634
                        foreach($this->outlines as $i=>$o) {
 
6635
                                if($o['l'] > 0) {
 
6636
                                        $parent = $lru[$o['l'] - 1];
 
6637
                                        //Set parent and last pointers
 
6638
                                        $this->outlines[$i]['parent'] = $parent;
 
6639
                                        $this->outlines[$parent]['last'] = $i;
 
6640
                                        if($o['l'] > $level) {
 
6641
                                                //Level increasing: set first pointer
 
6642
                                                $this->outlines[$parent]['first'] = $i;
 
6643
                                        }
 
6644
                                } else {
 
6645
                                        $this->outlines[$i]['parent']=$nb;
 
6646
                                }
 
6647
                                if($o['l']<=$level and $i>0) {
 
6648
                                        //Set prev and next pointers
 
6649
                                        $prev = $lru[$o['l']];
 
6650
                                        $this->outlines[$prev]['next'] = $i;
 
6651
                                        $this->outlines[$i]['prev'] = $prev;
 
6652
                                }
 
6653
                                $lru[$o['l']] = $i;
 
6654
                                $level = $o['l'];
 
6655
                        }
 
6656
                        //Outline items
 
6657
                        $n = $this->n+1;
 
6658
                        foreach($this->outlines as $i=>$o) {
 
6659
                                $this->_newobj();
 
6660
                                $this->_out('<</Title '.$this->_textstring($o['t']));
 
6661
                                $this->_out('/Parent '.($n+$o['parent']).' 0 R');
 
6662
                                if(isset($o['prev']))
 
6663
                                $this->_out('/Prev '.($n+$o['prev']).' 0 R');
 
6664
                                if(isset($o['next']))
 
6665
                                $this->_out('/Next '.($n+$o['next']).' 0 R');
 
6666
                                if(isset($o['first']))
 
6667
                                $this->_out('/First '.($n+$o['first']).' 0 R');
 
6668
                                if(isset($o['last']))
 
6669
                                $this->_out('/Last '.($n+$o['last']).' 0 R');
 
6670
                                $this->_out(sprintf('/Dest [%d 0 R /XYZ 0 %.2f null]',1+2*$o['p'],($this->h-$o['y'])*$this->k));
 
6671
                                $this->_out('/Count 0>>');
 
6672
                                $this->_out('endobj');
 
6673
                        }
 
6674
                        //Outline root
 
6675
                        $this->_newobj();
 
6676
                        $this->OutlineRoot=$this->n;
 
6677
                        $this->_out('<</Type /Outlines /First '.$n.' 0 R');
 
6678
                        $this->_out('/Last '.($n+$lru[0]).' 0 R>>');
 
6679
                        $this->_out('endobj');
 
6680
                }
 
6681
                
 
6682
                
 
6683
                // --- JAVASCRIPT - FORMS ------------------------------
 
6684
                
 
6685
                /*
 
6686
                * Adds a javascript
 
6687
                * @access public
 
6688
                * @author Johannes G�ntert, Nicola Asuni
 
6689
                * @since 2.1.002 (2008-02-12)
 
6690
                */
 
6691
                public function IncludeJS($script) {
 
6692
                        $this->javascript .= $script;
 
6693
                }
 
6694
                
 
6695
                /*
 
6696
                * Create a javascript PDF string.
 
6697
                * @access private
 
6698
                * @author Johannes G�ntert, Nicola Asuni
 
6699
                * @since 2.1.002 (2008-02-12)
 
6700
                */
 
6701
                private function _putjavascript() {
 
6702
                        if (empty($this->javascript)) {
 
6703
                                return;
 
6704
                        }
 
6705
                        $this->_newobj();
 
6706
                        $this->n_js = $this->n;
 
6707
                        $this->_out('<<');
 
6708
                        $this->_out('/Names [(EmbeddedJS) '.($this->n+1).' 0 R ]');
 
6709
                        $this->_out('>>');
 
6710
                        $this->_out('endobj');
 
6711
                        $this->_newobj();
 
6712
                        $this->_out('<<');
 
6713
                        $this->_out('/S /JavaScript');
 
6714
                        $this->_out('/JS '.$this->_textstring($this->javascript));
 
6715
                        $this->_out('>>');
 
6716
                        $this->_out('endobj');
 
6717
                }
 
6718
                
 
6719
                /*
 
6720
                * Convert color to javascript color.
 
6721
                * @param string $color color name or #RRGGBB
 
6722
                * @access private
 
6723
                * @author Denis Van Nuffelen, Nicola Asuni
 
6724
                * @since 2.1.002 (2008-02-12)
 
6725
                */
 
6726
                private function _JScolor($color) {
 
6727
                        static $aColors = array('transparent','black','white','red','green','blue','cyan','magenta','yellow','dkGray','gray','ltGray');
 
6728
                        if(substr($color,0,1) == '#') {
 
6729
                                return sprintf("['RGB',%.3f,%.3f,%.3f]", hexdec(substr($color,1,2))/255, hexdec(substr($color,3,2))/255, hexdec(substr($color,5,2))/255);
 
6730
                        }
 
6731
                        if(!in_array($color,$aColors)) {
 
6732
                                $this->Error('Invalid color: '.$color);
 
6733
                        }
 
6734
                        return 'color.'.$color;
 
6735
                }
 
6736
                
 
6737
                /*
 
6738
                * Adds a javascript form field.
 
6739
                * @param string $type field type
 
6740
                * @param string $name field name
 
6741
                * @param int $x horizontal position
 
6742
                * @param int $y vertical position
 
6743
                * @param int $w width
 
6744
                * @param int $h height
 
6745
                * @param string $prop properties
 
6746
                * @access private
 
6747
                * @author Denis Van Nuffelen, Nicola Asuni
 
6748
                * @since 2.1.002 (2008-02-12)
 
6749
                */
 
6750
                private function _addfield($type, $name, $x, $y, $w, $h, $prop) {
 
6751
                        $k = $this->k;
 
6752
                        $this->javascript .= sprintf("f=addField('%s','%s',%d,[%.2f,%.2f,%.2f,%.2f]);",$name,$type,$this->PageNo()-1,$x*$k,($this->h-$y)*$k+1,($x+$w)*$k,($this->h-$y-$h)*$k+1);
 
6753
                        $this->javascript .= 'f.textSize='.$this->FontSizePt.';';
 
6754
                        if(isset($prop['value'])) {
 
6755
                                $this->javascript .= "f.value='".addslashes($prop['value'])."';";
 
6756
                        }
 
6757
                        if(isset($prop['TextColor'])) {
 
6758
                                $this->javascript .= 'f.textColor='.$this->_JScolor($prop['TextColor']).';';
 
6759
                        }
 
6760
                        if(isset($prop['FillColor'])) {
 
6761
                                $this->javascript .= 'f.fillColor='.$this->_JScolor($prop['FillColor']).';';
 
6762
                        }
 
6763
                        if(isset($prop['BorderColor'])) {
 
6764
                                $this->javascript .= 'f.strokeColor='.$this->_JScolor($prop['BorderColor']).';';
 
6765
                        }
 
6766
                        if(isset($prop['BorderStyle'])) {
 
6767
                                $this->javascript .= "f.borderStyle='".$prop['BorderStyle']."';";
 
6768
                        }
 
6769
                        $this->x+=$w;
 
6770
                }
 
6771
                
 
6772
                /*
 
6773
                * Creates a text field
 
6774
                * @param string $name field name
 
6775
                * @param int $w width
 
6776
                * @param int $h height
 
6777
                * @param string $prop properties. The value property allows to set the initial value. The multiline property allows to define the field as multiline.
 
6778
                * @access public
 
6779
                * @author Denis Van Nuffelen, Nicola Asuni
 
6780
                * @since 2.1.002 (2008-02-12)
 
6781
                */
 
6782
                public function TextField($name, $w, $h, $prop=array()) {
 
6783
                        $this->_addfield('text',$name,$this->x,$this->y,$w,$h,$prop);
 
6784
                        if(isset($prop['multiline']) AND $prop['multiline']) {
 
6785
                                $this->javascript .= 'f.multiline=true;';
 
6786
                        }
 
6787
                }
 
6788
                
 
6789
                /*
 
6790
                * Creates a Combo-box field
 
6791
                * @param string $name field name
 
6792
                * @param int $w width
 
6793
                * @param int $h height
 
6794
                * @param array $values array containing the list of values.
 
6795
                * @param string $prop properties.
 
6796
                * @access public
 
6797
                * @author Denis Van Nuffelen, Nicola Asuni
 
6798
                * @since 2.1.002 (2008-02-12)
 
6799
                */
 
6800
                public function ComboBox($name, $w, $h, $values, $prop=array()) {
 
6801
                        $this->_addfield('combobox',$name,$this->x,$this->y,$w,$h,$prop);
 
6802
                        $s = '';
 
6803
                        foreach($values as $value) {
 
6804
                                $s .= "'".addslashes($value)."',";
 
6805
                        }
 
6806
                        $this->javascript .= 'f.setItems(['.substr($s,0,-1).']);';
 
6807
                }
 
6808
                
 
6809
                /*
 
6810
                * Creates a CheckBox field
 
6811
                * @param string $name field name
 
6812
                * @param int $w width
 
6813
                * @param boolean $checked define the initial state (default = false).
 
6814
                * @param string $prop properties.
 
6815
                * @access public
 
6816
                * @author Denis Van Nuffelen, Nicola Asuni
 
6817
                * @since 2.1.002 (2008-02-12)
 
6818
                */
 
6819
                public function CheckBox($name, $w, $checked=false, $prop=array()) {
 
6820
                        $prop['value'] = ($checked ? 'Yes' : 'Off');
 
6821
                        if(!isset($prop['BorderColor'])) {
 
6822
                                $prop['BorderColor']='black';
 
6823
                        }
 
6824
                        $this->_addfield('checkbox',$name,$this->x,$this->y,$w,$w,$prop);
 
6825
                }
 
6826
                
 
6827
                /*
 
6828
                * Creates a button field
 
6829
                * @param string $name field name
 
6830
                * @param int $w width
 
6831
                * @param int $h height
 
6832
                * @param string $caption caption.
 
6833
                * @param string $action action triggered by the button (JavaScript code).
 
6834
                * @param string $prop properties.
 
6835
                * @access public
 
6836
                * @author Denis Van Nuffelen, Nicola Asuni
 
6837
                * @since 2.1.002 (2008-02-12)
 
6838
                */
 
6839
                public function Button($name, $w, $h, $caption, $action, $prop=array()) {
 
6840
                        if(!isset($prop['BorderColor'])) {
 
6841
                                $prop['BorderColor']='black';
 
6842
                        }
 
6843
                        $prop['BorderStyle']='beveled';
 
6844
                        $this->_addfield('button',$name,$this->x,$this->y,$w,$h,$prop);
 
6845
                        $this->javascript .= "f.buttonSetCaption('".addslashes($caption)."');";
 
6846
                        $this->javascript .= "f.setAction('MouseUp','".addslashes($action)."');";
 
6847
                        $this->javascript .= "f.highlight='push';";
 
6848
                        $this->javascript .= 'f.print=false;';
 
6849
                }
 
6850
                
 
6851
                // END JAVASCRIPT - FORMS ------------------------------
 
6852
                
 
6853
        } // END OF TCPDF CLASS
4127
6854
 
4128
6855
        //Handle special IE contype request
4129
6856
        if(isset($_SERVER['HTTP_USER_AGENT']) AND ($_SERVER['HTTP_USER_AGENT']=='contype')) {