1<?php 2/** 3 * webtrees: online genealogy 4 * Copyright (C) 2018 webtrees development team 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16namespace Fisharebest\Webtrees\Report; 17 18/** 19 * Class ReportHtmlTextbox 20 */ 21class ReportHtmlTextbox extends ReportBaseTextbox 22{ 23 /** 24 * Render the elements. 25 * 26 * @param ReportHtml $renderer 27 * 28 * @return void 29 */ 30 public function render($renderer) 31 { 32 // checkFootnote 33 $newelements = []; 34 $lastelement = []; 35 $footnote_element = []; 36 // Element counter 37 $cE = count($this->elements); 38 //-- collapse duplicate elements 39 for ($i = 0; $i < $cE; $i++) { 40 $element = $this->elements[$i]; 41 if (is_object($element)) { 42 if ($element instanceof ReportBaseText) { 43 if (!empty($footnote_element)) { 44 ksort($footnote_element); 45 foreach ($footnote_element as $links) { 46 $newelements[] = $links; 47 } 48 $footnote_element = []; 49 } 50 if (empty($lastelement)) { 51 $lastelement = $element; 52 } else { 53 // Checking if the Text has the same style 54 if ($element->getStyleName() == $lastelement->getStyleName()) { 55 $lastelement->addText(str_replace("\n", '<br>', $element->getValue())); 56 } elseif (!empty($lastelement)) { 57 $newelements[] = $lastelement; 58 $lastelement = $element; 59 } 60 } 61 } elseif ($element instanceof ReportBaseFootnote) { 62 // Check if the Footnote has been set with it’s link number 63 $renderer->checkFootnote($element); 64 // Save first the last element if any 65 if (!empty($lastelement)) { 66 $newelements[] = $lastelement; 67 $lastelement = []; 68 } 69 // Save the Footnote with it’s link number as key for sorting later 70 $footnote_element[$element->num] = $element; 71 } elseif (!($element instanceof ReportBaseFootnote) || trim($element->getValue()) != '') { 72 // Do not keep empty footnotes 73 if (!empty($footnote_element)) { 74 ksort($footnote_element); 75 foreach ($footnote_element as $links) { 76 $newelements[] = $links; 77 } 78 $footnote_element = []; 79 } 80 if (!empty($lastelement)) { 81 $newelements[] = $lastelement; 82 $lastelement = []; 83 } 84 $newelements[] = $element; 85 } 86 } else { 87 if (!empty($lastelement)) { 88 $newelements[] = $lastelement; 89 $lastelement = []; 90 } 91 if (!empty($footnote_element)) { 92 ksort($footnote_element); 93 foreach ($footnote_element as $links) { 94 $newelements[] = $links; 95 } 96 $footnote_element = []; 97 } 98 $newelements[] = $element; 99 } 100 } 101 if (!empty($lastelement)) { 102 $newelements[] = $lastelement; 103 } 104 if (!empty($footnote_element)) { 105 ksort($footnote_element); 106 foreach ($footnote_element as $links) { 107 $newelements[] = $links; 108 } 109 } 110 $this->elements = $newelements; 111 unset($footnote_element, $lastelement, $links, $newelements); 112 113 $cP = 0; // Class Padding 114 115 // Used with line breaks and cell height calculation within this box only 116 $renderer->largestFontHeight = 0; 117 118 // Current position 119 if ($this->left == '.') { 120 $cX = $renderer->getX(); 121 } else { 122 $cX = $this->left; 123 $renderer->setX($cX); 124 } 125 // Current position (top) 126 if ($this->top == '.') { 127 $this->top = $renderer->getY(); 128 } else { 129 $renderer->setY($this->top); 130 } 131 132 // Check the width if set to page wide OR set by xml to larger then page wide 133 if ($this->width == 0 || $this->width > $renderer->getRemainingWidth()) { 134 $this->width = $renderer->getRemainingWidth(); 135 } 136 // Setup the CellPadding 137 if ($this->padding) { 138 $cP = $renderer->cPadding; 139 } 140 141 // For padding, we have to use less wrap width 142 $cW = $this->width - ($cP * 2); 143 144 //-- calculate the text box height 145 // Number of lines, will be converted to height 146 $cHT = 0; 147 // Element height (exept text) 148 $eH = 0; 149 // Footnote height (in points) 150 $fH = 0; 151 $w = 0; 152 //-- $lw is an array 153 // 0 => last line width 154 // 1 => 1 if text was wrapped, 0 if text did not wrap 155 // 2 => number of LF 156 $lw = []; 157 // Element counter 158 $cE = count($this->elements); 159 for ($i = 0; $i < $cE; $i++) { 160 if (is_object($this->elements[$i])) { 161 $ew = $this->elements[$i]->setWrapWidth($cW - $w - 2, $cW); 162 if ($ew == $cW) { 163 $w = 0; 164 } 165 $lw = $this->elements[$i]->getWidth($renderer); 166 // Text is already gets the # LF 167 $cHT += $lw[2]; 168 if ($lw[1] == 1) { 169 $w = $lw[0]; 170 } elseif ($lw[1] == 2) { 171 $w = 0; 172 } else { 173 $w += $lw[0]; 174 } 175 if ($w > $cW) { 176 $w = $lw[0]; 177 } 178 // For anything else but text (images), get the height 179 $eH += $this->elements[$i]->getHeight($renderer); 180 } else { 181 $fH += abs($renderer->getFootnotesHeight($cW)); 182 } 183 } 184 // Add up what’s the final height 185 $cH = $this->height; 186 // If any element exist 187 if ($cE > 0) { 188 // Check if this is text or some other element, like images 189 if ($eH == 0) { 190 // Number of LF but at least one line 191 $cHT = ($cHT + 1) * $renderer->cellHeightRatio; 192 // Calculate the cell hight with the largest font size used 193 $cHT = $cHT * $renderer->largestFontHeight; 194 if ($cH < $cHT) { 195 $cH = $cHT; 196 } 197 } else { 198 // This is any other element 199 if ($cH < $eH) { 200 $cH = $eH; 201 } 202 // Add Footnote height to the rest of the height 203 $cH += $fH; 204 } 205 } 206 207 unset($lw, $cHT, $fH, $w); 208 209 // Finaly, check the last cells height 210 if ($cH < $renderer->lastCellHeight) { 211 $cH = $renderer->lastCellHeight; 212 } 213 // Update max Y incase of a pagebreak 214 // We don't want to over write any images or other stuff 215 $renderer->addMaxY($this->top + $cH); 216 217 // Start to print HTML 218 echo '<div style="position:absolute;top:', $this->top, 'pt;'; 219 // LTR (left) or RTL (right) 220 echo $renderer->alignRTL, ':', $cX, 'pt;'; 221 // Background color 222 if ($this->fill) { 223 if (!empty($this->bgcolor)) { 224 echo ' background-color:', $this->bgcolor, ';'; 225 } 226 } 227 // Print padding only when it’s set 228 if ($this->padding) { 229 // Use Cell around padding to support RTL also 230 echo 'padding:', $cP, 'pt;'; 231 } 232 // Border setup 233 if ($this->border) { 234 echo ' border:solid black 1pt;'; 235 echo 'width:', ($this->width - 1 - ($cP * 2)), 'pt;height:', $cH - 1, 'pt;'; 236 } else { 237 echo 'width:', ($this->width - ($cP * 2)), 'pt;height:', $cH, 'pt;'; 238 } 239 echo '">'; 240 241 // Do a little "margin" trick before print 242 // to get the correct current position => "." 243 $cXT = $renderer->getX(); 244 $cYT = $renderer->getY(); 245 $renderer->setXy(0, 0); 246 247 // Print the text elements 248 foreach ($this->elements as $element) { 249 if (is_object($element)) { 250 $element->render($renderer, $cX, false); 251 } elseif (is_string($element) && $element == 'footnotetexts') { 252 $renderer->footnotes(); 253 } elseif (is_string($element) && $element == 'addpage') { 254 $renderer->addPage(); 255 } 256 } 257 echo "</div>\n"; 258 259 // Reset "margins" 260 $renderer->setXy($cXT, $cYT); 261 // This will be mostly used to trick the multiple images last height 262 if ($this->reseth) { 263 $cH = 0; 264 } 265 // New line and some clean up 266 if (!$this->newline) { 267 $renderer->setXy($cX + $this->width, $this->top); 268 $renderer->lastCellHeight = $cH; 269 } else { 270 $renderer->setXy(0, $this->top + $cH + ($cP * 2)); 271 $renderer->lastCellHeight = 0; 272 } 273 } 274} 275