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 function count; 23use function explode; 24use function str_replace; 25use function substr_count; 26 27/** 28 * Class ReportHtmlFootnote 29 */ 30class ReportHtmlFootnote extends ReportBaseFootnote 31{ 32 /** 33 * HTML Footnotes number renderer 34 * 35 * @param HtmlRenderer $renderer 36 * 37 * @return void 38 */ 39 public function render($renderer) 40 { 41 $renderer->setCurrentStyle('footnotenum'); 42 echo '<a href="#footnote', $this->num, '"><sup>'; 43 $renderer->write($renderer->entityRTL . $this->num); 44 echo "</sup></a>\n"; 45 } 46 47 /** 48 * Write the Footnote text 49 * Uses style name "footnote" by default 50 * 51 * @param HtmlRenderer $renderer 52 * 53 * @return void 54 */ 55 public function renderFootnote($renderer): void 56 { 57 if ($renderer->getCurrentStyle() !== $this->styleName) { 58 $renderer->setCurrentStyle($this->styleName); 59 } 60 61 $temptext = str_replace('#PAGENUM#', (string) $renderer->pageNo(), $this->text); 62 // underline «title» part of Source item 63 $temptext = str_replace([ 64 '«', 65 '»', 66 ], [ 67 '<u>', 68 '</u>', 69 ], $temptext); 70 echo '<div><a id="footnote', $this->num, '"></a>'; 71 $renderer->write($this->num . '. ' . $temptext); 72 echo '</div>'; 73 74 $renderer->setXy(0, $renderer->getY() + $this->getFootnoteHeight($renderer)); 75 } 76 77 /** 78 * Calculates the Footnotes height 79 * 80 * @param HtmlRenderer $html 81 * @param float $cellWidth The width of the cell to use it for text wraping 82 * 83 * @return float Footnote height in points 84 */ 85 public function getFootnoteHeight($html, float $cellWidth = 0): float 86 { 87 if ($html->getCurrentStyle() !== $this->styleName) { 88 $html->setCurrentStyle($this->styleName); 89 } 90 91 if ($cellWidth > 0) { 92 $this->text = $html->textWrap($this->text, $cellWidth); 93 } 94 95 $this->text .= "\n\n"; 96 $ct = substr_count($this->text, "\n"); 97 $fsize = $html->getCurrentStyleHeight(); 98 99 return ($fsize * $ct) * $html->cellHeightRatio; 100 } 101 102 /** 103 * Get the width of text 104 * Breaks up a text into lines if needed 105 * 106 * @param HtmlRenderer $renderer 107 * 108 * @return float|array 109 */ 110 public function getWidth($renderer) 111 { 112 // Setup the style name 113 $renderer->setCurrentStyle('footnotenum'); 114 115 // Check for the largest font size in the box 116 $fsize = $renderer->getCurrentStyleHeight(); 117 if ($fsize > $renderer->largestFontHeight) { 118 $renderer->largestFontHeight = $fsize; 119 } 120 121 // Returns the Object if already numbered else false 122 if (empty($this->num)) { 123 $renderer->checkFootnote($this); 124 } 125 126 // Get the line width for the text in points + a little margin 127 $lw = $renderer->getStringWidth($this->numText); 128 // Line Feed counter - Number of lines in the text 129 $lfct = $renderer->countLines($this->numText); 130 // If there is still remaining wrap width... 131 if ($this->wrapWidthRemaining > 0) { 132 // Check with line counter too! 133 if ($lw >= $this->wrapWidthRemaining || $lfct > 1) { 134 $newtext = ''; 135 $wrapWidthRemaining = $this->wrapWidthRemaining; 136 $lines = explode("\n", $this->numText); 137 // Go throught the text line by line 138 foreach ($lines as $line) { 139 // Line width in points + a little margin 140 $lw = $renderer->getStringWidth($line); 141 // If the line has to be wraped 142 if ($lw > $wrapWidthRemaining) { 143 $words = explode(' ', $line); 144 $addspace = count($words); 145 $lw = 0; 146 foreach ($words as $word) { 147 $addspace--; 148 $lw += $renderer->getStringWidth($word . ' '); 149 if ($lw <= $wrapWidthRemaining) { 150 $newtext .= $word; 151 if ($addspace !== 0) { 152 $newtext .= ' '; 153 } 154 } else { 155 $lw = $renderer->getStringWidth($word . ' '); 156 $newtext .= "\n$word"; 157 if ($addspace !== 0) { 158 $newtext .= ' '; 159 } 160 // Reset the wrap width to the cell width 161 $wrapWidthRemaining = $this->wrapWidthCell; 162 } 163 } 164 } else { 165 $newtext .= $line; 166 } 167 // Check the Line Feed counter 168 if ($lfct > 1) { 169 // Add a new line feed as long as it’s not the last line 170 $newtext .= "\n"; 171 // Reset the line width 172 $lw = 0; 173 // Reset the wrap width to the cell width 174 $wrapWidthRemaining = $this->wrapWidthCell; 175 } 176 $lfct--; 177 } 178 $this->numText = $newtext; 179 $lfct = substr_count($this->numText, "\n"); 180 181 return [ 182 $lw, 183 1, 184 $lfct, 185 ]; 186 } 187 } 188 $l = 0; 189 $lfct = substr_count($this->numText, "\n"); 190 if ($lfct > 0) { 191 $l = 2; 192 } 193 194 return [ 195 $lw, 196 $l, 197 $lfct, 198 ]; 199 } 200} 201