7b96db8fa97a7a53e7ea842a1509cfea755f8182
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Imaging / ImageManipulation / Area.php
1 <?php
2 declare(strict_types=1);
3 namespace TYPO3\CMS\Core\Imaging\ImageManipulation;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 use TYPO3\CMS\Core\Resource\FileInterface;
19
20 class Area
21 {
22 /**
23 * @var float
24 */
25 protected $x;
26
27 /**
28 * @var float
29 */
30 protected $y;
31
32 /**
33 * @var float
34 */
35 protected $width;
36
37 /**
38 * @var float
39 */
40 protected $height;
41
42 /**
43 * @param float $x
44 * @param float $y
45 * @param float $width
46 * @param float $height
47 */
48 public function __construct(float $x, float $y, float $width, float $height)
49 {
50 $this->x = $x;
51 $this->y = $y;
52 $this->width = $width;
53 $this->height = $height;
54 }
55
56 /**
57 * @param array $config
58 * @return Area
59 * @throws InvalidConfigurationException
60 */
61 public static function createFromConfiguration(array $config): Area
62 {
63 try {
64 return new self(
65 (float)$config['x'],
66 (float)$config['y'],
67 (float)$config['width'],
68 (float)$config['height']
69 );
70 } catch (\Throwable $throwable) {
71 throw new InvalidConfigurationException(sprintf('Invalid type for area property given: %s', $throwable->getMessage()), 1485279226, $throwable);
72 }
73 }
74
75 /**
76 * @param array $config
77 * @return Area[]
78 * @throws InvalidConfigurationException
79 */
80 public static function createMultipleFromConfiguration(array $config): array
81 {
82 $areas = [];
83 foreach ($config as $areaConfig) {
84 $areas[] = self::createFromConfiguration($areaConfig);
85 }
86 return $areas;
87 }
88
89 /**
90 * @return Area
91 */
92 public static function createEmpty()
93 {
94 return new self(0.0, 0.0, 1.0, 1.0);
95 }
96
97 /**
98 * @return array
99 * @internal
100 */
101 public function asArray(): array
102 {
103 return [
104 'x' => $this->x,
105 'y' => $this->y,
106 'width' => $this->width,
107 'height' => $this->height,
108 ];
109 }
110
111 /**
112 * @param FileInterface $file
113 * @return Area
114 */
115 public function makeAbsoluteBasedOnFile(FileInterface $file)
116 {
117 return new self(
118 $this->x * $file->getProperty('width'),
119 $this->y * $file->getProperty('height'),
120 $this->width * $file->getProperty('width'),
121 $this->height * $file->getProperty('height')
122 );
123 }
124
125 /**
126 * @param FileInterface $file
127 * @return Area
128 */
129 public function makeRelativeBasedOnFile(FileInterface $file)
130 {
131 $width = $file->getProperty('width');
132 $height = $file->getProperty('height');
133
134 if (empty($width) || empty($height)) {
135 return self::createEmpty();
136 }
137
138 return new self(
139 $this->x / $width,
140 $this->y / $height,
141 $this->width / $width,
142 $this->height / $height
143 );
144 }
145
146 /**
147 * @param Ratio $ratio
148 * @return Area
149 */
150 public function applyRatioRestriction(Ratio $ratio): Area
151 {
152 if ($ratio->isFree()) {
153 return $this;
154 }
155 $expectedRatio = $ratio->getRatioValue();
156 $newArea = clone $this;
157 if ($newArea->height * $expectedRatio > $newArea->width) {
158 $newArea->height = $newArea->width / $expectedRatio;
159 $newArea->y += ($this->height - $newArea->height) / 2;
160 } else {
161 $newArea->width = $newArea->height * $expectedRatio;
162 $newArea->x += ($this->width - $newArea->width) / 2;
163 }
164 return $newArea;
165 }
166
167 /**
168 * @return bool
169 */
170 public function isEmpty()
171 {
172 return $this->x === 0.0 && $this->y === 0.0 && $this->width === 1.0 && $this->height === 1.0;
173 }
174
175 /**
176 * @return string
177 */
178 public function __toString()
179 {
180 if ($this->isEmpty()) {
181 return '';
182 } else {
183 return json_encode($this->asArray());
184 }
185 }
186 }