diff --git a/src/Utils/Image.php b/src/Utils/Image.php index f6c53b79b..ce2cb50e5 100644 --- a/src/Utils/Image.php +++ b/src/Utils/Image.php @@ -614,6 +614,49 @@ public function place(self $image, int|string $left = 0, int|string $top = 0, in } + /** + * Calculates the bounding box for a TrueType text. Returns keys left, top, width and height. + */ + public static function calculateTextBox( + string $text, + string $fontFile, + float $size, + float $angle = 0, + array $options = [], + ): array + { + $box = imagettfbbox($size, $angle, $fontFile, $text, $options); + return [ + 'left' => $minX = min([$box[0], $box[2], $box[4], $box[6]]), + 'top' => $minY = min([$box[1], $box[3], $box[5], $box[7]]), + 'width' => max([$box[0], $box[2], $box[4], $box[6]]) - $minX + 1, + 'height' => max([$box[1], $box[3], $box[5], $box[7]]) - $minY + 1, + ]; + } + + + /** + * Draw a rectangle. + */ + public function rectangleWH(int $x, int $y, int $width, int $height, ImageColor $color): void + { + if ($width !== 0 && $height !== 0) { + $this->rectangle($x, $y, $x + $width + ($width > 0 ? -1 : 1), $y + $height + ($height > 0 ? -1 : 1), $color); + } + } + + + /** + * Draw a filled rectangle. + */ + public function filledRectangleWH(int $x, int $y, int $width, int $height, ImageColor $color): void + { + if ($width !== 0 && $height !== 0) { + $this->filledRectangle($x, $y, $x + $width + ($width > 0 ? -1 : 1), $y + $height + ($height > 0 ? -1 : 1), $color); + } + } + + /** * Saves image to the file. Quality is in the range 0..100 for JPEG (default 85), WEBP (default 80) and AVIF (default 30) and 0..9 for PNG (default 9). * @param ImageType::*|null $type diff --git a/tests/Utils/Image.drawing.phpt b/tests/Utils/Image.drawing.phpt index f279e3ab1..dd50af2ee 100644 --- a/tests/Utils/Image.drawing.phpt +++ b/tests/Utils/Image.drawing.phpt @@ -8,6 +8,7 @@ declare(strict_types=1); use Nette\Utils\Image; +use Nette\Utils\ImageColor; use Tester\Assert; @@ -17,8 +18,14 @@ require __DIR__ . '/../bootstrap.php'; $size = 300; $image = Image::fromBlank($size, $size); -$image->filledRectangle(0, 0, $size - 1, $size - 1, Image::rgb(255, 255, 255)); -$image->rectangle(0, 0, $size - 1, $size - 1, Image::rgb(0, 0, 0)); +$image->filledRectangleWH(0, 0, 300, 300, ImageColor::rgb(255, 255, 255)); +$image->rectangleWH(0, 0, 300, 300, ImageColor::rgb(0, 0, 0)); + +$image->filledRectangleWH(20, 20, -5, -5, ImageColor::rgb(100, 0, 0)); +$image->rectangleWH(20, 20, -5, -5, ImageColor::rgb(100, 255, 255)); + +$image->filledRectangleWH(30, 30, 0, 0, ImageColor::rgb(127, 127, 0)); +$image->rectangleWH(35, 35, 0, 0, ImageColor::rgb(127, 127, 0)); $radius = 150; @@ -28,10 +35,7 @@ $image->filledEllipse(187, 125, $radius, $radius, Image::rgb(0, 0, 255, 75)); $image->copyResampled($image, 200, 200, 0, 0, 80, 80, $size, $size); -$file = !defined('PHP_WINDOWS_VERSION_BUILD') || PHP_VERSION_ID >= 70424 - ? '/expected/Image.drawing.1b.png' - : '/expected/Image.drawing.1.png'; -Assert::same(file_get_contents(__DIR__ . $file), $image->toString($image::PNG)); +Assert::same(file_get_contents(__DIR__ . '/expected/Image.drawing.1.png'), $image->toString($image::PNG)); // palette-based image diff --git a/tests/Utils/expected/Image.drawing.1.png b/tests/Utils/expected/Image.drawing.1.png index 776a71e78..f7a5998ff 100644 Binary files a/tests/Utils/expected/Image.drawing.1.png and b/tests/Utils/expected/Image.drawing.1.png differ diff --git a/tests/Utils/expected/Image.drawing.1b.png b/tests/Utils/expected/Image.drawing.1b.png deleted file mode 100644 index b30ee2412..000000000 Binary files a/tests/Utils/expected/Image.drawing.1b.png and /dev/null differ