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