Source for file PDF.php
Documentation is available at PDF.php
* The File_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).
* Copyright 2003-2006 Olivier Plathey <olivier@fpdf.org>
* Copyright 2003-2006 Marko Djukic <marko@oblo.com>
* Copyright 2006 Jan Schneider <jan@horde.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.
* $Horde: framework/File_PDF/PDF.php,v 1.42 2006/08/28 17:43:12 jan Exp $
* @author Olivier Plathey <olivier@fpdf.org>
* @author Marko Djukic <marko@oblo.com>
* @author Jan Schneider <jan@horde.org>
* Array of object offsets.
* Buffer holding in-memory PDF.
* Array containing the pages.
* Current document state.
* Flag indicating if PDF file is to be compressed or not.
* The default page orientation.
var $_default_orientation;
* The current page orientation.
var $_current_orientation;
* Array indicating orientation changes.
var $_orientation_changes = array ();
* Current width of page format in points.
* Current height of page format in points.
* Current width of page format in user units.
* Current height of page format in user units.
* Current width of page in points.
* Current height of page in points.
* Current width of page in user units
* Current height of page in user units
* Scale factor (number of points in user units).
* Right page margin size.
* Break page margin size, the bottom margin which triggers a page break.
* The current horizontal position for cell positioning.
* Value is set in user units and is calculated from the top left corner
* The current vertical position for cell positioning.
* Value is set in user units and is calculated from the top left corner
* The height of the last cell printed.
* Line width in user units.
* An array of standard font names.
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',
'zapfdingbats' => 'ZapfDingbats');
* An array of used fonts.
* An array of font files.
var $_font_files = array ();
* An array of encoding differences.
* An array of used images.
* An array of links in pages.
* An array of internal links.
* An array containing current font info.
* Current font size in points.
* Current font size in user units.
* Commands for filling color.
var $_fill_color = '0 g';
* Commands for text color.
var $_text_color = '0 g';
* Whether text color is different from fill color.
var $_color_flag = false;
* Commands for drawing color.
var $_draw_color = '0 G';
* Automatic page breaking.
* Threshold used to trigger page breaks.
var $_page_break_trigger;
* Flag set when processing footer.
* An array containing the document info, consisting of:
* Alias for total number of pages.
var $_alias_nb_pages = '{nb}';
* 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).
* $pdf = &File_PDF::factory(array('orientation' => 'P',
* 'format' => 'A4'));</pre>
* @param array $params A hash with parameters for the created PDF object.
* Possible parameters are:
* orientation - Default page orientation. Possible
* values are (case insensitive):
* - P or Portrait (default)
* unit - User measure units. Possible values values
* - mm: millimeter (default)
* A point equals 1/72 of inch, that is to say about
* 0.35 mm (an inch being 2.54 cm). This is a very
* common unit in typography; font sizes are
* expressed in that unit.
* format - The format used for pages. It can be
* either one of the following values (case
* or a custom format in the form of a two-element
* array containing the width and the height
* (expressed in the unit given by the unit
* @param string $class The concrete class name to return an instance of.
function &factory($params = array (), $class = 'File_PDF')
/* Check for PHP locale-related bug. */
$error = File_PDF::raiseError('Do not alter the locale before including the class file.');
/* Default parameters. */
$defaults = array ('orientation' => 'P', 'unit' => 'mm', 'format' => 'A4');
/* Backward compatibility with old method signature. */
/* Should be removed a few versions later. */
/* Create the PDF object. */
if ($params['unit'] == 'pt') {
} elseif ($params['unit'] == 'mm') {
$pdf->_scale = 72 / 25.4;
} elseif ($params['unit'] == 'cm') {
$pdf->_scale = 72 / 2.54;
} elseif ($params['unit'] == 'in') {
$params['format'] = strtolower($params['format']);
if ($params['format'] == 'a3') {
$params['format'] = array (841.89 , 1190.55 );
} elseif ($params['format'] == 'a4') {
$params['format'] = array (595.28 , 841.89 );
} elseif ($params['format'] == 'a5') {
$params['format'] = array (420.94 , 595.28 );
} elseif ($params['format'] == 'letter') {
$params['format'] = array (612 , 792 );
} elseif ($params['format'] == 'legal') {
$params['format'] = array (612 , 1008 );
$pdf->fwPt = $params['format'][0 ];
$pdf->fhPt = $params['format'][1 ];
$pdf->fwPt = $params['format'][0 ] * $pdf->_scale;
$pdf->fhPt = $params['format'][1 ] * $pdf->_scale;
$pdf->fw = $pdf->fwPt / $pdf->_scale;
$pdf->fh = $pdf->fhPt / $pdf->_scale;
$params['orientation'] = strtolower($params['orientation']);
if ($params['orientation'] == 'p' || $params['orientation'] == 'portrait') {
$pdf->_default_orientation = 'P';
} elseif ($params['orientation'] == 'l' || $params['orientation'] == 'landscape') {
$pdf->_default_orientation = 'L';
$pdf->_current_orientation = $pdf->_default_orientation;
$pdf->w = $pdf->wPt / $pdf->_scale;
$pdf->h = $pdf->hPt / $pdf->_scale;
/* Page margins (1 cm) */
$margin = 28.35 / $pdf->_scale;
$pdf->setMargins ($margin, $margin);
/* Interior cell margin (1 mm) */
$pdf->_cell_margin = $margin / 10;
/* Line width (0.2 mm) */
$pdf->_line_width = .567 / $pdf->_scale;
/* Automatic page break */
$pdf->setAutoPageBreak (true , 2 * $margin);
/* Full width display mode */
$pdf->setDisplayMode ('fullwidth');
$pdf->setCompression (true );
* Returns a PEAR_Error object. Wraps around PEAR::raiseError() to
* avoid having to include PEAR.php unless an error occurs.
* @param mixed $error The error message.
* @return object PEAR_Error
return PEAR ::raiseError ($error);
* Defines the left, top and right margins. By default, they equal
* 1 cm. Call this method to change them.
* @param float $left Left margin.
* @param float $top Top margin.
* @param float $right Right margin. If not specified default to the value
* @see File_PDF::setAutoPageBreak
* @see File_PDF::setLeftMargin
* @see File_PDF::setRightMargin
* @see File_PDF::setTopMargin
/* Set left and top margins. */
$this->_left_margin = $left;
$this->_top_margin = $top;
/* If no right margin set default to same as left. */
$this->_right_margin = (is_null($right) ? $left : $right);
* Defines the left margin. The method can be called before creating the
* If the current abscissa gets out of page, it is brought back to the
* @param float $margin The margin.
* @see File_PDF::setAutoPageBreak
* @see File_PDF::setMargins
* @see File_PDF::setRightMargin
* @see File_PDF::setTopMargin
$this->_left_margin = $margin;
/* If there is a current page and the current X position is less than
* margin set the X position to the margin value. */
if ($this->_page > 0 && $this->x < $margin) {
* Defines the top margin. The method can be called before creating the
* @param float $margin The margin.
$this->_top_margin = $margin;
* Defines the right margin. The method can be called before creating the
* @param float $margin The margin.
$this->_right_margin = $margin;
* Enables or disables the automatic page breaking mode. When enabling,
* the second parameter is the distance from the bottom of the page that
* defines the triggering limit. By default, the mode is on and the margin
* @param boolean auto Boolean indicating if mode should be on or off.
* @param float $margin Distance from the bottom of the page.
$this->_auto_page_break = $auto;
$this->_break_margin = $margin;
$this->_page_break_trigger = $this->h - $margin;
* Defines the way the document is to be displayed by the viewer. The zoom
* level can be set: pages can be displayed entirely on screen, occupy the
* full width of the window, use real size, be scaled by a specific
* zooming factor or use viewer default (configured in the Preferences
* menu of Acrobat). The page layout can be specified too: single at once,
* continuous display, two columns or viewer default.
* By default, documents use the full width mode with continuous display.
* @param mixed $zoom The zoom to use. It can be one of the
* following string values:
* - fullpage: entire page on screen
* - fullwidth: maximum width of window
* - real: uses real size (100% zoom)
* - default: uses viewer default mode
* or a number indicating the zooming factor.
* @param string layout The page layout. Possible values are:
* - single: one page at once
* - continuous: pages in continuously
* - two: two pages on two columns
* - default: uses viewer default mode
* Default value is continuous.
if ($zoom == 'fullpage' || $zoom == 'fullwidth' || $zoom == 'real'
|| $zoom == 'default' || !is_string($zoom)) {
$this->_zoom_mode = $zoom;
} elseif ($zoom == 'zoom') {
$this->_zoom_mode = $layout;
if ($layout == 'single' || $layout == 'continuous' || $layout == 'two'
|| $layout == 'default') {
$this->_layout_mode = $layout;
} elseif ($zoom != 'zoom') {
* 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 boolean $compress Boolean indicating if compression must be
/* If no gzcompress function is available then default to false. */
* Set the info to a document. Possible info settings are:
* @param mixed $info If passed as an array then the complete hash
* containing the info to be inserted into the
* document. Otherwise the name of setting to be set.
* @param string $value The value of the setting.
function setInfo($info, $value = '')
$this->_info[$info] = $value;
* Defines an alias for the total number of pages. It will be substituted
* as the document is closed.
* class My_File_PDF extends File_PDF {
* // Go to 1.5 cm from bottom
* // Select Arial italic 8
* $this->setFont('Arial', 'I', 8);
* // Print current and total page numbers
* $this->cell(0, 10, 'Page ' . $this->getPageNo() . '/{nb}', 0,
* $pdf = &My_File_PDF::factory();
* @param string $alias The alias. Default value: {nb}.
* @see File_PDF::getPageNo
$this->_alias_nb_pages = $alias;
* 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 File_PDF::addPage.
* Terminates the PDF document. It is not necessary to call this method
* explicitly because File_PDF::output does it automatically.
* If the document contains no page, File_PDF::addPage is called to prevent
* from getting an invalid document.
$this->_in_footer = true;
$this->_in_footer = false;
* Adds a new page to the document. If a page is already present, the
* File_PDF::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 File_PDF::header is called to display
* The font which was set before calling is automatically restored. There
* is no need to call File_PDF::setFont again if you want to continue with
* the same font. The same is true for colors and line width.
* The origin of the coordinate system is at the top-left corner and
* increasing ordinates go downwards.
* @param string $orientation Page orientation. Possible values
* are (case insensitive):
* The default value is the one passed to the
* @see File_PDF::setMargins
function addPage($orientation = '')
/* For good measure make sure this is called. */
/* Save style settings so that they are not overridden by footer(). */
$lw = $this->_line_width;
$dc = $this->_draw_color;
$fc = $this->_fill_color;
$tc = $this->_text_color;
$cf = $this->_color_flag;
$this->_in_footer = true;
$this->_in_footer = false;
$this->_beginPage ($orientation);
/* Set line cap style to square. */
$this->_line_width = $lw;
$this->_out (sprintf('%.2f w', $lw * $this->_scale));
/* Set font for the beginning of the page. */
if ($this->_font_family) {
$font_family = $this->_font_family;
$font_style = $this->_font_style . ($this->_underline ? 'U' : '');
$font_size = $this->_font_size_pt;
$this->setFont($font_family, $font_style, $font_size);
$this->_fill_color = $fc;
/* Check if fill color has been set before this page. */
if ($this->_fill_color != '0 g') {
$this->_out ($this->_fill_color);
$this->_draw_color = $dc;
/* Check if draw color has been set before this page. */
if ($this->_draw_color != '0 G') {
$this->_out ($this->_draw_color);
$this->_text_color = $tc;
$this->_color_flag = $cf;
/* Restore line width. */
if ($this->_line_width != $lw) {
$this->_line_width = $lw;
$this->_out (sprintf('%.2f w', $lw * $this->_scale));
/* Make sure the font is set for this page as it was before the
$this->setFont($font_family, $font_style, $font_size, true );
if ($this->_draw_color != $dc) {
$this->_draw_color = $dc;
if ($this->_fill_color != $fc) {
$this->_fill_color = $fc;
$this->_text_color = $tc;
$this->_color_flag = $cf;
* This method is used to render the page header. It is automatically
* called by File_PDF::addPage and should not be called directly by the
* application. The implementation in File_PDF:: is empty, so you have to
* subclass it and override the method if you want a specific processing.
* class My_File_PDF extends File_PDF {
* // Select Arial bold 15
* $this->setFont('Arial', 'B', 15);
* $this->cell(30, 10, 'Title', 1, 0, 'C');
/* To be implemented in your own inherited class. */
* This method is used to render the page footer. It is automatically
* called by File_PDF::addPage and File_PDF::close and should not be called
* directly by the application. The implementation in File_PDF:: is empty,
* so you have to subclass it and override the method if you want a specific
* class My_File_PDF extends File_PDF {
* // Go to 1.5 cm from bottom
* // Select Arial italic 8
* $this->setFont('Arial', 'I', 8);
* // Print centered page number
* $this->cell(0, 10, 'Page ' . $this->getPageNo(), 0, 0, 'C');
/* To be implemented in your own inherited class. */
* Returns the current page number.
* @see File_PDF::aliasNbPages
* 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
* @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 float $c2 Second color component, floating point value between
* 0 and 1. Required for rgb and cmyk.
* @param float $c3 Third color component, floating point value between
* 0 and 1. Required for rgb and cmyk.
* @param float $c4 Fourth color component, floating point value between
* 0 and 1. Required for cmyk.
* @see File_PDF::setTextColor
* @see File_PDF::setDrawColor
* @see File_PDF::multiCell
function setFillColor($cs = 'rgb', $c1, $c2 = 0 , $c3 = 0 , $c4 = 0 )
$this->_fill_color = sprintf('%.3f %.3f %.3f rg', $c1, $c2, $c3);
} elseif ($cs == 'cmyk') {
$this->_fill_color = sprintf('%.3f %.3f %.3f %.3f k', $c1, $c2, $c3, $c4);
$this->_fill_color = sprintf('%.3f g', $c1);
$this->_out ($this->_fill_color);
$this->_color_flag = $this->_fill_color != $this->_text_color;
* 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
* @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 float $c2 Second color component, floating point value between
* 0 and 1. Required for rgb and cmyk.
* @param float $c3 Third color component, floating point value between
* 0 and 1. Required for rgb and cmyk.
* @param float $c4 Fourth color component, floating point value between
* 0 and 1. Required for cmyk.
* @see File_PDF::setFillColor
* @see File_PDF::setDrawColor
* @see File_PDF::multiCell
function setTextColor($cs = 'rgb', $c1, $c2 = 0 , $c3 = 0 , $c4 = 0 )
$this->_text_color = sprintf('%.3f %.3f %.3f rg', $c1, $c2, $c3);
} elseif ($cs == 'cmyk') {
$this->_text_color = sprintf('%.3f %.3f %.3f %.3f k', $c1, $c2, $c3, $c4);
$this->_text_color = sprintf('%.3f g', $c1);
$this->_out ($this->_text_color);
$this->_color_flag = $this->_fill_color != $this->_text_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.
* @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 float $c2 Second color component, floating point value between
* 0 and 1. Required for rgb and cmyk.
* @param float $c3 Third color component, floating point value between 0
* and 1. Required for rgb and cmyk.
* @param float $c4 Fourth color component, floating point value between
* 0 and 1. Required for cmyk.
* @see File_PDF::setFillColor
* @see File_PDF::multiCell
function setDrawColor($cs = 'rgb', $c1, $c2 = 0 , $c3 = 0 , $c4 = 0 )
$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);
$this->_draw_color = sprintf('%.3f G', $c1);
$this->_out ($this->_draw_color);
* Returns the length of a text string. A font must be selected.
* @param string $text The text whose length is to be computed.
* @param boolean $pt Boolean to indicate if the width should be returned
* in points or user units. Default is 'false'.
for ($i = 0; $i < $length; $i++ ) {
$width += $this->_current_font['cw'][$text{$i}];
/* Adjust for word spacing. */
$width += $this->_word_spacing * substr_count($text, ' ') * $this->_current_font['cw'][' '];
return $width * $this->_font_size_pt / 1000;
return $width * $this->_font_size / 1000;
* 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.
* @param float $width The width.
* @see File_PDF::multiCell
$this->_line_width = $width;
$this->_out (sprintf('%.2f w', $width * $this->_scale));
* Draws a line between two points.
* All coordinates can be negative to provide values from the right or
* bottom edge of the page (since File_PDF 0.2.0, Horde 3.2).
* @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.
* @see File_PDF::setLineWidth
* @see File_PDF::setDrawColor.
function line($x1, $y1, $x2, $y2)
$this->_out (sprintf('%.2f %.2f m %.2f %.2f l S', $x1 * $this->_scale, ($this->h - $y1) * $this->_scale, $x2 * $this->_scale, ($this->h - $y2) * $this->_scale));
* Outputs a rectangle. It can be drawn (border only), filled (with no
* All coordinates can be negative to provide values from the right or
* bottom edge of the page (since File_PDF 0.2.0, Horde 3.2).
* @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 float $style Style of rendering. Possible values are:
* - D or empty string: draw (default)
* - DF or FD: draw and fill
* @see File_PDF::setLineWidth
* @see File_PDF::setDrawColor
* @see File_PDF::setFillColor
function rect($x, $y, $width, $height, $style = '')
} elseif ($style == 'FD' || $style == 'DF') {
$width = $this->_toPt ($width);
$height = $this->_toPt ($height);
$this->_out (sprintf('%.2f %.2f %.2f %.2f re %s', $x, $this->hPt - $y, $width, - $height, $op));
* Outputs a circle. It can be drawn (border only), filled (with no
* All coordinates can be negative to provide values from the right or
* bottom edge of the page (since File_PDF 0.2.0, Horde 3.2).
* @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 string $style Style of rendering. Possible values are:
* - D or empty string: draw (default)
* - DF or FD: draw and fill
function circle($x, $y, $r, $style = '')
$op = 'f'; // Style is fill only.
} elseif ($style == 'fd' || $style == 'df') {
$op = 'B'; // Style is fill and stroke.
$op = 'S'; // Style is stroke only.
/* Invert the y scale. */
/* Length of the Bezier control. */
/* 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);
/* 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. */
/* Second circle quarter. */
$c .= sprintf(' %.2f %.2f %.2f %.2f %.2f %.2f c',
/* Set x/y to the final point. */
/* Third circle quarter. */
$c .= sprintf(' %.2f %.2f %.2f %.2f %.2f %.2f c',
/* Set x/y to the final point. */
/* Fourth circle quarter. */
$c .= sprintf(' %.2f %.2f %.2f %.2f %.2f %.2f c %s',
/* Output the whole string. */
* Imports a TrueType or Type1 font and makes it available. It is
* necessary to generate a font definition file first with the
* The location of the definition file (and the font file itself when
* embedding) must be found at the full path name included.
* $pdf->addFont('Comic', 'I');
* $pdf->addFont('Comic', 'I', 'comici.php');
* @param string $family Font family. The name can be chosen arbitrarily.
* If it is a standard family name, it will
* override the corresponding font.
* @param string $style Font style. Possible values are (case
* - empty string: regular (default)
* - BI or IB: bold italic
* @param string $file The font definition file. By default, the name is
* built from the family and style, in lower case
function addFont($family, $style = '', $file = '')
if ($family == 'arial') {
if (isset ($this->_fonts[$family . $style])) {
return $this->raiseError('Could not include font definition file.');
$i = count($this->_fonts) + 1;
$this->_fonts[$family . $style] = array ('i' => $i, 'type' => $type, 'name' => $name, 'desc' => $desc, 'up' => $up, 'ut' => $ut, 'cw' => $cw, 'enc' => $enc, 'file' => $file);
/* Search existing encodings. */
$nb = count($this->_diffs);
for ($i = 1; $i <= $nb; $i++ ) {
if ($this->_diffs[$i] == $diff) {
$this->_diffs[$d] = $diff;
$this->_fonts[$family. $style]['diff'] = $d;
if ($type == 'TrueType') {
$this->_font_files[$file] = array ('length1' => $originalsize);
$this->_font_files[$file] = array ('length1' => $size1, 'length2' => $size2);
* 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 can be either a standard one or a
* font added via the File_PDF::addFont method. 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
* @param string $family Family font. It can be either a name defined by
* File_PDF::addFont or one of the standard families
* - Courier (fixed-width)
* - Helvetica or Arial (sans serif)
* - ZapfDingbats (symbolic)
* It is also possible to pass an empty string. In
* that case, the current family is retained.
* @param string $style Font style. Possible values are (case
* - empty string: regular
* or any combination. The default value is regular.
* Bold and italic styles do not apply to Symbol and
* @param integer $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
* @param boolean $force Force the setting of the font. Each new page will
* require a new call to File_PDF::setFont and
* settings this to true will make sure that the
* checks for same font calls will be skipped.
* @see File_PDF::setFontSize
* @see File_PDF::multiCell
function setFont($family, $style = '', $size = null , $force = false )
if ($family == 'arial') {
/* Use helvetica instead of arial. */
} elseif ($family == 'symbol' || $family == 'zapfdingbats') {
/* These two fonts do not have styles available. */
/* Underline is handled separately, if specified in the style var
* remove it from the style and set the underline flag. */
if (strpos($style, 'U') !== false ) {
$this->_underline = true;
$this->_underline = false;
/* If no size specified, use current size. */
$size = $this->_font_size_pt;
/* If font requested is already the current font and no force setting
* of the font is requested (eg. when adding a new page) don't bother
* with the rest of the function and simply return. */
if ($this->_font_family == $family && $this->_font_style == $style &&
$this->_font_size_pt == $size && !$force) {
$fontkey = $family . $style;
/* Test if already cached. */
if (!isset ($this->_fonts[$fontkey])) {
/* Get the character width definition file. */
$font_widths = &File_PDF::_getFontFile ($fontkey);
if (is_a($font_widths, 'PEAR_Error')) {
$i = count($this->_fonts) + 1;
$this->_fonts[$fontkey] = array (
'name' => $this->_core_fonts[$fontkey],
'cw' => $font_widths[$fontkey]);
/* Store font information as current font. */
$this->_font_family = $family;
$this->_font_style = $style;
$this->_font_size_pt = $size;
$this->_font_size = $size / $this->_scale;
$this->_current_font = &$this->_fonts[$fontkey];
/* Output font information if at least one page has been defined. */
$this->_out (sprintf('BT /F%d %.2f Tf ET', $this->_current_font['i'], $this->_font_size_pt));
* Defines the size of the current font.
* @param float $size The size (in points).
/* If the font size is already the current font size, just return. */
if ($this->_font_size_pt == $size) {
/* Set the current font size, both in points and scaled to user
$this->_font_size_pt = $size;
$this->_font_size = $size / $this->_scale;
/* Output font information if at least one page has been defined. */
$this->_out (sprintf('BT /F%d %.2f Tf ET', $this->_current_font['i'], $this->_font_size_pt));
* Defines the style of the current font.
* @param string $style The font style.
$this->setFont($this->_font_family, $style);
* Creates a new internal link and returns its identifier. An internal
* link is a clickable area which directs to another place within the
* The identifier can then be passed to File_PDF::cell, File_PDF::write,
* File_PDF::image or File_PDF::link. The destination is defined with
$n = count($this->_links) + 1;
$this->_links[$n] = array (0 , 0 );
* Defines the page and position a link points to.
* @param integer $link The link identifier returned by File_PDF::addLink.
* @param float $y Ordinate of target position; -1 indicates the
* current position. The default value is 0 (top of
* @param integer $page Number of target page; -1 indicates the current
* page. This is the default value.
function setLink($link, $y = 0 , $page = -1 )
$this->_links[$link] = array ($page, $y);
* Puts a link on a rectangular area of the page. Text or image links are
* generally put via File_PDF::cell, File_PDF::Write or File_PDF::image,
* but this method can be useful for instance to define a clickable area
* All coordinates can be negative to provide values from the right or
* bottom edge of the page (since File_PDF 0.2.0, Horde 3.2).
* @param float $x Abscissa of the upper-left corner of the rectangle.
* @param float $y Ordinate of the upper-left corner of the rectangle.
* @param float $width Width of the rectangle.
* @param float $height Height of the rectangle.
* @param mixed $link URL or identifier returned by File_PDF::addLink.
function link($x, $y, $width, $height, $link)
/* Set up the coordinates with correct scaling in pt. */
$y = $this->hPt - $this->_toPt ($y);
$width = $this->_toPt ($width);
$height = $this->_toPt ($height);
/* Save link to page links array. */
$this->_link ($x, $y, $width, $height, $link);
* 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, but it is usually easier to use File_PDF::cell,
* File_PDF::multiCell or File_PDF::Write which are the standard methods to
* All coordinates can be negative to provide values from the right or
* bottom edge of the page (since File_PDF 0.2.0, Horde 3.2).
* @param float $x Abscissa of the origin.
* @param float $y Ordinate of the origin.
* @param string $text String to print.
* @see File_PDF::multiCell
function text($x, $y, $text)
/* Scale coordinates into points and set correct Y position. */
$y = $this->hPt - $this->_toPt ($y);
/* Escape any potentially harmful characters. */
$text = $this->_escape ($text);
$out = sprintf('BT %.2f %.2f Td (%s) Tj ET', $x, $y, $text);
if ($this->_underline && $text != '') {
$out .= ' ' . $this->_doUnderline ($x, $y, $text);
if ($this->_color_flag) {
$out = sprintf('q %s %s Q', $this->_text_color, $out);
* Whenever a page break condition is met, the method is called, and the
* break is issued or not depending on the returned value. The default
* implementation returns a value according to the mode selected by
* File_PDF:setAutoPageBreak.
* This method is called automatically and should not be called directly
* @see File_PDF::setAutoPageBreak.
return $this->_auto_page_break;
* Prints a cell (rectangular area) with optional borders, background
* color and character string. The upper-left corner of the cell
* corresponds to the current position. The text can be aligned or
* centered. After the call, the current position moves to the right or to
* the next line. It is possible to put a link on the text.
* If automatic page breaking is enabled and the cell goes beyond the
* limit, a page break is done before outputting.
* @param float $width Cell width. If 0, the cell extends up to the right
* @param float $height Cell height. Default value: 0.
* @param string $text String to print. Default value: empty.
* @param mixed $border Indicates if borders must be drawn around the
* cell. The value can be either a number:
* - 0: no border (default)
* or a string containing some or all of the
* following characters (in any order):
* @param integer $ln Indicates where the current position should go
* after the call. Possible values are:
* - 0: to the right (default)
* - 1: to the beginning of the next line
* Putting 1 is equivalent to putting 0 and calling
* File_PDF::newLine just after.
* @param string $align Allows to center or align the text. Possible
* - L or empty string: left (default)
* @param integer $fill Indicates if the cell fill type. Possible values
* - 0: transparent (default)
* @param string $link URL or identifier returned by
* @see File_PDF::setDrawColor
* @see File_PDF::setFillColor
* @see File_PDF::setLineWidth
* @see File_PDF::multiCell
* @see File_PDF::setAutoPageBreak
function cell($width, $height = 0 , $text = '', $border = 0 , $ln = 0 ,
$align = '', $fill = 0 , $link = '')
if ($this->y + $height > $this->_page_break_trigger &&
!$this->_in_footer && $this->AcceptPageBreak ()) {
$ws = $this->_word_spacing;
$this->_word_spacing = 0;
$this->addPage($this->_current_orientation);
$this->_word_spacing = $ws;
$this->_out (sprintf('%.3f Tw', $ws * $k));
$width = $this->w - $this->_right_margin - $this->x;
if ($fill == 1 || $border == 1 ) {
$op = ($border == 1 ) ? 'B' : 'f';
$s = sprintf('%.2f %.2f %.2f %.2f re %s ', $this->x * $k, ($this->h - $this->y) * $k, $width * $k, - $height * $k, $op);
if (strpos($border, 'L') !== false ) {
$s .= sprintf('%.2f %.2f m %.2f %.2f l S ', $this->x * $k, ($this->h - $this->y) * $k, $this->x * $k, ($this->h - ($this->y + $height)) * $k);
if (strpos($border, 'T') !== false ) {
$s .= sprintf('%.2f %.2f m %.2f %.2f l S ', $this->x * $k, ($this->h - $this->y) * $k, ($this->x + $width) * $k, ($this->h - $this->y) * $k);
if (strpos($border, 'R') !== false ) {
$s .= sprintf('%.2f %.2f m %.2f %.2f l S ', ($this->x + $width) * $k, ($this->h - $this->y) * $k, ($this->x + $width) * $k, ($this->h - ($this->y + $height)) * $k);
if (strpos($border, 'B') !== false ) {
$s .= sprintf('%.2f %.2f m %.2f %.2f l S ', $this->x * $k, ($this->h - ($this->y + $height)) * $k, ($this->x + $width) * $k, ($this->h - ($this->y + $height)) * $k);
} elseif ($align == 'C') {
$dx = $this->_cell_margin;
if ($this->_color_flag) {
$s .= 'q ' . $this->_text_color . ' ';
$test2 = ((.5 * $height) + (.3 * $this->_font_size));
$test1 = $this->fhPt - (($this->y + $test2) * $k);
$s .= sprintf('BT %.2f %.2f Td (%s) Tj ET', ($this->x + $dx) * $k, ($this->h - ($this->y + .5 * $height + .3 * $this->_font_size)) * $k, $text);
$s .= ' ' . $this->_doUnderline ($this->x + $dx, $this->y + .5 * $height + .3 * $this->_font_size, $text);
if ($this->_color_flag) {
$this->link($this->x + $dx, $this->y + .5 * $height-.5 * $this->_font_size, $this->getStringWidth($text), $this->_font_size, $link);
$this->_last_height = $height;
$this->x = $this->_left_margin;
* This method allows printing text with line breaks. They can be
* automatic (as soon as the text reaches the right border of the cell) or
* explicit (via the \n character). As many cells as necessary are output,
* Text can be aligned, centered or justified. The cell block can be
* framed and the background painted.
* @param float $width Width of cells. If 0, they extend up to the right
* @param float $height Height of cells.
* @param string $text String to print.
* @param mixed $border Indicates if borders must be drawn around the cell
* block. The value can be either a number:
* - 0: no border (default)
* or a string containing some or all of the
* following characters (in any order):
* @param string $align Sets the text alignment. Possible values are:
* - J: justification (default value)
* @param integer $fill Indicates if the cell background must:
* - 0: transparent (default)
* @see File_PDF::setDrawColor
* @see File_PDF::setFillColor
* @see File_PDF::setLineWidth
* @see File_PDF::setAutoPageBreak
function multiCell($width, $height, $text, $border = 0 , $align = 'J',
$cw = &$this->_current_font['cw'];
$width = $this->w - $this->_right_margin - $this->x;
$wmax = ($width-2 * $this->_cell_margin) * 1000 / $this->_font_size;
if ($nb > 0 && $s[$nb-1 ] == "\n") {
if (strpos($border, 'L') !== false ) {
if (strpos($border, 'R') !== false ) {
$b = (strpos($border, 'T') !== false ) ? $b2 . 'T' : $b2;
/* Get next character. */
/* Explicit line break. */
if ($this->_word_spacing > 0 ) {
$this->_word_spacing = 0;
$this->cell($width, $height, substr($s, $j, $i- $j), $b, 2 , $align, $fill);
if ($border && $nl == 2 ) {
/* Automatic line break. */
if ($this->_word_spacing > 0 ) {
$this->_word_spacing = 0;
$this->cell($width, $height, substr($s, $j, $i - $j), $b, 2 , $align, $fill);
$this->_word_spacing = ($ns>1 ) ? ($wmax - $ls)/1000 * $this->_font_size / ($ns - 1 ) : 0;
$this->_out (sprintf('%.3f Tw', $this->_word_spacing * $this->_scale));
$this->cell($width, $height, substr($s, $j, $sep - $j), $b, 2 , $align, $fill);
if ($border && $nl == 2 ) {
if ($this->_word_spacing > 0 ) {
$this->_word_spacing = 0;
if ($border && strpos($border, 'B') !== false ) {
$this->cell($width, $height, substr($s, $j, $i), $b, 2 , $align, $fill);
$this->x = $this->_left_margin;
* This method prints text from the current position. When the right
* margin is reached (or the \n character is met) a line break occurs and
* text continues from the left margin. Upon method exit, the current
* position is left just at the end of the text.
* It is possible to put a link on the text.
* //Begin with regular font
* $pdf->setFont('Arial','',14);
* $pdf->write(5,'Visit ');
* //Then put a blue underlined link
* $pdf->setTextColor(0,0,255);
* $pdf->write(5,'www.fpdf.org','http://www.fpdf.org');
* @param float $height Line height.
* @param string $text String to print.
* @param mixed $link URL or identifier returned by AddLink().
* @see File_PDF::multiCell
* @see File_PDF::setAutoPageBreak
function write($height, $text, $link = '')
$cw = &$this->_current_font['cw'];
$width = $this->w - $this->_right_margin - $this->x;
$wmax = ($width - 2 * $this->_cell_margin) * 1000 / $this->_font_size;
/* Get next character. */
/* Explicit line break. */
$this->cell($width, $height, substr($s, $j, $i - $j), 0 , 2 , '', 0 , $link);
$this->x = $this->_left_margin;
$width = $this->w - $this->_right_margin - $this->x;
$wmax = ($width - 2 * $this->_cell_margin) * 1000 / $this->_font_size;
/* Automatic line break. */
if ($this->x > $this->_left_margin) {
$this->x = $this->_left_margin;
$width = $this->w - $this->_right_margin - $this->x;
$wmax = ($width - 2 * $this->_cell_margin) * 1000 / $this->_font_size;
$this->cell($width, $height, substr($s, $j, $i - $j), 0 , 2 , '', 0 , $link);
$this->cell($width, $height, substr($s, $j, $sep - $j), 0 , 2 , '', 0 , $link);
$this->x = $this->_left_margin;
$width = $this->w - $this->_right_margin - $this->x;
$wmax = ($width - 2 * $this->_cell_margin) * 1000 / $this->_font_size;
$this->cell($l / 1000 * $this->_font_size, $height, substr($s, $j, $i), 0 , 0 , '', 0 , $link);
* Writes text at an angle.
* All coordinates can be negative to provide values from the right or
* bottom edge of the page (since File_PDF 0.2.0, Horde 3.2).
* @param integer $x X coordinate.
* @param integer $y Y coordinate.
* @param string $text Text to write.
* @param float $text_angle Angle to rotate (Eg. 90 = bottom to top).
* @param float $font_angle Rotate characters as well as text.
function writeRotated($x, $y, $text, $text_angle, $font_angle = 0 )
$text = $this->_escape ($text);
$font_angle += 90 + $text_angle;
$text_angle *= M_PI / 180;
$font_angle *= M_PI / 180;
$text_dx = cos($text_angle);
$text_dy = sin($text_angle);
$font_dx = cos($font_angle);
$font_dy = sin($font_angle);
$s= sprintf('BT %.2f %.2f %.2f %.2f %.2f %.2f Tm (%s) Tj ET',
$text_dx, $text_dy, $font_dx, $font_dy,
$x * $this->_scale, ($this->h- $y) * $this->_scale, $text);
if ($this->_draw_color) {
$s = 'q ' . $this->_draw_color . ' ' . $s . ' Q';
* 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 formats are JPEG and PNG.
* All coordinates can be negative to provide values from the right or
* bottom edge of the page (since File_PDF 0.2.0, Horde 3.2).
* For JPEG, all flavors are allowed:
* - true colors (24 bits)
* - gray scales on at most 8 bits (256 levels)
* - true colors (24 bits)
* If a transparent color is defined, it will be taken into account (but
* will be only interpreted by Acrobat 4 and above).
* The format can be specified explicitly or inferred from the file
* It is possible to put a link on the image.
* Remark: if an image is used several times, only one copy will be
* @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
* @param 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.
* @param string $type Image format. Possible values are (case
* insensitive) : JPG, JPEG, PNG. If not specified,
* the type is inferred from the file extension.
* @param mixed $link URL or identifier returned by File_PDF::addLink.
function image($file, $x, $y, $width = 0 , $height = 0 , $type = '',
if (!isset ($this->_images[$file])) {
/* First use of image, get some file info. */
return $this->raiseError(sprintf('Image file has no extension and no type was specified: %s', $file));
$type = substr($file, $pos + 1 );
if ($type == 'jpg' || $type == 'jpeg') {
$info = $this->_parseJPG ($file);
} elseif ($type == 'png') {
$info = $this->_parsePNG ($file);
$info['i'] = count($this->_images) + 1;
$this->_images[$file] = $info;
$info = $this->_images[$file];
/* Make sure all vars are converted to pt scale. */
$width = $this->_toPt ($width);
$height = $this->_toPt ($height);
/* If not specified do automatic width and height calculations. */
if (empty ($width) && empty ($height)) {
} 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->hPt - ($y + $height), $info['i']));
/* Set any link if requested. */
$this->_link ($x, $y, $width, $height, $link);
* Performs a line break. The current abscissa goes back to the left
* margin and the ordinate increases by the amount passed in parameter.
* @param float $height The height of the break. By default, the value
* equals the height of the last printed cell.
$this->x = $this->_left_margin;
$this->y += $this->_last_height;
* Returns the abscissa of the current position in user units.
* Defines the abscissa of the current position. If the passed value is
* negative, it is relative to the right of the page.
* @param float $x The value of the abscissa.
/* Negative, so relative to right edge of the page. */
$this->x = $this->w + $x;
* Returns the ordinate of the current position in user units.
* Defines the ordinate of the current position. If the passed value is
* negative, it is relative to the bottom of the page.
* @param float $y The value of the ordinate.
/* Negative, so relative to bottom edge of the page. */
$this->y = $this->h + $y;
* 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.
* @param float $x The value of the abscissa.
* @param float $y The value of the ordinate.
* Returns the raw PDF file.
/* Check whether file has been closed. */
* Function to output the buffered data to the browser.
* @param string $filename The filename for the output file.
* @param boolean $inline True if inline, false if attachment.
function output($filename = 'unknown.pdf', $inline = false )
/* Check whether file has been closed. */
/* Check if headers have been sent. */
return $this->raiseError('Unable to send PDF file, some data has already been output to browser.');
/* If HTTP_Download is not available return a PEAR_Error. */
if (!include_once 'HTTP/Download.php') {
return $this->raiseError('Missing PEAR package HTTP_Download.');
/* Params for the output. */
$disposition = !$inline ? HTTP_DOWNLOAD_ATTACHMENT : HTTP_DOWNLOAD_INLINE;
$params = array ('data' => $this->_buffer,
'contenttype' => 'application/pdf',
'contentdisposition' => array ($disposition, $filename));
return HTTP_Download ::staticSend ($params);
* Function to save the PDF file somewhere local to the server.
* @param string $filename The filename for the output file.
function save($filename = 'unknown.pdf')
/* Check whether file has been closed. */
$f = fopen($filename, 'wb');
return $val * $this->_scale;
function &_getFontFile ($fontkey, $path = '')
if (!isset ($font_widths[$fontkey])) {
$file = 'File/PDF/fonts/' . strtolower($fontkey) . '.php';
if (!isset ($font_widths[$fontkey])) {
function _link ($x, $y, $width, $height, $link)
/* Save link to page links array. */
$this->_page_links[$this->_page][] = array ($x, $y, $width, $height, $link);
/* Start document, but only if not yet started. */
if (!empty ($this->_alias_nb_pages)) {
/* Replace number of pages. */
for ($n = 1; $n <= $nb; $n++ ) {
$this->_pages[$n] = str_replace($this->_alias_nb_pages, $nb, $this->_pages[$n]);
if ($this->_default_orientation == 'P') {
$filter = ($this->_compress) ? '/Filter /FlateDecode ' : '';
for ($n = 1; $n <= $nb; $n++ ) {
$this->_out ('<</Type /Page');
$this->_out ('/Parent 1 0 R');
if (isset ($this->_orientation_changes[$n])) {
$this->_out (sprintf('/MediaBox [0 0 %.2f %.2f]', $hPt, $wPt));
$this->_out ('/Resources 2 0 R');
if (isset ($this->_page_links[$n])) {
foreach ($this->_page_links[$n] as $pl) {
$rect = sprintf('%.2f %.2f %.2f %.2f', $pl[0 ], $pl[1 ], $pl[0 ] + $pl[2 ], $pl[1 ] - $pl[3 ]);
$annots .= '<</Type /Annot /Subtype /Link /Rect [' . $rect . '] /Border [0 0 0] ';
$annots .= '/A <</S /URI /URI ' . $this->_textString ($pl[4 ]) . '>>>>';
$l = $this->_links[$pl[4 ]];
$height = isset ($this->_orientation_changes[$l[0 ]]) ? $wPt : $hPt;
$annots .= sprintf('/Dest [%d 0 R /XYZ 0 %.2f null]>>', 1 + 2 * $l[0 ], $height - $l[1 ] * $this->_scale);
$this->_out ($annots. ']');
$this->_out ('/Contents ' . ($this->_n + 1 ) . ' 0 R>>');
$p = ($this->_compress) ? gzcompress($this->_pages[$n]) : $this->_pages[$n];
$this->_out ('<<' . $filter . '/Length ' . strlen($p) . '>>');
$this->_offsets[1 ] = strlen($this->_buffer);
$this->_out ('<</Type /Pages');
for ($i = 0; $i < $nb; $i++ ) {
$kids .= (3 + 2 * $i) . ' 0 R ';
$this->_out ($kids . ']');
$this->_out ('/Count ' . $nb);
$this->_out (sprintf('/MediaBox [0 0 %.2f %.2f]', $wPt, $hPt));
foreach ($this->_diffs as $diff) {
$this->_out ('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [' . $diff . ']>>');
foreach ($this->_font_files as $file => $info) {
/* Font file embedding. */
$this->_font_files[$file]['n'] = $this->_n;
$this->_out ('<</Length ' . $size);
if (substr($file, -2 ) == '.z') {
$this->_out ('/Filter /FlateDecode');
$this->_out ('/Length1 ' . $info['length1']);
if (isset ($info['length2'])) {
$this->_out ('/Length2 ' . $info['length2'] . ' /Length3 0');
$this->_putStream (fread($f, $size));
foreach ($this->_fonts as $k => $font) {
$this->_fonts[$k]['n'] = $this->_n;
$this->_out ('<</Type /Font');
$this->_out ('/BaseFont /' . $name);
if ($font['type'] == 'core') {
$this->_out ('/Subtype /Type1');
if ($name != 'Symbol' && $name != 'ZapfDingbats') {
$this->_out ('/Encoding /WinAnsiEncoding');
$this->_out ('/Subtype /' . $font['type']);
$this->_out ('/FirstChar 32');
$this->_out ('/LastChar 255');
$this->_out ('/Widths ' . ($this->_n + 1 ) . ' 0 R');
$this->_out ('/FontDescriptor ' . ($this->_n + 2 ) . ' 0 R');
if (isset ($font['diff'])) {
$this->_out ('/Encoding ' . ($nf + $font['diff']). ' 0 R');
$this->_out ('/Encoding /WinAnsiEncoding');
if ($font['type'] != 'core') {
for ($i = 32; $i <= 255; $i++ ) {
$s .= $cw[chr($i)] . ' ';
$s = '<</Type /FontDescriptor /FontName /' . $name;
foreach ($font['desc'] as $k => $v) {
$s .= ' /' . $k . ' ' . $v;
$s .= ' /FontFile' . ($font['type'] == 'Type1' ? '' : '2') . ' ' . $this->_font_files[$file]['n'] . ' 0 R';
$filter = ($this->_compress) ? '/Filter /FlateDecode ' : '';
foreach ($this->_images as $file => $info) {
$this->_images[$file]['n'] = $this->_n;
$this->_out ('<</Type /XObject');
$this->_out ('/Subtype /Image');
$this->_out ('/Width ' . $info['w']);
$this->_out ('/Height ' . $info['h']);
if ($info['cs'] == 'Indexed') {
$this->_out ('/ColorSpace [/Indexed /DeviceRGB ' . (strlen($info['pal'])/3 - 1 ) . ' ' . ($this->_n + 1 ). ' 0 R]');
$this->_out ('/ColorSpace /' . $info['cs']);
if ($info['cs'] == 'DeviceCMYK') {
$this->_out ('/Decode [1 0 1 0 1 0 1 0]');
$this->_out ('/BitsPerComponent ' . $info['bpc']);
$this->_out ('/Filter /' . $info['f']);
if (isset ($info['parms'])) {
$this->_out ($info['parms']);
if (isset ($info['trns']) && is_array($info['trns'])) {
$i_max = count($info['trns']);
for ($i = 0; $i < $i_max; $i++ ) {
$trns .= $info['trns'][$i] . ' ' . $info['trns'][$i]. ' ';
$this->_out ('/Mask [' . $trns . ']');
$this->_out ('/Length ' . strlen($info['data']) . '>>');
$this->_putStream ($info['data']);
if ($info['cs'] == 'Indexed') {
$pal = ($this->_compress) ? gzcompress($info['pal']) : $info['pal'];
$this->_out ('<<' . $filter . '/Length ' . strlen($pal) . '>>');
/* Resource dictionary */
$this->_offsets[2 ] = strlen($this->_buffer);
$this->_out ('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
foreach ($this->_fonts as $font) {
$this->_out ('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R');
if (count($this->_images)) {
$this->_out ('/XObject <<');
foreach ($this->_images as $image) {
$this->_out ('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R');
$this->_out ('/Producer ' . $this->_textString ('Horde PDF'));
if (!empty ($this->_info['title'])) {
$this->_out ('/Title ' . $this->_textString ($this->_info['title']));
if (!empty ($this->_info['subject'])) {
$this->_out ('/Subject ' . $this->_textString ($this->_info['subject']));
if (!empty ($this->_info['author'])) {
$this->_out ('/Author ' . $this->_textString ($this->_info['author']));
if (!empty ($this->keywords)) {
$this->_out ('/Keywords ' . $this->_textString ($this->keywords));
if (!empty ($this->creator)) {
$this->_out ('/Creator ' . $this->_textString ($this->creator));
$this->_out ('/CreationDate ' . $this->_textString ('D:' . date('YmdHis')));
$this->_out ('/Type /Catalog');
$this->_out ('/Pages 1 0 R');
if ($this->_zoom_mode == 'fullpage') {
$this->_out ('/OpenAction [3 0 R /Fit]');
} elseif ($this->_zoom_mode == 'fullwidth') {
$this->_out ('/OpenAction [3 0 R /FitH null]');
} elseif ($this->_zoom_mode == 'real') {
$this->_out ('/OpenAction [3 0 R /XYZ null null 1]');
$this->_out ('/OpenAction [3 0 R /XYZ null null ' . ($this->_zoom_mode / 100 ). ']');
if ($this->_layout_mode == 'single') {
$this->_out ('/PageLayout /SinglePage');
} elseif ($this->_layout_mode == 'continuous') {
$this->_out ('/PageLayout /OneColumn');
} elseif ($this->_layout_mode == 'two') {
$this->_out ('/PageLayout /TwoColumnLeft');
$this->_out ('/Size ' . ($this->_n + 1 ));
$this->_out ('/Root ' . $this->_n . ' 0 R');
$this->_out ('/Info ' . ($this->_n - 1 ) . ' 0 R');
$this->_out ('0 ' . ($this->_n + 1 ));
$this->_out ('0000000000 65535 f ');
for ($i = 1; $i <= $this->_n; $i++ ) {
$this->_out (sprintf('%010d 00000 n ', $this->_offsets[$i]));
$this->_out ('startxref');
function _beginPage ($orientation)
$this->_pages[$this->_page] = '';
$this->x = $this->_left_margin;
$this->y = $this->_top_margin;
$orientation = $this->_default_orientation;
if ($orientation != $this->_default_orientation) {
$this->_orientation_changes[$this->_page] = true;
if ($orientation != $this->_current_orientation) {
if ($orientation == 'P') {
$this->_page_break_trigger = $this->h - $this->_break_margin;
$this->_current_orientation = $orientation;
/* End of page contents */
$this->_offsets[$this->_n] = strlen($this->_buffer);
$this->_out ($this->_n . ' 0 obj');
function _doUnderline ($x, $y, $text)
/* Set the rectangle width according to text width. */
/* Set rectangle position and height, using underline position and
* thickness settings scaled by the font size. */
$y = $y + ($this->_current_font['up'] * $this->_font_size_pt / 1000 );
$height = - $this->_current_font['ut'] * $this->_font_size_pt / 1000;
return sprintf('%.2f %.2f %.2f %.2f re f', $x, $y, $width, $height);
function _parseJPG ($file)
/* Extract info from a JPEG file. */
if (!isset ($img['channels']) || $img['channels'] == 3 ) {
} elseif ($img['channels'] == 4 ) {
$colspace = 'DeviceCMYK';
$colspace = 'DeviceGray';
$bpc = isset ($img['bits']) ? $img['bits'] : 8;
return array ('w' => $img[0 ], 'h' => $img[1 ], 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'DCTDecode', 'data' => $data);
function _parsePNG ($file)
/* Extract info from a PNG file. */
if (fread($f, 4 ) != 'IHDR') {
$width = $this->_freadInt ($f);
$height = $this->_freadInt ($f);
$colspace = 'DeviceGray';
$parms = '/DecodeParms <</Predictor 15 /Colors ' . ($ct == 2 ? 3 : 1 ). ' /BitsPerComponent ' . $bpc . ' /Columns ' . $width. '>>';
/* Scan chunks looking for palette, transparency and image data. */
$n = $this->_freadInt ($f);
} elseif ($type == 'tRNS') {
/* Read transparency info */
} elseif ($type == 'IDAT') {
/* Read image data block */
} elseif ($type == 'IEND') {
if ($colspace == 'Indexed' && empty ($pal)) {
return array ('w' => $width, 'h' => $height, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'FlateDecode', 'parms' => $parms, 'pal' => $pal, 'trns' => $trns, 'data' => $data);
/* Read a 4-byte integer from file. */
/* Format a text string */
return '(' . $this->_escape ($s) . ')';
/* Add \ before \, ( and ) */
array ('\\)','\\(','\\\\'),
$this->_out ('endstream');
/* Add a line to the document. */
if ($this->_state == 2 ) {
$this->_pages[$this->_page] .= $s . "\n";
$this->_buffer .= $s . "\n";
Documentation generated on Mon, 11 Mar 2019 14:43:33 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|