1<?php 2 3/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 4 5/** 6 * Class for handling output in PDF format. 7 * 8 * Requires PHP extension PDFlib 9 * 10 * PHP versions 4 and 5 11 * 12 * LICENSE: This library is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU Lesser General Public License as published by 14 * the Free Software Foundation; either version 2.1 of the License, or (at your 15 * option) any later version. This library is distributed in the hope that it 16 * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 17 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 18 * General Public License for more details. You should have received a copy of 19 * the GNU Lesser General Public License along with this library; if not, write 20 * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 21 * 02111-1307 USA 22 * 23 * @category Images 24 * @package Image_Canvas 25 * @author Jesper Veggerby <pear.nosey@veggerby.dk> 26 * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen 27 * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 28 * @version CVS: $Id: PDF.php 287471 2009-08-18 23:12:01Z clockwerx $ 29 * @link http://pear.php.net/package/Image_Canvas 30 */ 31 32/** 33 * Include file Image/Canvas.php 34 */ 35require_once 'Image/Canvas.php'; 36 37/** 38 * Include file Image/Canvas/Color.php 39 */ 40require_once 'Image/Canvas/Color.php'; 41 42/** 43 * PDF Canvas class. 44 * 45 * @category Images 46 * @package Image_Canvas 47 * @author Jesper Veggerby <pear.nosey@veggerby.dk> 48 * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen 49 * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 50 * @version Release: @package_version@ 51 * @link http://pear.php.net/package/Image_Canvas 52 */ 53class Image_Canvas_PDF extends Image_Canvas 54{ 55 56 /** 57 * The PDF document 58 * @var resource 59 * @access private 60 */ 61 var $_pdf; 62 63 /** 64 * The major version of PDFlib 65 * @var int 66 * @access private 67 */ 68 var $_pdflib; 69 70 /** 71 * The font 72 * @var mixed 73 * @access private 74 */ 75 var $_pdfFont = false; 76 77 /** 78 * The width of the page 79 * @var int 80 * @access private 81 */ 82 var $_pageWidth; 83 84 /** 85 * The height of the page 86 * @var int 87 * @access private 88 */ 89 var $_pageHeight; 90 91 /** 92 * Create the PDF canvas. 93 * 94 * Parameters available: 95 * 96 * 'page' Specify the page/paper format for the graph's page, available 97 * formats are: A0, A1, A2, A3, A4, A5, A6, B5, letter, legal, ledger, 98 * 11x17, cd_front, inlay, inlay_nosides 99 * 100 * 'align' Alignment of the graph on the page, available options are: 101 * topleft, topcenter, topright, leftcenter, center, rightcenter, 102 * leftbottom, centerbottom, rightbottom 103 * 104 * 'orientation' Specifies the paper orientation, default is 'portrait' and 105 * 'landscape' is also supported. 106 * 107 * 'creator' The creator tag of the PDF/graph 108 * 109 * 'author' The author tag of the PDF/graph 110 * 111 * 'title' The title tag of the PDF/graph 112 * 113 * 'width' The width of the graph on the page 114 * 115 * 'height' The height of the graph on the page 116 * 117 * 'left' The left offset of the graph on the page 118 * 119 * 'top' The top offset of the graph on the page 120 * 121 * 'filename' The PDF file to open/add page to, using 'filename' requires 122 * the commercial version of PDFlib (http://www.pdflib.com/), this has for 123 * obvious ($ 450) reasons not been tested 124 * 125 * 'pdf' An existing PDFlib PDF document to add the page to 126 * 127 * 'add_page' (true/false) Used together with 'pdf', to specify whether the 128 * canvas should add a new graph page (true) or create the graph on the 129 * current page (false), default is 'true' 130 * 131 * The 'page' and 'width' & 'height' can be mutually omitted, if 'page' is 132 * omitted the page is created using dimensions of width x height, and if 133 * width and height are omitted the page dimensions are used for the graph. 134 * 135 * If 'pdf' is specified, 'filename', 'creator', 'author' and 'title' has no 136 * effect. 137 * 138 * 'left' and 'top' are overridden by 'align' 139 * 140 * It is required either to specify 'width' & 'height' or 'page'. 141 * 142 * The PDF format/PDFlib has some limitations on the capabilities, which 143 * means some functionality available using other canvass (fx. alpha 144 * blending and gradient fills) are not supported with PDF (see Canvas.txt 145 * in the docs/ folder for further details) 146 * 147 * @param array $param Parameter array 148 */ 149 function Image_Canvas_PDF($param) 150 { 151 if (isset($param['page'])) { 152 switch (strtoupper($param['page'])) { 153 case 'A0': 154 $this->_pageWidth = 2380; 155 $this->_pageHeight = 3368; 156 break; 157 158 case 'A1': 159 $this->_pageWidth = 1684; 160 $this->_pageHeight = 2380; 161 break; 162 163 case 'A2': 164 $this->_pageWidth = 1190; 165 $this->_pageHeight = 1684; 166 break; 167 168 case 'A3': 169 $this->_pageWidth = 842; 170 $this->_pageHeight = 1190; 171 break; 172 173 case 'A4': 174 $this->_pageWidth = 595; 175 $this->_pageHeight = 842; 176 break; 177 178 case 'A5': 179 $this->_pageWidth = 421; 180 $this->_pageHeight = 595; 181 break; 182 183 case 'A6': 184 $this->_pageWidth = 297; 185 $this->_pageHeight = 421; 186 break; 187 188 case 'B5': 189 $this->_pageWidth = 501; 190 $this->_pageHeight = 709; 191 break; 192 193 case 'LETTER': 194 $this->_pageWidth = 612; 195 $this->_pageHeight = 792; 196 break; 197 198 case 'LEGAL': 199 $this->_pageWidth = 612; 200 $this->_pageHeight = 1008; 201 break; 202 203 case 'LEDGER': 204 $this->_pageWidth = 1224; 205 $this->_pageHeight = 792; 206 break; 207 208 case '11X17': 209 $this->_pageWidth = 792; 210 $this->_pageHeight = 1224; 211 break; 212 213 case 'CD_FRONT': 214 $this->_pageWidth = 337; 215 $this->_pageHeight = 337; 216 break; 217 218 case 'INLAY': 219 $this->_pageWidth = 425; 220 $this->_pageHeight = 332; 221 break; 222 223 case 'INLAY_NOSIDES': 224 $this->_pageWidth = 390; 225 $this->_pageHeight = 332; 226 break; 227 } 228 } 229 230 if ((isset($param['orientation'])) && (strtoupper($param['orientation']) == 'LANDSCAPE')) { 231 $w = $this->_pageWidth; 232 $this->_pageWidth = $this->_pageHeight; 233 $this->_pageHeight = $w; 234 } 235 236 parent::Image_Canvas($param); 237 238 if (!$this->_pageWidth) { 239 $this->_pageWidth = $this->_width; 240 } elseif (!$this->_width) { 241 $this->_width = $this->_pageWidth; 242 } 243 244 if (!$this->_pageHeight) { 245 $this->_pageHeight = $this->_height; 246 } elseif (!$this->_height) { 247 $this->_height = $this->_pageHeight; 248 } 249 250 $this->_width = min($this->_width, $this->_pageWidth); 251 $this->_height = min($this->_height, $this->_pageHeight); 252 253 if ((isset($param['align'])) && 254 (($this->_width != $this->_pageWidth) || ($this->_height != $this->_pageHeight)) 255 ) { 256 switch (strtoupper($param['align'])) { 257 case 'TOPLEFT': 258 $this->_top = 0; 259 $this->_left = 0; 260 break; 261 262 case 'TOPCENTER': 263 $this->_top = 0; 264 $this->_left = ($this->_pageWidth - $this->_width) / 2; 265 break; 266 267 case 'TOPRIGHT': 268 $this->_top = 0; 269 $this->_left = $this->_pageWidth - $this->_width; 270 break; 271 272 case 'LEFTCENTER': 273 $this->_top = ($this->_pageHeight - $this->_height) / 2; 274 $this->_left = 0; 275 break; 276 277 case 'CENTER': 278 $this->_top = ($this->_pageHeight - $this->_height) / 2; 279 $this->_left = ($this->_pageWidth - $this->_width) / 2; 280 break; 281 282 case 'RIGHTCENTER': 283 $this->_top = ($this->_pageHeight - $this->_height) / 2; 284 $this->_left = $this->_pageWidth - $this->_width; 285 break; 286 287 case 'LEFTBOTTOM': 288 $this->_top = $this->_pageHeight - $this->_height; 289 $this->_left = 0; 290 break; 291 292 case 'CENTERBOTTOM': 293 $this->_top = $this->_pageHeight - $this->_height; 294 $this->_left = ($this->_pageWidth - $this->_width) / 2; 295 break; 296 297 case 'RIGHTBOTTOM': 298 $this->_top = $this->_pageHeight - $this->_height; 299 $this->_left = $this->_pageWidth - $this->_width; 300 break; 301 } 302 } 303 304 $addPage = true; 305 if ((isset($param['pdf'])) && (is_resource($param['pdf']))) { 306 $this->_pdf =& $param['pdf']; 307 if ((isset($param['add_page'])) && ($param['add_page'] === false)) { 308 $addPage = false; 309 } 310 } else { 311 $this->_pdf = pdf_new(); 312 313 if (isset($param['filename'])) { 314 pdf_open_file($this->_pdf, $param['filename']); 315 } else { 316 pdf_open_file($this->_pdf, ''); 317 } 318 319 pdf_set_parameter($this->_pdf, 'warning', 'true'); 320 321 pdf_set_info($this->_pdf, 'Creator', (isset($param['creator']) ? $param['creator'] : 'PEAR::Image_Canvas')); 322 pdf_set_info($this->_pdf, 'Author', (isset($param['author']) ? $param['author'] : 'Jesper Veggerby')); 323 pdf_set_info($this->_pdf, 'Title', (isset($param['title']) ? $param['title'] : 'Image_Canvas')); 324 } 325 326 if ($addPage) { 327 pdf_begin_page($this->_pdf, $this->_pageWidth, $this->_pageHeight); 328 } 329 $this->_reset(); 330 331 $this->_pdflib = $this->_version(); 332 } 333 334 /** 335 * Get the x-point from the relative to absolute coordinates 336 * 337 * @param float $x The relative x-coordinate (in percentage of total width) 338 * @return float The x-coordinate as applied to the canvas 339 * @access private 340 */ 341 function _getX($x) 342 { 343 return $this->_left + $x; 344 } 345 346 /** 347 * Get the y-point from the relative to absolute coordinates 348 * 349 * @param float $y The relative y-coordinate (in percentage of total width) 350 * @return float The y-coordinate as applied to the canvas 351 * @access private 352 */ 353 function _getY($y) 354 { 355 return $this->_pageHeight - ($this->_top + $y); 356 } 357 358 /** 359 * Get the color index for the RGB color 360 * 361 * @param int $color The color 362 * @return int The GD image index of the color 363 * @access private 364 */ 365 function _color($color = false) 366 { 367 if (($color === false) || ($color === 'opague') || ($color === 'transparent')) { 368 return false; 369 } else { 370 $color = Image_Canvas_Color::color2RGB($color); 371 $color[0] = $color[0]/255; 372 $color[1] = $color[1]/255; 373 $color[2] = $color[2]/255; 374 return $color; 375 } 376 } 377 378 /** 379 * Get the PDF linestyle 380 * 381 * @param mixed $lineStyle The line style to return, false if the one 382 * explicitly set 383 * @return bool True if set (so that a line should be drawn) 384 * @access private 385 */ 386 function _setLineStyle($lineStyle = false) 387 { 388 if ($lineStyle === false) { 389 $lineStyle = $this->_lineStyle; 390 } 391 392 if (($lineStyle == 'transparent') || ($lineStyle === false)) { 393 return false; 394 } 395 396 if (is_array($lineStyle)) { 397 // TODO Implement linestyles in PDFlib (using pdf_setcolor(.., 'pattern'...); ? 398 reset($lineStyle); 399 $lineStyle = current($lineStyle); 400 } 401 402 $color = $this->_color($lineStyle); 403 404 pdf_setlinewidth($this->_pdf, $this->_thickness); 405 if ($this->_pdflib < 4) { 406 pdf_setrgbcolor_stroke($this->_pdf, $color[0]/255, $color[1]/255, $color[2]/255); 407 } else { 408 pdf_setcolor($this->_pdf, 'stroke', 'rgb', $color[0], $color[1], $color[2], 0); 409 } 410 return true; 411 } 412 413 /** 414 * Set the PDF fill style 415 * 416 * @param mixed $fillStyle The fillstyle to return, false if the one 417 * explicitly set 418 * @return bool True if set (so that a line should be drawn) 419 * @access private 420 */ 421 function _setFillStyle($fillStyle = false) 422 { 423 if ($fillStyle === false) { 424 $fillStyle = $this->_fillStyle; 425 } 426 427 if (($fillStyle == 'transparent') || ($fillStyle === false)) { 428 return false; 429 } 430 431 $color = $this->_color($fillStyle); 432 433 if ($this->_pdflib < 4) { 434 pdf_setrgbcolor_fill($this->_pdf, $color[0]/255, $color[1]/255, $color[2]/255); 435 } else { 436 pdf_setcolor($this->_pdf, 'fill', 'rgb', $color[0], $color[1], $color[2], 0); 437 } 438 return true; 439 } 440 441 /** 442 * Set the PDF font 443 * 444 * @access private 445 */ 446 function _setFont() 447 { 448 $this->_pdfFont = false; 449 if (isset($this->_font['name'])) { 450 pdf_set_parameter($this->_pdf, 'FontOutline', $this->_font['name'] . '=' . $this->_font['file']); 451 $this->_pdfFont = pdf_findfont($this->_pdf, $this->_font['name'], $this->_font['encoding'], 1); 452 453 if ($this->_pdfFont) { 454 pdf_setfont($this->_pdf, $this->_pdfFont, $this->_font['size']); 455 $this->_setFillStyle($this->_font['color']); 456 } 457 } else { 458 $this->_setFillStyle('black'); 459 } 460 } 461 462 /** 463 * Sets an image that should be used for filling. 464 * 465 * Image filling is not supported with PDF, filling 'transparent' 466 * 467 * @param string $filename The filename of the image to fill with 468 */ 469 function setFillImage($filename) 470 { 471 $this->_fillStyle = 'transparent'; 472 } 473 474 /** 475 * Sets a gradient fill 476 * 477 * Gradient filling is not supported with PDF, end color used as solid fill. 478 * 479 * @param array $gradient Gradient fill options 480 */ 481 function setGradientFill($gradient) 482 { 483 $this->_fillStyle = $gradient['end']; 484 } 485 486 /** 487 * Sets the font options. 488 * 489 * The $font array may have the following entries: 490 * 491 * 'ttf' = the .ttf file (either the basename, filename or full path) 492 * If 'ttf' is specified, then the following can be specified 493 * 494 * 'size' = size in pixels 495 * 496 * 'angle' = the angle with which to write the text 497 * 498 * @param array $font The font options. 499 */ 500 function setFont($fontOptions) 501 { 502 parent::setFont($fontOptions); 503 504 if (!isset($this->_font['size'])) { 505 $this->_font['size'] = 12; 506 } 507 508 if (!isset($this->_font['encoding'])) { 509 $this->_font['encoding'] = 'winansi'; 510 } 511 512 if (!isset($this->_font['color'])) { 513 $this->_font['color'] = 'black'; 514 } 515 } 516 517 /** 518 * Resets the canvas. 519 * 520 * Includes fillstyle, linestyle, thickness and polygon 521 * 522 * @access private 523 */ 524 function _reset() 525 { 526 pdf_initgraphics($this->_pdf); 527 parent::_reset(); 528 } 529 530 /** 531 * Draw a line 532 * 533 * Parameter array: 534 * 'x0': int X start point 535 * 'y0': int Y start point 536 * 'x1': int X end point 537 * 'y1': int Y end point 538 * 'color': mixed [optional] The line color 539 * @param array $params Parameter array 540 */ 541 function line($params) 542 { 543 $color = (isset($params['color']) ? $params['color'] : false); 544 if ($this->_setLineStyle($color)) { 545 pdf_moveto($this->_pdf, $this->_getX($params['x0']), $this->_getY($params['y0'])); 546 pdf_lineto($this->_pdf, $this->_getX($params['x1']), $this->_getY($params['y1'])); 547 pdf_stroke($this->_pdf); 548 } 549 parent::line($params); 550 } 551 552 /** 553 * Parameter array: 554 * 'connect': bool [optional] Specifies whether the start point should be 555 * connected to the endpoint (closed polygon) or not (connected line) 556 * 'fill': mixed [optional] The fill color 557 * 'line': mixed [optional] The line color 558 * @param array $params Parameter array 559 */ 560 function polygon($params = array()) 561 { 562 $connectEnds = (isset($params['connect']) ? $params['connect'] : false); 563 $fillColor = (isset($params['fill']) ? $params['fill'] : false); 564 $lineColor = (isset($params['line']) ? $params['line'] : false); 565 566 $line = $this->_setLineStyle($lineColor); 567 $fill = false; 568 if ($connectEnds) { 569 $fill = $this->_setFillStyle($fillColor); 570 } 571 572 $first = true; 573 foreach ($this->_polygon as $point) { 574 if ($first === true) { 575 pdf_moveto($this->_pdf, $point['X'], $point['Y']); 576 $first = $point; 577 } else { 578 if (isset($last['P1X'])) { 579 pdf_curveto($this->_pdf, 580 $last['P1X'], 581 $last['P1Y'], 582 $last['P2X'], 583 $last['P2Y'], 584 $point['X'], 585 $point['Y'] 586 ); 587 } else { 588 pdf_lineto($this->_pdf, 589 $point['X'], 590 $point['Y'] 591 ); 592 } 593 } 594 $last = $point; 595 } 596 597 if ($connectEnds) { 598 if (isset($last['P1X'])) { 599 pdf_curveto($this->_pdf, 600 $last['P1X'], 601 $last['P1Y'], 602 $last['P2X'], 603 $last['P2Y'], 604 $first['X'], 605 $first['Y'] 606 ); 607 } else { 608 pdf_lineto($this->_pdf, 609 $first['X'], 610 $first['Y'] 611 ); 612 } 613 } 614 615 if (($line) && ($fill)) { 616 pdf_fill_stroke($this->_pdf); 617 } elseif ($line) { 618 pdf_stroke($this->_pdf); 619 } elseif ($fill) { 620 pdf_fill($this->_pdf); 621 } 622 parent::polygon($params); 623 } 624 625 /** 626 * Draw a rectangle 627 * 628 * Parameter array: 629 * 'x0': int X start point 630 * 'y0': int Y start point 631 * 'x1': int X end point 632 * 'y1': int Y end point 633 * 'fill': mixed [optional] The fill color 634 * 'line': mixed [optional] The line color 635 * @param array $params Parameter array 636 */ 637 function rectangle($params) 638 { 639 $x0 = $this->_getX($params['x0']); 640 $y0 = $this->_getY($params['y0']); 641 $x1 = $this->_getX($params['x1']); 642 $y1 = $this->_getY($params['y1']); 643 $fillColor = (isset($params['fill']) ? $params['fill'] : false); 644 $lineColor = (isset($params['line']) ? $params['line'] : false); 645 646 $line = $this->_setLineStyle($lineColor); 647 $fill = $this->_setFillStyle($fillColor); 648 if (($line) || ($fill)) { 649 pdf_rect($this->_pdf, min($x0, $x1), min($y0, $y1), abs($x1 - $x0), abs($y1 - $y0)); 650 if (($line) && ($fill)) { 651 pdf_fill_stroke($this->_pdf); 652 } elseif ($line) { 653 pdf_stroke($this->_pdf); 654 } elseif ($fill) { 655 pdf_fill($this->_pdf); 656 } 657 } 658 parent::rectangle($params); 659 } 660 661 /** 662 * Draw an ellipse 663 * 664 * Parameter array: 665 * 'x': int X center point 666 * 'y': int Y center point 667 * 'rx': int X radius 668 * 'ry': int Y radius 669 * 'fill': mixed [optional] The fill color 670 * 'line': mixed [optional] The line color 671 * @param array $params Parameter array 672 */ 673 function ellipse($params) 674 { 675 $x = $params['x']; 676 $y = $params['y']; 677 $rx = $params['rx']; 678 $ry = $params['ry']; 679 $fillColor = (isset($params['fill']) ? $params['fill'] : false); 680 $lineColor = (isset($params['line']) ? $params['line'] : false); 681 682 $line = $this->_setLineStyle($lineColor); 683 $fill = $this->_setFillStyle($fillColor); 684 if (($line) || ($fill)) { 685 if ($rx == $ry) { 686 pdf_circle($this->_pdf, $this->_getX($x), $this->_getY($y), $rx); 687 } else { 688 pdf_moveto($this->_pdf, $this->_getX($x - $rx), $this->_getY($y)); 689 pdf_curveto($this->_pdf, 690 $this->_getX($x - $rx), $this->_getY($y), 691 $this->_getX($x - $rx), $this->_getY($y - $ry), 692 $this->_getX($x), $this->_getY($y - $ry) 693 ); 694 pdf_curveto($this->_pdf, 695 $this->_getX($x), $this->_getY($y - $ry), 696 $this->_getX($x + $rx), $this->_getY($y - $ry), 697 $this->_getX($x + $rx), $this->_getY($y) 698 ); 699 pdf_curveto($this->_pdf, 700 $this->_getX($x + $rx), $this->_getY($y), 701 $this->_getX($x + $rx), $this->_getY($y + $ry), 702 $this->_getX($x), $this->_getY($y + $ry) 703 ); 704 pdf_curveto($this->_pdf, 705 $this->_getX($x), $this->_getY($y + $ry), 706 $this->_getX($x - $rx), $this->_getY($y + $ry), 707 $this->_getX($x - $rx), $this->_getY($y) 708 ); 709 } 710 711 if (($line) && ($fill)) { 712 pdf_fill_stroke($this->_pdf); 713 } elseif ($line) { 714 pdf_stroke($this->_pdf); 715 } elseif ($fill) { 716 pdf_fill($this->_pdf); 717 } 718 } 719 parent::ellipse($params); 720 } 721 722 /** 723 * Draw a pie slice 724 * 725 * Parameter array: 726 * 'x': int X center point 727 * 'y': int Y center point 728 * 'rx': int X radius 729 * 'ry': int Y radius 730 * 'v1': int The starting angle (in degrees) 731 * 'v2': int The end angle (in degrees) 732 * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) 733 * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) 734 * 'fill': mixed [optional] The fill color 735 * 'line': mixed [optional] The line color 736 * @param array $params Parameter array 737 */ 738 function pieslice($params) 739 { 740 $x = $this->_getX($params['x']); 741 $y = $this->_getY($params['y']); 742 $rx = $this->_getX($params['rx']); 743 $ry = $this->_getY($params['ry']); 744 $v1 = $this->_getX($params['v1']); 745 $v2 = $this->_getY($params['v2']); 746 $srx = $this->_getX($params['srx']); 747 $sry = $this->_getY($params['sry']); 748 $fillColor = (isset($params['fill']) ? $params['fill'] : false); 749 $lineColor = (isset($params['line']) ? $params['line'] : false); 750 751 // TODO Implement PDFLIB::pieSlice() 752 parent::pieslice($params); 753 } 754 755 /** 756 * Get the width of a text, 757 * 758 * @param string $text The text to get the width of 759 * @return int The width of the text 760 */ 761 function textWidth($text) 762 { 763 if ($this->_pdfFont === false) { 764 return $this->_font['size'] * 0.7 * strlen($text); 765 } else { 766 return pdf_stringwidth($this->_pdf, $text, $this->_pdfFont, $this->_font['size']); 767 } 768 } 769 770 /** 771 * Get the height of a text, 772 * 773 * @param string $text The text to get the height of 774 * @return int The height of the text 775 */ 776 function textHeight($text) 777 { 778 if (isset($this->_font['size'])) { 779 return $this->_font['size']; 780 } else { 781 return 12; 782 } 783 } 784 785 /** 786 * Writes text 787 * 788 * Parameter array: 789 * 'x': int X-point of text 790 * 'y': int Y-point of text 791 * 'text': string The text to add 792 * 'alignment': array [optional] Alignment 793 * 'color': mixed [optional] The color of the text 794 */ 795 function addText($params) 796 { 797 $x = $this->_getX($params['x']); 798 $y = $this->_getY($params['y']); 799 $text = $params['text']; 800 $color = (isset($params['color']) ? $params['color'] : false); 801 $alignment = (isset($params['alignment']) ? $params['alignment'] : false); 802 803 $this->_setFont(); 804 805 $textWidth = $this->textWidth($text); 806 $textHeight = $this->textHeight($text); 807 808 if (!is_array($alignment)) { 809 $alignment = array('vertical' => 'top', 'horizontal' => 'left'); 810 } 811 812 if (!isset($alignment['vertical'])) { 813 $alignment['vertical'] = 'top'; 814 } 815 816 if (!isset($alignment['horizontal'])) { 817 $alignment['horizontal'] = 'left'; 818 } 819 820 if ($alignment['horizontal'] == 'right') { 821 $x = $x - $textWidth; 822 } elseif ($alignment['horizontal'] == 'center') { 823 $x = $x - ($textWidth / 2); 824 } 825 826 $y -= $textHeight; 827 828 if ($alignment['vertical'] == 'bottom') { 829 $y = $y + $textHeight; 830 } elseif ($alignment['vertical'] == 'center') { 831 $y = $y + ($textHeight / 2); 832 } 833 834 if (($color === false) && (isset($this->_font['color']))) { 835 $color = $this->_font['color']; 836 } 837 838 pdf_show_xy($this->_pdf, $text, $x, $y); 839 840 parent::addText($params); 841 } 842 843 /** 844 * Overlay image 845 * 846 * Parameter array: 847 * 'x': int X-point of overlayed image 848 * 'y': int Y-point of overlayed image 849 * 'filename': string The filename of the image to overlay 850 * 'width': int [optional] The width of the overlayed image (resizing if possible) 851 * 'height': int [optional] The height of the overlayed image (resizing if possible) 852 * 'alignment': array [optional] Alignment 853 */ 854 function image($params) 855 { 856 $x = $this->_getX($params['x']); 857 $y = $this->_getY($params['y']); 858 $filename = $params['filename']; 859 $width = (isset($params['width']) ? $params['width'] : false); 860 $height = (isset($params['height']) ? $params['height'] : false); 861 $alignment = (isset($params['alignment']) ? $params['alignment'] : false); 862 863 if (substr($filename, -4) == '.png') { 864 $type = 'png'; 865 } elseif (substr($filename, -4) == '.jpg') { 866 $type = 'jpeg'; 867 } 868 869 $image = pdf_load_image($this->_pdf, $type, realpath($filename), ''); 870 $width_ = pdf_get_value($this->_pdf, 'imagewidth', $image); 871 $height_ = pdf_get_value($this->_pdf, 'imageheight', $image); 872 873 $outputWidth = ($width !== false ? $width : $width_); 874 $outputHeight = ($height !== false ? $height : $height_); 875 876 if (!is_array($alignment)) { 877 $alignment = array('vertical' => 'top', 'horizontal' => 'left'); 878 } 879 880 if (!isset($alignment['vertical'])) { 881 $alignment['vertical'] = 'top'; 882 } 883 884 if (!isset($alignment['horizontal'])) { 885 $alignment['horizontal'] = 'left'; 886 } 887 888 if ($alignment['horizontal'] == 'right') { 889 $x -= $outputWidth; 890 } elseif ($alignment['horizontal'] == 'center') { 891 $x -= $outputWidth / 2; 892 } 893 894 if ($alignment['vertical'] == 'top') { 895 $y += $outputHeight; 896 } elseif ($alignment['vertical'] == 'center') { 897 $y += $outputHeight / 2; 898 } 899 900 if (($width === false) && ($height === false)) { 901 $scale = 1; 902 } else { 903 $scale = max(($height/$height_), ($width/$width_)); 904 } 905 906 pdf_place_image($this->_pdf, $image, $x, $y, $scale); 907 pdf_close_image($this->_pdf, $image); 908 909 parent::image($params); 910 } 911 912 /** 913 * Output the result of the canvas 914 * 915 * @param array $param Parameter array 916 * @abstract 917 */ 918 function show($param = false) 919 { 920 parent::show($param); 921 pdf_end_page($this->_pdf); 922 pdf_close($this->_pdf); 923 924 $buf = pdf_get_buffer($this->_pdf); 925 $len = strlen($buf); 926 927 header('Content-type: application/pdf'); 928 header('Content-Length: ' . $len); 929 header('Content-Disposition: inline; filename=image_graph.pdf'); 930 print $buf; 931 932 pdf_delete($this->_pdf); 933 } 934 935 /** 936 * Output the result of the canvas 937 * 938 * @param array $param Parameter array 939 * @abstract 940 */ 941 function save($param = false) 942 { 943 parent::save($param); 944 pdf_end_page($this->_pdf); 945 pdf_close($this->_pdf); 946 947 $buf = pdf_get_buffer($this->_pdf); 948 $len = strlen($buf); 949 950 $fp = @fopen($param['filename'], 'wb'); 951 if ($fp) { 952 fwrite($fp, $buf, strlen($buf)); 953 fclose($fp); 954 } 955 pdf_delete($this->_pdf); 956 } 957 958 /** 959 * Get a canvas specific HTML tag. 960 * 961 * This method implicitly saves the canvas to the filename in the 962 * filesystem path specified and parses it as URL specified by URL path 963 * 964 * Parameter array: 965 * 'filename': string 966 * 'filepath': string Path to the file on the file system. Remember the final slash 967 * 'urlpath': string Path to the file available through an URL. Remember the final slash 968 * 'title': string The url title 969 */ 970 function toHtml($params) 971 { 972 parent::toHtml($params); 973 return '<a href="' . $params['urlpath'] . $params['filename'] . '">' . $params['title'] . '</a>'; 974 } 975 976 /** 977 * Check which major version of PDFlib is installed 978 * 979 * @return int The mahor version number of PDFlib 980 * @access private 981 */ 982 function _version() 983 { 984 $result = false; 985 $version = ''; 986 if (function_exists('pdf_get_majorversion')) { 987 $version = pdf_get_majorversion(); 988 } else if (function_exists('pdf_get_value')) { 989 $version = pdf_get_value($this->_pdf, 'major', 0); 990 } else { 991 ob_start(); 992 phpinfo(8); 993 $php_info = ob_get_contents(); 994 ob_end_clean(); 995 996 if (preg_match("/<td[^>]*>PDFlib GmbH Version *<\/td><td[^>]*>([^<]*)<\/td>/", 997 $php_info, $result)) 998 { 999 $version = $result[1]; 1000 } 1001 } 1002 1003 if (preg_match('/([0-9]{1,2})\.[0-9]{1,2}(\.[0-9]{1,2})?/', trim($version), $result)) { 1004 return $result[1]; 1005 } else { 1006 return $version; 1007 } 1008 } 1009 1010} 1011 1012?> 1013