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