~rmwenyekheri/sarisiae/trunk

« back to all changes in this revision

Viewing changes to admission/include/PDF.php

  • Committer: NDIMBOJr
  • Date: 2015-08-13 10:09:13 UTC
  • Revision ID: rmwenyekheri@gmail.com-20150813100913-wa5o4k7vvarmzl4n
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * PDF::
 
4
 *
 
5
 * The PDF:: class provides a PHP-only implementation of a PDF library.
 
6
 * No external libs or PHP extensions are required.
 
7
 *
 
8
 * Based on the FPDF class by Olivier Plathey (http://www.fpdf.org) and the
 
9
 * Horde Framework PDF package (http://www.horde.org)
 
10
 *
 
11
 * Copyright 2003 Marko Djukic <marko@oblo.com>
 
12
 * Copyright 2003 Olivier Plathey <olivier@fpdf.org>
 
13
 *
 
14
 * See the enclosed file COPYING for license information (LGPL). If you did not
 
15
 * receive this file, see http://www.fsf.org/copyleft/lgpl.html.
 
16
 *
 
17
 * @author  Olivier Plathey <olivier@fpdf.org>
 
18
 * @author  Marko Djukic <marko@oblo.com>
 
19
 */
 
20
//include ('class.pdf.php');
 
21
//include ('fpdf.php');
 
22
class PDF {
 
23
 
 
24
    var $_buffer = '';          // Buffer holding in-memory PDF.
 
25
    var $_state = 0;            // Current document state.
 
26
    var $_page = 0;             // Current page number.
 
27
    var $_n = 2;                // Current object number.
 
28
    var $_offsets = array();    // Array of object offsets.
 
29
    var $_pages = array();      // Array containing the pages.
 
30
    var $_w;                    // Page width in points.
 
31
    var $_h;                    // Page height in points
 
32
    var $_fonts = array();      // An array of used fonts.
 
33
    var $_font_family = '';     // Current font family.
 
34
    var $_font_style = '';      // Current font style.
 
35
    var $_current_font;         // Array with current font info.
 
36
    var $_font_size = 12;       // Current font size in points.
 
37
    var $_compress;             // Flag to compress or not.
 
38
    var $_core_fonts = array('courier'      => 'Courier',
 
39
                             'courierB'     => 'Courier-Bold',
 
40
                             'courierI'     => 'Courier-Oblique',
 
41
                             'courierBI'    => 'Courier-BoldOblique',
 
42
                             'helvetica'    => 'Helvetica',
 
43
                             'helveticaB'   => 'Helvetica-Bold',
 
44
                             'helveticaI'   => 'Helvetica-Oblique',
 
45
                             'helveticaBI'  => 'Helvetica-BoldOblique',
 
46
                             'times'        => 'Times-Roman',
 
47
                             'timesB'       => 'Times-Bold',
 
48
                             'timesI'       => 'Times-Italic',
 
49
                             'timesBI'      => 'Times-BoldItalic',
 
50
                             'symbol'       => 'Symbol',
 
51
                             'zapfdingbats' => 'ZapfDingbats');
 
52
    var $_fill_color = '0 g';   // Color used on text and fills.
 
53
    var $_draw_color = '0 G';   // Line draw color.
 
54
    var $_line_width = 1;       // Drawing line width.
 
55
    var $_images = array();     // An array of used images.
 
56
 
 
57
    /**
 
58
     * Attempts to return a conrete PDF instance. It allows to set up the page
 
59
     * format, the orientation and the units of measurement used in all the
 
60
     * methods (except for the font sizes).
 
61
     *
 
62
     * Example:
 
63
     * $pdf = &PDF::factory('P', 'A4');
 
64
     *
 
65
     * @access public
 
66
     *
 
67
     * @param optional string $orientation  Default page orientation.
 
68
     *                                      Possible values are (case
 
69
     *                                      insensitive):
 
70
     *                                        - P or Portrait (default)
 
71
     *                                        - L or Landscape
 
72
     * @param optional mixed format         The format used for pages. It can
 
73
     *                                      be either one of the following
 
74
     *                                      values (case insensitive):
 
75
     *                                        - A3
 
76
     *                                        - A4 (default)
 
77
     *                                        - A5
 
78
     *                                        - Letter
 
79
     *                                        - Legal
 
80
     *                                      or a custom format in the form of
 
81
     *                                      a two-element array containing the
 
82
     *                                      width and the height (expressed in
 
83
     *                                      the unit given by unit).
 
84
     */
 
85
    function &factory($orientation = 'P', $format = 'A4')
 
86
    {
 
87
        /* Create the PDF object. */
 
88
        $pdf = &new PDF();
 
89
 
 
90
        /* Page format. */
 
91
        $format = strtolower($format);
 
92
        if ($format == 'a3') {           // A3 page size.
 
93
            $format = array(841.89, 1190.55);
 
94
        } elseif ($format == 'a4') {     // A4 page size.
 
95
            $format = array(595.28, 841.89);
 
96
        } elseif ($format == 'a5') {     // A5 page size.
 
97
            $format = array(420.94, 595.28);
 
98
        } elseif ($format == 'letter') { // Letter page size.
 
99
            $format = array(612, 792);
 
100
        } elseif ($format == 'legal') {  // Legal page size.
 
101
            $format = array(612, 1008);
 
102
        } else {
 
103
            die(sprintf('Unknown page format: %s', $format));
 
104
        }   
 
105
        $pdf->_w = $format[0];
 
106
        $pdf->_h = $format[1];
 
107
 
 
108
        /* Page orientation. */
 
109
        $orientation = strtolower($orientation);
 
110
        if ($orientation == 'l' || $orientation == 'landscape') {
 
111
            $w = $pdf->_w;
 
112
            $pdf->_w = $pdf->_h;
 
113
            $pdf->_h = $w;
 
114
        } elseif ($orientation != 'p' && $orientation != 'portrait') {
 
115
            die(sprintf('Incorrect orientation: %s', $orientation));
 
116
        }
 
117
 
 
118
        /* Turn on compression by default. */
 
119
        $pdf->setCompression(true);
 
120
 
 
121
        return $pdf;
 
122
    }
 
123
 
 
124
    /**
 
125
     * Activates or deactivates page compression. When activated, the internal
 
126
     * representation of each page is compressed, which leads to a compression
 
127
     * ratio of about 2 for the resulting document.
 
128
     * Compression is on by default.
 
129
     * Note: the Zlib extension is required for this feature. If not present,
 
130
     * compression will be turned off.
 
131
     *
 
132
     * @param bool $compress  Boolean indicating if compression must be
 
133
     *                        enabled or not.
 
134
     */
 
135
    function setCompression($compress)
 
136
    {   
 
137
        /* If no gzcompress function is available then default to
 
138
         * false. */
 
139
        $this->_compress = (function_exists('gzcompress') ? $compress : false);
 
140
    }
 
141
 
 
142
    /**
 
143
     * This method begins the generation of the PDF document; it must be
 
144
     * called before any output commands. No page is created by this method,
 
145
     * therefore it is necessary to call PDF::addPage.
 
146
     *
 
147
     * @access public
 
148
     */
 
149
    function open()
 
150
    {   
 
151
        $this->_state = 1;          // Set state to initialised.
 
152
        $this->_out('%PDF-1.3');    // Output the PDF header.
 
153
    }
 
154
 
 
155
    /**
 
156
     * Adds a new page to the document. The font which was set before calling
 
157
     * is automatically restored. There is no need to call PDF::setFont again
 
158
     * if you want to continue with the same font.
 
159
     *
 
160
     * @access public
 
161
     */
 
162
    function addPage()
 
163
    {   
 
164
        $this->_page++;                    // Increment page count.
 
165
        $this->_pages[$this->_page] = '';  // Start the page buffer.
 
166
        $this->_state = 2;                 // Set state to page
 
167
                                           // opened.
 
168
        /* Check if font has been set before this page. */
 
169
        if ($this->_font_family) {
 
170
            $this->setFont($this->_font_family, $this->_font_style, $this->_font_size);
 
171
        }
 
172
        /* Check if fill color has been set before this page. */
 
173
        if ($this->_fill_color != '0 g') {
 
174
            $this->_out($this->_fill_color);
 
175
        }   
 
176
        /* Check if draw color has been set before this page. */
 
177
        if ($this->_draw_color != '0 G') {
 
178
            $this->_out($this->_draw_color);
 
179
        }
 
180
        /* Check if line width has been set before this page. */
 
181
        if ($this->_line_width != 1) {
 
182
            $this->_out($this->_line_width);
 
183
        }
 
184
    }
 
185
 
 
186
    /**
 
187
     * Sets the font used to print character strings. It is mandatory to call
 
188
     * this method at least once before printing text or the resulting
 
189
     * document would not be valid. The font must be a standard one. Standard
 
190
     * fonts use Windows encoding cp1252 (Western Europe).
 
191
     * The method can be called before the first page is created and the font
 
192
     * is retained from page to page.
 
193
     * If you just wish to change the current font size, it is simpler to call
 
194
     * PDF::setFontSize.
 
195
     *
 
196
     * @access public
 
197
     *
 
198
     * @param string $family          Family font. It must be one of the
 
199
     *                                standard families (case insensitive):
 
200
     *                                  - Courier (fixed-width)
 
201
     *                                  - Helvetica or Arial (sans serif)
 
202
     *                                  - Times (serif)
 
203
     *                                  - Symbol (symbolic)
 
204
     *                                  - ZapfDingbats (symbolic)
 
205
     *                                It is also possible to pass an empty
 
206
     *                                string. In that case, the current
 
207
     *                                family is retained.
 
208
     * @param optional string $style  Font style. Possible values are (case
 
209
     *                                insensitive):
 
210
     *                                  - empty string: regular
 
211
     *                                  - B: bold
 
212
     *                                  - I: italic
 
213
     *                                or any combination. The default value is
 
214
     *                                regular. Bold and italic styles do not
 
215
     *                                apply to Symbol and ZapfDingbats.
 
216
     * @param optional int $size      Font size in points. The default value
 
217
     *                                is the current size. If no size has been
 
218
     *                                specified since the beginning of the
 
219
     *                                document, the value taken is 12.
 
220
     */
 
221
    function setFont($family, $style = '', $size = null)
 
222
    {
 
223
        $family = strtolower($family);
 
224
        if ($family == 'arial') {               // Use helvetica.
 
225
            $family = 'helvetica';
 
226
        } elseif ($family == 'symbol' ||        // No styles for
 
227
                  $family == 'zapfdingbats') {  // these two fonts.
 
228
            $style = '';
 
229
        }
 
230
 
 
231
        $style = strtoupper($style);
 
232
        if ($style == 'IB') {                   // Accept any order
 
233
            $style = 'BI';                      // of B and I.
 
234
        }
 
235
 
 
236
        if (is_null($size)) {                   // No size specified,
 
237
            $size = $this->_font_size;          // use current size.
 
238
        }
 
239
 
 
240
        if ($this->_font_family == $family &&   // If font is already 
 
241
            $this->_font_style == $style &&     // current font
 
242
            $this->_font_size == $size) {       // simply return.
 
243
            return;
 
244
        }
 
245
 
 
246
        /* Set the font key. */
 
247
        $fontkey = $family . $style;
 
248
 
 
249
        if (!isset($this->_fonts[$fontkey])) {  // Test if cached.
 
250
            $i = count($this->_fonts) + 1;      // Increment font
 
251
            $this->_fonts[$fontkey] = array(    // object count and
 
252
                'i'    => $i,                   // store cache.
 
253
                'name' => $this->_core_fonts[$fontkey]);
 
254
        }
 
255
 
 
256
        /* Store current font information. */
 
257
        $this->_font_family  = $family;
 
258
        $this->_font_style   = $style;
 
259
        $this->_font_size    = $size;
 
260
        $this->_current_font = $this->_fonts[$fontkey];
 
261
 
 
262
        /* Output font information if at least one page has been
 
263
         * defined. */
 
264
        if ($this->_page > 0) {
 
265
            $this->_out(sprintf('BT /F%d %.2f Tf ET', $this->_current_font['i'], $this->_font_size));
 
266
        }
 
267
    }
 
268
 
 
269
    /**
 
270
     * Defines the size of the current font.
 
271
     *
 
272
     * @access public
 
273
     *
 
274
     * @param float $size  The size (in points).
 
275
     */
 
276
    function setFontSize($size)
 
277
    {
 
278
        if ($this->_font_size == $size) {   // If already current
 
279
            return;                         // size simply return.
 
280
        }
 
281
 
 
282
        $this->_font_size = $size;          // Set the font.
 
283
 
 
284
        /* Output font information if at least one page has been
 
285
         * defined. */
 
286
        if ($this->_page > 0) {
 
287
            $this->_out(sprintf('BT /F%d %.2f Tf ET',
 
288
                                $this->_current_font['i'],
 
289
                                $this->_font_size));
 
290
        }
 
291
    }
 
292
 
 
293
    /**
 
294
     * Sets the fill color. Specifies the color for both filled areas and
 
295
     * text. Depending on the colorspace called, the number of color component
 
296
     * parameters required can be either 1, 3 or 4. The method can be called
 
297
     * before the first page is created and the color is retained from page to
 
298
     * page.
 
299
     *
 
300
     * @access public
 
301
     *
 
302
     * @param string $cs          Indicates the colorspace which can be either
 
303
     *                            'rgb', 'cmyk' or 'gray'. Defaults to 'rgb'.
 
304
     * @param float $c1           First color component, floating point value
 
305
     *                            between 0 and 1. Required for gray, rgb and
 
306
     *                            cmyk.
 
307
     * @param optional float $c2  Second color component, floating point value
 
308
     *                            between 0 and 1. Required for rgb and cmyk.
 
309
     * @param optional float $c3  Third color component, floating point value
 
310
     *                            between 0 and 1. Required for rgb and cmyk.
 
311
     * @param optional float $c4  Fourth color component, floating point value
 
312
     *                            between 0 and 1. Required for cmyk.
 
313
     */
 
314
    function setFillColor($cs = 'rgb', $c1, $c2 = 0, $c3 = 0, $c4 = 0)
 
315
    {
 
316
        $cs = strtolower($cs);
 
317
        if ($cs = 'rgb') {
 
318
            /* Using a three component RGB color. */
 
319
            $this->_fill_color = sprintf('%.3f %.3f %.3f rg',
 
320
                                         $c1, $c2, $c3);
 
321
        } elseif ($cs = 'cmyk') {
 
322
            /* Using a four component CMYK color. */
 
323
            $this->_fill_color = sprintf('%.3f %.3f %.3f %.3f k',
 
324
                                         $c1, $c2, $c3, $c4);
 
325
        } else {
 
326
            /* Grayscale one component color. */
 
327
            $this->_fill_color = sprintf('%.3f g', $c1);
 
328
        }
 
329
        /* If document started output to buffer. */
 
330
        if ($this->_page > 0) {
 
331
            $this->_out($this->_fill_color);
 
332
        }
 
333
    }
 
334
 
 
335
    /**
 
336
     * Sets the draw color, used when drawing lines. Depending on the
 
337
     * colorspace called, the number of color component parameters required
 
338
     * can be either 1, 3 or 4. The method can be called before the first page
 
339
     * is created and the color is retained from page to page.
 
340
     *
 
341
     * @access public
 
342
     *
 
343
     * @param string $cs          Indicates the colorspace which can be either
 
344
     *                            'rgb', 'cmyk' or 'gray'. Defaults to 'rgb'.
 
345
     * @param float $c1           First color component, floating point value
 
346
     *                            between 0 and 1. Required for gray, rgb and
 
347
     *                            cmyk.
 
348
     * @param optional float $c2  Second color component, floating point value
 
349
     *                            between 0 and 1. Required for rgb and cmyk.
 
350
     * @param optional float $c3  Third color component, floating point value
 
351
     *                            between 0 and 1. Required for rgb and cmyk.
 
352
     * @param optional float $c4  Fourth color component, floating point value
 
353
     *                            between 0 and 1. Required for cmyk.
 
354
     */
 
355
    function setDrawColor($cs = 'rgb', $c1, $c2 = 0, $c3 = 0, $c4 = 0)
 
356
    {   
 
357
        $cs = strtolower($cs);
 
358
        if ($cs = 'rgb') {
 
359
            $this->_draw_color = sprintf('%.3f %.3f %.3f RG',
 
360
                                         $c1, $c2, $c3);
 
361
        } elseif ($cs = 'cmyk') {
 
362
            $this->_draw_color = sprintf('%.3f %.3f %.3f %.3f K',
 
363
                                         $c1, $c2, $c3, $c4);
 
364
        } else {
 
365
            $this->_draw_color = sprintf('%.3f G', $c1);
 
366
        }   
 
367
        /* If document started output to buffer. */
 
368
        if ($this->_page > 0) {
 
369
            $this->_out($this->_draw_color);
 
370
        }
 
371
    }
 
372
 
 
373
    /**
 
374
     * Defines the line width. By default, the value equals 1 pt. The method
 
375
     * can be called before the first page is created and the value is
 
376
     * retained from page to page. 
 
377
     * 
 
378
     * @access public
 
379
     * 
 
380
     * @param float $width  The width.
 
381
     */
 
382
    function setLineWidth($width)
 
383
    {
 
384
        $this->_line_width = $width;
 
385
        if ($this->_page > 0) {
 
386
            $this->_out(sprintf('%.2f w', $width));
 
387
        }
 
388
    }
 
389
 
 
390
    /**
 
391
     * Prints a character string. The origin is on the left of the first
 
392
     * character, on the baseline. This method allows to place a string
 
393
     * precisely on the page.
 
394
     *
 
395
     * @access public
 
396
     *
 
397
     * @param float $x      Abscissa of the origin.
 
398
     * @param float $y      Ordinate of the origin.
 
399
     * @param string $text  String to print.
 
400
     */
 
401
    function text($x, $y, $text)
 
402
    {
 
403
        $text = $this->_escape($text);    // Escape any harmful
 
404
                                          // characters.
 
405
 
 
406
        $out = sprintf('BT %.2f %.2f Td (%s) Tj ET',
 
407
                       $x, $this->_h - $y, $text);
 
408
        $this->_out($out);
 
409
    }
 
410
 
 
411
    /**
 
412
     * Prints an image in the page. The upper-left corner and at least one of
 
413
     * the dimensions must be specified; the height or the width can be
 
414
     * calculated automatically in order to keep the image proportions.
 
415
     * Supported format is JPEG.
 
416
     *
 
417
     * For JPEG, all flavors are allowed:
 
418
     *   - gray scales
 
419
     *   - true colors (24 bits)
 
420
     *   - CMYK (32 bits)
 
421
     *
 
422
     * The format will be inferred from the file extension.
 
423
     *
 
424
     * Remark: if an image is used several times, only one copy will be
 
425
     * embedded in the file.
 
426
     *
 
427
     * @access public
 
428
     *
 
429
     * @param string $file            Name of the file containing the image.
 
430
     * @param float $x                Abscissa of the upper-left corner.
 
431
     * @param float $y                Ordinate of the upper-left corner.
 
432
     * @param float $width            Width of the image in the page. If equal
 
433
     *                                to zero, it is automatically calculated
 
434
     *                                to keep the original proportions.
 
435
     * @param optional float $height  Height of the image in the page. If not
 
436
     *                                specified or equal to zero, it is
 
437
     *                                automatically calculated to keep the
 
438
     *                                original proportions.
 
439
     */
 
440
    function image($file, $x, $y, $width = 0, $height = 0)
 
441
    {
 
442
        if (!isset($this->_images[$file])) {
 
443
            /* First use of requested image, get the extension. */
 
444
            if (($pos = strrpos($file, '.')) === false) {
 
445
                die(sprintf('Image file %s has no extension and no type was specified', $file));
 
446
            }
 
447
            $type = strtolower(substr($file, $pos + 1));
 
448
 
 
449
            /* Check the image type and parse. */
 
450
            if ($type == 'jpg' || $type == 'jpeg') {
 
451
                $info = $this->_parseJPG($file);
 
452
            } else {
 
453
                die(sprintf('Unsupported image file type: %s', $type));
 
454
            }
 
455
            /* Set the image object id. */
 
456
            $info['i'] = count($this->_images) + 1;
 
457
            /* Set image to array. */
 
458
 
 
459
            $this->_images[$file] = $info;
 
460
        } else {
 
461
            $info = $this->_images[$file];          // Known image, retrieve
 
462
                                                    // from array.
 
463
        }
 
464
 
 
465
        /* If not specified, do automatic width and height
 
466
         * calculations, either setting to original or
 
467
         * proportionally scaling to one or the other given
 
468
         * dimension. */
 
469
        if (empty($width) && empty($height)) {
 
470
            $width = $info['w'];
 
471
            $height = $info['h'];
 
472
        } elseif (empty($width)) {
 
473
            $width = $height * $info['w'] / $info['h'];
 
474
        } elseif (empty($height)) {
 
475
            $height = $width * $info['h'] / $info['w'];
 
476
        }
 
477
 
 
478
        $this->_out(sprintf('q %.2f 0 0 %.2f %.2f %.2f cm /I%d Do Q', $width, $height, $x, $this->_h - ($y + $height), $info['i']));
 
479
    }
 
480
 
 
481
    /**
 
482
     * Draws a line between two points.
 
483
     * 
 
484
     * @access public
 
485
     * 
 
486
     * @param float $x1  Abscissa of first point. 
 
487
     * @param float $y1  Ordinate of first point.
 
488
     * @param float $x2  Abscissa of second point.
 
489
     * @param float $y2  Ordinate of second point.
 
490
     * 
 
491
     */                           
 
492
    function line($x1, $y1, $x2, $y2)
 
493
    {   
 
494
        $this->_out(sprintf('%.2f %.2f m %.2f %.2f l S', $x1, $this->_h - $y1, $x2, $this->_h - $y2));
 
495
    }
 
496
 
 
497
    /**                           
 
498
     * Outputs a rectangle. It can be drawn (border only), filled (with no
 
499
     * border) or both.
 
500
     *
 
501
     * @access public
 
502
     *
 
503
     * @param float $x                Abscissa of upper left corner.
 
504
     * @param float $y                Ordinate of upper left corner.
 
505
     * @param float $width            Width.
 
506
     * @param float $height           Height.
 
507
     * @param optional string $style  Style of rendering. Possible values are:
 
508
     *                                  - D or empty string: draw (default)
 
509
     *                                  - F: fill
 
510
     *                                  - DF or FD: draw and fill
 
511
     */
 
512
    function rect($x, $y, $width, $height, $style = '')
 
513
    {
 
514
        $style = strtolower($style);
 
515
        if ($style == 'f') {
 
516
            $op = 'f';      // Style is fill only.
 
517
        } elseif ($style == 'fd' || $style == 'df') {
 
518
            $op = 'B';      // Style is fill and stroke.
 
519
        } else {
 
520
            $op = 'S';      // Style is stroke only.
 
521
        }
 
522
 
 
523
        $this->_out(sprintf('%.2f %.2f %.2f %.2f re %s', $x, $this->_h - $y, $width, -$height, $op));
 
524
    }
 
525
 
 
526
    /**
 
527
     * Outputs a circle. It can be drawn (border only), filled (with no
 
528
     * border) or both.
 
529
     *
 
530
     * @access public
 
531
     *
 
532
     * @param float $x                Abscissa of the center of the circle.
 
533
     * @param float $y                Ordinate of the center of the circle.
 
534
     * @param float $r                Circle radius.
 
535
     * @param optional string $style  Style of rendering. Possible values are:
 
536
     *                                  - D or empty string: draw (default)
 
537
     *                                  - F: fill
 
538
     *                                  - DF or FD: draw and fill
 
539
     */
 
540
    function circle($x, $y, $r, $style = '')
 
541
    {
 
542
        $style = strtolower($style);
 
543
        if ($style == 'f') {
 
544
            $op = 'f';      // Style is fill only.
 
545
        } elseif ($style == 'fd' || $style == 'df') {
 
546
            $op = 'B';      // Style is fill and stroke.
 
547
        } else {
 
548
            $op = 'S';      // Style is stroke only.
 
549
        }
 
550
 
 
551
        $y = $this->_h - $y;                 // Adjust y value.
 
552
        $b = $r * 0.552;                     // Length of the Bezier
 
553
                                             // controls.
 
554
        /* Move from the given origin and set the current point
 
555
         * to the start of the first Bezier curve. */
 
556
        $c = sprintf('%.2f %.2f m', $x - $r, $y);
 
557
        $x = $x - $r;
 
558
        /* First circle quarter. */
 
559
        $c .= sprintf(' %.2f %.2f %.2f %.2f %.2f %.2f c',
 
560
                      $x, $y + $b,           // First control point.
 
561
                      $x + $r - $b, $y + $r, // Second control point.
 
562
                      $x + $r, $y + $r);     // Final point.
 
563
        /* Set x/y to the final point. */
 
564
        $x = $x + $r;
 
565
        $y = $y + $r;
 
566
        /* Second circle quarter. */
 
567
        $c .= sprintf(' %.2f %.2f %.2f %.2f %.2f %.2f c',
 
568
                      $x + $b, $y,
 
569
                      $x + $r, $y - $r + $b,
 
570
                      $x + $r, $y - $r);
 
571
        /* Set x/y to the final point. */
 
572
        $x = $x + $r;
 
573
        $y = $y - $r;
 
574
        /* Third circle quarter. */
 
575
        $c .= sprintf(' %.2f %.2f %.2f %.2f %.2f %.2f c',
 
576
                      $x, $y - $b,
 
577
                      $x - $r + $b, $y - $r,
 
578
                      $x - $r, $y - $r);
 
579
        /* Set x/y to the final point. */
 
580
        $x = $x - $r;
 
581
        $y = $y - $r;
 
582
        /* Fourth circle quarter. */
 
583
        $c .= sprintf(' %.2f %.2f %.2f %.2f %.2f %.2f c %s',
 
584
                      $x - $b, $y,
 
585
                      $x - $r, $y + $r - $b,
 
586
                      $x - $r, $y + $r,
 
587
                      $op);
 
588
        /* Output the whole string. */
 
589
        $this->_out($c);
 
590
    }
 
591
 
 
592
    /**
 
593
     * Terminates the PDF document. It is not necessary to call this method
 
594
     * explicitly because PDF::output does it automatically.
 
595
     * If the document contains no page, PDF::addPage is called to prevent
 
596
     * from getting an invalid document.
 
597
     *
 
598
     * @access public
 
599
     */
 
600
    function close()
 
601
    {
 
602
        if ($this->_page == 0) {    // If not yet initialised, add
 
603
            $this->addPage();       // one page to make this a valid
 
604
        }                           // PDF.
 
605
 
 
606
        $this->_state = 1;          // Set the state page closed.
 
607
 
 
608
        /* Pages and resources. */
 
609
        $this->_putPages();
 
610
        $this->_putResources();
 
611
 
 
612
        /* Print some document info. */
 
613
        $this->_newobj();
 
614
        $this->_out('<<');
 
615
        $this->_out('/Producer (My First PDF Class)');
 
616
        $this->_out(sprintf('/CreationDate (D:%s)',
 
617
                            date('YmdHis')));
 
618
        $this->_out('>>');
 
619
        $this->_out('endobj');
 
620
 
 
621
        /* Print catalog. */
 
622
        $this->_newobj();
 
623
        $this->_out('<<');
 
624
        $this->_out('/Type /Catalog');
 
625
        $this->_out('/Pages 1 0 R');
 
626
        $this->_out('/OpenAction [3 0 R /FitH null]');
 
627
        $this->_out('/PageLayout /OneColumn');
 
628
        $this->_out('>>');
 
629
        $this->_out('endobj');
 
630
 
 
631
        /* Print cross reference. */
 
632
        $start_xref = strlen($this->_buffer); // Get the xref offset.
 
633
        $this->_out('xref');                  // Announce the xref.
 
634
        $this->_out('0 ' . ($this->_n + 1));  // Number of objects.
 
635
        $this->_out('0000000000 65535 f ');
 
636
        /* Loop through all objects and output their offset. */
 
637
        for ($i = 1; $i <= $this->_n; $i++) {
 
638
            $this->_out(sprintf('%010d 00000 n ', $this->_offsets[$i]));
 
639
        }
 
640
 
 
641
        /* Print trailer. */
 
642
        $this->_out('trailer');
 
643
        $this->_out('<<');
 
644
        /* The total number of objects. */
 
645
        $this->_out('/Size ' . ($this->_n + 1));
 
646
        /* The root object. */
 
647
        $this->_out('/Root ' . $this->_n . ' 0 R');
 
648
        /* The document information object. */
 
649
        $this->_out('/Info ' . ($this->_n - 1) . ' 0 R');
 
650
        $this->_out('>>');
 
651
        $this->_out('startxref');
 
652
        $this->_out($start_xref);  // Where to find the xref.
 
653
        $this->_out('%%EOF');
 
654
        $this->_state = 3;         // Set the document state to
 
655
                                   // closed.
 
656
    }
 
657
 
 
658
    /**
 
659
     * Function to output the buffered data to the browser.
 
660
     *
 
661
     * @access public
 
662
     */
 
663
    function output($filename)
 
664
    {
 
665
        if ($this->_state < 3) {    // If document not yet closed
 
666
            $this->close();         // close it now.
 
667
        }
 
668
 
 
669
        /* Make sure no content already sent. */
 
670
        if (headers_sent()) {
 
671
            die('Unable to send PDF file, some data has already been output to browser.');
 
672
        }
 
673
 
 
674
        /* Offer file for download and do some browser checks
 
675
         * for correct download. */
 
676
        $agent = trim($_SERVER['HTTP_USER_AGENT']);
 
677
        if ((preg_match('|MSIE ([0-9.]+)|', $agent, $version)) ||
 
678
            (preg_match('|Internet Explorer/([0-9.]+)|', $agent, $version))) {
 
679
            header('Content-Type: application/x-msdownload');
 
680
            Header('Content-Length: ' . strlen($this->_buffer));
 
681
            if ($version == '5.5') {
 
682
                header('Content-Disposition: filename="' . $filename . '"');
 
683
            } else {
 
684
                header('Content-Disposition: attachment; filename="' . $filename . '"');
 
685
            }
 
686
        } else {
 
687
            Header('Content-Type: application/pdf');
 
688
            Header('Content-Length: ' . strlen($this->_buffer));
 
689
            Header('Content-disposition: attachment; filename=' . $filename);
 
690
        }
 
691
        echo $this->_buffer;
 
692
    }
 
693
 
 
694
    function _out($s)
 
695
    {
 
696
        if ($this->_state == 2) {
 
697
            $this->_pages[$this->_page] .= $s . "\n";
 
698
        } else {
 
699
            $this->_buffer .= $s . "\n";
 
700
        }
 
701
    }
 
702
 
 
703
    function _escape($s)
 
704
    {   
 
705
        $s = str_replace('\\', '\\\\', $s);   // Escape any '\\'
 
706
        $s = str_replace('(', '\\(', $s);     // Escape any '('
 
707
        return str_replace(')', '\\)', $s);   // Escape any ')'
 
708
    }
 
709
 
 
710
 
 
711
    function _newobj()
 
712
    {
 
713
        /* Increment the object count. */
 
714
        $this->_n++;
 
715
        /* Save the byte offset of this object. */
 
716
        $this->_offsets[$this->_n] = strlen($this->_buffer);
 
717
        /* Output to buffer. */
 
718
        $this->_out($this->_n . ' 0 obj');
 
719
    }
 
720
 
 
721
    function _putPages()
 
722
    {
 
723
        /* If compression is required set the compression tag. */
 
724
        $filter = ($this->_compress) ? '/Filter /FlateDecode ' : '';
 
725
        /* Print out pages, loop through each. */
 
726
        for ($n = 1; $n <= $this->_page; $n++) {
 
727
            $this->_newobj();                 // Start a new object.
 
728
            $this->_out('<</Type /Page');     // Object type.
 
729
            $this->_out('/Parent 1 0 R');
 
730
            $this->_out('/Resources 2 0 R');
 
731
            $this->_out('/Contents ' . ($this->_n + 1) . ' 0 R>>');
 
732
            $this->_out('endobj');
 
733
 
 
734
            /* If compression required gzcompress() the page content. */
 
735
            $p = ($this->_compress) ? gzcompress($this->_pages[$n]) : $this->_pages[$n];
 
736
 
 
737
            /* Output the page content. */
 
738
            $this->_newobj();                 // Start a new object.
 
739
            $this->_out('<<' . $filter . '/Length ' . strlen($p) . '>>');
 
740
            $this->_putStream($p);            // Output the page.
 
741
            $this->_out('endobj');
 
742
        }
 
743
 
 
744
        /* Set the offset of the first object. */
 
745
        $this->_offsets[1] = strlen($this->_buffer);
 
746
        $this->_out('1 0 obj');
 
747
        $this->_out('<</Type /Pages');
 
748
        $kids = '/Kids [';
 
749
        for ($i = 0; $i < $this->_page; $i++) {
 
750
            $kids .= (3 + 2 * $i) . ' 0 R ';
 
751
        }   
 
752
        $this->_out($kids . ']');
 
753
        $this->_out('/Count ' . $this->_page);
 
754
        /* Output the page size. */
 
755
        $this->_out(sprintf('/MediaBox [0 0 %.2f %.2f]',
 
756
                            $this->_w, $this->_h));
 
757
        $this->_out('>>');
 
758
        $this->_out('endobj');
 
759
    }
 
760
 
 
761
    function _putStream($s)
 
762
    {
 
763
        $this->_out('stream');
 
764
        $this->_out($s);
 
765
        $this->_out('endstream');
 
766
    }
 
767
 
 
768
    function _putResources()
 
769
    {
 
770
        $this->_putFonts();              // Output any fonts.
 
771
        $this->_putImages();             // Output any images.
 
772
 
 
773
        /* Resources are always object number 2. */
 
774
        $this->_offsets[2] = strlen($this->_buffer);
 
775
        $this->_out('2 0 obj');
 
776
        $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
 
777
        $this->_out('/Font <<');
 
778
        foreach ($this->_fonts as $font) {
 
779
            $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R');
 
780
        }
 
781
        $this->_out('>>');
 
782
        if (count($this->_images)) {     // Loop through any images
 
783
            $this->_out('/XObject <<');  // and output the objects.
 
784
            foreach ($this->_images as $image) {
 
785
                $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R');
 
786
            }
 
787
            $this->_out('>>');
 
788
        }
 
789
        $this->_out('>>');
 
790
        $this->_out('endobj');
 
791
    }
 
792
 
 
793
    function _putFonts()
 
794
    {
 
795
        /* Print out font details. */
 
796
        foreach ($this->_fonts as $k => $font) {
 
797
            $this->_newobj();
 
798
            $this->_fonts[$k]['n'] = $this->_n;
 
799
            $name = $font['name'];
 
800
            $this->_out('<</Type /Font');
 
801
            $this->_out('/BaseFont /' . $name);
 
802
            $this->_out('/Subtype /Type1');
 
803
            if ($name != 'Symbol' && $name != 'ZapfDingbats') {
 
804
                $this->_out('/Encoding /WinAnsiEncoding');
 
805
            }
 
806
            $this->_out('>>');
 
807
            $this->_out('endobj');
 
808
        }
 
809
    }
 
810
 
 
811
    function _putImages()
 
812
    {
 
813
        /* Output any images. */
 
814
        $filter = ($this->_compress) ? '/Filter /FlateDecode ' : ''; 
 
815
        foreach ($this->_images as $file => $info) {
 
816
            $this->_newobj();
 
817
            $this->_images[$file]['n'] = $this->_n;
 
818
            $this->_out('<</Type /XObject');
 
819
            $this->_out('/Subtype /Image');
 
820
            $this->_out('/Width ' . $info['w']);    // Image width.
 
821
            $this->_out('/Height ' . $info['h']);   // Image height.
 
822
            $this->_out('/ColorSpace /' . $info['cs']); //Colorspace
 
823
            if ($info['cs'] == 'DeviceCMYK') {
 
824
                $this->_out('/Decode [1 0 1 0 1 0 1 0]');
 
825
            }   
 
826
            $this->_out('/BitsPerComponent ' . $info['bpc']); // Bits
 
827
            $this->_out('/Filter /' . $info['f']);  // Filter used.
 
828
            $this->_out('/Length ' . strlen($info['data']) . '>>');
 
829
            $this->_putStream($info['data']);       // Image data.
 
830
            $this->_out('endobj');
 
831
        }
 
832
    }
 
833
 
 
834
    function _parseJPG($file)
 
835
    {
 
836
        /* Extract info from the JPEG file. */
 
837
        $img = @getimagesize($file);
 
838
        if (!$img) {
 
839
            die(sprintf('Missing or incorrect image file: %s', $file));
 
840
        }
 
841
 
 
842
        /* Check if dealing with an actual JPEG. */
 
843
        if ($img[2] != 2) {
 
844
            die(sprintf('Not a JPEG file: %s', $file));
 
845
        }
 
846
        /* Get the image colorspace. */
 
847
        if (!isset($img['channels']) || $img['channels'] == 3) {
 
848
            $colspace = 'DeviceRGB';
 
849
        } elseif ($img['channels'] == 4) {
 
850
            $colspace = 'DeviceCMYK';
 
851
        } else {
 
852
            $colspace = 'DeviceGray';
 
853
        }
 
854
        $bpc = isset($img['bits']) ? $img['bits'] : 8;
 
855
 
 
856
        /* Read the whole file. */
 
857
        $f = fopen($file, 'rb');
 
858
        $data = fread($f, filesize($file));
 
859
        fclose($f);
 
860
 
 
861
        return array('w' => $img[0], 'h' => $img[1], 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'DCTDecode', 'data' => $data);
 
862
    }
 
863
        
 
864
        #lungo's extension
 
865
        function AcceptPageBreak()
 
866
        {
 
867
                //Accept automatic page break or not
 
868
                return $this->AutoPageBreak;
 
869
        }
 
870
 
 
871
        function Cell($w,$h=0,$txt='',$border=0,$ln=0,$align='',$fill=0,$link='')
 
872
    {
 
873
        //Output a cell
 
874
        $k=$this->k;
 
875
        if($this->y+$h>$this->PageBreakTrigger and !$this->InFooter and $this->AcceptPageBreak())
 
876
        {
 
877
                //Automatic page break
 
878
                $x=$this->x;
 
879
                $ws=$this->ws;
 
880
                if($ws>0)
 
881
                {
 
882
                        $this->ws=0;
 
883
                        $this->_out('0 Tw');
 
884
                }
 
885
                $this->AddPage($this->CurOrientation);
 
886
                $this->x=$x;
 
887
                if($ws>0)
 
888
                {
 
889
                        $this->ws=$ws;
 
890
                        $this->_out(sprintf('%.3f Tw',$ws*$k));
 
891
                }
 
892
        }
 
893
        if($w==0)
 
894
                $w=$this->w-$this->rMargin-$this->x;
 
895
        $s='';
 
896
        if($fill==1 or $border==1)
 
897
        {
 
898
                if($fill==1)
 
899
                        $op=($border==1) ? 'B' : 'f';
 
900
                else
 
901
                        $op='S';
 
902
                $s=sprintf('%.2f %.2f %.2f %.2f re %s ',$this->x*$k,($this->h-$this->y)*$k,$w*$k,-$h*$k,$op);
 
903
        }
 
904
        if(is_string($border))
 
905
        {
 
906
                $x=$this->x;
 
907
                $y=$this->y;
 
908
                if(is_int(strpos($border,'L')))
 
909
                        $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-$y)*$k,$x*$k,($this->h-($y+$h))*$k);
 
910
                if(is_int(strpos($border,'T')))
 
911
                        $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-$y)*$k);
 
912
                if(is_int(strpos($border,'R')))
 
913
                        $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',($x+$w)*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-($y+$h))*$k);
 
914
                if(is_int(strpos($border,'B')))
 
915
                        $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-($y+$h))*$k,($x+$w)*$k,($this->h-($y+$h))*$k);
 
916
        }
 
917
        if($txt!='')
 
918
        {
 
919
                if($align=='R')
 
920
                        $dx=$w-$this->cMargin-$this->GetStringWidth($txt);
 
921
                elseif($align=='C')
 
922
                        $dx=($w-$this->GetStringWidth($txt))/2;
 
923
                else
 
924
                        $dx=$this->cMargin;
 
925
                if($this->ColorFlag)
 
926
                        $s.='q '.$this->TextColor.' ';
 
927
                $txt2=str_replace(')','\\)',str_replace('(','\\(',str_replace('\\','\\\\',$txt)));
 
928
                $s.=sprintf('BT %.2f %.2f Td (%s) Tj ET',($this->x+$dx)*$k,($this->h-($this->y+.5*$h+.3*$this->FontSize))*$k,$txt2);
 
929
                if($this->underline)
 
930
                        $s.=' '.$this->_dounderline($this->x+$dx,$this->y+.5*$h+.3*$this->FontSize,$txt);
 
931
                if($this->ColorFlag)
 
932
                        $s.=' Q';
 
933
                if($link)
 
934
                        $this->Link($this->x+$dx,$this->y+.5*$h-.5*$this->FontSize,$this->GetStringWidth($txt),$this->FontSize,$link);
 
935
        }
 
936
        if($s)
 
937
                $this->_out($s);
 
938
        $this->lasth=$h;
 
939
        if($ln>0)
 
940
        {
 
941
                //Go to next line
 
942
                $this->y+=$h;
 
943
                if($ln==1)
 
944
                        $this->x=$this->lMargin;
 
945
        }
 
946
        else
 
947
                $this->x+=$w;
 
948
    }
 
949
 
 
950
   function MultiCell($w,$h,$txt,$border=0,$align='J',$fill=0)
 
951
   {
 
952
        //Output text with automatic or explicit line breaks
 
953
        $cw=&$this->CurrentFont['cw'];
 
954
        if($w==0)
 
955
                $w=$this->w-$this->rMargin-$this->x;
 
956
        $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
 
957
        $s=str_replace("\r",'',$txt);
 
958
        $nb=strlen($s);
 
959
        if($nb>0 and $s[$nb-1]=="\n")
 
960
                $nb--;
 
961
        $b=0;
 
962
        if($border)
 
963
        {
 
964
                if($border==1)
 
965
                {
 
966
                        $border='LTRB';
 
967
                        $b='LRT';
 
968
                        $b2='LR';
 
969
                }
 
970
                else
 
971
                {
 
972
                        $b2='';
 
973
                        if(is_int(strpos($border,'L')))
 
974
                                $b2.='L';
 
975
                        if(is_int(strpos($border,'R')))
 
976
                                $b2.='R';
 
977
                        $b=is_int(strpos($border,'T')) ? $b2.'T' : $b2;
 
978
                }
 
979
        }
 
980
        $sep=-1;
 
981
        $i=0;
 
982
        $j=0;
 
983
        $l=0;
 
984
        $ns=0;
 
985
        $nl=1;
 
986
        while($i<$nb)
 
987
        {
 
988
                //Get next character
 
989
                $c=$s{$i};
 
990
                if($c=="\n")
 
991
                {
 
992
                        //Explicit line break
 
993
                        if($this->ws>0)
 
994
                        {
 
995
                                $this->ws=0;
 
996
                                $this->_out('0 Tw');
 
997
                        }
 
998
                        $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
 
999
                        $i++;
 
1000
                        $sep=-1;
 
1001
                        $j=$i;
 
1002
                        $l=0;
 
1003
                        $ns=0;
 
1004
                        $nl++;
 
1005
                        if($border and $nl==2)
 
1006
                                $b=$b2;
 
1007
                        continue;
 
1008
                }
 
1009
                if($c==' ')
 
1010
                {
 
1011
                        $sep=$i;
 
1012
                        $ls=$l;
 
1013
                        $ns++;
 
1014
                }
 
1015
                $l+=$cw[$c];
 
1016
                if($l>$wmax)
 
1017
                {
 
1018
                        //Automatic line break
 
1019
                        if($sep==-1)
 
1020
                        {
 
1021
                                if($i==$j)
 
1022
                                        $i++;
 
1023
                                if($this->ws>0)
 
1024
                                {
 
1025
                                        $this->ws=0;
 
1026
                                        $this->_out('0 Tw');
 
1027
                                }
 
1028
                                $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
 
1029
                        }
 
1030
                        else
 
1031
                        {
 
1032
                                if($align=='J')
 
1033
                                {
 
1034
                                        $this->ws=($ns>1) ? ($wmax-$ls)/1000*$this->FontSize/($ns-1) : 0;
 
1035
                                        $this->_out(sprintf('%.3f Tw',$this->ws*$this->k));
 
1036
                                }
 
1037
                                $this->Cell($w,$h,substr($s,$j,$sep-$j),$b,2,$align,$fill);
 
1038
                                $i=$sep+1;
 
1039
                        }
 
1040
                        $sep=-1;
 
1041
                        $j=$i;
 
1042
                        $l=0;
 
1043
                        $ns=0;
 
1044
                        $nl++;
 
1045
                        if($border and $nl==2)
 
1046
                                $b=$b2;
 
1047
                }
 
1048
                else
 
1049
                        $i++;
 
1050
        }
 
1051
        //Last chunk
 
1052
        if($this->ws>0)
 
1053
        {
 
1054
                $this->ws=0;
 
1055
                $this->_out('0 Tw');
 
1056
        }
 
1057
        if($border and is_int(strpos($border,'B')))
 
1058
                $b.='B';
 
1059
        $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
 
1060
        $this->x=$this->lMargin;
 
1061
}
 
1062
 
 
1063
        
 
1064
        function addTextWrap($xb, $yb, $w, $h, $text, $align='J', $border=0, $fill=0) {
 
1065
                $txt = html_entity_decode($text);
 
1066
                $this->x = $xb;
 
1067
                $this->y = $this->h - $yb - $h;
 
1068
                
 
1069
                switch($align) {
 
1070
                        case 'right':
 
1071
                        $align = 'R'; break;
 
1072
                        case 'center':    
 
1073
                        $align = 'C'; break;
 
1074
                        default: 
 
1075
                        $align = 'L';
 
1076
                
 
1077
                }
 
1078
                $this->SetFontSize($h);
 
1079
                $cw=&$this->CurrentFont['cw'];
 
1080
                if($w==0) {
 
1081
                        $w=$this->w-$this->rMargin-$this->x;
 
1082
                }
 
1083
                $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
 
1084
                $s=str_replace("\r",'',$text);
 
1085
                $s=str_replace("\n",' ',$s);
 
1086
                $s = trim($s).' ';
 
1087
                $nb=strlen($s);
 
1088
                $b=0;
 
1089
                if ($border) {
 
1090
                        if ($border==1) {
 
1091
                                $border='LTRB';
 
1092
                                $b='LRT';
 
1093
                                $b2='LR';
 
1094
                        } else {
 
1095
                                $b2='';
 
1096
                                if(is_int(strpos($border,'L'))) {
 
1097
                                        $b2.='L';
 
1098
                                }
 
1099
                                if(is_int(strpos($border,'R'))) {
 
1100
                                        $b2.='R';
 
1101
                                }
 
1102
                                $b=is_int(strpos($border,'T')) ? $b2.'T' : $b2;
 
1103
                        }
 
1104
                }
 
1105
                $sep=-1;
 
1106
                $i=0;
 
1107
                $l= $ls=0;
 
1108
                $ns=0;
 
1109
                while($i<$nb) {
 
1110
                
 
1111
                        $c=$s{$i};
 
1112
                
 
1113
                        if($c==' ' AND $i>0) {
 
1114
                                $sep=$i;
 
1115
                                $ls=$l;
 
1116
                                $ns++;
 
1117
                        }
 
1118
                        $l+=$cw[$c];
 
1119
                        if($l>$wmax)
 
1120
                        break;
 
1121
                        else 
 
1122
                        $i++;
 
1123
                }
 
1124
                if($sep==-1) {
 
1125
                        if($i==0) $i++;
 
1126
                        
 
1127
                        if($this->ws>0) {
 
1128
                                $this->ws=0;
 
1129
                                $this->_out('0 Tw');
 
1130
                        }
 
1131
                        $sep = $i;
 
1132
                } else {
 
1133
                        if($align=='J') {
 
1134
                        $this->ws=($ns>1) ? ($wmax-$ls)/1000*$this->FontSize/($ns-1) : 0;
 
1135
                                $this->_out(sprintf('%.3f Tw',$this->ws*$this->k));
 
1136
                        }       
 
1137
                }
 
1138
                
 
1139
                $this->Cell($w,$h,substr($s,0,$sep),$b,2,$align,$fill);
 
1140
                $this->x=$this->lMargin;
 
1141
                
 
1142
                return substr($s,$sep);
 
1143
        }
 
1144
 
 
1145
 
 
1146
}
 
1147
 
 
1148
?>