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