1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2021 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 <https://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\FilesystemOperator; 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), 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 * Add an element. 126 * 127 * @param ReportBaseElement|string $element 128 * 129 * @return void 130 */ 131 abstract public function addElement($element): void; 132 133 /** 134 * Run the report. 135 * 136 * @return void 137 */ 138 abstract public function run(): void; 139 140 /** 141 * Create a new Cell object. 142 * 143 * @param int $width cell width (expressed in points) 144 * @param int $height cell height (expressed in points) 145 * @param mixed $border Border style 146 * @param string $align Text alignement 147 * @param string $bgcolor Background color code 148 * @param string $style The name of the text style 149 * @param int $ln Indicates where the current position should go after the call 150 * @param mixed $top Y-position 151 * @param mixed $left X-position 152 * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 1 153 * @param int $stretch Stretch carachter mode 154 * @param string $bocolor Border color 155 * @param string $tcolor Text color 156 * @param bool $reseth 157 * 158 * @return ReportBaseCell 159 */ 160 abstract public function createCell( 161 int $width, 162 int $height, 163 $border, 164 string $align, 165 string $bgcolor, 166 string $style, 167 int $ln, 168 $top, 169 $left, 170 int $fill, 171 int $stretch, 172 string $bocolor, 173 string $tcolor, 174 bool $reseth 175 ): ReportBaseCell; 176 177 /** 178 * Create a new TextBox object. 179 * 180 * @param float $width Text box width 181 * @param float $height Text box height 182 * @param bool $border 183 * @param string $bgcolor Background color code in HTML 184 * @param bool $newline 185 * @param float $left 186 * @param float $top 187 * @param bool $pagecheck 188 * @param string $style 189 * @param bool $fill 190 * @param bool $padding 191 * @param bool $reseth 192 * 193 * @return ReportBaseTextbox 194 */ 195 abstract public function createTextBox( 196 float $width, 197 float $height, 198 bool $border, 199 string $bgcolor, 200 bool $newline, 201 float $left, 202 float $top, 203 bool $pagecheck, 204 string $style, 205 bool $fill, 206 bool $padding, 207 bool $reseth 208 ): ReportBaseTextbox; 209 210 /** 211 * Create a text element. 212 * 213 * @param string $style 214 * @param string $color 215 * 216 * @return ReportBaseText 217 */ 218 abstract public function createText(string $style, string $color): ReportBaseText; 219 220 /** 221 * Create a line. 222 * 223 * @param float $x1 224 * @param float $y1 225 * @param float $x2 226 * @param float $y2 227 * 228 * @return ReportBaseLine 229 */ 230 abstract public function createLine(float $x1, float $y1, float $x2, float $y2): ReportBaseLine; 231 232 /** 233 * Create a new image object. 234 * 235 * @param string $file Filename 236 * @param float $x 237 * @param float $y 238 * @param float $w Image width 239 * @param float $h Image height 240 * @param string $align L:left, C:center, R:right or empty to use x/y 241 * @param string $ln T:same line, N:next line 242 * 243 * @return ReportBaseImage 244 */ 245 abstract public function createImage(string $file, float $x, float $y, float $w, float $h, string $align, string $ln): ReportBaseImage; 246 247 /** 248 * Create a new image object from Media Object. 249 * 250 * @param MediaFile $media_file 251 * @param float $x 252 * @param float $y 253 * @param float $w Image width 254 * @param float $h Image height 255 * @param string $align L:left, C:center, R:right or empty to use x/y 256 * @param string $ln T:same line, N:next line 257 * @param FilesystemOperator $data_filesystem 258 * 259 * @return ReportBaseImage 260 */ 261 abstract public function createImageFromObject( 262 MediaFile $media_file, 263 float $x, 264 float $y, 265 float $w, 266 float $h, 267 string $align, 268 string $ln, 269 FilesystemOperator $data_filesystem 270 ): ReportBaseImage; 271 272 /** 273 * Create a new Footnote object. 274 * 275 * @param string $style Style name 276 * 277 * @return ReportBaseFootnote 278 */ 279 abstract public function createFootnote(string $style): ReportBaseFootnote; 280 281 /** 282 * Initial Setup 283 * Setting up document wide defaults that will be inherited of the report modules 284 * As DEFAULT A4 and Portrait will be used if not set 285 * 286 * @return void 287 */ 288 public function setup(): void 289 { 290 $this->rtl = I18N::direction() === 'rtl'; 291 292 $this->rkeywords = ''; 293 294 // I18N: This is a report footer. %s is the name of the application. 295 $this->generated_by = I18N::translate('Generated by %s', Webtrees::NAME . ' ' . Webtrees::VERSION); 296 297 // Paper size - defaults to A4 if the report fails to define a size. 298 [$this->page_width, $this->page_height] = self::PAPER_SIZES[$this->page_format] ?? self::PAPER_SIZES['A4']; 299 } 300 301 /** 302 * Process the Header, Body or Footer 303 * 304 * @param string $p Header (H), Body (B) or Footer (F) 305 * 306 * @return void 307 */ 308 public function setProcessing(string $p): void 309 { 310 $this->processing = $p; 311 } 312 313 /** 314 * Add the Title when raw character data is used in Title 315 * 316 * @param string $data 317 * 318 * @return void 319 */ 320 public function addTitle(string $data): void 321 { 322 $this->title .= $data; 323 } 324 325 /** 326 * Add the Description when raw character data is used in Description 327 * 328 * @param string $data 329 * 330 * @return void 331 */ 332 public function addDescription(string $data): void 333 { 334 $this->rsubject .= $data; 335 } 336 337 /** 338 * Add Style to Styles array 339 * 340 * @param string[] $style 341 * 342 * @return void 343 */ 344 public function addStyle(array $style): void 345 { 346 $this->styles[$style['name']] = $style; 347 } 348 349 /** 350 * Get a style from the Styles array 351 * 352 * @param string $s Style name 353 * 354 * @return array 355 */ 356 public function getStyle(string $s): array 357 { 358 return $this->styles[$s] ?? current($this->styles); 359 } 360} 361