From dc1bf0b6fb9333a731079444abd70eacde376b5b Mon Sep 17 00:00:00 2001 From: Pavel Bychko Date: Fri, 27 May 2022 20:50:53 +0300 Subject: [PATCH] refactoring --- src/OpenGraphImages.php | 413 +++++++++++++++++++++++++--------------- 1 file changed, 255 insertions(+), 158 deletions(-) diff --git a/src/OpenGraphImages.php b/src/OpenGraphImages.php index 0ac1216..db100f9 100644 --- a/src/OpenGraphImages.php +++ b/src/OpenGraphImages.php @@ -46,6 +46,18 @@ class OpenGraphImages private int $appNameBoxWidth; private int $appNameBoxHeight; + private int $appNameStartX; + private int $appNameStartY; + + private int $appNameDefaultPaddingY = 30; + private int $appNameDefaultPaddingX = 60; + + private int $rectangleX1; + private int $rectangleX2; + private int $rectangleY1; + private int $rectangleY2; + + private Imagick $image; private ?string $imageBlob = null; @@ -286,18 +298,12 @@ protected function createImage(string $text): void { $this->image = new Imagick(); $this->image->newImage($this->imageWidth, $this->imageHeight, $this->backgroundColor); - - /** @var string $text */ - $text = preg_replace('~\s+~', ' ', $text); $this->text = $text; - $this->setTextParameters(); + $this->setParameters(); $this->createText(); - - if ($this->appName) { - $this->setAppNameParameters(); - $this->createAppName(); - } + $this->createAppNameDecoration(); + $this->createAppName(); $format = 'png'; $compression = Imagick::COMPRESSION_ZIP; @@ -362,6 +368,99 @@ protected function fitTextToBox(): void $this->text = $text; } + /** + * @throws ImagickException + * @throws ImagickDrawException + * @throws ImagickPixelException + */ + protected function createText(): void + { + $draw = new ImagickDraw(); + $draw->setStrokeAntialias(true); + $draw->setTextAntialias(true); + $draw->setFont($this->font); + $draw->setFontSize($this->fontSize); + $draw->setFillColor(new ImagickPixel($this->textColor)); + + switch (strtolower($this->textAlignment)) { + case 'center': + $align = Imagick::ALIGN_CENTER; + + break; + case 'right': + $align = Imagick::ALIGN_RIGHT; + + break; + default: + $align = Imagick::ALIGN_LEFT; + + break; + } + $draw->setTextAlignment($align); + + // corrections + $dimensions = $this->image->queryFontMetrics($draw, $this->text); + $this->textStartY = $this->textStartY + $dimensions['characterHeight']; + + $this->image->annotateImage($draw, $this->textStartX, $this->textStartY, 0, $this->text); + } + + /** + * @throws ImagickException + * @throws ImagickPixelException + * @throws ImagickDrawException + */ + protected function createAppName(): void + { + if (is_null($this->appName)) { + return; + } + + $draw = new ImagickDraw(); + $draw->setStrokeAntialias(true); + $draw->setTextAntialias(true); + $draw->setFont($this->appNameFont); + $draw->setFontSize($this->appNameFontSize); + $draw->setFillColor(new ImagickPixel($this->appNameColor)); + + // corrections + $dimensions = $this->image->queryFontMetrics($draw, $this->appName, false); + $this->appNameStartY = $this->appNameStartY + $dimensions['characterHeight']; + + $this->image->annotateImage($draw, $this->appNameStartX, $this->appNameStartY, 0, $this->appName); + } + + /** + * @throws ImagickDrawException + * @throws ImagickPixelException + * @throws ImagickException + */ + protected function createAppNameDecoration(): void + { + if (is_null($this->appName) || is_null($this->appNameDecorationStyle)) { + return; + } + + $draw = new ImagickDraw(); + $draw->setFillColor(new ImagickPixel($this->appNameDecorationColor)); + $draw->rectangle($this->rectangleX1, $this->rectangleY1, $this->rectangleX2, $this->rectangleY2); + $this->image->drawImage($draw); + } + + /** + * @throws ImagickException + * @throws ImagickDrawException + */ + protected function setParameters(): void + { + $this->setTextParameters(); + $this->setAppNameParameters(); + + $this->setLineCoordinates(); + $this->setLabelCoordinates(); + $this->setRectangleCoordinates(); + } + /** * @throws ImagickException * @throws ImagickDrawException @@ -434,221 +533,219 @@ protected function setAppNameParameters(): void } } } - } - /** - * @throws ImagickException - * @throws ImagickDrawException - * @throws ImagickPixelException - */ - protected function createText(): void - { - $draw = new ImagickDraw(); - $draw->setStrokeAntialias(true); - $draw->setTextAntialias(true); - $draw->setFont($this->font); - $draw->setFontSize($this->fontSize); - $draw->setFillColor(new ImagickPixel($this->textColor)); + switch ($this->appNamePosition) { + case 'top-left': + case 'left-top': + $this->appNameStartY = $this->appNameDefaultPaddingY; + $this->appNameStartX = $this->appNameDefaultPaddingX; - switch (strtolower($this->textAlignment)) { - case 'center': - $align = Imagick::ALIGN_CENTER; + break; + case 'bottom-left': + case 'left-bottom': + $this->appNameStartY = $this->imageHeight - $this->appNameDefaultPaddingY - $this->appNameBoxHeight; + $this->appNameStartX = $this->appNameDefaultPaddingX; break; + case 'top-center': + case 'center-top': + $this->appNameStartY = $this->appNameDefaultPaddingY; + $this->appNameStartX = intval(($this->imageWidth / 2) - ($this->appNameBoxWidth / 2)); - case 'right': - $align = Imagick::ALIGN_RIGHT; + break; + case 'bottom-center': + case 'center-bottom': + $this->appNameStartY = $this->imageHeight - $this->appNameDefaultPaddingY - $this->appNameBoxHeight; + $this->appNameStartX = intval(($this->imageWidth / 2) - ($this->appNameBoxWidth / 2)); break; + case 'top-right': + case 'right-top': + $this->appNameStartY = $this->appNameDefaultPaddingY; + $this->appNameStartX = $this->imageWidth - $this->appNameDefaultPaddingX - $this->appNameBoxWidth; - default: - $align = Imagick::ALIGN_LEFT; + break; + case 'bottom-right': + case 'right-bottom': + $this->appNameStartY = $this->imageHeight - $this->appNameDefaultPaddingY - $this->appNameBoxHeight; + $this->appNameStartX = $this->imageWidth - $this->appNameDefaultPaddingX - $this->appNameBoxWidth; break; + default: + $this->appNameStartY = $this->appNameDefaultPaddingY; + $this->appNameStartX = $this->imageWidth - $this->appNameDefaultPaddingX - $this->appNameBoxWidth; } - $draw->setTextAlignment($align); - - // corrections - $dimensions = $this->image->queryFontMetrics($draw, $this->text); - $this->textStartY = $this->textStartY + $dimensions['characterHeight']; - - $this->image->annotateImage($draw, $this->textStartX, $this->textStartY, 0, $this->text); } - /** - * @throws ImagickException - * @throws ImagickPixelException - * @throws ImagickDrawException - */ - protected function createAppName(): void + protected function setLineCoordinates(): void { - if (is_null($this->appName)) { + if ($this->appNameDecorationStyle !== 'line') { return; } - $defaultPaddingY = 30; - $defaultPaddingX = 60; - - $defaultPaddingCenterLabel = 30; - $defaultPaddingLine = 10; - - switch ($this->appNameDecorationStyle) { - case 'label': - $rectangleWidth = 30; - $rectangleHeight = $this->appNameBoxHeight + ($defaultPaddingY * 2); + $defaultPaddingLine = 7; + $rectangleHeight = intval(round($this->imageWidth / 200)); - break; - case 'rectangle': - $rectangleWidth = (($defaultPaddingX) * 2) + $this->appNameBoxWidth; - $rectangleHeight = $this->appNameBoxHeight + ($defaultPaddingY * 2); + switch ($this->appNamePosition) { + case 'top-left': + case 'top-center': + case 'top-right': + case 'left-top': + case 'center-top': + case 'right-top': + $this->rectangleX1 = $this->appNameStartX; + $this->rectangleY1 = $this->appNameStartY + $this->appNameBoxHeight + $defaultPaddingLine; break; + case 'bottom-left': + case 'bottom-center': + case 'bottom-right': + case 'center-bottom': + case 'right-bottom': + case 'left-bottom': default: - $rectangleWidth = 0; - $rectangleHeight = 0; + $this->rectangleX1 = $this->appNameStartX; + $this->rectangleY1 = $this->appNameStartY - $defaultPaddingLine - $rectangleHeight; } + $this->rectangleX2 = $this->rectangleX1 + $this->appNameBoxWidth; + $this->rectangleY2 = $this->rectangleY1 + $rectangleHeight; + } + + protected function setLabelCoordinates(): void + { + if ($this->appNameDecorationStyle !== 'label') { + return; + } + + $rectangleWidth = 30; + $rectangleHeight = $this->appNameBoxHeight + ($this->appNameDefaultPaddingY * 2); + switch ($this->appNamePosition) { case 'top-left': case 'left-top': - $startY = $defaultPaddingY; - $startX = $defaultPaddingX; - - $rectangleY1 = 0; - $rectangleY2 = $rectangleHeight; - $rectangleX1 = 0; - $rectangleX2 = $rectangleWidth; + $this->rectangleX1 = 0; + $this->rectangleY1 = 0; - $lineY1 = $lineY2 = $defaultPaddingY + $this->appNameBoxHeight + $defaultPaddingLine; - $lineX1 = $defaultPaddingX; - $lineX2 = $defaultPaddingX + $this->appNameBoxWidth; + $this->rectangleX2 = $rectangleWidth; + $this->rectangleY2 = $rectangleHeight; break; case 'bottom-left': case 'left-bottom': - $startY = $this->imageHeight - $defaultPaddingY - $this->appNameBoxHeight; - $startX = $defaultPaddingX; + $this->rectangleX1 = 0; + $this->rectangleY1 = $this->imageHeight - $rectangleHeight; - $rectangleY1 = $this->imageHeight - $rectangleHeight; - $rectangleY2 = $this->imageHeight; - $rectangleX1 = 0; - $rectangleX2 = $rectangleWidth; - - $lineY1 = $lineY2 = $startY - $defaultPaddingLine; - $lineX1 = $startX; - $lineX2 = $startX + $this->appNameBoxWidth; + $this->rectangleX2 = $rectangleWidth; + $this->rectangleY2 = $this->imageHeight; break; case 'top-center': case 'center-top': - $startY = $defaultPaddingY; - $startX = intval(($this->imageWidth / 2) - ($this->appNameBoxWidth / 2)); - - $rectangleY1 = 0; - $rectangleY2 = $rectangleHeight; - $rectangleX1 = $startX - $defaultPaddingCenterLabel; - $rectangleX2 = $rectangleX1 + $this->appNameBoxWidth + ($defaultPaddingCenterLabel * 2); - - $lineY1 = $lineY2 = $defaultPaddingY + $this->appNameBoxHeight + $defaultPaddingLine; - $lineX1 = $startX; - $lineX2 = $startX + $this->appNameBoxWidth; - - break; case 'bottom-center': case 'center-bottom': - $startY = $this->imageHeight - $defaultPaddingY - $this->appNameBoxHeight; - $startX = intval(($this->imageWidth / 2) - ($this->appNameBoxWidth / 2)); - - $rectangleY1 = $this->imageHeight - $rectangleHeight; - $rectangleY2 = $this->imageHeight; - $rectangleX1 = $startX - $defaultPaddingCenterLabel; - $rectangleX2 = $rectangleX1 + $this->appNameBoxWidth + ($defaultPaddingCenterLabel * 2); + default: + $this->rectangleX1 = 0; + $this->rectangleY1 = 0; - $lineY1 = $lineY2 = $startY - $defaultPaddingLine; - $lineX1 = $startX; - $lineX2 = $startX + $this->appNameBoxWidth; + $this->rectangleX2 = 0; + $this->rectangleY2 = 0; break; case 'top-right': case 'right-top': - $startY = $defaultPaddingY; - $startX = $this->imageWidth - $defaultPaddingX - $this->appNameBoxWidth; + $this->rectangleX1 = $this->imageWidth - $rectangleWidth; + $this->rectangleY1 = 0; - $rectangleY1 = 0; - $rectangleY2 = $rectangleHeight; - $rectangleX1 = $this->imageWidth - $rectangleWidth; - $rectangleX2 = $this->imageWidth; - - $lineY1 = $lineY2 = $defaultPaddingY + $this->appNameBoxHeight + $defaultPaddingLine; - $lineX1 = $startX; - $lineX2 = $startX + $this->appNameBoxWidth; + $this->rectangleX2 = $this->imageWidth; + $this->rectangleY2 = $rectangleHeight; break; case 'bottom-right': case 'right-bottom': - $startY = $this->imageHeight - $defaultPaddingY - $this->appNameBoxHeight; - $startX = $this->imageWidth - $defaultPaddingX - $this->appNameBoxWidth; + $this->rectangleX1 = $this->imageWidth - $rectangleWidth; + $this->rectangleY1 = $this->imageHeight - $rectangleHeight; - $rectangleY1 = $this->imageHeight - $rectangleHeight; - $rectangleY2 = $this->imageHeight; - $rectangleX1 = $this->imageWidth - $rectangleWidth; - $rectangleX2 = $this->imageWidth; + $this->rectangleX2 = $this->imageWidth; + $this->rectangleY2 = $this->imageHeight; - $lineY1 = $lineY2 = $startY - $defaultPaddingLine; - $lineX1 = $startX; - $lineX2 = $startX + $this->appNameBoxWidth; + break; + } + } + + protected function setRectangleCoordinates(): void + { + if ($this->appNameDecorationStyle !== 'rectangle') { + return; + } + + $defaultPaddingCenterLabel = 30; + $rectangleWidth = (($this->appNameDefaultPaddingX) * 2) + $this->appNameBoxWidth; + $rectangleHeight = $this->appNameBoxHeight + ($this->appNameDefaultPaddingY * 2); + + switch ($this->appNamePosition) { + case 'top-left': + case 'left-top': + $this->rectangleX1 = 0; + $this->rectangleY1 = 0; + + $this->rectangleX2 = $rectangleWidth; + $this->rectangleY2 = $rectangleHeight; break; - default: - $startY = $defaultPaddingY; - $startX = $this->imageWidth - $defaultPaddingX - $this->appNameBoxWidth; + case 'bottom-left': + case 'left-bottom': + $this->rectangleX1 = 0; + $this->rectangleY1 = $this->imageHeight - $rectangleHeight; - $rectangleY1 = $this->imageHeight - $rectangleHeight; - $rectangleY2 = $this->imageHeight; - $rectangleX1 = $this->imageWidth - $rectangleWidth; - $rectangleX2 = $this->imageWidth; + $this->rectangleX2 = $rectangleWidth; + $this->rectangleY2 = $this->imageHeight; - $lineY1 = $lineY2 = $defaultPaddingY + $this->appNameBoxHeight + $defaultPaddingLine; - $lineX1 = $startX; - $lineX2 = $startX + $this->appNameBoxWidth; - } + break; + case 'top-center': + case 'center-top': + $this->rectangleX1 = $this->appNameStartX - $defaultPaddingCenterLabel; + $this->rectangleY1 = 0; - switch ($this->appNameDecorationStyle) { - case 'label': - case 'rectangle': - $draw = new ImagickDraw(); - $draw->setFillColor(new ImagickPixel($this->appNameDecorationColor)); - $draw->rectangle($rectangleX1, $rectangleY1, $rectangleX2, $rectangleY2); - $this->image->drawImage($draw); + $this->rectangleX2 = $this->rectangleX1 + $this->appNameBoxWidth + ($defaultPaddingCenterLabel * 2); + $this->rectangleY2 = $rectangleHeight; break; - case 'line': - $draw = new ImagickDraw(); - $draw->setFillColor(new ImagickPixel($this->appNameDecorationColor)); - $draw->setStrokeColor(new ImagickPixel($this->appNameDecorationColor)); - $draw->setStrokeWidth(intval(round($this->imageWidth / 200))); - $draw->line($lineX1, $lineY1, $lineX2, $lineY2); - $this->image->drawImage($draw); + case 'bottom-center': + case 'center-bottom': + default: + $this->rectangleX1 = $this->appNameStartX - $defaultPaddingCenterLabel; + $this->rectangleY1 = $this->imageHeight - $rectangleHeight; + + $this->rectangleX2 = $this->rectangleX1 + $this->appNameBoxWidth + ($defaultPaddingCenterLabel * 2); + $this->rectangleY2 = $this->imageHeight; break; - } + case 'top-right': + case 'right-top': + $this->rectangleX1 = $this->imageWidth - $rectangleWidth; + $this->rectangleY1 = 0; - $draw = new ImagickDraw(); - $draw->setStrokeAntialias(true); - $draw->setTextAntialias(true); - $draw->setFont($this->appNameFont); - $draw->setFontSize($this->appNameFontSize); - $draw->setFillColor(new ImagickPixel($this->appNameColor)); + $this->rectangleX2 = $this->imageWidth; + $this->rectangleY2 = $rectangleHeight; - // corrections - $dimensions = $this->image->queryFontMetrics($draw, $this->appName); - $startY = $startY + $dimensions['characterHeight']; + break; + case 'bottom-right': + case 'right-bottom': + $this->rectangleX1 = $this->imageWidth - $rectangleWidth; + $this->rectangleY1 = $this->imageHeight - $rectangleHeight; - $this->image->annotateImage($draw, $startX, $startY, 0, $this->appName); + $this->rectangleX2 = $this->imageWidth; + $this->rectangleY2 = $this->imageHeight; + + break; + } } protected function multiLine(string $string, int $width = 75, bool $cut = true): string { + /** @var string $string */ + $string = preg_replace('~\s+~', ' ', $string); $break = "\n"; $lines = explode($break, $string);