xref: /webtrees/app/Report/ReportHtmlText.php (revision ca50fb84724cb523ca8f4be8abd453a667296dcf)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * Copyright (C) 2019 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 <http://www.gnu.org/licenses/>.
16 */
17
18declare(strict_types=1);
19
20namespace Fisharebest\Webtrees\Report;
21
22/**
23 * Class ReportHtmlText
24 */
25class ReportHtmlText extends ReportBaseText
26{
27    /**
28     * Render the elements.
29     *
30     * @param ReportHtml $renderer
31     * @param int        $curx
32     * @param bool       $attrib Is is called from a different element?
33     *
34     * @return void
35     */
36    public function render($renderer, $curx = 0, $attrib = true)
37    {
38        // Set up the style
39        if ($renderer->getCurrentStyle() != $this->styleName) {
40            $renderer->setCurrentStyle($this->styleName);
41        }
42        $temptext = str_replace('#PAGENUM#', (string) $renderer->pageNo(), $this->text);
43        // underline «title» part of Source item
44        $temptext = str_replace([
45            '«',
46            '»',
47        ], [
48            '<u>',
49            '</u>',
50        ], $temptext);
51
52        // If any text at all
53        if (!empty($temptext)) {
54            // If called by an other element
55            if (!$attrib) {
56                $renderer->write($temptext, $this->color);
57            } else {
58                // Save the start positions
59                $startX = $renderer->getX();
60                $startY = $renderer->getY();
61                $width  = $renderer->getRemainingWidth();
62                // If text is wider then page width then wrap it
63                if ($renderer->getStringWidth($temptext) > $width) {
64                    $lines = explode("\n", $temptext);
65                    foreach ($lines as $line) {
66                        echo '<div style="position:absolute;top:', $startY, 'pt;', $renderer->alignRTL, ':', $startX, 'pt;width:', $width, 'pt;">';
67                        $line = $renderer->textWrap($line, $width);
68                        $startY += $renderer->getTextCellHeight($line);
69                        $renderer->setY($startY);
70                        $renderer->write($line, $this->color);
71                        echo "</div>\n";
72                    }
73                } else {
74                    echo '<div style="position:absolute;top:', $startY, 'pt;', $renderer->alignRTL, ':', $startX, 'pt;width:', $width, 'pt;">';
75                    $renderer->write($temptext, $this->color);
76                    echo "</div>\n";
77                    $renderer->setX($startX + $renderer->getStringWidth($temptext));
78                    if ($renderer->countLines($temptext) != 1) {
79                        $renderer->setXy(0, $startY + $renderer->getTextCellHeight($temptext));
80                    }
81                }
82            }
83        }
84    }
85
86    /**
87     * Returns the height in points of the text element
88     * The height is already calculated in getWidth()
89     *
90     * @param ReportHtml $renderer
91     *
92     * @return float
93     */
94    public function getHeight($renderer): float
95    {
96        $ct = substr_count($this->text, "\n");
97        if ($ct > 0) {
98            $ct += 1;
99        }
100        $style = $renderer->getStyle($this->styleName);
101
102        return ($style['size'] * $ct) * $renderer->cellHeightRatio;
103    }
104
105    /**
106     * Get the width of text and wrap it too
107     *
108     * @param ReportHtml $renderer
109     *
110     * @return float|array
111     */
112    public function getWidth($renderer)
113    {
114        // Setup the style name, a font must be selected to calculate the width
115        if ($renderer->getCurrentStyle() != $this->styleName) {
116            $renderer->setCurrentStyle($this->styleName);
117        }
118
119        // Check for the largest font size in the box
120        $fsize = $renderer->getCurrentStyleHeight();
121        if ($fsize > $renderer->largestFontHeight) {
122            $renderer->largestFontHeight = $fsize;
123        }
124
125        // Get the line width for the text in points
126        $lw = $renderer->getStringWidth($this->text);
127        // Line Feed counter - Number of lines in the text
128        $lfct = $renderer->countLines($this->text);
129        // If there is still remaining wrap width...
130        $wrapWidthRemaining = $this->wrapWidthRemaining;
131        if ($wrapWidthRemaining > 0) {
132            // Check with line counter too!
133            if ($lw >= $wrapWidthRemaining || $lfct > 1) {
134                $newtext            = '';
135                $lines              = explode("\n", $this->text);
136                // Go throught the text line by line
137                foreach ($lines as $line) {
138                    // Line width in points + a little margin
139                    $lw = $renderer->getStringWidth($line);
140                    // If the line has to be wraped
141                    if ($lw > $wrapWidthRemaining) {
142                        $words    = explode(' ', $line);
143                        $addspace = count($words);
144                        $lw       = 0;
145                        foreach ($words as $word) {
146                            $addspace--;
147                            $lw += $renderer->getStringWidth($word . ' ');
148                            if ($lw <= $wrapWidthRemaining) {
149                                $newtext .= $word;
150                                if ($addspace != 0) {
151                                    $newtext .= ' ';
152                                }
153                            } else {
154                                $lw = $renderer->getStringWidth($word . ' ');
155                                $newtext .= "\n$word";
156                                if ($addspace != 0) {
157                                    $newtext .= ' ';
158                                }
159                                // Reset the wrap width to the cell width
160                                $wrapWidthRemaining = $this->wrapWidthCell;
161                            }
162                        }
163                    } else {
164                        $newtext .= $line;
165                    }
166                    // Check the Line Feed counter
167                    if ($lfct > 1) {
168                        // Add a new line as long as it’s not the last line
169                        $newtext .= "\n";
170                        // Reset the line width
171                        $lw = 0;
172                        // Reset the wrap width to the cell width
173                        $wrapWidthRemaining = $this->wrapWidthCell;
174                    }
175                    $lfct--;
176                }
177                $this->text = $newtext;
178                $lfct       = substr_count($this->text, "\n");
179
180                return [
181                    $lw,
182                    1,
183                    $lfct,
184                ];
185            }
186        }
187        $l    = 0;
188        $lfct = substr_count($this->text, "\n");
189        if ($lfct > 0) {
190            $l = 2;
191        }
192
193        return [
194            $lw,
195            $l,
196            $lfct,
197        ];
198    }
199}
200