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