Skip to content

Commit 5806f69

Browse files
committed
Use composition instead of inheritance
1 parent f0fe689 commit 5806f69

File tree

5 files changed

+277
-219
lines changed

5 files changed

+277
-219
lines changed

src/Writer/AbstractGdWriter.php

Lines changed: 9 additions & 207 deletions
Original file line numberDiff line numberDiff line change
@@ -4,229 +4,31 @@
44

55
namespace Endroid\QrCode\Writer;
66

7-
use Endroid\QrCode\Bacon\MatrixFactory;
8-
use Endroid\QrCode\Exception\ValidationException;
9-
use Endroid\QrCode\ImageData\LabelImageData;
10-
use Endroid\QrCode\ImageData\LogoImageData;
11-
use Endroid\QrCode\Label\LabelAlignment;
127
use Endroid\QrCode\Label\LabelInterface;
138
use Endroid\QrCode\Logo\LogoInterface;
14-
use Endroid\QrCode\Matrix\MatrixInterface;
159
use Endroid\QrCode\QrCodeInterface;
16-
use Endroid\QrCode\RoundBlockSizeMode;
1710
use Endroid\QrCode\Writer\Result\GdResult;
1811
use Endroid\QrCode\Writer\Result\ResultInterface;
19-
use Zxing\QrReader;
2012

13+
/**
14+
* @deprecated since 6.0, use GdWriter instead. This class will be removed in 7.0.
15+
*/
2116
abstract class AbstractGdWriter implements WriterInterface, ValidatingWriterInterface
2217
{
23-
protected function getMatrix(QrCodeInterface $qrCode): MatrixInterface
24-
{
25-
$matrixFactory = new MatrixFactory();
26-
27-
return $matrixFactory->create($qrCode);
28-
}
29-
30-
public function write(QrCodeInterface $qrCode, ?LogoInterface $logo = null, ?LabelInterface $label = null, array $options = []): ResultInterface
31-
{
32-
if (!extension_loaded('gd')) {
33-
throw new \Exception('Unable to generate image: please check if the GD extension is enabled and configured correctly');
34-
}
35-
36-
$matrix = $this->getMatrix($qrCode);
37-
38-
$baseBlockSize = RoundBlockSizeMode::None === $qrCode->getRoundBlockSizeMode() ? 10 : intval($matrix->getBlockSize());
39-
/** @var int<1, max> $baseImageSize */
40-
$baseImageSize = $matrix->getBlockCount() * $baseBlockSize;
41-
$baseImage = imagecreatetruecolor($baseImageSize, $baseImageSize);
42-
43-
if (!$baseImage) {
44-
throw new \Exception('Unable to generate image: please check if the GD extension is enabled and configured correctly');
45-
}
46-
47-
$foregroundColor = imagecolorallocatealpha(
48-
$baseImage,
49-
$qrCode->getForegroundColor()->getRed(),
50-
$qrCode->getForegroundColor()->getGreen(),
51-
$qrCode->getForegroundColor()->getBlue(),
52-
$qrCode->getForegroundColor()->getAlpha()
53-
);
54-
55-
if (false === $foregroundColor) {
56-
throw new \Exception('Unable to generate image: please check if the GD extension is enabled and configured correctly');
57-
}
58-
59-
$transparentColor = imagecolorallocatealpha($baseImage, 255, 255, 255, 127);
60-
61-
if (false === $transparentColor) {
62-
throw new \Exception('Unable to generate image: please check if the GD extension is enabled and configured correctly');
63-
}
64-
65-
imagefill($baseImage, 0, 0, $transparentColor);
66-
67-
for ($rowIndex = 0; $rowIndex < $matrix->getBlockCount(); ++$rowIndex) {
68-
for ($columnIndex = 0; $columnIndex < $matrix->getBlockCount(); ++$columnIndex) {
69-
if (1 === $matrix->getBlockValue($rowIndex, $columnIndex)) {
70-
imagefilledrectangle(
71-
$baseImage,
72-
$columnIndex * $baseBlockSize,
73-
$rowIndex * $baseBlockSize,
74-
($columnIndex + 1) * $baseBlockSize - 1,
75-
($rowIndex + 1) * $baseBlockSize - 1,
76-
$foregroundColor
77-
);
78-
}
79-
}
80-
}
81-
82-
/** @var int<1, max> $targetWidth */
83-
$targetWidth = $matrix->getOuterSize();
84-
/** @var int<1, max> $targetHeight */
85-
$targetHeight = $matrix->getOuterSize();
86-
87-
if ($label instanceof LabelInterface) {
88-
$labelImageData = LabelImageData::createForLabel($label);
89-
$targetHeight += $labelImageData->getHeight() + $label->getMargin()->getTop() + $label->getMargin()->getBottom();
90-
}
91-
92-
/** @var int<1, max> $targetHeight */
93-
$targetImage = imagecreatetruecolor($targetWidth, $targetHeight);
94-
95-
if (!$targetImage) {
96-
throw new \Exception('Unable to generate image: please check if the GD extension is enabled and configured correctly');
97-
}
98-
99-
$backgroundColor = imagecolorallocatealpha(
100-
$targetImage,
101-
$qrCode->getBackgroundColor()->getRed(),
102-
$qrCode->getBackgroundColor()->getGreen(),
103-
$qrCode->getBackgroundColor()->getBlue(),
104-
$qrCode->getBackgroundColor()->getAlpha()
105-
);
106-
107-
if (false === $backgroundColor) {
108-
throw new \Exception('Unable to generate image: please check if the GD extension is enabled and configured correctly');
109-
}
110-
111-
imagefill($targetImage, 0, 0, $backgroundColor);
112-
113-
imagecopyresampled(
114-
$targetImage,
115-
$baseImage,
116-
$matrix->getMarginLeft(),
117-
$matrix->getMarginLeft(),
118-
0,
119-
0,
120-
$matrix->getInnerSize(),
121-
$matrix->getInnerSize(),
122-
imagesx($baseImage),
123-
imagesy($baseImage)
124-
);
18+
private GdWriter $gdWriter;
12519

126-
if ($qrCode->getBackgroundColor()->getAlpha() > 0) {
127-
imagesavealpha($targetImage, true);
128-
}
129-
130-
$result = new GdResult($matrix, $targetImage);
131-
132-
if ($logo instanceof LogoInterface) {
133-
$result = $this->addLogo($logo, $result);
134-
}
135-
136-
if ($label instanceof LabelInterface) {
137-
$result = $this->addLabel($label, $result);
138-
}
139-
140-
return $result;
141-
}
142-
143-
private function addLogo(LogoInterface $logo, GdResult $result): GdResult
20+
public function __construct()
14421
{
145-
$logoImageData = LogoImageData::createForLogo($logo);
146-
147-
if ('image/svg+xml' === $logoImageData->getMimeType()) {
148-
throw new \Exception('PNG Writer does not support SVG logo');
149-
}
150-
151-
$targetImage = $result->getImage();
152-
$matrix = $result->getMatrix();
153-
154-
if ($logoImageData->getPunchoutBackground()) {
155-
$transparent = imagecolorallocatealpha($targetImage, 255, 255, 255, 127);
156-
157-
if (false === $transparent) {
158-
throw new \Exception('Unable to allocate color: please check if the GD extension is enabled and configured correctly');
159-
}
160-
161-
imagealphablending($targetImage, false);
162-
$xOffsetStart = intval($matrix->getOuterSize() / 2 - $logoImageData->getWidth() / 2);
163-
$yOffsetStart = intval($matrix->getOuterSize() / 2 - $logoImageData->getHeight() / 2);
164-
for ($xOffset = $xOffsetStart; $xOffset < $xOffsetStart + $logoImageData->getWidth(); ++$xOffset) {
165-
for ($yOffset = $yOffsetStart; $yOffset < $yOffsetStart + $logoImageData->getHeight(); ++$yOffset) {
166-
imagesetpixel($targetImage, $xOffset, $yOffset, $transparent);
167-
}
168-
}
169-
}
170-
171-
imagecopyresampled(
172-
$targetImage,
173-
$logoImageData->getImage(),
174-
intval($matrix->getOuterSize() / 2 - $logoImageData->getWidth() / 2),
175-
intval($matrix->getOuterSize() / 2 - $logoImageData->getHeight() / 2),
176-
0,
177-
0,
178-
$logoImageData->getWidth(),
179-
$logoImageData->getHeight(),
180-
imagesx($logoImageData->getImage()),
181-
imagesy($logoImageData->getImage())
182-
);
183-
184-
return new GdResult($matrix, $targetImage);
22+
$this->gdWriter = new GdWriter();
18523
}
18624

187-
private function addLabel(LabelInterface $label, GdResult $result): GdResult
25+
public function write(QrCodeInterface $qrCode, ?LogoInterface $logo = null, ?LabelInterface $label = null, array $options = []): GdResult
18826
{
189-
$targetImage = $result->getImage();
190-
191-
$labelImageData = LabelImageData::createForLabel($label);
192-
193-
$textColor = imagecolorallocatealpha(
194-
$targetImage,
195-
$label->getTextColor()->getRed(),
196-
$label->getTextColor()->getGreen(),
197-
$label->getTextColor()->getBlue(),
198-
$label->getTextColor()->getAlpha()
199-
);
200-
201-
if (false === $textColor) {
202-
throw new \Exception('Unable to allocate color: please check if the GD extension is enabled and configured correctly');
203-
}
204-
205-
$x = intval(imagesx($targetImage) / 2 - $labelImageData->getWidth() / 2);
206-
$y = imagesy($targetImage) - $label->getMargin()->getBottom();
207-
208-
if (LabelAlignment::Left === $label->getAlignment()) {
209-
$x = $label->getMargin()->getLeft();
210-
} elseif (LabelAlignment::Right === $label->getAlignment()) {
211-
$x = imagesx($targetImage) - $labelImageData->getWidth() - $label->getMargin()->getRight();
212-
}
213-
214-
imagettftext($targetImage, $label->getFont()->getSize(), 0, $x, $y, $textColor, $label->getFont()->getPath(), $label->getText());
215-
216-
return new GdResult($result->getMatrix(), $targetImage);
27+
return $this->gdWriter->write($qrCode, $logo, $label, $options);
21728
}
21829

21930
public function validateResult(ResultInterface $result, string $expectedData): void
22031
{
221-
$string = $result->getString();
222-
223-
if (!class_exists(QrReader::class)) {
224-
throw ValidationException::createForMissingPackage('khanamiryan/qrcode-detector-decoder');
225-
}
226-
227-
$reader = new QrReader($string, QrReader::SOURCE_TYPE_BLOB);
228-
if ($reader->text() !== $expectedData) {
229-
throw ValidationException::createForInvalidData($expectedData, strval($reader->text()));
230-
}
32+
$this->gdWriter->validateResult($result, $expectedData);
23133
}
23234
}

0 commit comments

Comments
 (0)