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