Skip to content

Commit

Permalink
Merge pull request #790 from mlocati/gd-alphablending-drawer
Browse files Browse the repository at this point in the history
Let users specify the alpha-blending of the GD drawer
  • Loading branch information
mlocati authored Oct 7, 2021
2 parents a2a1af9 + 030854a commit c306a84
Show file tree
Hide file tree
Showing 8 changed files with 319 additions and 33 deletions.
34 changes: 34 additions & 0 deletions src/Draw/AlphaBlendingAwareDrawerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace Imagine\Draw;

/**
* Interface for the drawers that support configuring the alpha blending.
*/
interface AlphaBlendingAwareDrawerInterface extends DrawerInterface
{
/**
* Is the alpha blending activated?
*
* @return bool
*/
public function getAlphaBlending();

/**
* Enable/disable the alpha blending.
*
* @param bool $value
*
* @return $this
*/
public function setAlphaBlending($value);

/**
* Create a new instance of this drawer with the specified alpha blending value.
*
* @param bool $value
*
* @return static
*/
public function withAlphaBlending($value);
}
123 changes: 93 additions & 30 deletions src/Gd/Drawer.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

namespace Imagine\Gd;

use Imagine\Draw\DrawerInterface;
use Imagine\Draw\AlphaBlendingAwareDrawerInterface;
use Imagine\Exception\InvalidArgumentException;
use Imagine\Exception\RuntimeException;
use Imagine\Image\AbstractFont;
Expand All @@ -24,7 +24,7 @@
/**
* Drawer implementation using the GD PHP extension.
*/
final class Drawer implements DrawerInterface
final class Drawer implements AlphaBlendingAwareDrawerInterface
{
/**
* @var resource|\GdImage
Expand All @@ -36,6 +36,11 @@ final class Drawer implements DrawerInterface
*/
private $info;

/**
* @var bool
*/
private $alphaBlending = true;

/**
* Constructs Drawer with a given gd image resource.
*
Expand All @@ -60,16 +65,16 @@ public function arc(PointInterface $center, BoxInterface $size, $start, $end, Co
}
imagesetthickness($this->resource, $thickness);

if (imagealphablending($this->resource, true) === false) {
if ($this->applyAlphaBlending() === false) {
throw new RuntimeException('Draw arc operation failed');
}

if (imagearc($this->resource, $center->getX(), $center->getY(), $size->getWidth(), $size->getHeight(), $start, $end, $this->getColor($color)) === false) {
imagealphablending($this->resource, false);
$this->revertAlphaBlending();
throw new RuntimeException('Draw arc operation failed');
}

if (imagealphablending($this->resource, false) === false) {
if ($this->revertAlphaBlending() === false) {
throw new RuntimeException('Draw arc operation failed');
}

Expand All @@ -91,26 +96,26 @@ public function chord(PointInterface $center, BoxInterface $size, $start, $end,
}
imagesetthickness($this->resource, $thickness);

if (imagealphablending($this->resource, true) === false) {
if ($this->applyAlphaBlending() === false) {
throw new RuntimeException('Draw chord operation failed');
}

if ($fill) {
$style = IMG_ARC_CHORD;
if (imagefilledarc($this->resource, $center->getX(), $center->getY(), $size->getWidth(), $size->getHeight(), $start, $end, $this->getColor($color), $style) === false) {
imagealphablending($this->resource, false);
$this->revertAlphaBlending();
throw new RuntimeException('Draw chord operation failed');
}
} else {
foreach (array(IMG_ARC_NOFILL, IMG_ARC_NOFILL | IMG_ARC_CHORD) as $style) {
if (imagefilledarc($this->resource, $center->getX(), $center->getY(), $size->getWidth(), $size->getHeight(), $start, $end, $this->getColor($color), $style) === false) {
imagealphablending($this->resource, false);
$this->revertAlphaBlending();
throw new RuntimeException('Draw chord operation failed');
}
}
}

if (imagealphablending($this->resource, false) === false) {
if ($this->revertAlphaBlending() === false) {
throw new RuntimeException('Draw chord operation failed');
}

Expand Down Expand Up @@ -154,19 +159,19 @@ public function ellipse(PointInterface $center, BoxInterface $size, ColorInterfa
if (function_exists('imageantialias')) {
imageantialias($this->resource, true);
}
if (imagealphablending($this->resource, true) === false) {
if ($this->applyAlphaBlending() === false) {
throw new RuntimeException('Draw ellipse operation failed');
}

if (function_exists('imageantialias')) {
imageantialias($this->resource, true);
}
if ($callback($this->resource, $center->getX(), $center->getY(), $size->getWidth(), $size->getHeight(), $this->getColor($color)) === false) {
imagealphablending($this->resource, false);
$this->revertAlphaBlending();
throw new RuntimeException('Draw ellipse operation failed');
}

if (imagealphablending($this->resource, false) === false) {
if ($this->revertAlphaBlending() === false) {
throw new RuntimeException('Draw ellipse operation failed');
}

Expand All @@ -186,16 +191,16 @@ public function line(PointInterface $start, PointInterface $end, ColorInterface
}
imagesetthickness($this->resource, $thickness);

if (imagealphablending($this->resource, true) === false) {
if ($this->applyAlphaBlending() === false) {
throw new RuntimeException('Draw line operation failed');
}

if (imageline($this->resource, $start->getX(), $start->getY(), $end->getX(), $end->getY(), $this->getColor($color)) === false) {
imagealphablending($this->resource, false);
$this->revertAlphaBlending();
throw new RuntimeException('Draw line operation failed');
}

if (imagealphablending($this->resource, false) === false) {
if ($this->revertAlphaBlending() === false) {
throw new RuntimeException('Draw line operation failed');
}

Expand All @@ -221,16 +226,16 @@ public function pieSlice(PointInterface $center, BoxInterface $size, $start, $en
$style = IMG_ARC_EDGED | IMG_ARC_NOFILL;
}

if (imagealphablending($this->resource, true) === false) {
if ($this->applyAlphaBlending() === false) {
throw new RuntimeException('Draw chord operation failed');
}

if (imagefilledarc($this->resource, $center->getX(), $center->getY(), $size->getWidth(), $size->getHeight(), $start, $end, $this->getColor($color), $style) === false) {
imagealphablending($this->resource, false);
$this->revertAlphaBlending();
throw new RuntimeException('Draw chord operation failed');
}

if (imagealphablending($this->resource, false) === false) {
if ($this->revertAlphaBlending() === false) {
throw new RuntimeException('Draw chord operation failed');
}

Expand All @@ -244,16 +249,16 @@ public function pieSlice(PointInterface $center, BoxInterface $size, $start, $en
*/
public function dot(PointInterface $position, ColorInterface $color)
{
if (imagealphablending($this->resource, true) === false) {
if ($this->applyAlphaBlending() === false) {
throw new RuntimeException('Draw point operation failed');
}

if (imagesetpixel($this->resource, $position->getX(), $position->getY(), $this->getColor($color)) === false) {
imagealphablending($this->resource, false);
$this->revertAlphaBlending();
throw new RuntimeException('Draw point operation failed');
}

if (imagealphablending($this->resource, false) === false) {
if ($this->revertAlphaBlending() === false) {
throw new RuntimeException('Draw point operation failed');
}

Expand Down Expand Up @@ -284,16 +289,16 @@ public function rectangle(PointInterface $leftTop, PointInterface $rightBottom,
$callback = 'imagerectangle';
}

if (imagealphablending($this->resource, true) === false) {
if ($this->applyAlphaBlending() === false) {
throw new RuntimeException('Draw polygon operation failed');
}

if ($callback($this->resource, $minX, $minY, $maxX, $maxY, $this->getColor($color)) === false) {
imagealphablending($this->resource, false);
$this->revertAlphaBlending();
throw new RuntimeException('Draw polygon operation failed');
}

if (imagealphablending($this->resource, false) === false) {
if ($this->revertAlphaBlending() === false) {
throw new RuntimeException('Draw polygon operation failed');
}

Expand Down Expand Up @@ -327,7 +332,7 @@ public function polygon(array $coordinates, ColorInterface $color, $fill = false
$callback = 'imagepolygon';
}

if (imagealphablending($this->resource, true) === false) {
if ($this->applyAlphaBlending() === false) {
throw new RuntimeException('Draw polygon operation failed');
}

Expand All @@ -336,11 +341,11 @@ public function polygon(array $coordinates, ColorInterface $color, $fill = false
? $callback($this->resource, $points, count($coordinates), $this->getColor($color))
: $callback($this->resource, $points, $this->getColor($color))
)) {
imagealphablending($this->resource, false);
$this->revertAlphaBlending();
throw new RuntimeException('Draw polygon operation failed');
}

if (imagealphablending($this->resource, false) === false) {
if ($this->revertAlphaBlending() === false) {
throw new RuntimeException('Draw polygon operation failed');
}

Expand Down Expand Up @@ -368,7 +373,7 @@ public function text($string, AbstractFont $font, PointInterface $position, $ang
$string = $font->wrapText($string, $width, $angle);
}

if (imagealphablending($this->resource, true) === false) {
if ($this->applyAlphaBlending() === false) {
throw new RuntimeException('Font mask operation failed');
}

Expand All @@ -380,17 +385,51 @@ public function text($string, AbstractFont $font, PointInterface $position, $ang
}
}
if (imagefttext($this->resource, $fontsize, $angle, $x, $y, $this->getColor($font->getColor()), $fontfile, $string) === false) {
imagealphablending($this->resource, false);
$this->revertAlphaBlending();
throw new RuntimeException('Font mask operation failed');
}

if (imagealphablending($this->resource, false) === false) {
if ($this->revertAlphaBlending() === false) {
throw new RuntimeException('Font mask operation failed');
}

return $this;
}

/**
* {@inheritdoc}
*
* @see \Imagine\Draw\AlphaBlendingAwareDrawerInterface::getAlphaBlending()
*/
public function getAlphaBlending()
{
return $this->alphaBlending;
}

/**
* {@inheritdoc}
*
* @see \Imagine\Draw\AlphaBlendingAwareDrawerInterface::setAlphaBlending()
*/
public function setAlphaBlending($value)
{
$this->alphaBlending = (bool) $value;

return $this;
}

/**
* {@inheritdoc}
*
* @see \Imagine\Draw\AlphaBlendingAwareDrawerInterface::withAlphaBlending()
*/
public function withAlphaBlending($value)
{
$result = clone $this;

return $result->setAlphaBlending($value);
}

/**
* Generates a GD color from Color instance.
*
Expand Down Expand Up @@ -423,4 +462,28 @@ private function loadGdInfo()

$this->info = gd_info();
}

/**
* Apply the alpha blending value.
*
* @param resource|\GdImage|null $to the GD image. If null we'll apply the alpha blending to the current resource.
*
* @return bool
*/
protected function applyAlphaBlending($to = null)
{
return $this->getAlphaBlending() ? imagealphablending($to ? $to : $this->resource, true) : true;
}

/**
* Revert the alpha blending value to the initial state.
*
* @param resource|\GdImage|null $to the GD image. If null we'll apply the alpha blending to the current resource.
*
* @return bool
*/
protected function revertAlphaBlending($to = null)
{
return $this->getAlphaBlending() ? imagealphablending($to ? $to : $this->resource, false) : true;
}
}
3 changes: 2 additions & 1 deletion src/Image/ImageInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,9 @@ public function __toString();

/**
* Instantiates and returns a DrawerInterface instance for image drawing.
* Some drivers may also return a DrawerInterface drawer that's also AlphaBlendingAwareDrawerInterface.
*
* @return \Imagine\Draw\DrawerInterface
* @return \Imagine\Draw\DrawerInterface|\Imagine\Draw\AlphaBlendingAwareDrawerInterface
*/
public function draw();

Expand Down
Loading

0 comments on commit c306a84

Please sign in to comment.