xref: /webtrees/app/Report/ReportHtmlFootnote.php (revision b11cdcd45131b1585d66693fab363cfeb18c51a4)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * 'Copyright (C) 2023 webtrees development team
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18declare(strict_types=1);
19
20namespace Fisharebest\Webtrees\Report;
21
22use function count;
23use function explode;
24use function str_replace;
25use function substr_count;
26
27/**
28 * Class ReportHtmlFootnote
29 */
30class ReportHtmlFootnote extends ReportBaseFootnote
31{
32    /**
33     * HTML Footnotes number renderer
34     *
35     * @param HtmlRenderer $renderer
36     *
37     * @return void
38     */
39    public function render($renderer): void
40    {
41        $renderer->setCurrentStyle('footnotenum');
42        echo '<a href="#footnote', $this->num, '"><sup>';
43        $renderer->write($renderer->entityRTL . $this->num);
44        echo "</sup></a>\n";
45    }
46
47    /**
48     * Write the Footnote text
49     * Uses style name "footnote" by default
50     *
51     * @param HtmlRenderer $renderer
52     *
53     * @return void
54     */
55    public function renderFootnote($renderer): void
56    {
57        if ($renderer->getCurrentStyle() !== $this->styleName) {
58            $renderer->setCurrentStyle($this->styleName);
59        }
60
61        $temptext = str_replace('#PAGENUM#', (string) $renderer->pageNo(), $this->text);
62        // underline «title» part of Source item
63        $temptext = str_replace([
64            '«',
65            '»',
66        ], [
67            '<u>',
68            '</u>',
69        ], $temptext);
70        echo '<div><a id="footnote', $this->num, '"></a>';
71        $renderer->write($this->num . '. ' . $temptext);
72        echo '</div>';
73
74        $renderer->setXy(0, $renderer->getY() + $this->getFootnoteHeight($renderer));
75    }
76
77    /**
78     * Calculates the Footnotes height
79     *
80     * @param HtmlRenderer $renderer
81     * @param float        $cellWidth The width of the cell to use it for text wraping
82     *
83     * @return float     Footnote height in points
84     */
85    public function getFootnoteHeight(HtmlRenderer $renderer, float $cellWidth = 0): float
86    {
87        if ($renderer->getCurrentStyle() !== $this->styleName) {
88            $renderer->setCurrentStyle($this->styleName);
89        }
90
91        if ($cellWidth > 0) {
92            $this->text = $renderer->textWrap($this->text, $cellWidth);
93        }
94
95        $this->text .= "\n\n";
96        $ct         = substr_count($this->text, "\n");
97        $fsize      = $renderer->getCurrentStyleHeight();
98
99        return $fsize * $ct * $renderer->cellHeightRatio;
100    }
101
102    /**
103     * Get the width of text
104     * Breaks up a text into lines if needed
105     *
106     * @param HtmlRenderer $renderer
107     *
108     * @return array{0:float,1:int,2:float}
109     */
110    public function getWidth($renderer): array
111    {
112        // Setup the style name
113        $renderer->setCurrentStyle('footnotenum');
114
115        // Check for the largest font size in the box
116        $fsize = $renderer->getCurrentStyleHeight();
117        if ($fsize > $renderer->largestFontHeight) {
118            $renderer->largestFontHeight = $fsize;
119        }
120
121        // Returns the Object if already numbered else false
122        if (empty($this->num)) {
123            $renderer->checkFootnote($this);
124        }
125
126        // Get the line width for the text in points + a little margin
127        $lw = $renderer->getStringWidth($this->numText);
128        // Line Feed counter - Number of lines in the text
129        $lfct = $renderer->countLines($this->numText);
130        // If there is still remaining wrap width...
131        if ($this->wrapWidthRemaining > 0) {
132            // Check with line counter too!
133            if ($lw >= $this->wrapWidthRemaining || $lfct > 1) {
134                $newtext            = '';
135                $wrapWidthRemaining = $this->wrapWidthRemaining;
136                $lines              = explode("\n", $this->numText);
137                // Go throught the text line by line
138                foreach ($lines as $line) {
139                    // Line width in points + a little margin
140                    $lw = $renderer->getStringWidth($line);
141                    // If the line has to be wraped
142                    if ($lw > $wrapWidthRemaining) {
143                        $words    = explode(' ', $line);
144                        $addspace = count($words);
145                        $lw       = 0;
146                        foreach ($words as $word) {
147                            $addspace--;
148                            $lw += $renderer->getStringWidth($word . ' ');
149                            if ($lw <= $wrapWidthRemaining) {
150                                $newtext .= $word;
151                                if ($addspace !== 0) {
152                                    $newtext .= ' ';
153                                }
154                            } else {
155                                $lw = $renderer->getStringWidth($word . ' ');
156                                $newtext .= "\n$word";
157                                if ($addspace !== 0) {
158                                    $newtext .= ' ';
159                                }
160                                // Reset the wrap width to the cell width
161                                $wrapWidthRemaining = $this->wrapWidthCell;
162                            }
163                        }
164                    } else {
165                        $newtext .= $line;
166                    }
167                    // Check the Line Feed counter
168                    if ($lfct > 1) {
169                        // Add a new line feed as long as it’s not the last line
170                        $newtext .= "\n";
171                        // Reset the line width
172                        $lw = 0;
173                        // Reset the wrap width to the cell width
174                        $wrapWidthRemaining = $this->wrapWidthCell;
175                    }
176                    $lfct--;
177                }
178                $this->numText = $newtext;
179                $lfct          = substr_count($this->numText, "\n");
180
181                return [
182                    $lw,
183                    1,
184                    $lfct,
185                ];
186            }
187        }
188        $l    = 0;
189        $lfct = substr_count($this->numText, "\n");
190        if ($lfct > 0) {
191            $l = 2;
192        }
193
194        return [
195            $lw,
196            $l,
197            $lfct,
198        ];
199    }
200}
201