1<?php 2// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project 3// 4// All Rights Reserved. See copyright.txt for details and a complete list of authors. 5// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details. 6// $Id$ 7 8/* This library is LGPL 9 * written by Louis-Philippe Huberdeau 10 * 11 * vim: fdm=marker tabstop=4 shiftwidth=4 noet: 12 * 13 * This file contains the PostScript graphic renderer. (Using PSLib) 14 */ 15require_once('lib/graph-engine/core.php'); 16 17class PS_GRenderer extends GRenderer // {{{1 18{ 19 var $ps; 20 var $styles; 21 var $font; 22 23 var $width; 24 var $height; 25 26 function __construct($format = null, $orientation = 'landscape') // {{{2 27 { 28 // Null size does not create a graphic. 29 $this->styles = []; 30 $this->font = null; 31 32 if (! is_null($format)) { 33 $size = $this->_getFormat($format, $orientation); 34 $this->width = $size[0]; 35 $this->height = $size[1]; 36 37 $this->ps = ps_new(); 38 ps_open_file($this->ps, ''); 39 ps_begin_page($this->ps, $this->width, $this->height); 40 41 $this->font = ps_findfont($this->ps, 'Helvetica', '', 0); 42 } 43 } 44 45 function addLink($target, $left, $top, $right, $bottom, $title = null) // {{{2 46 { 47 } 48 49 function drawLine($x1, $y1, $x2, $y2, $style) // {{{2 50 { 51 $this->_convertPosition($x1, $y1); 52 $this->_convertPosition($x2, $y2); 53 54 ps_setcolor( 55 $this->ps, 56 'stroke', 57 $style['line'][0], 58 $style['line'][1], 59 $style['line'][2], 60 $style['line'][3], 61 $style['line'][4] 62 ); 63 64 ps_setlinewidth($this->ps, $style['line-width']); 65 66 ps_moveto($this->ps, $x1, $y1); 67 ps_lineto($this->ps, $x2, $y2); 68 ps_stroke($this->ps); 69 } 70 71 function drawRectangle($left, $top, $right, $bottom, $style) // {{{2 72 { 73 $this->_convertPosition($left, $top); 74 $this->_convertPosition($right, $bottom); 75 76 ps_setcolor( 77 $this->ps, 78 'stroke', 79 $style['line'][0], 80 $style['line'][1], 81 $style['line'][2], 82 $style['line'][3], 83 $style['line'][4] 84 ); 85 86 if (isset($style['fill'])) { 87 ps_setcolor( 88 $this->ps, 89 'fill', 90 $style['fill'][0], 91 $style['fill'][1], 92 $style['fill'][2], 93 $style['fill'][3], 94 $style['fill'][4] 95 ); 96 } 97 98 ps_setlinewidth($this->ps, $style['line-width']); 99 100 ps_rect($this->ps, $left, $top, $right - $left, $bottom - $top); 101 102 if (isset($style['fill'])) { 103 ps_fill_stroke($this->ps); 104 } else { 105 ps_stroke($this->ps); 106 } 107 } 108 109 function drawPie($centerX, $centerY, $radius, $begin, $end, $style) // {{{2 110 { 111 $this->_convertPosition($centerX, $centerY); 112 $radius = $radius * min($this->width, $this->height); 113 114 ps_setcolor( 115 $this->ps, 116 'stroke', 117 $style['line'][0], 118 $style['line'][1], 119 $style['line'][2], 120 $style['line'][3], 121 $style['line'][4] 122 ); 123 124 if (isset($style['fill'])) { 125 ps_setcolor( 126 $this->ps, 127 'fill', 128 $style['fill'][0], 129 $style['fill'][1], 130 $style['fill'][2], 131 $style['fill'][3], 132 $style['fill'][4] 133 ); 134 } 135 136 ps_setlinewidth($this->ps, $style['line-width']); 137 138 ps_moveto($this->ps, $centerX, $centerY); 139 ps_arc($this->ps, $centerX, $centerY, $radius, $begin, $end); 140 ps_lineto($this->ps, $centerX, $centerY); 141 ps_closepath($this->ps); 142 143 if (isset($style['fill'])) { 144 ps_fill_stroke($this->ps); 145 } else { 146 ps_stroke($this->ps); 147 } 148 } 149 150 function drawText($text, $left, $right, $height, $style) // {{{2 151 { 152 $h = $height; // Creating duplicate (temp) 153 $this->_convertPosition($left, $height); 154 $this->_convertPosition($right, $h); 155 156 ps_setcolor( 157 $this->ps, 158 'fill', 159 $style['fill'][0], 160 $style['fill'][1], 161 $style['fill'][2], 162 $style['fill'][3], 163 $style['fill'][4] 164 ); 165 166 ps_setfont($this->ps, $this->font, $style['font']); 167 ps_show_boxed($this->ps, $text, $left, $height - $style['font'], $right - $left, $style['font'], $style['align'], ''); 168 } 169 170 function getTextWidth($text, $style) // {{{2 171 { 172 return ps_stringwidth($this->ps, $text, $this->font, $style['font']) / $this->width; 173 } 174 175 function getTextHeight($style) // {{{2 176 { 177 return $style['font'] / $this->height; 178 } 179 180 function getStyle($name) // {{{2 181 { 182 if (isset($this->styles[$name])) { 183 return $this->styles[$name]; 184 } 185 186 return $this->styles[$name] = $this->_findStyle($name); 187 } 188 189 function httpOutput($filename) // {{{2 190 { 191 ps_end_page($this->ps); 192 ps_close($this->ps); 193 194 $buf = ps_get_buffer($this->ps); 195 $len = strlen($buf); 196 197 header("Content-type: application/ps"); 198 header("Content-Length: $len"); 199 header("Content-Disposition: inline; filename=$name"); 200 echo $buf; 201 202 ps_delete($this->ps); 203 } 204 205 function writeToStream($stream) // {{{2 206 { 207 ps_end_page($this->ps); 208 ps_close($this->ps); 209 210 $buf = ps_get_buffer($this->ps); 211 fwrite($stream, $buf); 212 213 ps_delete($this->ps); 214 } 215 216 function _convertLength($value, $type) // {{{2 217 { 218 // $type is either 'width' or 'height' 219 // $value is a 0-1 float 220 return floor($value * $this->$type); 221 } 222 223 function _convertPosition(&$x, &$y) // {{{2 224 { 225 // Parameters passed by ref! 226 $x = $this->_convertLength($x, 'width'); 227 $y = $this->height - $this->_convertLength($y, 'height'); 228 } 229 230 function _findStyle($name) // {{{2 231 { 232 $parts = explode('-', $name); 233 $style = []; 234 235 switch ($parts[0]) { 236 case 'Thin': 237 $style['line-width'] = 1; 238 array_shift($parts); 239 break; 240 case 'Bold': 241 $style['line-width'] = 2; 242 array_shift($parts); 243 break; 244 case 'Bolder': 245 $style['line-width'] = 3; 246 array_shift($parts); 247 break; 248 case 'Large': 249 $style['font'] = 16; 250 array_shift($parts); 251 break; 252 case 'Small': 253 $style['font'] = 8; 254 array_shift($parts); 255 break; 256 case 'Normal': 257 array_shift($parts); 258 default: 259 if ($parts[0] == 'Text') { 260 $style['font'] = 12; 261 } else { 262 $style['line-width'] = 1; 263 } 264 break; 265 } 266 267 switch ($parts[0]) { 268 case 'LineStroke': 269 $style['line'] = $this->_getColor($parts[1]); 270 break; 271 case 'FillStroke': 272 $style['fill'] = $this->_getColor($parts[1]); 273 $style['line'] = $this->_getColor('Black'); 274 break; 275 case 'Text': 276 $style['fill'] = $this->_getColor('Black'); 277 switch ($parts[1]) { 278 case 'Center': 279 $style['align'] = 'center'; 280 break; 281 case 'Right': 282 $style['align'] = 'right'; 283 break; 284 case 'Left': 285 default: 286 $style['align'] = 'left'; 287 break; 288 } 289 break; 290 default: 291 return GRenderer::getStyle($name); 292 } 293 294 return $style; 295 } 296 297 function _getColor($name) // {{{2 298 { 299 $c = [ 'rgb' ]; 300 $color = $this->_getRawColor(strtolower($name)); 301 foreach ($color as $col) { 302 $c[] = $col / 255; 303 } 304 305 $c[] = null; 306 307 return $c; 308 } 309 310 function _getFormat($format, $orientation) // {{{2 311 { 312 /* 313 Taken from lib/pdflib/class.ezpdf.php 314 Copyright notices are in that file. 315 */ 316 switch (strtoupper($format)) { 317 case '4A0': 318 $size = [4767.87,6740.79]; 319 break; 320 case '2A0': 321 $size = [3370.39,4767.87]; 322 break; 323 case 'A0': 324 $size = [2383.94,3370.39]; 325 break; 326 case 'A1': 327 $size = [1683.78,2383.94]; 328 break; 329 case 'A2': 330 $size = [1190.55,1683.78]; 331 break; 332 case 'A3': 333 $size = [841.89,1190.55]; 334 break; 335 case 'A4': 336 $size = [595.28,841.89]; 337 break; 338 case 'A5': 339 $size = [419.53,595.28]; 340 break; 341 case 'A6': 342 $size = [297.64,419.53]; 343 break; 344 case 'A7': 345 $size = [209.76,297.64]; 346 break; 347 case 'A8': 348 $size = [147.40,209.76]; 349 break; 350 case 'A9': 351 $size = [104.88,147.40]; 352 break; 353 case 'A10': 354 $size = [73.70,104.88]; 355 break; 356 case 'B0': 357 $size = [2834.65,4008.19]; 358 break; 359 case 'B1': 360 $size = [2004.09,2834.65]; 361 break; 362 case 'B2': 363 $size = [1417.32,2004.09]; 364 break; 365 case 'B3': 366 $size = [1000.63,1417.32]; 367 break; 368 case 'B4': 369 $size = [708.66,1000.63]; 370 break; 371 case 'B5': 372 $size = [498.90,708.66]; 373 break; 374 case 'B6': 375 $size = [354.33,498.90]; 376 break; 377 case 'B7': 378 $size = [249.45,354.33]; 379 break; 380 case 'B8': 381 $size = [175.75,249.45]; 382 break; 383 case 'B9': 384 $size = [124.72,175.75]; 385 break; 386 case 'B10': 387 $size = [87.87,124.72]; 388 break; 389 case 'C0': 390 $size = [2599.37,3676.54]; 391 break; 392 case 'C1': 393 $size = [1836.85,2599.37]; 394 break; 395 case 'C2': 396 $size = [1298.27,1836.85]; 397 break; 398 case 'C3': 399 $size = [918.43,1298.27]; 400 break; 401 case 'C4': 402 $size = [649.13,918.43]; 403 break; 404 case 'C5': 405 $size = [459.21,649.13]; 406 break; 407 case 'C6': 408 $size = [323.15,459.21]; 409 break; 410 case 'C7': 411 $size = [229.61,323.15]; 412 break; 413 case 'C8': 414 $size = [161.57,229.61]; 415 break; 416 case 'C9': 417 $size = [113.39,161.57]; 418 break; 419 case 'C10': 420 $size = [79.37,113.39]; 421 break; 422 case 'RA0': 423 $size = [2437.80,3458.27]; 424 break; 425 case 'RA1': 426 $size = [1729.13,2437.80]; 427 break; 428 case 'RA2': 429 $size = [1218.90,1729.13]; 430 break; 431 case 'RA3': 432 $size = [864.57,1218.90]; 433 break; 434 case 'RA4': 435 $size = [609.45,864.57]; 436 break; 437 case 'SRA0': 438 $size = [2551.18,3628.35]; 439 break; 440 case 'SRA1': 441 $size = [1814.17,2551.18]; 442 break; 443 case 'SRA2': 444 $size = [1275.59,1814.17]; 445 break; 446 case 'SRA3': 447 $size = [907.09,1275.59]; 448 break; 449 case 'SRA4': 450 $size = [637.80,907.09]; 451 break; 452 case 'LETTER': 453 $size = [612.00,792.00]; 454 break; 455 case 'LEGAL': 456 $size = [612.00,1008.00]; 457 break; 458 case 'EXECUTIVE': 459 $size = [521.86,756.00]; 460 break; 461 case 'FOLIO': 462 $size = [612.00,936.00]; 463 break; 464 } 465 466 if (strtolower($orientation) == 'landscape') { 467 $a = $size[1]; 468 $size[1] = $size[0]; 469 $size[0] = $a; 470 } 471 472 return $size; 473 } 474} // }}}1 475