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