GlyphBlock::renderBySprites()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 4
eloc 7
c 2
b 0
f 0
nc 4
nop 0
dl 0
loc 9
ccs 8
cts 8
cp 1
crap 4
rs 10
1
<?php
2
3
namespace VPA\Console\Glyphs;
4
5
use VPA\Console\Color;
6
use VPA\Console\FrameConfigInterface;
7
use VPA\Console\Symbol;
8
use VPA\Console\SymbolMode;
9
10
abstract class GlyphBlock extends Glyph
11
{
12
    /**
13
     * @var mixed
14
     */
15
    private int $deltaWidth;
16
    private int $deltaHeight;
17
18 46
    public function __construct(protected FrameConfigInterface $globalConfig)
19
    {
20 46
        parent::__construct($globalConfig);
21 46
        $this->config = array_merge(
22 46
            parent::getConfig(),
23
            [
24 46
                'paddingTop' => 0,
25
                'paddingLeft' => 0,
26
                'paddingRight' => 0,
27
                'paddingBottom' => 0,
28
                'borderTop' => 0,
29
                'borderLeft' => 0,
30
                'borderRight' => 0,
31
                'borderBottom' => 0,
32
                'borderColor' => Color::WHITE,
33
                'backgroundColor' => Color::BLACK,
34
            ]
35
        );
36 46
        $this->calculateDeltaWidth();
37 46
        $this->calculateDeltaHeight();
38
    }
39
40 26
    public function getContentWidth(): int
41
    {
42 26
        return $this->width - $this->deltaWidth;
43
    }
44
45 29
    public function getDeltaWidth(): int
46
    {
47 29
        return $this->deltaWidth;
48
    }
49
50 19
    public function getDeltaHeight(): int
51
    {
52 19
        return $this->deltaHeight;
53
    }
54
55
56 1
    public function getContentHeight(): int
57
    {
58 1
        return $this->height - $this->deltaHeight;
59
    }
60
61 46
    private function calculateDeltaWidth(): void
62
    {
63 46
        $this->deltaWidth = $this->__get('paddingLeft') +
64 46
            $this->__get('borderLeft') +
65 46
            $this->__get('paddingRight') +
66 46
            $this->__get('borderRight');
67
    }
68
69 46
    private function calculateDeltaHeight(): void
70
    {
71 46
        $this->deltaHeight = $this->__get('paddingTop') +
72 46
            $this->__get('borderTop') +
73 46
            $this->__get('paddingBottom') +
74 46
            $this->__get('borderBottom');
75
    }
76
77 11
    public function setPadding(int $paddingLeft, int $paddingRight, int $paddingTop, int $paddingBottom): GlyphBlock
78
    {
79 11
        $this->__set('paddingTop', $paddingTop);
80 11
        $this->__set('paddingLeft', $paddingLeft);
81 11
        $this->__set('paddingRight', $paddingRight);
82 11
        $this->__set('paddingBottom', $paddingBottom);
83 11
        $this->calculateDeltaWidth();
84 11
        $this->calculateDeltaHeight();
85 11
        return $this;
86
    }
87
88 11
    public function setBorder(int $borderLeft, int $borderRight, int $borderTop, int $borderBottom): GlyphBlock
89
    {
90 11
        $this->__set('borderTop', $borderTop);
91 11
        $this->__set('borderLeft', $borderLeft);
92 11
        $this->__set('borderRight', $borderRight);
93 11
        $this->__set('borderBottom', $borderBottom);
94 11
        $this->calculateDeltaWidth();
95 11
        $this->calculateDeltaHeight();
96 11
        return $this;
97
    }
98
99 11
    public function appendWidth(int $value): void
100
    {
101 11
        $this->offsetX = $this->__get('paddingLeft') + $this->__get('borderLeft');
102 11
        $this->contentWidth = $value;
103 11
        $this->width = $value + $this->deltaWidth;
104
    }
105
106 11
    public function appendHeight(int $value): void
107
    {
108 11
        $this->offsetY = $this->__get('paddingTop') + $this->__get('borderTop');
109 11
        $this->contentHeight = $value;
110 11
        $this->height = $value + $this->deltaHeight;
111
    }
112
113 17
    public function getWidthByContent(int $endOfPreviousSibling = 0): int
114
    {
115 17
        if ($this->renderedWidth) {
116 5
            return $this->width;
117
        }
118 15
        $this->offsetX = $this->__get('paddingLeft') + $this->__get('borderLeft');
119 15
        $this->setX($endOfPreviousSibling);
120 15
        $this->contentWidth = 0;
121 15
        foreach ($this->getChildren() as $child) {
122 12
            $childWidth = $child->getWidthByContent();
123 12
            $this->contentWidth = ($childWidth > $this->contentWidth) ? $childWidth : $this->contentWidth;
124
        }
125 15
        $this->width = $this->contentWidth + $this->getDeltaWidth();
126 15
        $this->renderedWidth = true;
127 15
        return $this->width;
128
    }
129
130 19
    public function getHeightByContent(int $endOfPreviousSibling = 0): int
131
    {
132 19
        if ($this->renderedHeight) {
133 3
            return $this->height;
134
        }
135 19
        $deltaTop = $this->__get('paddingTop') + $this->__get('borderTop');
136 19
        $this->setY($endOfPreviousSibling);
137 19
        $this->offsetY = $deltaTop;
138 19
        $this->height = 0;
139 19
        $offset = 0;
140 19
        foreach ($this->children as $child) {
141 16
            $height = $child->getHeightByContent($offset);
142 16
            $offset += $height;
143 16
            $this->contentHeight = $offset;
144
        }
145 19
        $this->height = $this->contentHeight + $this->getDeltaHeight();
146 19
        $this->renderedHeight = true;
147 19
        return $this->height;
148
    }
149
150 14
    public function render(): Glyph
151
    {
152 14
        $this->getWidthByContent();
153 14
        $this->getHeightByContent();
154 14
        parent::render();
155 14
        $this->renderBorder();
156 14
        $this->renderBySprites();
157 14
        return $this;
158
    }
159
160 14
    protected function renderBorder(): void
161
    {
162 14
        $this->renderBorderTop();
163 14
        $this->renderBorderBottom();
164 14
        $this->renderBorderLeft();
165 14
        $this->renderBorderRight();
166
    }
167
168 14
    private function renderBorderTop(): void
169
    {
170 14
        if ($this->__get('borderTop')) {
171 8
            for ($i = 0; $i < $this->getWidth(); $i++) {
172 8
                $this->renderMap[0][$i] = clone $this->gc('lineHorizontal');
173
            }
174
        }
175
    }
176
177 14
    private function renderBorderBottom()
178
    {
179 14
        $height = $this->getHeight();
180 14
        if ($this->__get('borderBottom')) {
181 8
            for ($i = 0; $i < $this->getWidth(); $i++) {
182 8
                $this->renderMap[$height - 1][$i] = clone $this->gc('lineHorizontal');
183
            }
184
        }
185
    }
186
187 14
    private function renderBorderLeft()
188
    {
189 14
        $height = $this->getHeight();
190 14
        if ($this->__get('borderLeft')) {
191 8
            for ($i = 0; $i < $height; $i++) {
192 8
                if ($i == 0 && $this->renderMap[$i][0]->is($this->gc('lineHorizontal'))) {
193 8
                    $this->renderMap[$i][0] = clone $this->gc('cornerLeftTop');
194 8
                } elseif ($i == $height - 1 && $this->renderMap[$i][0]->is($this->gc('lineHorizontal'))) {
195 7
                    $this->renderMap[$i][0] = clone $this->gc('cornerLeftBottom');
196
                } else {
197 7
                    $this->renderMap[$i][0] = clone $this->gc('lineVertical');
198
                }
199
            }
200
        }
201
    }
202
203 14
    private function renderBorderRight(): void
204
    {
205 14
        $width = $this->getWidth();
206 14
        $height = $this->getHeight();
207 14
        if ($this->__get('borderRight')) {
208 8
            for ($i = 0; $i < $height; $i++) {
209 8
                if ($i == 0 && $this->renderMap[$i][$width - 1]->is($this->gc('lineHorizontal'))) {
210 8
                    $this->renderMap[$i][$width - 1] = clone $this->gc('cornerRightTop');
211
                } elseif (
212 8
                    $i == $height - 1 &&
213 8
                    $this->renderMap[$i][$width - 1]->is($this->gc('lineHorizontal'))
214
                ) {
215 8
                    $this->renderMap[$i][$width - 1] = clone $this->gc('cornerRightBottom');
216
                } else {
217 7
                    $this->renderMap[$i][$width - 1] = clone $this->gc('lineVertical');
218
                }
219
            }
220
        }
221
    }
222
223 14
    protected function renderBySprites(): void
224
    {
225 14
        $this->cachedRenderMap = $this->renderMap;
226 14
        foreach ($this->renderMap as $y => $line) {
227 14
            foreach ($line as $x => $symbol) {
228 14
                $codes = $this->getSprite($x, $y);
229 14
                $newSymbol = $this->pattern($codes);
230 14
                if ($newSymbol) {
231 6
                    $this->renderMap[$y][$x] = $newSymbol;
232
                }
233
            }
234
        }
235
    }
236
237 14
    private function getSprite(int $x, int $y): string
238
    {
239 14
        $codes = [
240 14
            $this->isFS($y - 1, $x) ? $this->cachedRenderMap[$y - 1][$x]->getAlias() : '0',
241 14
            $this->isFS($y, $x - 1) ? $this->cachedRenderMap[$y][$x - 1]->getAlias() : '0',
242 14
            $this->isFS($y, $x) ? $this->cachedRenderMap[$y][$x]->getAlias() : '0',
243 14
            $this->isFS($y, $x + 1) ? $this->cachedRenderMap[$y][$x + 1]->getAlias() : '0',
244 14
            $this->isFS($y + 1, $x) ? $this->cachedRenderMap[$y + 1][$x]->getAlias() : '0',
245
        ];
246 14
        return implode("", $codes);
247
    }
248
249 14
    private function isFS(int $y, int $x): bool
250
    {
251 14
        return isset($this->cachedRenderMap[$y][$x]) && $this->cachedRenderMap[$y][$x]->getAlias() != '';
252
    }
253
254 14
    private function pattern(string $codes): object|bool
255
    {
256 14
        $codesTable = [
257
            '00|-|' => 'cornerLeftTop',
258
            '00--|' => 'cornerLeftTop',
259
            '0-|0|' => 'cornerRightTop',
260
            '0--0|' => 'cornerRightTop',
261
            '|0|-|' => 'cornerLeftMiddle',
262
            '|0|-z' => 'cornerLeftMiddle',
263
            '|0z-|' => 'cornerLeftMiddle',
264
            '|-|0|' => 'cornerRightMiddle',
265
            '|-|0c' => 'cornerRightMiddle',
266
            '|-c0|' => 'cornerRightMiddle',
267
            '|-|00' => 'cornerRightBottom',
268
            '|0|-0' => 'cornerLeftBottom',
269
            '0---|' => 'cornerMiddleTop',
270
            '0-|-|' => 'cornerMiddleTop',
271
            '0-e-|' => 'cornerMiddleTop',
272
            '|---0' => 'cornerMiddleBottom',
273
            '--|-0' => 'cornerMiddleBottom',
274
            '|-c-0' => 'cornerMiddleBottom',
275
            '|-|-|' => 'cornerMiddleMiddle',
276
            '|-c-|' => 'cornerMiddleMiddle',
277
            '|-q-|' => 'cornerMiddleMiddle',
278
            '|-x-|' => 'cornerMiddleMiddle',
279
        ];
280 14
        if (array_key_exists($codes, $codesTable) && $codesTable[$codes]) {
281 6
            return clone $this->gc($codesTable[$codes]);
282
        }
283 14
        return false;
284
    }
285
286
287
}
288