xref: /webtrees/app/Report/ReportHtmlText.php (revision 52f124b09c3bc79f2e314c64c3ad971d9a17c818)
1a25f0a04SGreg Roach<?php
23976b470SGreg Roach
3a25f0a04SGreg Roach/**
4a25f0a04SGreg Roach * webtrees: online genealogy
5d11be702SGreg Roach * Copyright (C) 2023 webtrees development team
6a25f0a04SGreg Roach * This program is free software: you can redistribute it and/or modify
7a25f0a04SGreg Roach * it under the terms of the GNU General Public License as published by
8a25f0a04SGreg Roach * the Free Software Foundation, either version 3 of the License, or
9a25f0a04SGreg Roach * (at your option) any later version.
10a25f0a04SGreg Roach * This program is distributed in the hope that it will be useful,
11a25f0a04SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
12a25f0a04SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13a25f0a04SGreg Roach * GNU General Public License for more details.
14a25f0a04SGreg Roach * You should have received a copy of the GNU General Public License
1589f7189bSGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>.
16a25f0a04SGreg Roach */
17fcfa147eSGreg Roach
18e7f56f2aSGreg Roachdeclare(strict_types=1);
19e7f56f2aSGreg Roach
2076692c8bSGreg Roachnamespace Fisharebest\Webtrees\Report;
21a25f0a04SGreg Roach
22b6f35a76SGreg Roachuse function count;
23b6f35a76SGreg Roachuse function explode;
24b6f35a76SGreg Roachuse function str_replace;
25b6f35a76SGreg Roachuse function substr_count;
26b6f35a76SGreg Roach
27a25f0a04SGreg Roach/**
28a25f0a04SGreg Roach * Class ReportHtmlText
29a25f0a04SGreg Roach */
30c1010edaSGreg Roachclass ReportHtmlText extends ReportBaseText
31c1010edaSGreg Roach{
32a25f0a04SGreg Roach    /**
3376692c8bSGreg Roach     * Render the elements.
3476692c8bSGreg Roach     *
35b6f35a76SGreg Roach     * @param HtmlRenderer $renderer
36cbc1590aSGreg Roach     * @param bool         $attrib Is is called from a different element?
37c7ff4153SGreg Roach     *
38c7ff4153SGreg Roach     * @return void
39a25f0a04SGreg Roach     */
4077bab461SGreg Roach    public function render($renderer, bool $attrib = true): void
41c1010edaSGreg Roach    {
4267c69ce5SGreg Roach        // Set up the style
43b6f35a76SGreg Roach        if ($renderer->getCurrentStyle() !== $this->styleName) {
44a25f0a04SGreg Roach            $renderer->setCurrentStyle($this->styleName);
45a25f0a04SGreg Roach        }
468a4ee39cSGreg Roach        $temptext = str_replace('#PAGENUM#', (string) $renderer->pageNo(), $this->text);
47a25f0a04SGreg Roach        // underline «title» part of Source item
48c1010edaSGreg Roach        $temptext = str_replace([
49c1010edaSGreg Roach            '«',
50c1010edaSGreg Roach            '»',
51c1010edaSGreg Roach        ], [
52c1010edaSGreg Roach            '<u>',
53c1010edaSGreg Roach            '</u>',
54c1010edaSGreg Roach        ], $temptext);
55a25f0a04SGreg Roach
56a25f0a04SGreg Roach        // If any text at all
57a25f0a04SGreg Roach        if (!empty($temptext)) {
58a25f0a04SGreg Roach            // If called by an other element
59a25f0a04SGreg Roach            if (!$attrib) {
60a25f0a04SGreg Roach                $renderer->write($temptext, $this->color);
61a25f0a04SGreg Roach            } else {
62a25f0a04SGreg Roach                // Save the start positions
63a25f0a04SGreg Roach                $startX = $renderer->getX();
64a25f0a04SGreg Roach                $startY = $renderer->getY();
65a25f0a04SGreg Roach                $width  = $renderer->getRemainingWidth();
66a25f0a04SGreg Roach                // If text is wider then page width then wrap it
677820e4d7SGreg Roach                if ($renderer->getStringWidth($temptext) > $width) {
68a25f0a04SGreg Roach                    $lines = explode("\n", $temptext);
69a25f0a04SGreg Roach                    foreach ($lines as $line) {
707a6ee1acSGreg Roach                        echo '<div style="position:absolute;top:', $startY, 'pt;', $renderer->alignRTL, ':', $startX, 'pt;width:', $width, 'pt;">';
71a25f0a04SGreg Roach                        $line = $renderer->textWrap($line, $width);
72a25f0a04SGreg Roach                        $startY += $renderer->getTextCellHeight($line);
73a25f0a04SGreg Roach                        $renderer->setY($startY);
74a25f0a04SGreg Roach                        $renderer->write($line, $this->color);
75a25f0a04SGreg Roach                        echo "</div>\n";
76a25f0a04SGreg Roach                    }
77a25f0a04SGreg Roach                } else {
787a6ee1acSGreg Roach                    echo '<div style="position:absolute;top:', $startY, 'pt;', $renderer->alignRTL, ':', $startX, 'pt;width:', $width, 'pt;">';
79a25f0a04SGreg Roach                    $renderer->write($temptext, $this->color);
80a25f0a04SGreg Roach                    echo "</div>\n";
817820e4d7SGreg Roach                    $renderer->setX($startX + $renderer->getStringWidth($temptext));
82b6f35a76SGreg Roach                    if ($renderer->countLines($temptext) !== 1) {
83e364afe4SGreg Roach                        $renderer->setXy(0, $startY + $renderer->getTextCellHeight($temptext));
84a25f0a04SGreg Roach                    }
85a25f0a04SGreg Roach                }
86a25f0a04SGreg Roach            }
87a25f0a04SGreg Roach        }
88a25f0a04SGreg Roach    }
89a25f0a04SGreg Roach
90a25f0a04SGreg Roach    /**
91a25f0a04SGreg Roach     * Returns the height in points of the text element
92a25f0a04SGreg Roach     * The height is already calculated in getWidth()
93a25f0a04SGreg Roach     *
94b6f35a76SGreg Roach     * @param HtmlRenderer $renderer
95a25f0a04SGreg Roach     *
96a25f0a04SGreg Roach     * @return float
97a25f0a04SGreg Roach     */
9867c69ce5SGreg Roach    public function getHeight($renderer): float
99c1010edaSGreg Roach    {
100a25f0a04SGreg Roach        $ct = substr_count($this->text, "\n");
101a25f0a04SGreg Roach        if ($ct > 0) {
102a25f0a04SGreg Roach            $ct += 1;
103a25f0a04SGreg Roach        }
10467c69ce5SGreg Roach        $style = $renderer->getStyle($this->styleName);
105cbc1590aSGreg Roach
10652135727SGreg Roach        return $style['size'] * $ct * $renderer->cellHeightRatio;
107a25f0a04SGreg Roach    }
108a25f0a04SGreg Roach
109a25f0a04SGreg Roach    /**
110a25f0a04SGreg Roach     * Get the width of text and wrap it too
111a25f0a04SGreg Roach     *
112b6f35a76SGreg Roach     * @param HtmlRenderer $renderer
113a25f0a04SGreg Roach     *
11477bab461SGreg Roach     * @return array{0:float,1:int,2:float}
115a25f0a04SGreg Roach     */
11641cfb9e2SGreg Roach    public function getWidth($renderer): array
117c1010edaSGreg Roach    {
11867c69ce5SGreg Roach        // Setup the style name, a font must be selected to calculate the width
119b6f35a76SGreg Roach        if ($renderer->getCurrentStyle() !== $this->styleName) {
12067c69ce5SGreg Roach            $renderer->setCurrentStyle($this->styleName);
121a25f0a04SGreg Roach        }
122a25f0a04SGreg Roach
123a25f0a04SGreg Roach        // Check for the largest font size in the box
12467c69ce5SGreg Roach        $fsize = $renderer->getCurrentStyleHeight();
12567c69ce5SGreg Roach        if ($fsize > $renderer->largestFontHeight) {
12667c69ce5SGreg Roach            $renderer->largestFontHeight = $fsize;
127a25f0a04SGreg Roach        }
128a25f0a04SGreg Roach
129a25f0a04SGreg Roach        // Get the line width for the text in points
13067c69ce5SGreg Roach        $lw = $renderer->getStringWidth($this->text);
131a25f0a04SGreg Roach        // Line Feed counter - Number of lines in the text
13267c69ce5SGreg Roach        $lfct = $renderer->countLines($this->text);
133a25f0a04SGreg Roach        // If there is still remaining wrap width...
134a25f0a04SGreg Roach        $wrapWidthRemaining = $this->wrapWidthRemaining;
13567c69ce5SGreg Roach        if ($wrapWidthRemaining > 0) {
13667c69ce5SGreg Roach            // Check with line counter too!
13767c69ce5SGreg Roach            if ($lw >= $wrapWidthRemaining || $lfct > 1) {
13867c69ce5SGreg Roach                $newtext            = '';
139a25f0a04SGreg Roach                $lines              = explode("\n", $this->text);
140*52f124b0SAlejandro Criado-Pérez                // Go through the text line by line
141a25f0a04SGreg Roach                foreach ($lines as $line) {
142a25f0a04SGreg Roach                    // Line width in points + a little margin
14367c69ce5SGreg Roach                    $lw = $renderer->getStringWidth($line);
144*52f124b0SAlejandro Criado-Pérez                    // If the line has to be wrapped
145a25f0a04SGreg Roach                    if ($lw > $wrapWidthRemaining) {
1467a6ee1acSGreg Roach                        $words    = explode(' ', $line);
147a25f0a04SGreg Roach                        $addspace = count($words);
148a25f0a04SGreg Roach                        $lw       = 0;
149a25f0a04SGreg Roach                        foreach ($words as $word) {
150a25f0a04SGreg Roach                            $addspace--;
15167c69ce5SGreg Roach                            $lw += $renderer->getStringWidth($word . ' ');
152a25f0a04SGreg Roach                            if ($lw <= $wrapWidthRemaining) {
153a25f0a04SGreg Roach                                $newtext .= $word;
154b6f35a76SGreg Roach                                if ($addspace !== 0) {
1557a6ee1acSGreg Roach                                    $newtext .= ' ';
156a25f0a04SGreg Roach                                }
157a25f0a04SGreg Roach                            } else {
15867c69ce5SGreg Roach                                $lw = $renderer->getStringWidth($word . ' ');
159a25f0a04SGreg Roach                                $newtext .= "\n$word";
160b6f35a76SGreg Roach                                if ($addspace !== 0) {
1617a6ee1acSGreg Roach                                    $newtext .= ' ';
162a25f0a04SGreg Roach                                }
163a25f0a04SGreg Roach                                // Reset the wrap width to the cell width
164a25f0a04SGreg Roach                                $wrapWidthRemaining = $this->wrapWidthCell;
165a25f0a04SGreg Roach                            }
166a25f0a04SGreg Roach                        }
167a25f0a04SGreg Roach                    } else {
168a25f0a04SGreg Roach                        $newtext .= $line;
169a25f0a04SGreg Roach                    }
170a25f0a04SGreg Roach                    // Check the Line Feed counter
171a25f0a04SGreg Roach                    if ($lfct > 1) {
17267c69ce5SGreg Roach                        // Add a new line as long as it’s not the last line
173a25f0a04SGreg Roach                        $newtext .= "\n";
174a25f0a04SGreg Roach                        // Reset the line width
175a25f0a04SGreg Roach                        $lw = 0;
176a25f0a04SGreg Roach                        // Reset the wrap width to the cell width
177a25f0a04SGreg Roach                        $wrapWidthRemaining = $this->wrapWidthCell;
178a25f0a04SGreg Roach                    }
179a25f0a04SGreg Roach                    $lfct--;
180a25f0a04SGreg Roach                }
181a25f0a04SGreg Roach                $this->text = $newtext;
182a25f0a04SGreg Roach                $lfct       = substr_count($this->text, "\n");
183cbc1590aSGreg Roach
184c1010edaSGreg Roach                return [
185c1010edaSGreg Roach                    $lw,
186c1010edaSGreg Roach                    1,
187c1010edaSGreg Roach                    $lfct,
188c1010edaSGreg Roach                ];
189a25f0a04SGreg Roach            }
190a25f0a04SGreg Roach        }
191a25f0a04SGreg Roach        $l    = 0;
192a25f0a04SGreg Roach        $lfct = substr_count($this->text, "\n");
193a25f0a04SGreg Roach        if ($lfct > 0) {
194a25f0a04SGreg Roach            $l = 2;
195a25f0a04SGreg Roach        }
196cbc1590aSGreg Roach
197c1010edaSGreg Roach        return [
198c1010edaSGreg Roach            $lw,
199c1010edaSGreg Roach            $l,
200c1010edaSGreg Roach            $lfct,
201c1010edaSGreg Roach        ];
202a25f0a04SGreg Roach    }
203a25f0a04SGreg Roach}
204