diff --git a/src/Renderer/AbstractRenderer.php b/src/Renderer/AbstractRenderer.php index d70f04e..df65748 100644 --- a/src/Renderer/AbstractRenderer.php +++ b/src/Renderer/AbstractRenderer.php @@ -79,6 +79,12 @@ abstract class AbstractRenderer implements RendererInterface */ protected $resource; + /** + * Show a transparent background + * @var Boolean + */ + protected $transparentBackground = false; + /** * Constructor * @param array|Traversable $options @@ -135,6 +141,28 @@ public function getRendererNamespace() return $this->rendererNamespace; } + /** + * Set whether background should be transparent + * Will work for SVG and Image (png and gif only) + * + * @param $bool + * @return $this + */ + public function setTransparentBackground($bool) + { + $this->transparentBackground = $bool; + + return $this; + } + + /** + * @return bool + */ + public function getTransparentBackground() + { + return $this->transparentBackground; + } + /** * Retrieve renderer type * @return string diff --git a/src/Renderer/Image.php b/src/Renderer/Image.php index c59be39..c0323dc 100644 --- a/src/Renderer/Image.php +++ b/src/Renderer/Image.php @@ -22,8 +22,8 @@ class Image extends AbstractRenderer * @var array */ protected $allowedImageType = array('png', - 'jpeg', - 'gif' ); + 'jpeg', + 'gif' ); /** * Image format @@ -194,22 +194,7 @@ protected function initRenderer() $barcodeWidth = $this->barcode->getWidth(true); $barcodeHeight = $this->barcode->getHeight(true); - if ($this->resource !== null) { - $foreColor = $this->barcode->getForeColor(); - $backgroundColor = $this->barcode->getBackgroundColor(); - $this->imageBackgroundColor = imagecolorallocate( - $this->resource, - ($backgroundColor & 0xFF0000) >> 16, - ($backgroundColor & 0x00FF00) >> 8, - $backgroundColor & 0x0000FF - ); - $this->imageForeColor = imagecolorallocate( - $this->resource, - ($foreColor & 0xFF0000) >> 16, - ($foreColor & 0x00FF00) >> 8, - $foreColor & 0x0000FF - ); - } else { + if (is_null($this->resource)) { $width = $barcodeWidth; $height = $barcodeHeight; if ($this->userWidth && $this->barcode->getType() != 'error') { @@ -219,32 +204,44 @@ protected function initRenderer() $height = $this->userHeight; } - $foreColor = $this->barcode->getForeColor(); - $backgroundColor = $this->barcode->getBackgroundColor(); $this->resource = imagecreatetruecolor($width, $height); - $this->imageBackgroundColor = imagecolorallocate( - $this->resource, - ($backgroundColor & 0xFF0000) >> 16, - ($backgroundColor & 0x00FF00) >> 8, - $backgroundColor & 0x0000FF - ); - $this->imageForeColor = imagecolorallocate( - $this->resource, - ($foreColor & 0xFF0000) >> 16, - ($foreColor & 0x00FF00) >> 8, - $foreColor & 0x0000FF - ); $white = imagecolorallocate($this->resource, 255, 255, 255); imagefilledrectangle($this->resource, 0, 0, $width - 1, $height - 1, $white); } + + $foreColor = $this->barcode->getForeColor(); + $this->imageForeColor = imagecolorallocate( + $this->resource, + ($foreColor & 0xFF0000) >> 16, + ($foreColor & 0x00FF00) >> 8, + $foreColor & 0x0000FF + ); + + $backgroundColor = $this->barcode->getBackgroundColor(); + $this->imageBackgroundColor = imagecolorallocate( + $this->resource, + ($backgroundColor & 0xFF0000) >> 16, + ($backgroundColor & 0x00FF00) >> 8, + $backgroundColor & 0x0000FF + ); + + // JPEG does not support transparency, if transparentBackground is true and + // image type is JPEG, ignore transparency + if($this->getImageType() != "jpeg" && $this->transparentBackground) { + imagecolortransparent($this->resource, $this->imageBackgroundColor); + } + $this->adjustPosition(imagesy($this->resource), imagesx($this->resource)); - imagefilledrectangle($this->resource, - $this->leftOffset, - $this->topOffset, - $this->leftOffset + $barcodeWidth - 1, - $this->topOffset + $barcodeHeight - 1, - $this->imageBackgroundColor); + + imagefilledrectangle( + $this->resource, + $this->leftOffset, + $this->topOffset, + $this->leftOffset + $barcodeWidth - 1, + $this->topOffset + $barcodeHeight - 1, + $this->imageBackgroundColor + ); } /** @@ -330,18 +327,18 @@ public function render() protected function drawPolygon($points, $color, $filled = true) { $newPoints = array($points[0][0] + $this->leftOffset, - $points[0][1] + $this->topOffset, - $points[1][0] + $this->leftOffset, - $points[1][1] + $this->topOffset, - $points[2][0] + $this->leftOffset, - $points[2][1] + $this->topOffset, - $points[3][0] + $this->leftOffset, - $points[3][1] + $this->topOffset, ); + $points[0][1] + $this->topOffset, + $points[1][0] + $this->leftOffset, + $points[1][1] + $this->topOffset, + $points[2][0] + $this->leftOffset, + $points[2][1] + $this->topOffset, + $points[3][0] + $this->leftOffset, + $points[3][1] + $this->topOffset, ); $allocatedColor = imagecolorallocate($this->resource, - ($color & 0xFF0000) >> 16, - ($color & 0x00FF00) >> 8, - $color & 0x0000FF ); + ($color & 0xFF0000) >> 16, + ($color & 0x00FF00) >> 8, + $color & 0x0000FF ); if ($filled) { imagefilledpolygon($this->resource, $newPoints, 4, $allocatedColor); @@ -365,9 +362,9 @@ protected function drawPolygon($points, $color, $filled = true) protected function drawText($text, $size, $position, $font, $color, $alignment = 'center', $orientation = 0) { $allocatedColor = imagecolorallocate($this->resource, - ($color & 0xFF0000) >> 16, - ($color & 0x00FF00) >> 8, - $color & 0x0000FF ); + ($color & 0xFF0000) >> 16, + ($color & 0x00FF00) >> 8, + $color & 0x0000FF ); if ($font == null) { $font = 3; @@ -422,13 +419,13 @@ protected function drawText($text, $size, $position, $font, $color, $alignment = break; } imagettftext($this->resource, - $size, - $orientation, - $position[0] - ($width * cos(pi() * $orientation / 180)), - $position[1] + ($width * sin(pi() * $orientation / 180)), - $allocatedColor, - $font, - $text); + $size, + $orientation, + $position[0] - ($width * cos(pi() * $orientation / 180)), + $position[1] + ($width * sin(pi() * $orientation / 180)), + $allocatedColor, + $font, + $text); } } } diff --git a/src/Renderer/Svg.php b/src/Renderer/Svg.php index b05d140..8562a57 100644 --- a/src/Renderer/Svg.php +++ b/src/Renderer/Svg.php @@ -43,6 +43,13 @@ class Svg extends AbstractRenderer */ protected $userWidth = 0; + + /** + * Flag to determime if drawPolygon has been run once already + * @var bool + */ + protected $drawPolygonExecuted = false; + /** * Set height of the result image * @param null|int $value @@ -152,12 +159,17 @@ protected function initRenderer() } $this->adjustPosition($height, $width); - $this->appendRootElement('rect', - array('x' => $this->leftOffset, - 'y' => $this->topOffset, - 'width' => ($this->leftOffset + $barcodeWidth - 1), - 'height' => ($this->topOffset + $barcodeHeight - 1), - 'fill' => $imageBackgroundColor)); + $rect = array('x' => $this->leftOffset, + 'y' => $this->topOffset, + 'width' => ($this->leftOffset + $barcodeWidth - 1), + 'height' => ($this->topOffset + $barcodeHeight - 1), + 'fill' => $imageBackgroundColor); + + if($this->transparentBackground) { + $rect['fill-opacity'] = 0; + } + + $this->appendRootElement('rect', $rect); } protected function readRootElement() @@ -309,6 +321,17 @@ protected function drawPolygon($points, $color, $filled = true) $newPoints = implode(' ', $newPoints); $attributes['points'] = $newPoints; $attributes['fill'] = $color; + + // SVG passes a rect in as the first call to drawPolygon, we'll need to intercept + // this and set transparency if necessary. + $objId = spl_object_hash($this); + if(!$this->drawPolygonExecuted) { + if($this->transparentBackground) { + $attributes['fill-opacity'] = '0'; + } + $this->drawPolygonExecuted = true; + } + $this->appendRootElement('polygon', $attributes); } diff --git a/test/Renderer/ImageTest.php b/test/Renderer/ImageTest.php index 0f1ecca..08d9120 100644 --- a/test/Renderer/ImageTest.php +++ b/test/Renderer/ImageTest.php @@ -276,6 +276,78 @@ public function testTopOffsetOverrideVerticalPosition() parent::testTopOffsetOverrideVerticalPosition(); } + /** + * @group 4708 + */ + public function testImageGifWithNoTransparency() + { + $barcode = new Object\Code39(array('text' => '0123456789')); + $this->renderer->setBarcode($barcode); + + $this->renderer->setTransparentBackground(false); + $this->assertFalse($this->renderer->getTransparentBackground()); + + //Test Gif output + $this->renderer->setImageType('gif'); + $image = $this->renderer->draw(); + $index = imagecolortransparent($image); + $this->assertEquals($index, -1); + } + + /** + * @group 4708 + */ + public function testImagePngWithNoTransparency() + { + $barcode = new Object\Code39(array('text' => '0123456789')); + $this->renderer->setBarcode($barcode); + + $this->renderer->setTransparentBackground(false); + $this->assertFalse($this->renderer->getTransparentBackground()); + + //Test PNG output + $this->renderer->setImageType('png'); + $image = $this->renderer->draw(); + $index = imagecolortransparent($image); + $this->assertEquals($index, -1); + } + + /** + * @group 4708 + */ + public function testImageGifWithTransparency() + { + $barcode = new Object\Code39(array('text' => '0123456789')); + $this->renderer->setBarcode($barcode); + + $this->renderer->setTransparentBackground(true); + $this->assertTrue($this->renderer->getTransparentBackground()); + + //Test Gif output + $this->renderer->setImageType('gif'); + $image = $this->renderer->draw(); + $index = imagecolortransparent($image); + $this->assertTrue($index !== -1); + } + + /** + * @group 4708 + */ + public function testImagePngWithTransparency() + { + $barcode = new Object\Code39(array('text' => '0123456789')); + $this->renderer->setBarcode($barcode); + + $this->renderer->setTransparentBackground(true); + $this->assertTrue($this->renderer->getTransparentBackground()); + + //Test PNG output + $this->renderer->setImageType('png'); + $image = $this->renderer->draw(); + $index = imagecolortransparent($image); + $this->assertTrue($index !== -1); + } + protected function checkTTFRequirement() { if (!function_exists('imagettfbbox')) { diff --git a/test/Renderer/SvgTest.php b/test/Renderer/SvgTest.php index 4d7fa6c..c6c1b9b 100644 --- a/test/Renderer/SvgTest.php +++ b/test/Renderer/SvgTest.php @@ -24,6 +24,42 @@ protected function getRendererObject($options = null) return new Svg($options); } + /** + * @group 4708 + * + * Needs to be run first due to runOnce static on drawPolygon + */ + public function testSvgNoTransparency() + { + $svgCompare = file_get_contents(__DIR__ . '/_files/svg_transparency.xml'); + + Barcode\Barcode::setBarcodeFont(__DIR__ . '/../Object/_fonts/Vera.ttf'); + $barcode = new Code39(array('text' => '0123456789')); + $this->renderer->setBarcode($barcode); + + $this->assertFalse($this->renderer->getTransparentBackground()); + $svgOutput = $this->renderer->draw()->saveXML(); + $this->assertNotEquals($svgCompare, $svgOutput); + } + + /** + * @group 4708 + * + * Needs to be run first due to runOnce static on drawPolygon + */ + public function testSvgTransparency() + { + $svgCompare = file_get_contents(__DIR__ . '/_files/svg_transparency.xml'); + + Barcode\Barcode::setBarcodeFont(__DIR__ . '/../Object/_fonts/Vera.ttf'); + $barcode = new Code39(array('text' => '0123456789')); + $this->renderer->setBarcode($barcode); + $this->renderer->setTransparentBackground(true); + $this->assertTrue($this->renderer->getTransparentBackground()); + $svgOutput = $this->renderer->draw()->saveXML(); + $this->assertEquals($svgCompare, $svgOutput); + } + public function testType() { $this->assertSame('svg', $this->renderer->getType()); @@ -105,4 +141,5 @@ protected function getRendererWithWidth500AndHeight300() $svg->appendChild($rootElement); return $this->renderer->setResource($svg); } + } diff --git a/test/Renderer/_files/svg_transparency.xml b/test/Renderer/_files/svg_transparency.xml new file mode 100644 index 0000000..ce946b7 --- /dev/null +++ b/test/Renderer/_files/svg_transparency.xml @@ -0,0 +1,67 @@ + + + Barcode CODE39 *0123456789* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *0123456789* +