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\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), 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($width, $height, $border, $align, $bgcolor, $style, $ln, $top, $left, $fill, $stretch, $bocolor, $tcolor, $reseth): ReportBaseCell; 161 162 /** 163 * Create a new TextBox object. 164 * 165 * @param float $width Text box width 166 * @param float $height Text box height 167 * @param bool $border 168 * @param string $bgcolor Background color code in HTML 169 * @param bool $newline 170 * @param float $left 171 * @param float $top 172 * @param bool $pagecheck 173 * @param string $style 174 * @param bool $fill 175 * @param bool $padding 176 * @param bool $reseth 177 * 178 * @return ReportBaseTextbox 179 */ 180 abstract public function createTextBox( 181 float $width, 182 float $height, 183 bool $border, 184 string $bgcolor, 185 bool $newline, 186 float $left, 187 float $top, 188 bool $pagecheck, 189 string $style, 190 bool $fill, 191 bool $padding, 192 bool $reseth 193 ): ReportBaseTextbox; 194 195 /** 196 * Create a text element. 197 * 198 * @param string $style 199 * @param string $color 200 * 201 * @return ReportBaseText 202 */ 203 abstract public function createText(string $style, string $color): ReportBaseText; 204 205 /** 206 * Create a line. 207 * 208 * @param float $x1 209 * @param float $y1 210 * @param float $x2 211 * @param float $y2 212 * 213 * @return ReportBaseLine 214 */ 215 abstract public function createLine(float $x1, float $y1, float $x2, float $y2): ReportBaseLine; 216 217 /** 218 * Create a new image object. 219 * 220 * @param string $file Filename 221 * @param float $x 222 * @param float $y 223 * @param float $w Image width 224 * @param float $h Image height 225 * @param string $align L:left, C:center, R:right or empty to use x/y 226 * @param string $ln T:same line, N:next line 227 * 228 * @return ReportBaseImage 229 */ 230 abstract public function createImage(string $file, float $x, float $y, float $w, float $h, string $align, string $ln): ReportBaseImage; 231 232 /** 233 * Create a new image object from Media Object. 234 * 235 * @param MediaFile $media_file 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 * @param FilesystemInterface $data_filesystem 243 * 244 * @return ReportBaseImage 245 */ 246 abstract public function createImageFromObject( 247 MediaFile $media_file, 248 float $x, 249 float $y, 250 float $w, 251 float $h, 252 string $align, 253 string $ln, 254 FilesystemInterface $data_filesystem 255 ): ReportBaseImage; 256 257 /** 258 * Create a new Footnote object. 259 * 260 * @param string $style Style name 261 * 262 * @return ReportBaseFootnote 263 */ 264 abstract public function createFootnote($style): ReportBaseFootnote; 265 266 /** 267 * Initial Setup 268 * Setting up document wide defaults that will be inherited of the report modules 269 * As DEFAULT A4 and Portrait will be used if not set 270 * 271 * @return void 272 */ 273 public function setup(): void 274 { 275 $this->rtl = I18N::direction() === 'rtl'; 276 277 $this->rkeywords = ''; 278 279 // I18N: This is a report footer. %s is the name of the application. 280 $this->generated_by = I18N::translate('Generated by %s', Webtrees::NAME . ' ' . Webtrees::VERSION); 281 282 // Paper size - defaults to A4 if the report fails to define a size. 283 [$this->page_width, $this->page_height] = self::PAPER_SIZES[$this->page_format] ?? self::PAPER_SIZES['A4']; 284 } 285 286 /** 287 * Process the Header, Body or Footer 288 * 289 * @param string $p Header (H), Body (B) or Footer (F) 290 * 291 * @return void 292 */ 293 public function setProcessing(string $p): void 294 { 295 $this->processing = $p; 296 } 297 298 /** 299 * Add the Title when raw character data is used in Title 300 * 301 * @param string $data 302 * 303 * @return void 304 */ 305 public function addTitle(string $data): void 306 { 307 $this->title .= $data; 308 } 309 310 /** 311 * Add the Description when raw character data is used in Description 312 * 313 * @param string $data 314 * 315 * @return void 316 */ 317 public function addDescription(string $data): void 318 { 319 $this->rsubject .= $data; 320 } 321 322 /** 323 * Add Style to Styles array 324 * 325 * @param string[] $style 326 * 327 * @return void 328 */ 329 public function addStyle(array $style): void 330 { 331 $this->styles[$style['name']] = $style; 332 } 333 334 /** 335 * Get a style from the Styles array 336 * 337 * @param string $s Style name 338 * 339 * @return array 340 */ 341 public function getStyle(string $s): array 342 { 343 return $this->styles[$s] ?? current($this->styles); 344 } 345} 346