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 ReportHtmlText 29 */ 30class ReportHtmlText extends ReportBaseText 31{ 32 /** 33 * Render the elements. 34 * 35 * @param HtmlRenderer $renderer 36 * @param int $curx 37 * @param bool $attrib Is is called from a different element? 38 * 39 * @return void 40 */ 41 public function render($renderer, $curx = 0, $attrib = true) 42 { 43 // Set up the style 44 if ($renderer->getCurrentStyle() !== $this->styleName) { 45 $renderer->setCurrentStyle($this->styleName); 46 } 47 $temptext = str_replace('#PAGENUM#', (string) $renderer->pageNo(), $this->text); 48 // underline «title» part of Source item 49 $temptext = str_replace([ 50 '«', 51 '»', 52 ], [ 53 '<u>', 54 '</u>', 55 ], $temptext); 56 57 // If any text at all 58 if (!empty($temptext)) { 59 // If called by an other element 60 if (!$attrib) { 61 $renderer->write($temptext, $this->color); 62 } else { 63 // Save the start positions 64 $startX = $renderer->getX(); 65 $startY = $renderer->getY(); 66 $width = $renderer->getRemainingWidth(); 67 // If text is wider then page width then wrap it 68 if ($renderer->getStringWidth($temptext) > $width) { 69 $lines = explode("\n", $temptext); 70 foreach ($lines as $line) { 71 echo '<div style="position:absolute;top:', $startY, 'pt;', $renderer->alignRTL, ':', $startX, 'pt;width:', $width, 'pt;">'; 72 $line = $renderer->textWrap($line, $width); 73 $startY += $renderer->getTextCellHeight($line); 74 $renderer->setY($startY); 75 $renderer->write($line, $this->color); 76 echo "</div>\n"; 77 } 78 } else { 79 echo '<div style="position:absolute;top:', $startY, 'pt;', $renderer->alignRTL, ':', $startX, 'pt;width:', $width, 'pt;">'; 80 $renderer->write($temptext, $this->color); 81 echo "</div>\n"; 82 $renderer->setX($startX + $renderer->getStringWidth($temptext)); 83 if ($renderer->countLines($temptext) !== 1) { 84 $renderer->setXy(0, $startY + $renderer->getTextCellHeight($temptext)); 85 } 86 } 87 } 88 } 89 } 90 91 /** 92 * Returns the height in points of the text element 93 * The height is already calculated in getWidth() 94 * 95 * @param HtmlRenderer $renderer 96 * 97 * @return float 98 */ 99 public function getHeight($renderer): float 100 { 101 $ct = substr_count($this->text, "\n"); 102 if ($ct > 0) { 103 $ct += 1; 104 } 105 $style = $renderer->getStyle($this->styleName); 106 107 return ($style['size'] * $ct) * $renderer->cellHeightRatio; 108 } 109 110 /** 111 * Get the width of text and wrap it too 112 * 113 * @param HtmlRenderer $renderer 114 * 115 * @return float|array 116 */ 117 public function getWidth($renderer) 118 { 119 // Setup the style name, a font must be selected to calculate the width 120 if ($renderer->getCurrentStyle() !== $this->styleName) { 121 $renderer->setCurrentStyle($this->styleName); 122 } 123 124 // Check for the largest font size in the box 125 $fsize = $renderer->getCurrentStyleHeight(); 126 if ($fsize > $renderer->largestFontHeight) { 127 $renderer->largestFontHeight = $fsize; 128 } 129 130 // Get the line width for the text in points 131 $lw = $renderer->getStringWidth($this->text); 132 // Line Feed counter - Number of lines in the text 133 $lfct = $renderer->countLines($this->text); 134 // If there is still remaining wrap width... 135 $wrapWidthRemaining = $this->wrapWidthRemaining; 136 if ($wrapWidthRemaining > 0) { 137 // Check with line counter too! 138 if ($lw >= $wrapWidthRemaining || $lfct > 1) { 139 $newtext = ''; 140 $lines = explode("\n", $this->text); 141 // Go throught the text line by line 142 foreach ($lines as $line) { 143 // Line width in points + a little margin 144 $lw = $renderer->getStringWidth($line); 145 // If the line has to be wraped 146 if ($lw > $wrapWidthRemaining) { 147 $words = explode(' ', $line); 148 $addspace = count($words); 149 $lw = 0; 150 foreach ($words as $word) { 151 $addspace--; 152 $lw += $renderer->getStringWidth($word . ' '); 153 if ($lw <= $wrapWidthRemaining) { 154 $newtext .= $word; 155 if ($addspace !== 0) { 156 $newtext .= ' '; 157 } 158 } else { 159 $lw = $renderer->getStringWidth($word . ' '); 160 $newtext .= "\n$word"; 161 if ($addspace !== 0) { 162 $newtext .= ' '; 163 } 164 // Reset the wrap width to the cell width 165 $wrapWidthRemaining = $this->wrapWidthCell; 166 } 167 } 168 } else { 169 $newtext .= $line; 170 } 171 // Check the Line Feed counter 172 if ($lfct > 1) { 173 // Add a new line as long as it’s not the last line 174 $newtext .= "\n"; 175 // Reset the line width 176 $lw = 0; 177 // Reset the wrap width to the cell width 178 $wrapWidthRemaining = $this->wrapWidthCell; 179 } 180 $lfct--; 181 } 182 $this->text = $newtext; 183 $lfct = substr_count($this->text, "\n"); 184 185 return [ 186 $lw, 187 1, 188 $lfct, 189 ]; 190 } 191 } 192 $l = 0; 193 $lfct = substr_count($this->text, "\n"); 194 if ($lfct > 0) { 195 $l = 2; 196 } 197 198 return [ 199 $lw, 200 $l, 201 $lfct, 202 ]; 203 } 204} 205