Passed
Push — main ( 52f862...f41333 )
by ANDREY
02:25
created

GlyphBlock::isFS()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

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