1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2019 webtrees development team 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18declare(strict_types=1); 19 20namespace Fisharebest\Webtrees\Report; 21 22use Fisharebest\Webtrees\I18N; 23use Fisharebest\Webtrees\MediaFile; 24use Fisharebest\Webtrees\Webtrees; 25use League\Flysystem\FilesystemInterface; 26 27use function current; 28 29/** 30 * Class AbstractRenderer - base for PDF and HTML reports 31 */ 32abstract class AbstractRenderer 33{ 34 // Reports layouts are measured in points. 35 protected const UNITS = 'pt'; 36 37 // A point is 1/72 of an inch 38 protected const INCH_TO_POINTS = 72.0; 39 protected const MM_TO_POINTS = 72.0 / 25.4; 40 41 protected const PAPER_SIZES = [ 42 // ISO 216 43 'A0' => [841.0 * self::MM_TO_POINTS, 1189.0 * self::MM_TO_POINTS], 44 'A1' => [594.0 * self::MM_TO_POINTS, 841.0 * self::MM_TO_POINTS], 45 'A2' => [420.0 * self::MM_TO_POINTS, 594.0 * self::MM_TO_POINTS], 46 'A3' => [297.0 * self::MM_TO_POINTS, 420.0 * self::MM_TO_POINTS], 47 'A4' => [210.0 * self::MM_TO_POINTS, 297.0 * self::MM_TO_POINTS], 48 // US 49 'US-Letter' => [8.5 * self::INCH_TO_POINTS, 11.0 * self::INCH_TO_POINTS], 50 'US-Legal' => [8.5 * self::INCH_TO_POINTS, 14.0 * self::INCH_TO_POINTS], 51 'US-Tabloid' => [11.0 * self::INCH_TO_POINTS, 17.0 * self::INCH_TO_POINTS], 52 ]; 53 54 /** @var float Left Margin */ 55 public $left_margin = 18.0 * self::MM_TO_POINTS; 56 57 /** @var float Right Margin */ 58 public $right_margin = 9.9 * self::MM_TO_POINTS; 59 60 /** @var float Top Margin */ 61 public $top_margin = 26.8 * self::MM_TO_POINTS; 62 63 /** @var float Bottom Margin */ 64 public $bottom_margin = 21.6 * self::MM_TO_POINTS; 65 66 /** @var float Header Margin */ 67 public $header_margin = 4.9 * self::MM_TO_POINTS; 68 69 /** @var float Footer Margin */ 70 public $footer_margin = 9.9 * self::MM_TO_POINTS; 71 72 /** @var string Page orientation (portrait, landscape) */ 73 public $orientation = 'portrait'; 74 75 /** @var string Page format name */ 76 public $page_format = 'A4'; 77 78 /** @var float Height of page format in points */ 79 public $page_height = 0.0; 80 81 /** @var float Width of page format in points */ 82 public $page_width = 0.0; 83 84 /** @var string[][] An array of the Styles elements found in the document */ 85 public $styles = []; 86 87 /** @var string The default Report font name */ 88 public $default_font = 'dejavusans'; 89 90 /** @var float The default Report font size */ 91 public $default_font_size = 12.0; 92 93 /** @var string Header (H), Page header (PH), Body (B) or Footer (F) */ 94 public $processing = 'H'; 95 96 /** @var bool RTL Language (false=LTR, true=RTL) */ 97 public $rtl = false; 98 99 /** @var bool Show the Generated by... (true=show the text) */ 100 public $show_generated_by = true; 101 102 /** @var string Generated By... text */ 103 public $generated_by = ''; 104 105 /** @var string The report title */ 106 public $title = ''; 107 108 /** @var string Author of the report, the users full name */ 109 public $rauthor = Webtrees::NAME . ' ' . Webtrees::VERSION; 110 111 /** @var string Keywords */ 112 public $rkeywords = ''; 113 114 /** @var string Report Description / Subject */ 115 public $rsubject = ''; 116 117 /** 118 * Clear the Header. 119 * 120 * @return void 121 */ 122 abstract public function clearHeader(): void; 123 124 /** 125 * Create a new Page Header object 126 * 127 * @return ReportBasePageHeader 128 */ 129 abstract public function createPageHeader(): ReportBasePageHeader; 130 131 /** 132 * Add an element. 133 * 134 * @param ReportBaseElement|string $element 135 * 136 * @return void 137 */ 138 abstract public function addElement($element): void; 139 140 /** 141 * Run the report. 142 * 143 * @return void 144 */ 145 abstract public function run(): void; 146 147 /** 148 * Create a new Cell object. 149 * 150 * @param int $width cell width (expressed in points) 151 * @param int $height cell height (expressed in points) 152 * @param mixed $border Border style 153 * @param string $align Text alignement 154 * @param string $bgcolor Background color code 155 * @param string $style The name of the text style 156 * @param int $ln Indicates where the current position should go after the call 157 * @param mixed $top Y-position 158 * @param mixed $left X-position 159 * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 1 160 * @param int $stretch Stretch carachter mode 161 * @param string $bocolor Border color 162 * @param string $tcolor Text color 163 * @param bool $reseth 164 * 165 * @return ReportBaseCell 166 */ 167 abstract public function createCell($width, $height, $border, $align, $bgcolor, $style, $ln, $top, $left, $fill, $stretch, $bocolor, $tcolor, $reseth): ReportBaseCell; 168 169 /** 170 * Create a new TextBox object. 171 * 172 * @param float $width Text box width 173 * @param float $height Text box height 174 * @param bool $border 175 * @param string $bgcolor Background color code in HTML 176 * @param bool $newline 177 * @param float $left 178 * @param float $top 179 * @param bool $pagecheck 180 * @param string $style 181 * @param bool $fill 182 * @param bool $padding 183 * @param bool $reseth 184 * 185 * @return ReportBaseTextbox 186 */ 187 abstract public function createTextBox( 188 float $width, 189 float $height, 190 bool $border, 191 string $bgcolor, 192 bool $newline, 193 float $left, 194 float $top, 195 bool $pagecheck, 196 string $style, 197 bool $fill, 198 bool $padding, 199 bool $reseth 200 ): ReportBaseTextbox; 201 202 /** 203 * Create a text element. 204 * 205 * @param string $style 206 * @param string $color 207 * 208 * @return ReportBaseText 209 */ 210 abstract public function createText(string $style, string $color): ReportBaseText; 211 212 /** 213 * Create an HTML element. 214 * 215 * @param string $tag 216 * @param string[] $attrs 217 * 218 * @return ReportBaseHtml 219 */ 220 abstract public function createHTML(string $tag, array $attrs): ReportBaseHtml; 221 222 /** 223 * Create a line. 224 * 225 * @param float $x1 226 * @param float $y1 227 * @param float $x2 228 * @param float $y2 229 * 230 * @return ReportBaseLine 231 */ 232 abstract public function createLine(float $x1, float $y1, float $x2, float $y2): ReportBaseLine; 233 234 /** 235 * Create a new image object. 236 * 237 * @param string $file Filename 238 * @param float $x 239 * @param float $y 240 * @param float $w Image width 241 * @param float $h Image height 242 * @param string $align L:left, C:center, R:right or empty to use x/y 243 * @param string $ln T:same line, N:next line 244 * 245 * @return ReportBaseImage 246 */ 247 abstract public function createImage(string $file, float $x, float $y, float $w, float $h, string $align, string $ln): ReportBaseImage; 248 249 /** 250 * Create a new image object from Media Object. 251 * 252 * @param MediaFile $media_file 253 * @param float $x 254 * @param float $y 255 * @param float $w Image width 256 * @param float $h Image height 257 * @param string $align L:left, C:center, R:right or empty to use x/y 258 * @param string $ln T:same line, N:next line 259 * @param FilesystemInterface $data_filesystem 260 * 261 * @return ReportBaseImage 262 */ 263 abstract public function createImageFromObject( 264 MediaFile $media_file, 265 float $x, 266 float $y, 267 float $w, 268 float $h, 269 string $align, 270 string $ln, 271 FilesystemInterface $data_filesystem 272 ): ReportBaseImage; 273 274 /** 275 * Create a new Footnote object. 276 * 277 * @param string $style Style name 278 * 279 * @return ReportBaseFootnote 280 */ 281 abstract public function createFootnote($style): ReportBaseFootnote; 282 283 /** 284 * Initial Setup 285 * Setting up document wide defaults that will be inherited of the report modules 286 * As DEFAULT A4 and Portrait will be used if not set 287 * 288 * @return void 289 */ 290 public function setup(): void 291 { 292 $this->rtl = I18N::direction() === 'rtl'; 293 294 $this->rkeywords = ''; 295 296 // I18N: This is a report footer. %s is the name of the application. 297 $this->generated_by = I18N::translate('Generated by %s', Webtrees::NAME . ' ' . Webtrees::VERSION); 298 299 // Paper size - defaults to A4 if the report fails to define a size. 300 [$this->page_width, $this->page_height] = self::PAPER_SIZES[$this->page_format] ?? self::PAPER_SIZES['A4']; 301 } 302 303 /** 304 * Process the Header , Page header, Body or Footer 305 * 306 * @param string $p Header (H), Page header (PH), Body (B) or Footer (F) 307 * 308 * @return void 309 */ 310 public function setProcessing(string $p): void 311 { 312 $this->processing = $p; 313 } 314 315 /** 316 * Add the Title when raw character data is used in Title 317 * 318 * @param string $data 319 * 320 * @return void 321 */ 322 public function addTitle(string $data): void 323 { 324 $this->title .= $data; 325 } 326 327 /** 328 * Add the Description when raw character data is used in Description 329 * 330 * @param string $data 331 * 332 * @return void 333 */ 334 public function addDescription(string $data): void 335 { 336 $this->rsubject .= $data; 337 } 338 339 /** 340 * Add Style to Styles array 341 * 342 * @param string[] $style 343 * 344 * @return void 345 */ 346 public function addStyle(array $style): void 347 { 348 $this->styles[$style['name']] = $style; 349 } 350 351 /** 352 * Get a style from the Styles array 353 * 354 * @param string $s Style name 355 * 356 * @return array 357 */ 358 public function getStyle(string $s): array 359 { 360 if (!isset($this->styles[$s])) { 361 return current($this->styles); 362 } 363 364 return $this->styles[$s]; 365 } 366} 367