Page 1 of 1

I need help with PDF creation & attachments

Posted: Sat Jan 28, 2006 11:22 am
by ebarrantes
Hi, i'm new in PHP stuff and i'm working in a PHP based application that should create a PDF document on-line using data from a DB, and, without saving it in the server, it should use this PDF as attachment in a new e-mail. I need to develop this application as an automatic billing system.

I'd appreciate any help or ideas you could give me; the simplest the solution, the better.

let me explain myself better

Posted: Sat Jan 28, 2006 1:34 pm
by ebarrantes
At this moment i`m generating the pdf file dynamically using the following PDF.php class:

Code: Select all

<?php
/**
 * PDF::
 *
 * The PDF:: class provides a PHP-only implementation of a PDF library.
 * No external libs or PHP extensions are required.
 *
 * Based on the FPDF class by Olivier Plathey (http://www.fpdf.org) and the
 * Horde Framework PDF package (http://www.horde.org)
 *
 * Copyright 2003 Marko Djukic <marko@oblo.com>
 * Copyright 2003 Olivier Plathey <olivier@fpdf.org>
 *
 * See the enclosed file COPYING for license information (LGPL). If you did not
 * receive this file, see http://www.fsf.org/copyleft/lgpl.html.
 *
 * @author  Olivier Plathey <olivier@fpdf.org>
 * @author  Marko Djukic <marko@oblo.com>
 */

class PDF {

    var $_buffer = '';          // Buffer holding in-memory PDF.
    var $_state = 0;            // Current document state.
    var $_page = 0;             // Current page number.
    var $_n = 2;                // Current object number.
    var $_offsets = array();    // Array of object offsets.
    var $_pages = array();      // Array containing the pages.
    var $_w;                    // Page width in points.
    var $_h;                    // Page height in points
    var $_fonts = array();      // An array of used fonts.
    var $_font_family = '';     // Current font family.
    var $_font_style = '';      // Current font style.
    var $_current_font;         // Array with current font info.
    var $_font_size = 12;       // Current font size in points.
    var $_compress;             // Flag to compress or not.
    var $_core_fonts = array('courier'      => 'Courier',
                             'courierB'     => 'Courier-Bold',
                             'courierI'     => 'Courier-Oblique',
                             'courierBI'    => 'Courier-BoldOblique',
                             'helvetica'    => 'Helvetica',
                             'helveticaB'   => 'Helvetica-Bold',
                             'helveticaI'   => 'Helvetica-Oblique',
                             'helveticaBI'  => 'Helvetica-BoldOblique',
                             'times'        => 'Times-Roman',
                             'timesB'       => 'Times-Bold',
                             'timesI'       => 'Times-Italic',
                             'timesBI'      => 'Times-BoldItalic',
                             'symbol'       => 'Symbol',
                             'zapfdingbats' => 'ZapfDingbats');
    var $_fill_color = '0 g';   // Color used on text and fills.
    var $_draw_color = '0 G';   // Line draw color.
    var $_line_width = 1;       // Drawing line width.
    var $_images = array();     // An array of used images.

    /**
     * Attempts to return a conrete PDF instance. It allows to set up the page
     * format, the orientation and the units of measurement used in all the
     * methods (except for the font sizes).
     *
     * Example:
     * $pdf = &PDF::factory('P', 'A4');
     *
     * @access public
     *
     * @param optional string $orientation  Default page orientation.
     *                                      Possible values are (case
     *                                      insensitive):
     *                                        - P or Portrait (default)
     *                                        - L or Landscape
     * @param optional mixed format         The format used for pages. It can
     *                                      be either one of the following
     *                                      values (case insensitive):
     *                                        - A3
     *                                        - A4 (default)
     *                                        - A5
     *                                        - Letter
     *                                        - Legal
     *                                      or a custom format in the form of
     *                                      a two-element array containing the
     *                                      width and the height (expressed in
     *                                      the unit given by unit).
     */
    function &factory($orientation = 'P', $format = 'A4')
    {
        /* Create the PDF object. */
        $pdf = &new PDF();

        /* Page format. */
        $format = strtolower($format);
        if ($format == 'a3') {           // A3 page size.
            $format = array(841.89, 1190.55);
        } elseif ($format == 'a4') {     // A4 page size.
            $format = array(595.28, 841.89);
        } elseif ($format == 'a5') {     // A5 page size.
            $format = array(420.94, 595.28);
        } elseif ($format == 'letter') { // Letter page size.
            $format = array(612, 792);
        } elseif ($format == 'legal') {  // Legal page size.
            $format = array(612, 1008);
        } else {
            die(sprintf('Unknown page format: %s', $format));
        }
        $pdf->_w = $format[0];
        $pdf->_h = $format[1];

        /* Page orientation. */
        $orientation = strtolower($orientation);
        if ($orientation == 'l' || $orientation == 'landscape') {
            $w = $pdf->_w;
            $pdf->_w = $pdf->_h;
            $pdf->_h = $w;
        } elseif ($orientation != 'p' && $orientation != 'portrait') {
            die(sprintf('Incorrect orientation: %s', $orientation));
        }

        /* Turn on compression by default. */
        $pdf->setCompression(true);

        return $pdf;
    }

    /**
     * Activates or deactivates page compression. When activated, the internal
     * representation of each page is compressed, which leads to a compression
     * ratio of about 2 for the resulting document.
     * Compression is on by default.
     * Note: the Zlib extension is required for this feature. If not present,
     * compression will be turned off.
     *
     * @param bool $compress  Boolean indicating if compression must be
     *                        enabled or not.
     */
    function setCompression($compress)
    {
        /* If no gzcompress function is available then default to
         * false. */
        $this->_compress = (function_exists('gzcompress') ? $compress : false);
    }

    /**
     * This method begins the generation of the PDF document; it must be
     * called before any output commands. No page is created by this method,
     * therefore it is necessary to call PDF::addPage.
     *
     * @access public
     */
    function open()
    {
        $this->_state = 1;          // Set state to initialised.
        $this->_out('%PDF-1.3');    // Output the PDF header.
    }

    /**
     * Adds a new page to the document. The font which was set before calling
     * is automatically restored. There is no need to call PDF::setFont again
     * if you want to continue with the same font.
     *
     * @access public
     */
    function addPage()
    {
        $this->_page++;                    // Increment page count.
        $this->_pages[$this->_page] = '';  // Start the page buffer.
        $this->_state = 2;                 // Set state to page
                                           // opened.
        /* Check if font has been set before this page. */
        if ($this->_font_family) {
            $this->setFont($this->_font_family, $this->_font_style, $this->_font_size);
        }
        /* Check if fill color has been set before this page. */
        if ($this->_fill_color != '0 g') {
            $this->_out($this->_fill_color);
        }
        /* Check if draw color has been set before this page. */
        if ($this->_draw_color != '0 G') {
            $this->_out($this->_draw_color);
        }
        /* Check if line width has been set before this page. */
        if ($this->_line_width != 1) {
            $this->_out($this->_line_width);
        }
    }

    /**
     * Sets the font used to print character strings. It is mandatory to call
     * this method at least once before printing text or the resulting
     * document would not be valid. The font must be a standard one. Standard
     * fonts use Windows encoding cp1252 (Western Europe).
     * The method can be called before the first page is created and the font
     * is retained from page to page.
     * If you just wish to change the current font size, it is simpler to call
     * PDF::setFontSize.
     *
     * @access public
     *
     * @param string $family          Family font. It must be one of the
     *                                standard families (case insensitive):
     *                                  - Courier (fixed-width)
     *                                  - Helvetica or Arial (sans serif)
     *                                  - Times (serif)
     *                                  - Symbol (symbolic)
     *                                  - ZapfDingbats (symbolic)
     *                                It is also possible to pass an empty
     *                                string. In that case, the current
     *                                family is retained.
     * @param optional string $style  Font style. Possible values are (case
     *                                insensitive):
     *                                  - empty string: regular
     *                                  - B: bold
     *                                  - I: italic
     *                                or any combination. The default value is
     *                                regular. Bold and italic styles do not
     *                                apply to Symbol and ZapfDingbats.
     * @param optional int $size      Font size in points. The default value
     *                                is the current size. If no size has been
     *                                specified since the beginning of the
     *                                document, the value taken is 12.
     */
    function setFont($family, $style = '', $size = null)
    {
        $family = strtolower($family);
        if ($family == 'arial') {               // Use helvetica.
            $family = 'helvetica';
        } elseif ($family == 'symbol' ||        // No styles for
                  $family == 'zapfdingbats') {  // these two fonts.
            $style = '';
        }

        $style = strtoupper($style);
        if ($style == 'IB') {                   // Accept any order
            $style = 'BI';                      // of B and I.
        }

        if (is_null($size)) {                   // No size specified,
            $size = $this->_font_size;          // use current size.
        }

        if ($this->_font_family == $family &&   // If font is already
            $this->_font_style == $style &&     // current font
            $this->_font_size == $size) {       // simply return.
            return;
        }

        /* Set the font key. */
        $fontkey = $family . $style;

        if (!isset($this->_fonts[$fontkey])) {  // Test if cached.
            $i = count($this->_fonts) + 1;      // Increment font
            $this->_fonts[$fontkey] = array(    // object count and
                'i'    => $i,                   // store cache.
                'name' => $this->_core_fonts[$fontkey]);
        }

        /* Store current font information. */
        $this->_font_family  = $family;
        $this->_font_style   = $style;
        $this->_font_size    = $size;
        $this->_current_font = $this->_fonts[$fontkey];

        /* Output font information if at least one page has been
         * defined. */
        if ($this->_page > 0) {
            $this->_out(sprintf('BT /F%d %.2f Tf ET', $this->_current_font['i'], $this->_font_size));
        }
    }

    /**
     * Defines the size of the current font.
     *
     * @access public
     *
     * @param float $size  The size (in points).
     */
    function setFontSize($size)
    {
        if ($this->_font_size == $size) {   // If already current
            return;                         // size simply return.
        }

        $this->_font_size = $size;          // Set the font.

        /* Output font information if at least one page has been
         * defined. */
        if ($this->_page > 0) {
            $this->_out(sprintf('BT /F%d %.2f Tf ET',
                                $this->_current_font['i'],
                                $this->_font_size));
        }
    }

    /**
     * Sets the fill color. Specifies the color for both filled areas and
     * text. Depending on the colorspace called, the number of color component
     * parameters required can be either 1, 3 or 4. The method can be called
     * before the first page is created and the color is retained from page to
     * page.
     *
     * @access public
     *
     * @param string $cs          Indicates the colorspace which can be either
     *                            'rgb', 'cmyk' or 'gray'. Defaults to 'rgb'.
     * @param float $c1           First color component, floating point value
     *                            between 0 and 1. Required for gray, rgb and
     *                            cmyk.
     * @param optional float $c2  Second color component, floating point value
     *                            between 0 and 1. Required for rgb and cmyk.
     * @param optional float $c3  Third color component, floating point value
     *                            between 0 and 1. Required for rgb and cmyk.
     * @param optional float $c4  Fourth color component, floating point value
     *                            between 0 and 1. Required for cmyk.
     */
    function setFillColor($cs = 'rgb', $c1, $c2 = 0, $c3 = 0, $c4 = 0)
    {
        $cs = strtolower($cs);
        if ($cs == 'rgb') {
            /* Using a three component RGB color. */
            $this->_fill_color = sprintf('%.3f %.3f %.3f rg',
                                         $c1, $c2, $c3);
        } elseif ($cs == 'cmyk') {
            /* Using a four component CMYK color. */
            $this->_fill_color = sprintf('%.3f %.3f %.3f %.3f k',
                                         $c1, $c2, $c3, $c4);
        } else {
            /* Grayscale one component color. */
            $this->_fill_color = sprintf('%.3f g', $c1);
        }
        /* If document started output to buffer. */
        if ($this->_page > 0) {
            $this->_out($this->_fill_color);
        }
    }

    /**
     * Sets the draw color, used when drawing lines. Depending on the
     * colorspace called, the number of color component parameters required
     * can be either 1, 3 or 4. The method can be called before the first page
     * is created and the color is retained from page to page.
     *
     * @access public
     *
     * @param string $cs          Indicates the colorspace which can be either
     *                            'rgb', 'cmyk' or 'gray'. Defaults to 'rgb'.
     * @param float $c1           First color component, floating point value
     *                            between 0 and 1. Required for gray, rgb and
     *                            cmyk.
     * @param optional float $c2  Second color component, floating point value
     *                            between 0 and 1. Required for rgb and cmyk.
     * @param optional float $c3  Third color component, floating point value
     *                            between 0 and 1. Required for rgb and cmyk.
     * @param optional float $c4  Fourth color component, floating point value
     *                            between 0 and 1. Required for cmyk.
     */
    function setDrawColor($cs = 'rgb', $c1, $c2 = 0, $c3 = 0, $c4 = 0)
    {
        $cs = strtolower($cs);
        if ($cs == 'rgb') {
            $this->_draw_color = sprintf('%.3f %.3f %.3f RG',
                                         $c1, $c2, $c3);
        } elseif ($cs == 'cmyk') {
            $this->_draw_color = sprintf('%.3f %.3f %.3f %.3f K',
                                         $c1, $c2, $c3, $c4);
        } else {
            $this->_draw_color = sprintf('%.3f G', $c1);
        }
        /* If document started output to buffer. */
        if ($this->_page > 0) {
            $this->_out($this->_draw_color);
        }
    }

    /**
     * Defines the line width. By default, the value equals 1 pt. The method
     * can be called before the first page is created and the value is
     * retained from page to page.
     *
     * @access public
     *
     * @param float $width  The width.
     */
    function setLineWidth($width)
    {
        $this->_line_width = $width;
        if ($this->_page > 0) {
            $this->_out(sprintf('%.2f w', $width));
        }
    }

    /**
     * Prints a character string. The origin is on the left of the first
     * character, on the baseline. This method allows to place a string
     * precisely on the page.
     *
     * @access public
     *
     * @param float $x      Abscissa of the origin.
     * @param float $y      Ordinate of the origin.
     * @param string $text  String to print.
     */
    function text($x, $y, $text)
    {
        $text = $this->_escape($text);    // Escape any harmful
                                          // characters.

        $out = sprintf('BT %.2f %.2f Td (%s) Tj ET',
                       $x, $this->_h - $y, $text);
        $this->_out($out);
    }

    /**
     * Prints an image in the page. The upper-left corner and at least one of
     * the dimensions must be specified; the height or the width can be
     * calculated automatically in order to keep the image proportions.
     * Supported format is JPEG.
     *
     * For JPEG, all flavors are allowed:
     *   - gray scales
     *   - true colors (24 bits)
     *   - CMYK (32 bits)
     *
     * The format will be inferred from the file extension.
     *
     * Remark: if an image is used several times, only one copy will be
     * embedded in the file.
     *
     * @access public
     *
     * @param string $file            Name of the file containing the image.
     * @param float $x                Abscissa of the upper-left corner.
     * @param float $y                Ordinate of the upper-left corner.
     * @param float $width            Width of the image in the page. If equal
     *                                to zero, it is automatically calculated
     *                                to keep the original proportions.
     * @param optional float $height  Height of the image in the page. If not
     *                                specified or equal to zero, it is
     *                                automatically calculated to keep the
     *                                original proportions.
     */
    function image($file, $x, $y, $width = 0, $height = 0)
    {
        if (!isset($this->_images[$file])) {
            /* First use of requested image, get the extension. */
            if (($pos = strrpos($file, '.')) === false) {
                die(sprintf('Image file %s has no extension and no type was specified', $file));
            }
            $type = strtolower(substr($file, $pos + 1));

            /* Check the image type and parse. */
            if ($type == 'jpg' || $type == 'jpeg') {
                $info = $this->_parseJPG($file);
            } else {
                die(sprintf('Unsupported image file type: %s', $type));
            }
            /* Set the image object id. */
            $info['i'] = count($this->_images) + 1;
            /* Set image to array. */

            $this->_images[$file] = $info;
        } else {
            $info = $this->_images[$file];          // Known image, retrieve
                                                    // from array.
        }

        /* If not specified, do automatic width and height
         * calculations, either setting to original or
         * proportionally scaling to one or the other given
         * dimension. */
        if (empty($width) && empty($height)) {
            $width = $info['w'];
            $height = $info['h'];
        } elseif (empty($width)) {
            $width = $height * $info['w'] / $info['h'];
        } elseif (empty($height)) {
            $height = $width * $info['h'] / $info['w'];
        }

        $this->_out(sprintf('q %.2f 0 0 %.2f %.2f %.2f cm /I%d Do Q', $width, $height, $x, $this->_h - ($y + $height), $info['i']));
    }

    /**
     * Draws a line between two points.
     *
     * @access public
     *
     * @param float $x1  Abscissa of first point.
     * @param float $y1  Ordinate of first point.
     * @param float $x2  Abscissa of second point.
     * @param float $y2  Ordinate of second point.
     *
     */
    function line($x1, $y1, $x2, $y2)
    {
        $this->_out(sprintf('%.2f %.2f m %.2f %.2f l S', $x1, $this->_h - $y1, $x2, $this->_h - $y2));
    }

    /**
     * Outputs a rectangle. It can be drawn (border only), filled (with no
     * border) or both.
     *
     * @access public
     *
     * @param float $x                Abscissa of upper left corner.
     * @param float $y                Ordinate of upper left corner.
     * @param float $width            Width.
     * @param float $height           Height.
     * @param optional string $style  Style of rendering. Possible values are:
     *                                  - D or empty string: draw (default)
     *                                  - F: fill
     *                                  - DF or FD: draw and fill
     */
    function rect($x, $y, $width, $height, $style = '')
    {
        $style = strtolower($style);
        if ($style == 'f') {
            $op = 'f';      // Style is fill only.
        } elseif ($style == 'fd' || $style == 'df') {
            $op = 'B';      // Style is fill and stroke.
        } else {
            $op = 'S';      // Style is stroke only.
        }

        $this->_out(sprintf('%.2f %.2f %.2f %.2f re %s', $x, $this->_h - $y, $width, -$height, $op));
    }

    /**
     * Outputs a circle. It can be drawn (border only), filled (with no
     * border) or both.
     *
     * @access public
     *
     * @param float $x                Abscissa of the center of the circle.
     * @param float $y                Ordinate of the center of the circle.
     * @param float $r                Circle radius.
     * @param optional string $style  Style of rendering. Possible values are:
     *                                  - D or empty string: draw (default)
     *                                  - F: fill
     *                                  - DF or FD: draw and fill
     */
    function circle($x, $y, $r, $style = '')
    {
        $style = strtolower($style);
        if ($style == 'f') {
            $op = 'f';      // Style is fill only.
        } elseif ($style == 'fd' || $style == 'df') {
            $op = 'B';      // Style is fill and stroke.
        } else {
            $op = 'S';      // Style is stroke only.
        }

        $y = $this->_h - $y;                 // Adjust y value.
        $b = $r * 0.552;                     // Length of the Bezier
                                             // controls.
        /* Move from the given origin and set the current point
         * to the start of the first Bezier curve. */
        $c = sprintf('%.2f %.2f m', $x - $r, $y);
        $x = $x - $r;
        /* First circle quarter. */
        $c .= sprintf(' %.2f %.2f %.2f %.2f %.2f %.2f c',
                      $x, $y + $b,           // First control point.
                      $x + $r - $b, $y + $r, // Second control point.
                      $x + $r, $y + $r);     // Final point.
        /* Set x/y to the final point. */
        $x = $x + $r;
        $y = $y + $r;
        /* Second circle quarter. */
        $c .= sprintf(' %.2f %.2f %.2f %.2f %.2f %.2f c',
                      $x + $b, $y,
                      $x + $r, $y - $r + $b,
                      $x + $r, $y - $r);
        /* Set x/y to the final point. */
        $x = $x + $r;
        $y = $y - $r;
        /* Third circle quarter. */
        $c .= sprintf(' %.2f %.2f %.2f %.2f %.2f %.2f c',
                      $x, $y - $b,
                      $x - $r + $b, $y - $r,
                      $x - $r, $y - $r);
        /* Set x/y to the final point. */
        $x = $x - $r;
        $y = $y - $r;
        /* Fourth circle quarter. */
        $c .= sprintf(' %.2f %.2f %.2f %.2f %.2f %.2f c %s',
                      $x - $b, $y,
                      $x - $r, $y + $r - $b,
                      $x - $r, $y + $r,
                      $op);
        /* Output the whole string. */
        $this->_out($c);
    }

    /**
     * Terminates the PDF document. It is not necessary to call this method
     * explicitly because PDF::output does it automatically.
     * If the document contains no page, PDF::addPage is called to prevent
     * from getting an invalid document.
     *
     * @access public
     */
    function close()
    {
        if ($this->_page == 0) {    // If not yet initialised, add
            $this->addPage();       // one page to make this a valid
        }                           // PDF.

        $this->_state = 1;          // Set the state page closed.

        /* Pages and resources. */
        $this->_putPages();
        $this->_putResources();

        /* Print some document info. */
        $this->_newobj();
        $this->_out('<<');
        $this->_out('Microtroniks.com');
        $this->_out(sprintf('Creado (%s)',
                            date('YmdHis')));
        $this->_out('>>');
        $this->_out('endobj');

        /* Print catalog. */
        $this->_newobj();
        $this->_out('<<');
        $this->_out('/Type /Catalog');
        $this->_out('/Pages 1 0 R');
        $this->_out('/OpenAction [3 0 R /FitH null]');
        $this->_out('/PageLayout /OneColumn');
        $this->_out('>>');
        $this->_out('endobj');

        /* Print cross reference. */
        $start_xref = strlen($this->_buffer); // Get the xref offset.
        $this->_out('xref');                  // Announce the xref.
        $this->_out('0 ' . ($this->_n + 1));  // Number of objects.
        $this->_out('0000000000 65535 f ');
        /* Loop through all objects and output their offset. */
        for ($i = 1; $i <= $this->_n; $i++) {
            $this->_out(sprintf('%010d 00000 n ', $this->_offsets[$i]));
        }

        /* Print trailer. */
        $this->_out('trailer');
        $this->_out('<<');
        /* The total number of objects. */
        $this->_out('/Size ' . ($this->_n + 1));
        /* The root object. */
        $this->_out('/Root ' . $this->_n . ' 0 R');
        /* The document information object. */
        $this->_out('/Info ' . ($this->_n - 1) . ' 0 R');
        $this->_out('>>');
        $this->_out('startxref');
        $this->_out($start_xref);  // Where to find the xref.
        $this->_out('%%EOF');
        $this->_state = 3;         // Set the document state to
                                   // closed.
    }

    /**
     * Function to output the buffered data to the browser.
     *
     * @access public
     */
    function output($filename)
    {
        if ($this->_state < 3) {    // If document not yet closed
            $this->close();         // close it now.
        }

        /* Make sure no content already sent. */
        if (headers_sent()) {
            die('Unable to send PDF file, some data has already been output to browser.');
        }

        /* Offer file for download and do some browser checks
         * for correct download. */
        $agent = trim($_SERVER['HTTP_USER_AGENT']);
        if ((preg_match('|MSIE ([0-9.]+)|', $agent, $version)) ||
            (preg_match('|Internet Explorer/([0-9.]+)|', $agent, $version))) {
            header('Content-Type: application/x-msdownload');
            Header('Content-Length: ' . strlen($this->_buffer));
            if ($version == '5.5') {
                header('Content-Disposition: filename="' . $filename . '"');
            } else {
                header('Content-Disposition: attachment; filename="' . $filename . '"');
            }
        } else {
            Header('Content-Type: application/pdf');
            Header('Content-Length: ' . strlen($this->_buffer));
            Header('Content-disposition: attachment; filename=' . $filename);
        }
        //echo $this->_buffer;
    }

    function _out($s)
    {
        if ($this->_state == 2) {
            $this->_pages[$this->_page] .= $s . "\n";
        } else {
            $this->_buffer .= $s . "\n";
        }
    }

    function _escape($s)
    {
        $s = str_replace('\\', '\\\\', $s);   // Escape any '\\'
        $s = str_replace('(', '\\(', $s);     // Escape any '('
        return str_replace(')', '\\)', $s);   // Escape any ')'
    }


    function _newobj()
    {
        /* Increment the object count. */
        $this->_n++;
        /* Save the byte offset of this object. */
        $this->_offsets[$this->_n] = strlen($this->_buffer);
        /* Output to buffer. */
        $this->_out($this->_n . ' 0 obj');
    }

    function _putPages()
    {
        /* If compression is required set the compression tag. */
        $filter = ($this->_compress) ? '/Filter /FlateDecode ' : '';
        /* Print out pages, loop through each. */
        for ($n = 1; $n <= $this->_page; $n++) {
            $this->_newobj();                 // Start a new object.
            $this->_out('<</Type /Page');     // Object type.
            $this->_out('/Parent 1 0 R');
            $this->_out('/Resources 2 0 R');
            $this->_out('/Contents ' . ($this->_n + 1) . ' 0 R>>');
            $this->_out('endobj');

            /* If compression required gzcompress() the page content. */
            $p = ($this->_compress) ? gzcompress($this->_pages[$n]) : $this->_pages[$n];

            /* Output the page content. */
            $this->_newobj();                 // Start a new object.
            $this->_out('<<' . $filter . '/Length ' . strlen($p) . '>>');
            $this->_putStream($p);            // Output the page.
            $this->_out('endobj');
        }

        /* Set the offset of the first object. */
        $this->_offsets[1] = strlen($this->_buffer);
        $this->_out('1 0 obj');
        $this->_out('<</Type /Pages');
        $kids = '/Kids [';
        for ($i = 0; $i < $this->_page; $i++) {
            $kids .= (3 + 2 * $i) . ' 0 R ';
        }
        $this->_out($kids . ']');
        $this->_out('/Count ' . $this->_page);
        /* Output the page size. */
        $this->_out(sprintf('/MediaBox [0 0 %.2f %.2f]',
                            $this->_w, $this->_h));
        $this->_out('>>');
        $this->_out('endobj');
    }

    function _putStream($s)
    {
        $this->_out('stream');
        $this->_out($s);
        $this->_out('endstream');
    }

    function _putResources()
    {
        $this->_putFonts();              // Output any fonts.
        $this->_putImages();             // Output any images.

        /* Resources are always object number 2. */
        $this->_offsets[2] = strlen($this->_buffer);
        $this->_out('2 0 obj');
        $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
        $this->_out('/Font <<');
        foreach ($this->_fonts as $font) {
            $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R');
        }
        $this->_out('>>');
        if (count($this->_images)) {     // Loop through any images
            $this->_out('/XObject <<');  // and output the objects.
            foreach ($this->_images as $image) {
                $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R');
            }
            $this->_out('>>');
        }
        $this->_out('>>');
        $this->_out('endobj');
    }

    function _putFonts()
    {
        /* Print out font details. */
        foreach ($this->_fonts as $k => $font) {
            $this->_newobj();
            $this->_fonts[$k]['n'] = $this->_n;
            $name = $font['name'];
            $this->_out('<</Type /Font');
            $this->_out('/BaseFont /' . $name);
            $this->_out('/Subtype /Type1');
            if ($name != 'Symbol' && $name != 'ZapfDingbats') {
                $this->_out('/Encoding /WinAnsiEncoding');
            }
            $this->_out('>>');
            $this->_out('endobj');
        }
    }

    function _putImages()
    {
        /* Output any images. */
        $filter = ($this->_compress) ? '/Filter /FlateDecode ' : '';
        foreach ($this->_images as $file => $info) {
            $this->_newobj();
            $this->_images[$file]['n'] = $this->_n;
            $this->_out('<</Type /XObject');
            $this->_out('/Subtype /Image');
            $this->_out('/Width ' . $info['w']);    // Image width.
            $this->_out('/Height ' . $info['h']);   // Image height.
            $this->_out('/ColorSpace /' . $info['cs']); //Colorspace
            if ($info['cs'] == 'DeviceCMYK') {
                $this->_out('/Decode [1 0 1 0 1 0 1 0]');
            }
            $this->_out('/BitsPerComponent ' . $info['bpc']); // Bits
            $this->_out('/Filter /' . $info['f']);  // Filter used.
            $this->_out('/Length ' . strlen($info['data']) . '>>');
            $this->_putStream($info['data']);       // Image data.
            $this->_out('endobj');
        }
    }

    function _parseJPG($file)
    {
        /* Extract info from the JPEG file. */
        $img = @getimagesize($file);
        if (!$img) {
            die(sprintf('Missing or incorrect image file: %s', $file));
        }

        /* Check if dealing with an actual JPEG. */
        if ($img[2] != 2) {
            die(sprintf('Not a JPEG file: %s', $file));
        }
        /* Get the image colorspace. */
        if (!isset($img['channels']) || $img['channels'] == 3) {
            $colspace = 'DeviceRGB';
        } elseif ($img['channels'] == 4) {
            $colspace = 'DeviceCMYK';
        } else {
            $colspace = 'DeviceGray';
        }
        $bpc = isset($img['bits']) ? $img['bits'] : 8;

        /* Read the whole file. */
        $f = fopen($file, 'rb');
        $data = fread($f, filesize($file));
        fclose($f);

        return array('w' => $img[0], 'h' => $img[1], 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'DCTDecode', 'data' => $data);
    }

}

?>
The problem with it is that the code didn't create a valid file but allows downloading it using the output($filename) function :( and i need a valid file to use for the attachment! I thought in creating a temp file but i don't know how to parse from the $pdf object to a file...

Any other suggestion will be really appreciated

Posted: Sat Jan 28, 2006 6:27 pm
by duk
try do two outputs...

output("filename.pdf");
and then other output to display it... in case you want, if you leave just the first one, will just create a pdf file...

output(); <- to display in browser

if you can't just try to use the original class http://www.fpdf.org

i'll try it

Posted: Sat Jan 28, 2006 11:09 pm
by ebarrantes
i'm gonna try using the original FPDF class cause it seems that the output function is a little different from the one i'm using now

Thanks for the reply :wink: