0byt3m1n1
Path:
/
data
/
applications
/
aps.bak
/
phprojekt
/
6.0.6-0
/
standard
/
htdocs
/
library
/
Phprojekt
/
Pdf
/
[
Home
]
File: Page.php
<?php /** * Phprojekt Class for PFD creation. * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 3 as published by the Free Software Foundation * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * @category PHProjekt * @package Phprojekt * @subpackage Pdf * @copyright Copyright (c) 2010 Mayflower GmbH (http://www.mayflower.de) * @license LGPL v3 (See LICENSE file) * @link http://www.phprojekt.com * @since File available since Release 6.0 * @version Release: 6.0.6 * @author Alesia Khizhko <alesia.khizhko@mayflower.de> */ /** Zend_Pdf */ require_once 'Zend/Pdf.php'; /** * Phprojekt Class for PFD creation. * * @category PHProjekt * @package Phprojekt * @subpackage Pdf * @copyright Copyright (c) 2010 Mayflower GmbH (http://www.mayflower.de) * @license LGPL v3 (See LICENSE file) * @link http://www.phprojekt.com * @since File available since Release 6.0 * @version Release: 6.0.6 * @author Alesia Khizhko <alesia.khizhko@mayflower.de> */ class Phprojekt_Pdf_Page extends Zend_Pdf_Page { /** * pt/cm equals 72 pt/in / 2.54 cm/in. */ const PT_PER_CM = 28.346456692913385826771653543307; const DEFAULT_FONT_SIZE = 10; const HEADER_GRAY_LEVEL = 0.9; /** * Default border values. * * @var float */ public $borderLeft = 30; public $borderRight = 30; public $borderTop = 30; public $borderBottom = 30; /** * Default position X of the next element in the page. * * @var float */ public $freeLineX = 30; /** * Default position Y of the next element in the page. * * @var float */ public $freeLineY = 30; /** * Default text width for freetext in point. * * NULL acts as a default indicator. * * @var float */ public $textWidth = NULL; /** * Height of the line in text, in relation to font size. * * @var float */ public $lineHeight = 1.4; /** * Padding in the table in point. * * @var float */ public $tablePadding = 5; /** * Padding down for paragraphs in point. * * @var float */ public $paragraphPadding = 5; /** * Constructor. * * @param mixed $param1 * @param mixed $param2 * @param mixed $param3 * * @throws Zend_Pdf_Exception * * @return void */ public function __construct($param1, $param2 = NULL, $param3 = NULL) { parent::__construct($param1, $param2, $param3); if ($param1 instanceof Phprojekt_Pdf_Page && $param2 === null && $param3 === null) { // Clone additional properties $this->setBorder($param1->borderTop, $param1->borderRight, $param1->borderBottom, $param1->borderLeft); } } /** * Define the used border space. * * @param float $top Top value. * @param float $right Right value. * @param float $bottom Borrom value. * @param float $left Left value. * * @return void */ public function setBorder($top, $right = NULL, $bottom = NULL, $left = NULL) { if (is_null($left)) { $left = $right; } if (is_null($bottom)) { $bottom = $top; $left = $right; } if (is_null($right)) { $right = $top; $bottom = $top; $left = $top; } $this->borderTop = $top; $this->borderRight = $right; $this->borderBottom = $bottom; $this->borderLeft = $left; $this->freeLineX = $this->borderLeft; $this->freeLineY = $this->borderTop; } /** * Function inserts table with given rows to pdf pages. * * @param array $tableInfo specifies table for the PDF. * E.g. array( * 'type' =>'table', * 'startX'=> 35, * 'startY'=> 60, * 'rows' => array( * array(array('text' => 'first column', 'width' => 150), * array('text' => 'second column', 'width' => 100), * ), * array(...), * ) * ), * @param Phprojekt_Pdf_Page $currentPage Current page. * @param string $encoding Encoding of the text string $str, UTF-8 by default. * * @return array Array of Phprojekt_Pdf_Page. */ public function addTable($tableInfo, $currentPage = NULL, $encoding = 'UTF-8') { if (is_null($currentPage)) { $currentPage = $this; } if (!isset($tableInfo['rows'])) { throw new Exception("Missing data"); } if (isset($tableInfo['fontSize'])) { $fontSizeChangeRate = $tableInfo['fontSize'] - $currentPage->getFontSize(); $currentPage->freeLineY += $fontSizeChangeRate * $this->lineHeight; $currentPage->setFont($this->getFont(), $tableInfo['fontSize']); } $startX = isset($tableInfo['startX']) ? $tableInfo['startX'] : $this->borderLeft; $startY = (isset($tableInfo['startY']) ? $tableInfo['startY'] : ($this->freeLineY != $this->borderTop ? $this->freeLineY : $this->borderTop)); if (empty($tableInfo['rows']) || !is_array($tableInfo['rows'])) { throw new Exception("Rows are empty"); } if (isset($tableInfo['lineWidth'])) { $currentPage->setLineWidth($tableInfo['lineWidth']); } // Data is correct $table = new Phprojekt_Pdf_Table($currentPage, $startX, $startY); foreach ($tableInfo['rows'] as $row) { $tableRow = new Phprojekt_Pdf_Table_Row(); if (isset($row['isHeader']) && $row['isHeader']) { $tableRow->setHeader(); } foreach ($row as $cell) { if (!is_array($cell)) { continue; } // TODO: add validation for column data $column = new Phprojekt_Pdf_Table_Column(); $alignment = !empty($cell['align']) ? $cell['align'] : null; $column->setWidth($cell['width'])->setText($cell['text'], $encoding)->setAlignment($alignment); $tableRow->addColumn($column); } $table->addRow($tableRow); } $result = array($currentPage); $additionalPages = $table->render(); if (!empty($additionalPages)) { foreach ($additionalPages as $page) { $result[] = $page; } } return $result; } /** * Function inserts freetext into page. * * @param array $freetextInfo specifies free text for the PDF. * E.g. array( * 'type' =>'freetext', * 'startX'=> 35, * 'startY'=> 60, * 'lines' => array( * 'first line', * 'second line', * ), * 'fontSize' => 10, * ) * @param Phprojekt_Pdf_Page $currentPage Current page. * @param string $encoding Encoding of the text string $str, UTF-8 by default. * * @return Phprojekt_Pdf_Page An instance of Phprojekt_Pdf_Page. */ public function addFreetext($freetextInfo, $currentPage = NULL, $encoding = 'UTF-8') { if (is_null($currentPage)) { $currentPage = $this; } if (!isset($freetextInfo['lines'])) { throw new Exception("Missing data"); } // Change font size if (isset($freetextInfo['fontSize'])) { $fontSizeChangeRate = $freetextInfo['fontSize'] - $currentPage->getFontSize(); $currentPage->freeLineY += $fontSizeChangeRate * $this->lineHeight; $currentPage->setFont($this->getFont(), $freetextInfo['fontSize']); } $startX = isset($freetextInfo['startX']) ? $freetextInfo['startX'] : $this->borderLeft; $startY = (isset($freetextInfo['startY']) ? $freetextInfo['startY'] : ($this->freeLineY != $this->borderTop ? $this->freeLineY :$this->borderTop)) + $currentPage->getFontSize(); if (isset($freetextInfo['lineWidth'])) { $currentPage->setLineWidth($freetextInfo['lineWidth']); } if (isset($freetextInfo['width'])) { $this->textWidth = $freetextInfo['width']; } elseif (is_null($this->textWidth)) { $this->textWidth = $this->getWidth() - ($this->borderLeft + $this->borderRight); } $currentPage->drawMultilineText($freetextInfo['lines'], $startX, $startY, $this->textWidth, $encoding); return $currentPage; } /** * Function apply prototype of page (list of pdf tables and text lines). * * @param array $prototype Specifies form of elements in the PDF page. * E.g. array( * 'font' => 'Helvetica', * 'fontSize' => 10, * 0 => array( * 'type' =>'table', * 'startX'=> 35, * 'startY'=> 60, * 'rows' => array(...) * ), * 1 => array( * 'type' =>'freetext', * 'startX'=> 35, * 'startY'=> 100, * 'lines' => array('line1', 'line2') * ), * 2 => array( * 'type' =>'infoBox', * 'startX'=> 35, * 'startY'=> 100, * 'lines' => array('line1', 'line2'), * 'width' => 100, * 'height' => 100, * 'header' => 'Header' * ), * ) * @param string $encoding Encoding of the text string $str, UTF-8 by default. * * @return array Array of Phprojekt_Pdf_Page. */ public function parseTemplate($prototype, $encoding = 'UTF-8') { $pages = array($this); $currentPage = $this; $fontName = isset($prototype['font']) ? $prototype['font'] : Zend_Pdf_Font::FONT_HELVETICA; $fontSize = isset($prototype['fontSize']) ? $prototype['fontSize'] : self::DEFAULT_FONT_SIZE; $font = Zend_Pdf_Font::fontWithName($fontName); foreach ($prototype as $element) { if (!isset($element['type'])) { continue; } $currentPage->setFont($font, $fontSize); switch ($element['type']) { case 'table': $pages += $this->addTable($element, $currentPage, $encoding); $currentPage = end($pages); break; case 'freetext': $this->addFreetext($element, $currentPage, $encoding); break; } } return $pages; } /** * Add info box to the current page. * * @param string $header * @param array $lines Array of string. * @param integer $x * @param integer $y * @param integer $width * @param integer $height * @param string $encoding Encoding of the text string $str, UTF-8 by default. * * @return void */ public function drawInfoBox($header, $lines, $x, $y, $width, $height, $encoding = 'UTF-8') { $fontSize = $this->getFontSize(); // Draw the box $this->drawRectangle($x, $this->getHeight() - $y, $x + $width, $this->getHeight() - $y - $height, Zend_Pdf_Page::SHAPE_DRAW_STROKE); // Draw the header bottom $this->drawLine($x, $this->getHeight() - $y - ($fontSize * 2), $x + $width, $this->getHeight() - $y - ($fontSize * 2)); // Draw the header text $this->drawText($header, $x + ($fontSize / 2), $this->getHeight() - $y - $fontSize - ($fontSize / 4), $encoding); $this->drawMultilineText($lines, $x + 3, $y + ($fontSize * 3)); } /** * Add free text to the current page. * * @param array $lines Array of strings. * @param integer $x * @param integer $y * @param string $encoding Encoding of the text string $str, UTF-8 by default. * * @return void */ public function drawMultilineText($lines, $x, $y, $width, $encoding = 'UTF-8') { $y = $this->getHeight() - $y; $fontSize = $this->getFontSize(); $realLineCount = 0; if (!is_array($lines)) { $lines = array($lines); } $padding = 0; foreach ($lines as $line) { $parsedText = $this->getVariableText($line, $x, $y, $width); foreach ($parsedText['lines'] as $parsedLine) { list($str, $xTmp, $yTmp) = $parsedLine; $this->drawText(implode(' ', $str), $x + 2, $y - ($fontSize * $this->lineHeight * $realLineCount) - $padding, $encoding); $realLineCount++; } $padding += $this->paragraphPadding; } $this->freeLineY = $this->getHeight() - $y + ($fontSize * $this->lineHeight * $realLineCount) + $padding; } /** * Get size of cell in given font and font size. * * @param text $str * @param integer $x Start position X of the text. * @param integer $y Start position Y of the text. * @param integer $maxWidth Width of the column. * @param string $encoding Encoding of the text string $str, UTF-8 by default. * * @return array Amount of lines, width and height of the cell. */ public function getVariableText($str, $x, $y, $maxWidth, $encoding = 'UTF-8') { $y = $this->getHeight() - $y; $font = $this->getFont(); $fontSize = $this->getFontSize(); // Find out each word's width $words = explode(' ', $str); $wordsLength = array(); $em = $font->getUnitsPerEm(); $spaceSize = array_sum($font->widthsForGlyphs(array(ord(' ')))) / $em * $fontSize; foreach ($words as $i => $word) { $word .= ' '; $wordsLength[] = $this->_calculateTextWidth($word, $encoding); } // Push words onto lines to be drawn. $yInc = $y; $xInc = 0; $lines = array(); $line = array(); $i = 0; $maxLength = count($words); $paragraph = 0; while ($i < $maxLength) { // 10 - code of new line $wordsInside = explode(chr(10), $words[$i]); if (count($wordsInside) > 1) { // Add first word $firstWord = array_shift($wordsInside); $currentWordLength = $wordsLength[$i] * strlen($firstWord) / strlen($words[$i]); if (($xInc + $currentWordLength) > $maxWidth - 2 * $this->tablePadding) { $lines[] = array($line, $x, $yInc); $yInc -= $fontSize + $this->paragraphPadding; $xInc = $currentWordLength; $line = array(); $paragraph++; } $line[] = $firstWord; // Add other, each from new line foreach ($wordsInside as $word) { $currentWordLength = $wordsLength[$i] * strlen($word) / strlen($words[$i]); $lines[] = array($line, $x, $yInc); $yInc -= $fontSize; $xInc = $currentWordLength + $spaceSize; $line = array(); $line[] = $word; } $yInc -= $this->paragraphPadding; $paragraph++; } else { if (($xInc + $wordsLength[$i]) < $maxWidth - 2 * $this->tablePadding) { $xInc += $wordsLength[$i]; } else { $lines[] = array($line, $x, $yInc); $yInc -= $fontSize; $xInc = $wordsLength[$i]; $line = array(); } $line[] = $words[$i]; } $i++; } unset($wordsLength); $lines[] = array($line, $x, $yInc); return array('width' => $maxWidth, 'height' => ($fontSize * count($lines)) + $paragraph * $this->paragraphPadding, 'lines' => $lines); } /** * Add text in cell to the page. * * @param string $str * @param integer $x * @param integer $y * @param integer $maxWidth * @param string $align left, right or center. * @param string $encoding Encoding of the text string $str, UTF-8 by default. * * @return array */ public function drawVariableText($str, $x, $y, $maxWidth, $align = 'left', $encoding = 'UTF-8') { $text = $this->getVariableText($str, $x, $y, $maxWidth); foreach ($text['lines'] as $line) { list($str, $x, $y) = $line; $xPos = $x + $this->tablePadding; if ($align == 'right') { $length = $this->_calculateTextWidth(implode(' ', $str)); $xPos = $x + $maxWidth - $length - $this->tablePadding; } else if ($align == 'center') { $length = $this->_calculateTextWidth(implode(' ', $str)); $xPos = $x + ($maxWidth - $length) / 2; } $this->drawText(implode(' ', $str), $xPos, $y, $encoding); } return array('width' => $maxWidth, 'height' => $text['height']); } /** * Get text length in point. * * @param string $str * @param string $encoding Encoding of the text string $str, UTF-8 by default. * * @return integer */ protected final function _calculateTextWidth($str, $encoding = 'UTF-8') { $font = $this->getFont(); $fontSize = $this->getFontSize(); // Find out each word's width $em = $font->getUnitsPerEm(); $characters = array(); $drawingString = iconv($encoding, 'UTF-16BE', $str); for ($i = 0; $i < strlen($drawingString); $i++) { $characters[] = (ord($drawingString[$i++]) << 8) | ord($drawingString[$i]); } $glyphs = $font->glyphNumbersForCharacters($characters); return array_sum($font->widthsForGlyphs($glyphs)) / $em * $fontSize; } /** * Set paragraph padding down value. * * @param integer paragraphPadding value. * * @return void */ public function setParagraphPadding($value) { $this->paragraphPadding = $value; } /** * Set padding in table. * * @param integer $value tablePadding value. * * @return void */ public function setTablePadding($value) { $this->tablePadding = $value; } /** * Line height. * * @param integer $value lineHeight value. * * @return void */ public function setLineHeight($value) { $this->lineHeight = $value; } /** * Set free position coordinates. * * @param integer $x Position in pt. * @param integer $y Position in pt. * * @return void */ public function setStartPosition($x = null, $y = null) { if (!is_null($x)) { $this->freeLineX = $x; } else { $this->freeLineX = $this->borderLeft; } if (!is_null($y)) { $this->freeLineY = $y; } else { $this->freeLineY = $this->borderTop; } } }