Windows NT DGPENSV2LPKMN 10.0 build 14393 (Windows Server 2016) AMD64
Apache/2.4.46 (Win64) OpenSSL/1.1.1h PHP/7.3.25
: 172.16.0.66 | : 172.16.0.254
Cant Read [ /etc/named.conf ]
7.3.25
SYSTEM
www.github.com/MadExploits
Terminal
AUTO ROOT
Adminer
Backdoor Destroyer
Linux Exploit
Lock Shell
Lock File
Create User
CREATE RDP
PHP Mailer
BACKCONNECT
UNLOCK SHELL
HASH IDENTIFIER
CPANEL RESET
CREATE WP USER
BLACK DEFEND!
README
+ Create Folder
+ Create File
[ A ]
[ C ]
[ D ]
C: /
xampp7 /
php /
pear /
File /
[ HOME SHELL ]
Name
Size
Permission
Action
Iterator
[ DIR ]
drwxrwxrwx
PDF
[ DIR ]
drwxrwxrwx
Passwd
[ DIR ]
drwxrwxrwx
CSV.php
24.76
KB
-rw-rw-rw-
Find.php
14.88
KB
-rw-rw-rw-
HtAccess.php
12.67
KB
-rw-rw-rw-
Iterator.php
5.85
KB
-rw-rw-rw-
PDF.php
104.15
KB
-rw-rw-rw-
Passwd.php
13.23
KB
-rw-rw-rw-
Util.php
14.9
KB
-rw-rw-rw-
Delete
Unzip
Zip
${this.title}
Close
Code Editor : PDF.php
<?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/). * * $Horde: framework/File_PDF/PDF.php,v 1.18.10.22 2011/08/06 21:37:11 jan Exp $ * * Copyright 2001-2003 Olivier Plathey <olivier@fpdf.org> * Copyright 2003-2009 The Horde Project (http://www.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. * * @author Olivier Plathey <olivier@fpdf.org> * @author Marko Djukic <marko@oblo.com> * @author Jan Schneider <jan@horde.org> * @package File_PDF * @category Fileformats */ /** * This hack works around Horde bug #4094 * (http://bugs.horde.org/ticket/?id=4094) * * Once this package does not need to support PHP < 4.3.10 anymore the * following definiton can be removed and the ugly code can be removed * using * * sed -i -e 's/\' \. FILE_PDF_FLOAT \. \'/F/g' PDF.php */ if (version_compare(PHP_VERSION, '4.3.10', '>=')) { define('FILE_PDF_FLOAT', 'F'); } else { define('FILE_PDF_FLOAT', 'f'); } class File_PDF { /** * Current page number. * * @var integer */ var $_page = 0; /** * Current object number. * * @var integer */ var $_n = 2; /** * Array of object offsets. * * @var array */ var $_offsets = array(); /** * Buffer holding in-memory PDF. * * @var string */ var $_buffer = ''; /** * Buffer length, including already flushed content. * * @var integer */ var $_buflen = 0; /** * Whether the buffer has been flushed already. * * @var boolean */ var $_flushed = false; /** * Array containing the pages. * * @var array */ var $_pages = array(); /** * Current document state.<pre> * 0 - initial state * 1 - document opened * 2 - page opened * 3 - document closed * </pre> * * @var integer */ var $_state = 0; /** * Flag indicating if PDF file is to be compressed or not. * * @var boolean */ var $_compress; /** * The default page orientation. * * @var string */ var $_default_orientation; /** * The current page orientation. * * @var string */ var $_current_orientation; /** * Array indicating orientation changes. * * @var array */ var $_orientation_changes = array(); /** * Current width of page format in points. * * @var float */ var $fwPt; /** * Current height of page format in points. * * @var float */ var $fhPt; /** * Current width of page format in user units. * * @var float */ var $fw; /** * Current height of page format in user units. * * @var float */ var $fh; /** * Current width of page in points. * * @var float */ var $wPt; /** * Current height of page in points. * * @var float */ var $hPt; /** * Current width of page in user units * * @var float */ var $w; /** * Current height of page in user units * * @var float */ var $h; /** * Scale factor (number of points in user units). * * @var float */ var $_scale; /** * Left page margin size. * * @var float */ var $_left_margin; /** * Top page margin size. * * @var float */ var $_top_margin; /** * Right page margin size. * * @var float */ var $_right_margin; /** * Break page margin size, the bottom margin which triggers a page break. * * @var float */ var $_break_margin; /** * Cell margin size. * * @var float */ var $_cell_margin; /** * The current horizontal position for cell positioning. * Value is set in user units and is calculated from the top left corner * as origin. * * @var float */ var $x; /** * The current vertical position for cell positioning. * Value is set in user units and is calculated from the top left corner * as origin. * * @var float */ var $y; /** * The height of the last cell printed. * * @var float */ var $_last_height; /** * Line width in user units. * * @var float */ var $_line_width; /** * An array of standard font names. * * @var array */ 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'); /** * An array of used fonts. * * @var array */ var $_fonts = array(); /** * An array of font files. * * @var array */ var $_font_files = array(); /** * An array of encoding differences. * * @var array */ var $_diffs = array(); /** * An array of used images. * * @var array */ var $_images = array(); /** * An array of links in pages. * * @var array */ var $_page_links; /** * An array of internal links. * * @var array */ var $_links = array(); /** * Current font family. * * @var string */ var $_font_family = ''; /** * Current font style. * * @var string */ var $_font_style = ''; /** * Underlining flag. * * @var boolean */ var $_underline = false; /** * An array containing current font info. * * @var array */ var $_current_font; /** * Current font size in points. * * @var float */ var $_font_size_pt = 12; /** * Current font size in user units. * * @var float */ var $_font_size = 12; /** * Commands for filling color. * * @var string */ var $_fill_color = '0 g'; /** * Commands for text color. * * @var string */ var $_text_color = '0 g'; /** * Whether text color is different from fill color. * * @var boolean */ var $_color_flag = false; /** * Commands for drawing color. * * @var string */ var $_draw_color = '0 G'; /** * Word spacing. * * @var integer */ var $_word_spacing = 0; /** * Automatic page breaking. * * @var boolean */ var $_auto_page_break; /** * Threshold used to trigger page breaks. * * @var float */ var $_page_break_trigger; /** * Flag set when processing footer. * * @var boolean */ var $_in_footer = false; /** * Zoom display mode. * * @var string */ var $_zoom_mode; /** * Layout display mode. * * @var string */ var $_layout_mode; /** * An array containing the document info, consisting of: * - title * - subject * - author * - keywords * - creator * * @var array */ var $_info = array(); /** * Alias for total number of pages. * * @var string */ 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). * * Example: * <code> * $pdf = File_PDF::factory(array('orientation' => 'P', * 'unit' => 'mm', * 'format' => 'A4')); * </code> * * @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) * - L or Landscape * - unit - User measure units. Possible values * values are: * - pt: point * - mm: millimeter (default) * - cm: centimeter * - in: inch * 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 * 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 the unit * parameter). * @param string $class The concrete class name to return an instance of. * Defaults to File_PDF. */ function &factory($params = array(), $class = 'File_PDF') { /* Default parameters. */ $defaults = array('orientation' => 'P', 'unit' => 'mm', 'format' => 'A4'); /* Backward compatibility with old method signature. */ /* Should be removed a few versions later. */ if (!is_array($params)) { $class = 'File_PDF'; $params = $defaults; $names = array_keys($defaults); for ($i = 0; $i < func_num_args(); $i++) { $params[$names[$i]] = func_get_arg($i); } } else { $params = array_merge($defaults, $params); } /* Create the PDF object. */ $pdf = new $class($params); /* Scale factor. */ if ($params['unit'] == 'pt') { $pdf->_scale = 1; } elseif ($params['unit'] == 'mm') { $pdf->_scale = 72 / 25.4; } elseif ($params['unit'] == 'cm') { $pdf->_scale = 72 / 2.54; } elseif ($params['unit'] == 'in') { $pdf->_scale = 72; } else { $error = File_PDF::raiseError(sprintf('Incorrect units: %s', $params['unit'])); return $error; } /* Page format. */ if (is_string($params['format'])) { $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); } else { $error = File_PDF::raiseError(sprintf('Unknown page format: %s', $params['format'])); return $error; } $pdf->fwPt = $params['format'][0]; $pdf->fhPt = $params['format'][1]; } else { $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; /* Page orientation. */ $params['orientation'] = strtolower($params['orientation']); if ($params['orientation'] == 'p' || $params['orientation'] == 'portrait') { $pdf->_default_orientation = 'P'; $pdf->wPt = $pdf->fwPt; $pdf->hPt = $pdf->fhPt; } elseif ($params['orientation'] == 'l' || $params['orientation'] == 'landscape') { $pdf->_default_orientation = 'L'; $pdf->wPt = $pdf->fhPt; $pdf->hPt = $pdf->fwPt; } else { $error = File_PDF::raiseError(sprintf('Incorrect orientation: %s', $params['orientation'])); return $error; } $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'); /* Compression */ $pdf->setCompression(true); return $pdf; } /** * 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 */ function raiseError($error) { require_once 'PEAR.php'; 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 * of the left one. * * @see setAutoPageBreak() * @see setLeftMargin() * @see setRightMargin() * @see setTopMargin() */ function setMargins($left, $top, $right = null) { /* 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 first page. If the * current abscissa gets out of page, it is brought back to the margin. * * @param float $margin The margin. * * @see setAutoPageBreak() * @see setMargins() * @see setRightMargin() * @see setTopMargin() */ function setLeftMargin($margin) { $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) { $this->x = $margin; } } /** * Defines the top margin. * * The method can be called before creating the first page. * * @param float $margin The margin. */ function setTopMargin($margin) { $this->_top_margin = $margin; } /** * Defines the right margin. * * The method can be called before creating the first page. * * @param float $margin The margin. */ function setRightMargin($margin) { $this->_right_margin = $margin; } /** * Returns the actual page width. * * @since File_PDF 0.2.0 * @since Horde 3.2 * * @return float The page width. */ function getPageWidth() { return ($this->w - $this->_right_margin - $this->_left_margin); } /** * Returns the actual page height. * * @since File_PDF 0.2.0 * @since Horde 3.2 * * @return float The page height. */ function getPageHeight() { return ($this->h - $this->_top_margin - $this->_break_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 is 2 cm. * * @param boolean $auto Boolean indicating if mode should be on or off. * @param float $margin Distance from the bottom of the page. */ function setAutoPageBreak($auto, $margin = 0) { $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. */ function setDisplayMode($zoom, $layout = 'continuous') { $zoom = strtolower($zoom); if ($zoom == 'fullpage' || $zoom == 'fullwidth' || $zoom == 'real' || $zoom == 'default' || !is_string($zoom)) { $this->_zoom_mode = $zoom; } elseif ($zoom == 'zoom') { $this->_zoom_mode = $layout; } else { return $this->raiseError(sprintf('Incorrect zoom display mode: %s', $zoom)); } $layout = strtolower($layout); if ($layout == 'single' || $layout == 'continuous' || $layout == 'two' || $layout == 'default') { $this->_layout_mode = $layout; } elseif ($zoom != 'zoom') { return $this->raiseError(sprintf('Incorrect layout display mode: %s', $layout)); } } /** * 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 {@link http://www.php.net/zlib/ zlib extension} is required * for this feature. If not present, compression will be turned off. * * @param boolean $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); } /** * Set the info to a document. * * Possible info settings are: * - title * - subject * - author * - keywords * - creator * * @param array|string $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 = '') { if (is_array($info)) { $this->_info = $info; } else { $this->_info[$info] = $value; } } /** * Defines an alias for the total number of pages. * * It will be substituted as the document is closed. * * Example: * <code> * class My_File_PDF extends File_PDF { * function footer() * { * // Go to 1.5 cm from bottom * $this->setY(-15); * // Select Arial italic 8 * $this->setFont('Arial', 'I', 8); * // Print current and total page numbers * $this->cell(0, 10, 'Page ' . $this->getPageNo() . '/{nb}', 0, * 0, 'C'); * } * } * $pdf = My_File_PDF::factory(); * $pdf->aliasNbPages(); * </code> * * @param string $alias The alias. * * @see getPageNo() * @see footer() */ function aliasNbPages($alias = '{nb}') { $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 * {@link addPage()}. * * @see addPage() * @see close() */ function open() { $this->_beginDoc(); } /** * Terminates the PDF document. It is not necessary to call this method * explicitly because {@link output()} does it automatically. * * If the document contains no page, {@link addPage()} is called to * prevent from getting an invalid document. * * @see open() * @see output() */ function close() { /* Terminate document */ if ($this->_page == 0) { $result = $this->addPage(); if (is_a($result, 'PEAR_Error')) { return $result; } } /* Page footer */ $this->_in_footer = true; $this->x = $this->_left_margin; $this->footer(); $this->_in_footer = false; /* Close page */ $this->_endPage(); /* Close document */ $this->_endDoc(); } /** * Adds a new page to the document. * * If a page is already present, the {@link 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 {@link header()} is called to display the header. * * The font which was set before calling is automatically restored. There * is no need to call {@link 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): * - P or Portrait * - L or Landscape * The default value is the one passed to the * constructor. * * @see header() * @see footer() * @see setMargins() */ function addPage($orientation = '') { /* For good measure make sure this is called. */ $this->_beginDoc(); /* Save style settings so that they are not overridden by footer() or * header(). */ $lw = $this->_line_width; $dc = $this->_draw_color; $fc = $this->_fill_color; $tc = $this->_text_color; $cf = $this->_color_flag; $font_family = $this->_font_family; $font_style = $this->_font_style . ($this->_underline ? 'U' : ''); $font_size = $this->_font_size_pt; /* Close old page. */ if ($this->_page > 0) { /* Page footer. */ $this->_in_footer = true; $this->x = $this->_left_margin; $this->footer(); $this->_in_footer = false; /* Close page. */ $this->_endPage(); } /* Start new page. */ $this->_beginPage($orientation); /* Set line cap style to square. */ $this->_out('2 J'); /* Set line width. */ $this->_line_width = $lw; $this->_out(sprintf('%.2' . FILE_PDF_FLOAT . ' w', $lw * $this->_scale)); /* Force the setting of the font. Each new page requires a new * call. */ if ($font_family) { $result = $this->setFont($font_family, $font_style, $font_size, true); if (is_a($result, 'PEAR_Error')) { return $result; } } /* Restore styles. */ if ($this->_fill_color != $fc) { $this->_fill_color = $fc; $this->_out($this->_fill_color); } if ($this->_draw_color != $dc) { $this->_draw_color = $dc; $this->_out($this->_draw_color); } $this->_text_color = $tc; $this->_color_flag = $cf; /* Page header. */ $this->header(); /* Restore styles. */ if ($this->_line_width != $lw) { $this->_line_width = $lw; $this->_out(sprintf('%.2' . FILE_PDF_FLOAT . ' w', $lw * $this->_scale)); } $result = $this->setFont($font_family, $font_style, $font_size); if (is_a($result, 'PEAR_Error')) { return $result; } if ($this->_fill_color != $fc) { $this->_fill_color = $fc; $this->_out($this->_fill_color); } if ($this->_draw_color != $dc) { $this->_draw_color = $dc; $this->_out($this->_draw_color); } $this->_text_color = $tc; $this->_color_flag = $cf; } /** * This method is used to render the page header. * * It is automatically called by {@link 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. * * Example: * <code> * class My_File_PDF extends File_PDF { * function header() * { * // Select Arial bold 15 * $this->setFont('Arial', 'B', 15); * // Move to the right * $this->cell(80); * // Framed title * $this->cell(30, 10, 'Title', 1, 0, 'C'); * // Line break * $this->newLine(20); * } * } * </code> * * @see footer() */ function header() { /* To be implemented in your own inherited class. */ } /** * This method is used to render the page footer. * * It is automatically called by {@link addPage()} and {@link 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 processing. * * Example: * <code> * class My_File_PDF extends File_PDF { * function footer() * { * // Go to 1.5 cm from bottom * $this->setY(-15); * // Select Arial italic 8 * $this->setFont('Arial', 'I', 8); * // Print centered page number * $this->cell(0, 10, 'Page ' . $this->getPageNo(), 0, 0, 'C'); * } * } * </code> * * @see header() */ function footer() { /* To be implemented in your own inherited class. */ } /** * Returns the current page number. * * @return integer * * @see aliasNbPages() */ function getPageNo() { return $this->_page; } /** * Sets the fill 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 * 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 setTextColor() * @see setDrawColor() * @see rect() * @see cell() * @see multiCell() */ function setFillColor($cs = 'rgb', $c1, $c2 = 0, $c3 = 0, $c4 = 0) { $cs = strtolower($cs); if ($cs == 'rgb') { $this->_fill_color = sprintf('%.3' . FILE_PDF_FLOAT . ' %.3' . FILE_PDF_FLOAT . ' %.3' . FILE_PDF_FLOAT . ' rg', $c1, $c2, $c3); } elseif ($cs == 'cmyk') { $this->_fill_color = sprintf('%.3' . FILE_PDF_FLOAT . ' %.3' . FILE_PDF_FLOAT . ' %.3' . FILE_PDF_FLOAT . ' %.3' . FILE_PDF_FLOAT . ' k', $c1, $c2, $c3, $c4); } else { $this->_fill_color = sprintf('%.3' . FILE_PDF_FLOAT . ' g', $c1); } if ($this->_page > 0) { $this->_out($this->_fill_color); } $this->_color_flag = $this->_fill_color != $this->_text_color; } /** * Sets the 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 * 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. * * @since File_PDF 0.2.0 * @since Horde 3.2 * @see setFillColor() * @see setDrawColor() * @see rect() * @see cell() * @see multiCell() */ function setTextColor($cs, $c1, $c2 = 0, $c3 = 0, $c4 = 0) { $cs = strtolower($cs); if ($cs == 'rgb') { $this->_text_color = sprintf('%.3' . FILE_PDF_FLOAT . ' %.3' . FILE_PDF_FLOAT . ' %.3' . FILE_PDF_FLOAT . ' rg', $c1, $c2, $c3); } elseif ($cs == 'cmyk') { $this->_text_color = sprintf('%.3' . FILE_PDF_FLOAT . ' %.3' . FILE_PDF_FLOAT . ' %.3' . FILE_PDF_FLOAT . ' %.3' . FILE_PDF_FLOAT . ' k', $c1, $c2, $c3, $c4); } else { $this->_text_color = sprintf('%.3' . FILE_PDF_FLOAT . ' g', $c1); } $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 setFillColor() * @see line() * @see rect() * @see cell() * @see multiCell() */ function setDrawColor($cs = 'rgb', $c1, $c2 = 0, $c3 = 0, $c4 = 0) { $cs = strtolower($cs); if ($cs == 'rgb') { $this->_draw_color = sprintf('%.3' . FILE_PDF_FLOAT . ' %.3' . FILE_PDF_FLOAT . ' %.3' . FILE_PDF_FLOAT . ' RG', $c1, $c2, $c3); } elseif ($cs == 'cmyk') { $this->_draw_color = sprintf('%.3' . FILE_PDF_FLOAT . ' %.3' . FILE_PDF_FLOAT . ' %.3' . FILE_PDF_FLOAT . ' %.3' . FILE_PDF_FLOAT . ' K', $c1, $c2, $c3, $c4); } else { $this->_draw_color = sprintf('%.3' . FILE_PDF_FLOAT . ' G', $c1); } if ($this->_page > 0) { $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 Whether the width should be returned in points or * user units. * * @return float */ function getStringWidth($text, $pt = false) { $text = (string)$text; $width = 0; $length = strlen($text); 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'][' ']; if ($pt) { return $width * $this->_font_size_pt / 1000; } else { 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 line() * @see rect() * @see cell() * @see multiCell() */ function setLineWidth($width) { $this->_line_width = $width; if ($this->_page > 0) { $this->_out(sprintf('%.2' . FILE_PDF_FLOAT . ' 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 setLineWidth() * @see setDrawColor() */ function line($x1, $y1, $x2, $y2) { if ($x1 < 0) { $x1 += $this->w; } if ($y1 < 0) { $y1 += $this->h; } if ($x2 < 0) { $x2 += $this->w; } if ($y2 < 0) { $y2 += $this->h; } $this->_out(sprintf('%.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' m %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' 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 border) or both. * * 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) * - F: fill * - DF or FD: draw and fill * * @see setLineWidth() * @see setDrawColor() * @see setFillColor() */ function rect($x, $y, $width, $height, $style = '') { if ($x < 0) { $x += $this->w; } if ($y < 0) { $y += $this->h; } $style = strtoupper($style); if ($style == 'F') { $op = 'f'; } elseif ($style == 'FD' || $style == 'DF') { $op = 'B'; } else { $op = 'S'; } $x = $this->_toPt($x); $y = $this->_toPt($y); $width = $this->_toPt($width); $height = $this->_toPt($height); $this->_out(sprintf('%.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' re %s', $x, $this->hPt - $y, $width, -$height, $op)); } /** * Outputs a circle. It can be drawn (border only), filled (with no * border) or both. * * 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) * - F: fill * - DF or FD: draw and fill */ function circle($x, $y, $r, $style = '') { if ($x < 0) { $x += $this->w; } if ($y < 0) { $y += $this->h; } $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. } $x = $this->_toPt($x); $y = $this->_toPt($y); $r = $this->_toPt($r); /* Invert the y scale. */ $y = $this->hPt - $y; /* Length of the Bezier control. */ $b = $r * 0.552; /* Move from the given origin and set the current point * to the start of the first Bezier curve. */ $c = sprintf('%.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' m', $x - $r, $y); $x = $x - $r; /* First circle quarter. */ $c .= sprintf(' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' 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(' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' 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(' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' 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(' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' c %s', $x - $b, $y, $x - $r, $y + $r - $b, $x - $r, $y + $r, $op); /* Output the whole string. */ $this->_out($c); } /** * Imports a TrueType or Type1 font and makes it available. It is * necessary to generate a font definition file first with the * makefont.php utility. * The location of the definition file (and the font file itself when * embedding) must be found at the full path name included. * * Example: * <code> * $pdf->addFont('Comic', 'I'); * is equivalent to: * $pdf->addFont('Comic', 'I', 'comici.php'); * </code> * * @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 * insensitive): * - empty string: regular (default) * - B: bold * - I: italic * - 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 * with no space. * * @see setFont() */ function addFont($family, $style = '', $file = '') { $family = strtolower($family); if ($family == 'arial') { $family = 'helvetica'; } $style = strtoupper($style); if ($style == 'IB') { $style = 'BI'; } if (isset($this->_fonts[$family . $style])) { return $this->raiseError(sprintf('Font already added: %s %s', $family, $style)); } if ($file == '') { $file = str_replace(' ', '', $family) . strtolower($style) . '.php'; } include($file); if (!isset($name)) { 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); if ($diff) { /* Search existing encodings. */ $d = 0; $nb = count($this->_diffs); for ($i = 1; $i <= $nb; $i++) { if ($this->_diffs[$i] == $diff) { $d = $i; break; } } if ($d == 0) { $d = $nb + 1; $this->_diffs[$d] = $diff; } $this->_fonts[$family . $style]['diff'] = $d; } if ($file) { if ($type == 'TrueType') { $this->_font_files[$file] = array('length1' => $originalsize); } else { $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 {@link 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 * {@link setFontSize()}. * * @param string $family Family font. It can be either a name defined by * {@link addFont()} or 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 string $style Font style. Possible values are (case * insensitive): * - empty string: regular * - B: bold * - I: italic * - U: underline * or any combination. Bold and italic styles do not * apply to Symbol and ZapfDingbats. * @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 * is 12. * @param boolean $force Force the setting of the font. Each new page will * require a new call to {@link setFont()} and * settings this to true will make sure that the * checks for same font calls will be skipped. * * @see addFont() * @see setFontSize() * @see cell() * @see multiCell() * @see write() */ function setFont($family, $style = '', $size = null, $force = false) { $family = strtolower($family); if (empty($family)) { $family = $this->_font_family; } if ($family == 'arial') { /* Use helvetica instead of arial. */ $family = 'helvetica'; } elseif ($family == 'symbol' || $family == 'zapfdingbats') { /* These two fonts do not have styles available. */ $style = ''; } $style = strtoupper($style); /* 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; $style = str_replace('U', '', $style); } else { $this->_underline = false; } if ($style == 'IB') { $style = 'BI'; } /* If no size specified, use current size. */ if (is_null($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) { return; } /* Set the font key. */ $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')) { return $font_widths; } $i = count($this->_fonts) + 1; $this->_fonts[$fontkey] = array( 'i' => $i, 'type' => 'core', 'name' => $this->_core_fonts[$fontkey], 'up' => -100, 'ut' => 50, '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. */ if ($this->_page > 0) { $this->_out(sprintf('BT /F%d %.2' . FILE_PDF_FLOAT . ' Tf ET', $this->_current_font['i'], $this->_font_size_pt)); } } /** * Defines the size of the current font. * * @param float $size The size (in points). * * @see setFont() */ function setFontSize($size) { /* If the font size is already the current font size, just return. */ if ($this->_font_size_pt == $size) { return; } /* Set the current font size, both in points and scaled to user * units. */ $this->_font_size_pt = $size; $this->_font_size = $size / $this->_scale; /* Output font information if at least one page has been defined. */ if ($this->_page > 0) { $this->_out(sprintf('BT /F%d %.2' . FILE_PDF_FLOAT . ' Tf ET', $this->_current_font['i'], $this->_font_size_pt)); } } /** * Defines the style of the current font. * * @param string $style The font style. * * @since File_PDF 0.2.0 * @since Horde 3.2 * @see setFont() */ function setFontStyle($style) { return $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 document. * * The identifier can then be passed to {@link cell()}, {@link()} write, * {@link image()} or {@link link()}. The destination is defined with * {@link setLink()}. * * @see cell() * @see write() * @see image() * @see link() * @see setLink() */ function addLink() { $n = count($this->_links) + 1; $this->_links[$n] = array(0, 0); return $n; } /** * Defines the page and position a link points to. * * @param integer $link The link identifier returned by {@link addLink()}. * @param float $y Ordinate of target position; -1 indicates the * current position. The default value is 0 (top of * page). * @param integer $page Number of target page; -1 indicates the current * page. * * @see addLink() */ function setLink($link, $y = 0, $page = -1) { if ($y == -1) { $y = $this->y; } if ($page == -1) { $page = $this->_page; } $this->_links[$link] = array($page, $y); } /** * Puts a link on a rectangular area of the page. * * Text or image links are generally put via {@link cell()}, {@link * write()} or {@link image()}, but this method can be useful for instance * to define a clickable area inside an image. * * 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 {@link addLink()}. * * @see addLink() * @see cell() * @see write() * @see image() */ function link($x, $y, $width, $height, $link) { if ($x < 0) { $x += $this->w; } if ($y < 0) { $y += $this->h; } /* Set up the coordinates with correct scaling in pt. */ $x = $this->_toPt($x); $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 {@link cell()}, {@link multiCell()} or {@link * write()} which are the standard methods to print text. * * 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 setFont() * @see cell() * @see multiCell() * @see write() */ function text($x, $y, $text) { if ($x < 0) { $x += $this->w; } if ($y < 0) { $y += $this->h; } /* Scale coordinates into points and set correct Y position. */ $x = $this->_toPt($x); $y = $this->hPt - $this->_toPt($y); /* Escape any potentially harmful characters. */ $text = $this->_escape($text); $out = sprintf('BT %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' 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); } $this->_out($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 * {@link setAutoPageBreak()}. * This method is called automatically and should not be called directly * by the application. * * @return boolean * * @see setAutoPageBreak() */ function acceptPageBreak() { 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 * margin. * @param float $height Cell height. * @param string $text String to print. * @param mixed $border Indicates if borders must be drawn around the * cell. The value can be either a number: * - 0: no border (default) * - 1: frame * or a string containing some or all of the * following characters (in any order): * - L: left * - T: top * - R: right * - B: bottom * @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 * - 2: below * Putting 1 is equivalent to putting 0 and calling * {@link newLine()} just after. * @param string $align Allows to center or align the text. Possible * values are: * - L or empty string: left (default) * - C: center * - R: right * @param integer $fill Indicates if the cell fill type. Possible values * are: * - 0: transparent (default) * - 1: painted * @param string $link URL or identifier returned by {@link addLink()}. * * @see setFont() * @see setDrawColor() * @see setFillColor() * @see setLineWidth() * @see addLink() * @see newLine() * @see multiCell() * @see write() * @see setAutoPageBreak() */ function cell($width, $height = 0, $text = '', $border = 0, $ln = 0, $align = '', $fill = 0, $link = '') { $k = $this->_scale; if ($this->y + $height > $this->_page_break_trigger && !$this->_in_footer && $this->acceptPageBreak()) { $x = $this->x; $ws = $this->_word_spacing; if ($ws > 0) { $this->_word_spacing = 0; $this->_out('0 Tw'); } $result = $this->addPage($this->_current_orientation); if (is_a($result, 'PEAR_Error')) { return $result; } $this->x = $x; if ($ws > 0) { $this->_word_spacing = $ws; $this->_out(sprintf('%.3' . FILE_PDF_FLOAT . ' Tw', $ws * $k)); } } if ($width == 0) { $width = $this->w - $this->_right_margin - $this->x; } $s = ''; if ($fill == 1 || $border == 1) { if ($fill == 1) { $op = ($border == 1) ? 'B' : 'f'; } else { $op = 'S'; } $s = sprintf('%.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' re %s ', $this->x * $k, ($this->h - $this->y) * $k, $width * $k, -$height * $k, $op); } if (is_string($border)) { if (strpos($border, 'L') !== false) { $s .= sprintf('%.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' m %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' 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('%.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' m %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' 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('%.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' m %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' 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('%.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' m %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' l S ', $this->x * $k, ($this->h - ($this->y + $height)) * $k, ($this->x + $width) * $k, ($this->h - ($this->y + $height)) * $k); } } if ($text != '') { if ($align == 'R') { $dx = $width - $this->_cell_margin - $this->getStringWidth($text); } elseif ($align == 'C') { $dx = ($width - $this->getStringWidth($text)) / 2; } else { $dx = $this->_cell_margin; } if ($this->_color_flag) { $s .= 'q ' . $this->_text_color . ' '; } $text = str_replace(')', '\\)', str_replace('(', '\\(', str_replace('\\', '\\\\', $text))); $test2 = ((.5 * $height) + (.3 * $this->_font_size)); $test1 = $this->fhPt - (($this->y + $test2) * $k); $x = ($this->x + $dx) * $k; $y = ($this->h - ($this->y + .5 * $height + .3 * $this->_font_size)) * $k; $s .= sprintf('BT %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' Td (%s) Tj ET', $x, $y, $text); if ($this->_underline) { $s .= ' ' . $this->_doUnderline($x, $y, $text); } if ($this->_color_flag) { $s .= ' Q'; } if ($link) { $this->link($this->x + $dx, $this->y + .5 * $height- .5 * $this->_font_size, $this->getStringWidth($text), $this->_font_size, $link); } } if ($s) { $this->_out($s); } $this->_last_height = $height; if ($ln > 0) { /* Go to next line. */ $this->y += $height; if ($ln == 1) { $this->x = $this->_left_margin; } } else { $this->x += $width; } } /** * 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, one below the other. 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 * margin of the page. * @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) * - 1: frame * or a string containing some or all of the * following characters (in any order): * - L: left * - T: top * - R: right * - B: bottom * @param string $align Sets the text alignment. Possible values are: * - L: left alignment * - C: center * - R: right alignment * - J: justification (default value) * @param integer $fill Indicates if the cell background must: * - 0: transparent (default) * - 1: painted * * @see setFont() * @see setDrawColor() * @see setFillColor() * @see setLineWidth() * @see cell() * @see write() * @see setAutoPageBreak() */ function multiCell($width, $height, $text, $border = 0, $align = 'J', $fill = 0) { $cw = &$this->_current_font['cw']; if ($width == 0) { $width = $this->w - $this->_right_margin - $this->x; } $wmax = ($width-2 * $this->_cell_margin) * 1000 / $this->_font_size; $s = str_replace("\r", '', $text); $nb = strlen($s); if ($nb > 0 && $s[$nb-1] == "\n") { $nb--; } $b = 0; if ($border) { if ($border == 1) { $border = 'LTRB'; $b = 'LRT'; $b2 = 'LR'; } else { $b2 = ''; if (strpos($border, 'L') !== false) { $b2 .= 'L'; } if (strpos($border, 'R') !== false) { $b2 .= 'R'; } $b = (strpos($border, 'T') !== false) ? $b2 . 'T' : $b2; } } $sep = -1; $i = 0; $j = 0; $l = 0; $ns = 0; $nl = 1; while ($i < $nb) { /* Get next character. */ $c = $s[$i]; if ($c == "\n") { /* Explicit line break. */ if ($this->_word_spacing > 0) { $this->_word_spacing = 0; $this->_out('0 Tw'); } $result = $this->cell($width, $height, substr($s, $j, $i-$j), $b, 2, $align, $fill); if (is_a($result, 'PEAR_Error')) { return $result; } $i++; $sep = -1; $j = $i; $l = 0; $ns = 0; $nl++; if ($border && $nl == 2) { $b = $b2; } continue; } if ($c == ' ') { $sep = $i; $ls = $l; $ns++; } $l += $cw[$c]; if ($l > $wmax) { /* Automatic line break. */ if ($sep == -1) { if ($i == $j) { $i++; } if ($this->_word_spacing > 0) { $this->_word_spacing = 0; $this->_out('0 Tw'); } $result = $this->cell($width, $height, substr($s, $j, $i - $j), $b, 2, $align, $fill); if (is_a($result, 'PEAR_Error')) { return $result; } } else { if ($align == 'J') { $this->_word_spacing = ($ns>1) ? ($wmax - $ls) / 1000 * $this->_font_size / ($ns - 1) : 0; $this->_out(sprintf('%.3' . FILE_PDF_FLOAT . ' Tw', $this->_word_spacing * $this->_scale)); } $result = $this->cell($width, $height, substr($s, $j, $sep - $j), $b, 2, $align, $fill); if (is_a($result, 'PEAR_Error')) { return $result; } $i = $sep + 1; } $sep = -1; $j = $i; $l = 0; $ns = 0; $nl++; if ($border && $nl == 2) { $b = $b2; } } else { $i++; } } /* Last chunk. */ if ($this->_word_spacing > 0) { $this->_word_spacing = 0; $this->_out('0 Tw'); } if ($border && strpos($border, 'B') !== false) { $b .= 'B'; } $result = $this->cell($width, $height, substr($s, $j, $i), $b, 2, $align, $fill); if (is_a($result, 'PEAR_Error')) { return $result; } $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. * * Example: * <code> * // Begin with regular font * $pdf->setFont('Arial', '', 14); * $pdf->write(5, 'Visit '); * // Then put a blue underlined link * $pdf->setTextColor(0, 0, 255); * $pdf->setFont('', 'U'); * $pdf->write(5, 'www.fpdf.org', 'http://www.fpdf.org'); * </code> * * @param float $height Line height. * @param string $text String to print. * @param mixed $link URL or identifier returned by {@link addLink()}. * * @see setFont() * @see addLink() * @see multiCell() * @see 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; $s = str_replace("\r", '', $text); $nb = strlen($s); $sep = -1; $i = 0; $j = 0; $l = 0; $nl = 1; while ($i < $nb) { /* Get next character. */ $c = $s{$i}; if ($c == "\n") { /* Explicit line break. */ $result = $this->cell($width, $height, substr($s, $j, $i - $j), 0, 2, '', 0, $link); if (is_a($result, 'PEAR_Error')) { return $result; } $i++; $sep = -1; $j = $i; $l = 0; if ($nl == 1) { $this->x = $this->_left_margin; $width = $this->w - $this->_right_margin - $this->x; $wmax = ($width - 2 * $this->_cell_margin) * 1000 / $this->_font_size; } $nl++; continue; } if ($c == ' ') { $sep = $i; $ls = $l; } $l += (isset($cw[$c]) ? $cw[$c] : 0); if ($l > $wmax) { /* Automatic line break. */ if ($sep == -1) { if ($this->x > $this->_left_margin) { /* Move to next line. */ $this->x = $this->_left_margin; $this->y += $height; $width = $this->w - $this->_right_margin - $this->x; $wmax = ($width - 2 * $this->_cell_margin) * 1000 / $this->_font_size; $i++; $nl++; continue; } if ($i == $j) { $i++; } $result = $this->cell($width, $height, substr($s, $j, $i - $j), 0, 2, '', 0, $link); if (is_a($result, 'PEAR_Error')) { return $result; } } else { $result = $this->cell($width, $height, substr($s, $j, $sep - $j), 0, 2, '', 0, $link); if (is_a($result, 'PEAR_Error')) { return $result; } $i = $sep + 1; } $sep = -1; $j = $i; $l = 0; if ($nl == 1) { $this->x = $this->_left_margin; $width = $this->w - $this->_right_margin - $this->x; $wmax = ($width - 2 * $this->_cell_margin) * 1000 / $this->_font_size; } $nl++; } else { $i++; } } /* Last chunk. */ if ($i != $j) { $result = $this->cell($l / 1000 * $this->_font_size, $height, substr($s, $j, $i), 0, 0, '', 0, $link); if (is_a($result, 'PEAR_Error')) { return $result; } } } /** * 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. * * @see setFont() */ function writeRotated($x, $y, $text, $text_angle, $font_angle = 0) { if ($x < 0) { $x += $this->w; } if ($y < 0) { $y += $this->h; } /* Escape text. */ $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 %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' 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'; } $this->_out($s); } /** * 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: * - gray scales * - true colors (24 bits) * - CMYK (32 bits) * * For PNG, are allowed: * - gray scales on at most 8 bits (256 levels) * - indexed colors * - true colors (24 bits) * but are not supported: * - Interlacing * - Alpha channel * * 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 * extension. * It is possible to put a link on the image. * * Remark: if an image is used several times, only one copy will be * embedded in the file. * * @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 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 {@link addLink()}. * * @see addLink() */ function image($file, $x, $y, $width = 0, $height = 0, $type = '', $link = '') { if ($x < 0) { $x += $this->w; } if ($y < 0) { $y += $this->h; } if (!isset($this->_images[$file])) { /* First use of image, get some file info. */ if ($type == '') { $pos = strrpos($file, '.'); if ($pos === false) { return $this->raiseError(sprintf('Image file has no extension and no type was specified: %s', $file)); } $type = substr($file, $pos + 1); } $type = strtolower($type); $mqr = get_magic_quotes_runtime(); set_magic_quotes_runtime(0); if ($type == 'jpg' || $type == 'jpeg') { $info = $this->_parseJPG($file); } elseif ($type == 'png') { $info = $this->_parsePNG($file); } else { return $this->raiseError(sprintf('Unsupported image file type: %s', $type)); } if (is_a($info, 'PEAR_Error')) { return $info; } set_magic_quotes_runtime($mqr); $info['i'] = count($this->_images) + 1; $this->_images[$file] = $info; } else { $info = $this->_images[$file]; } /* Make sure all vars are converted to pt scale. */ $x = $this->_toPt($x); $y = $this->hPt - $this->_toPt($y); $width = $this->_toPt($width); $height = $this->_toPt($height); /* If not specified do automatic width and height calculations. */ 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 %.2' . FILE_PDF_FLOAT . ' 0 0 %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' cm /I%d Do Q', $width, $height, $x, $y - $height, $info['i'])); /* Set any link if requested. */ if ($link) { $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. * * @see cell() */ function newLine($height = '') { $this->x = $this->_left_margin; if (is_string($height)) { $this->y += $this->_last_height; } else { $this->y += $height; } } /** * Returns the abscissa of the current position in user units. * * @return float * * @see setX() * @see getY() * @see setY() */ function getX() { return $this->x; } /** * 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. * * @see getX() * @see getY() * @see setY() * @see setXY() */ function setX($x) { if ($x >= 0) { /* Absolute value. */ $this->x = $x; } else { /* Negative, so relative to right edge of the page. */ $this->x = $this->w + $x; } } /** * Returns the ordinate of the current position in user units. * * @return float * * @see setY() * @see getX() * @see setX() */ function getY() { return $this->y; } /** * 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. * * @see getX() * @see getY() * @see setY() * @see setXY() */ function setY($y) { if ($y >= 0) { /* Absolute value. */ $this->y = $y; } else { /* 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. * * @see setX() * @see setY() */ function setXY($x, $y) { $this->setY($y); $this->setX($x); } /** * Returns the current buffer content and resets the buffer. * * Use this method when creating large files to avoid memory problems. * This method doesn't work in combination with the output() or save() * methods, use getOutput() at the end. Calling this method doubles the * memory usage during the call. * * @since File_PDF 0.2.0 * @since Horde 3.2 * @see getOutput() */ function flush() { // Make sure we have the file header. $this->_beginDoc(); $buffer = $this->_buffer; $this->_buffer = ''; $this->_flushed = true; $this->_buflen += strlen($buffer); return $buffer; } /** * Returns the raw PDF file. * * @see output() * @see flush() */ function getOutput() { /* Check whether file has been closed. */ if ($this->_state < 3) { $result = $this->close(); if (is_a($result, 'PEAR_Error')) { return $result; } } return $this->_buffer; } /** * Sends 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 the buffer has been flushed already. */ if ($this->_flushed) { return $this->raiseError('The buffer has been flushed already, don\'t use output() in combination with flush().'); } /* Check whether file has been closed. */ if ($this->_state < 3) { $result = $this->close(); if (is_a($result, 'PEAR_Error')) { return $result; } } /* Check if headers have been sent. */ if (headers_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_INLINE : HTTP_DOWNLOAD_ATTACHMENT; $params = array('data' => $this->_buffer, 'contenttype' => 'application/pdf', 'contentdisposition' => array($disposition, $filename)); /* Output the file. */ return HTTP_Download::staticSend($params); } /** * Saves the PDF file on the filesystem. * * @param string $filename The filename for the output file. */ function save($filename = 'unknown.pdf') { /* Check whether the buffer has been flushed already. */ if ($this->_flushed) { return $this->raiseError('The buffer has been flushed already, don\'t use save() in combination with flush().'); } /* Check whether file has been closed. */ if ($this->_state < 3) { $result = $this->close(); if (is_a($result, 'PEAR_Error')) { return $result; } } $f = fopen($filename, 'wb'); if (!$f) { return $this->raiseError(sprintf('Unable to save PDF file: %s', $filename)); } fwrite($f, $this->_buffer, strlen($this->_buffer)); fclose($f); } function _toPt($val) { return $val * $this->_scale; } function _getFontFile($fontkey, $path = '') { static $font_widths = array(); if (!isset($font_widths[$fontkey])) { if (!empty($path)) { $file = $path . strtolower($fontkey) . '.php'; } else { $file = dirname(__FILE__) . '/PDF/fonts/' . strtolower($fontkey) . '.php'; } include $file; if (!isset($font_widths[$fontkey])) { return $this->raiseError(sprintf('Could not include font metric file: %s', $file)); } } return $font_widths; } function _link($x, $y, $width, $height, $link) { /* Save link to page links array. */ $this->_page_links[$this->_page][] = array($x, $y, $width, $height, $link); } function _beginDoc() { /* Start document, but only if not yet started. */ if ($this->_state < 1) { $this->_state = 1; $this->_out('%PDF-1.3'); } } function _putPages() { $nb = $this->_page; 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') { $wPt = $this->fwPt; $hPt = $this->fhPt; } else { $wPt = $this->fhPt; $hPt = $this->fwPt; } $filter = ($this->_compress) ? '/Filter /FlateDecode ' : ''; for ($n = 1; $n <= $nb; $n++) { /* Page */ $this->_newobj(); $this->_out('<</Type /Page'); $this->_out('/Parent 1 0 R'); if (isset($this->_orientation_changes[$n])) { $this->_out(sprintf('/MediaBox [0 0 %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ']', $hPt, $wPt)); } $this->_out('/Resources 2 0 R'); if (isset($this->_page_links[$n])) { /* Links */ $annots = '/Annots ['; foreach ($this->_page_links[$n] as $pl) { $rect = sprintf('%.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . '', $pl[0], $pl[1], $pl[0] + $pl[2], $pl[1] - $pl[3]); $annots .= '<</Type /Annot /Subtype /Link /Rect [' . $rect . '] /Border [0 0 0] '; if (is_string($pl[4])) { $annots .= '/A <</S /URI /URI ' . $this->_textString($pl[4]) . '>>>>'; } else { $l = $this->_links[$pl[4]]; $height = isset($this->_orientation_changes[$l[0]]) ? $wPt : $hPt; $annots .= sprintf('/Dest [%d 0 R /XYZ 0 %.2' . FILE_PDF_FLOAT . ' null]>>', 1 + 2 * $l[0], $height - $l[1] * $this->_scale); } } $this->_out($annots . ']'); } $this->_out('/Contents ' . ($this->_n + 1) . ' 0 R>>'); $this->_out('endobj'); /* Page content */ $p = ($this->_compress) ? gzcompress($this->_pages[$n]) : $this->_pages[$n]; $this->_newobj(); $this->_out('<<' . $filter . '/Length ' . strlen($p) . '>>'); $this->_putStream($p); $this->_out('endobj'); } /* Pages root */ $this->_offsets[1] = $this->_buflen + strlen($this->_buffer); $this->_out('1 0 obj'); $this->_out('<</Type /Pages'); $kids = '/Kids ['; 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 %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ']', $wPt, $hPt)); $this->_out('>>'); $this->_out('endobj'); } function _putFonts() { $nf = $this->_n; foreach ($this->_diffs as $diff) { /* Encodings */ $this->_newobj(); $this->_out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [' . $diff . ']>>'); $this->_out('endobj'); } $mqr = get_magic_quotes_runtime(); set_magic_quotes_runtime(0); foreach ($this->_font_files as $file => $info) { /* Font file embedding. */ $this->_newobj(); $this->_font_files[$file]['n'] = $this->_n; $size = filesize($file); if (!$size) { return $this->raiseError('Font file not found'); } $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->_out('>>'); $f = fopen($file, 'rb'); $this->_putStream(fread($f, $size)); fclose($f); $this->_out('endobj'); } set_magic_quotes_runtime($mqr); foreach ($this->_fonts as $k => $font) { /* Font objects */ $this->_newobj(); $this->_fonts[$k]['n'] = $this->_n; $name = $font['name']; $this->_out('<</Type /Font'); $this->_out('/BaseFont /' . $name); if ($font['type'] == 'core') { /* Standard font. */ $this->_out('/Subtype /Type1'); if ($name != 'Symbol' && $name != 'ZapfDingbats') { $this->_out('/Encoding /WinAnsiEncoding'); } } else { /* Additional font. */ $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 ($font['enc']) { if (isset($font['diff'])) { $this->_out('/Encoding ' . ($nf + $font['diff']) . ' 0 R'); } else { $this->_out('/Encoding /WinAnsiEncoding'); } } } $this->_out('>>'); $this->_out('endobj'); if ($font['type'] != 'core') { /* Widths. */ $this->_newobj(); $cw = &$font['cw']; $s = '['; for ($i = 32; $i <= 255; $i++) { $s .= $cw[chr($i)] . ' '; } $this->_out($s . ']'); $this->_out('endobj'); /* Descriptor. */ $this->_newobj(); $s = '<</Type /FontDescriptor /FontName /' . $name; foreach ($font['desc'] as $k => $v) { $s .= ' /' . $k . ' ' . $v; } $file = $font['file']; if ($file) { $s .= ' /FontFile' . ($font['type'] == 'Type1' ? '' : '2') . ' ' . $this->_font_files[$file]['n'] . ' 0 R'; } $this->_out($s . '>>'); $this->_out('endobj'); } } } function _putImages() { $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']); $this->_out('/Height ' . $info['h']); if ($info['cs'] == 'Indexed') { $this->_out('/ColorSpace [/Indexed /DeviceRGB ' . (strlen($info['pal'])/3 - 1) . ' ' . ($this->_n + 1) . ' 0 R]'); } else { $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'])) { $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']); $this->_out('endobj'); /* Palette. */ if ($info['cs'] == 'Indexed') { $this->_newobj(); $pal = ($this->_compress) ? gzcompress($info['pal']) : $info['pal']; $this->_out('<<' . $filter . '/Length ' . strlen($pal) . '>>'); $this->_putStream($pal); $this->_out('endobj'); } } } function _putResources() { $this->_putFonts(); $this->_putImages(); /* Resource dictionary */ $this->_offsets[2] = $this->_buflen + 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)) { $this->_out('/XObject <<'); foreach ($this->_images as $image) { $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R'); } $this->_out('>>'); } $this->_out('>>'); $this->_out('endobj'); } function _putInfo() { $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'))); } function _putCatalog() { $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]'); } elseif (!is_string($this->_zoom_mode)) { $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'); } } function _putTrailer() { $this->_out('/Size ' . ($this->_n + 1)); $this->_out('/Root ' . $this->_n . ' 0 R'); $this->_out('/Info ' . ($this->_n - 1) . ' 0 R'); } function _endDoc() { $this->_putPages(); $this->_putResources(); /* Info */ $this->_newobj(); $this->_out('<<'); $this->_putInfo(); $this->_out('>>'); $this->_out('endobj'); /* Catalog */ $this->_newobj(); $this->_out('<<'); $this->_putCatalog(); $this->_out('>>'); $this->_out('endobj'); /* Cross-ref */ $o = $this->_buflen + strlen($this->_buffer); $this->_out('xref'); $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])); } /* Trailer */ $this->_out('trailer'); $this->_out('<<'); $this->_putTrailer(); $this->_out('>>'); $this->_out('startxref'); $this->_out($o); $this->_out('%%EOF'); $this->_state = 3; } function _beginPage($orientation) { $this->_page++; $this->_pages[$this->_page] = ''; $this->_state = 2; $this->x = $this->_left_margin; $this->y = $this->_top_margin; $this->_last_height = 0; /* Page orientation */ if (!$orientation) { $orientation = $this->_default_orientation; } else { $orientation = strtoupper($orientation[0]); if ($orientation != $this->_default_orientation) { $this->_orientation_changes[$this->_page] = true; } } if ($orientation != $this->_current_orientation) { /* Change orientation */ if ($orientation == 'P') { $this->wPt = $this->fwPt; $this->hPt = $this->fhPt; $this->w = $this->fw; $this->h = $this->fh; } else { $this->wPt = $this->fhPt; $this->hPt = $this->fwPt; $this->w = $this->fh; $this->h = $this->fw; } $this->_page_break_trigger = $this->h - $this->_break_margin; $this->_current_orientation = $orientation; } } function _endPage() { /* End of page contents */ $this->_state = 1; } function _newobj() { /* Begin a new object */ $this->_n++; $this->_offsets[$this->_n] = $this->_buflen + strlen($this->_buffer); $this->_out($this->_n . ' 0 obj'); } function _doUnderline($x, $y, $text) { /* Set the rectangle width according to text width. */ $width = $this->getStringWidth($text, true); /* 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('%.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' %.2' . FILE_PDF_FLOAT . ' re f', $x, $y, $width, $height); } function _parseJPG($file) { /* Extract info from a JPEG file. */ $img = @getimagesize($file); if (!$img) { return $this->raiseError(sprintf('Missing or incorrect image file: %s', $file)); } if ($img[2] != 2) { return $this->raiseError(sprintf('Not a JPEG file: %s', $file)); } 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 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); } function _parsePNG($file) { /* Extract info from a PNG file. */ $f = fopen($file, 'rb'); if (!$f) { return $this->raiseError(sprintf('Unable to open image file: %s', $file)); } /* Check signature. */ if (fread($f, 8) != chr(137) . 'PNG' . chr(13) . chr(10) . chr(26) . chr(10)) { return $this->raiseError(sprintf('Not a PNG file: %s', $file)); } /* Read header chunk. */ fread($f, 4); if (fread($f, 4) != 'IHDR') { return $this->raiseError(sprintf('Incorrect PNG file: %s', $file)); } $width = $this->_freadInt($f); $height = $this->_freadInt($f); $bpc = ord(fread($f, 1)); if ($bpc > 8) { return $this->raiseError(sprintf('16-bit depth not supported: %s', $file)); } $ct = ord(fread($f, 1)); if ($ct == 0) { $colspace = 'DeviceGray'; } elseif ($ct == 2) { $colspace = 'DeviceRGB'; } elseif ($ct == 3) { $colspace = 'Indexed'; } else { return $this->raiseError(sprintf('Alpha channel not supported: %s', $file)); } if (ord(fread($f, 1)) != 0) { return $this->raiseError(sprintf('Unknown compression method: %s', $file)); } if (ord(fread($f, 1)) != 0) { return $this->raiseError(sprintf('Unknown filter method: %s', $file)); } if (ord(fread($f, 1)) != 0) { return $this->raiseError(sprintf('Interlacing not supported: %s', $file)); } fread($f, 4); $parms = '/DecodeParms <</Predictor 15 /Colors ' . ($ct == 2 ? 3 : 1) . ' /BitsPerComponent ' . $bpc . ' /Columns ' . $width . '>>'; /* Scan chunks looking for palette, transparency and image data. */ $pal = ''; $trns = ''; $data = ''; do { $n = $this->_freadInt($f); $type = fread($f, 4); if ($type == 'PLTE') { /* Read palette */ $pal = fread($f, $n); fread($f, 4); } elseif ($type == 'tRNS') { /* Read transparency info */ $t = fread($f, $n); if ($ct == 0) { $trns = array(ord(substr($t, 1, 1))); } elseif ($ct == 2) { $trns = array(ord(substr($t, 1, 1)), ord(substr($t, 3, 1)), ord(substr($t, 5, 1))); } else { $pos = strpos($t, chr(0)); if (is_int($pos)) { $trns = array($pos); } } fread($f, 4); } elseif ($type == 'IDAT') { /* Read image data block */ $data .= fread($f, $n); fread($f, 4); } elseif ($type == 'IEND') { break; } else { fread($f, $n + 4); } } while ($n); if ($colspace == 'Indexed' && empty($pal)) { return $this->raiseError(sprintf('Missing palette in: %s', $file)); } fclose($f); return array('w' => $width, 'h' => $height, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'FlateDecode', 'parms' => $parms, 'pal' => $pal, 'trns' => $trns, 'data' => $data); } function _freadInt($f) { /* Read a 4-byte integer from file. */ $i = ord(fread($f, 1)) << 24; $i += ord(fread($f, 1)) << 16; $i += ord(fread($f, 1)) << 8; $i += ord(fread($f, 1)); return $i; } function _textString($s) { /* Format a text string */ return '(' . $this->_escape($s) . ')'; } function _escape($s) { /* Add \ before \, ( and ) */ return str_replace(array('\\', ')', '('), array('\\\\', '\\)', '\\('), $s); } function _putStream($s) { $this->_out('stream'); $this->_out($s); $this->_out('endstream'); } function _out($s) { /* Add a line to the document. */ if ($this->_state == 2) { $this->_pages[$this->_page] .= $s . "\n"; } else { $this->_buffer .= $s . "\n"; } } }
Close