From: Matthias Schmidt Date: Tue, 23 Dec 2014 08:29:31 +0000 (+0100) Subject: Add IImageAdapter::drawTextRelative() X-Git-Tag: 2.1.0_Beta_3~96^2~2 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=cfdb4fa4830e4eec1b161c22b516042b13929b58;p=GitHub%2FWoltLab%2FWCF.git Add IImageAdapter::drawTextRelative() --- diff --git a/wcfsetup/install/files/lib/system/image/adapter/GDImageAdapter.class.php b/wcfsetup/install/files/lib/system/image/adapter/GDImageAdapter.class.php index f4420e30d1..5acc24b38c 100644 --- a/wcfsetup/install/files/lib/system/image/adapter/GDImageAdapter.class.php +++ b/wcfsetup/install/files/lib/system/image/adapter/GDImageAdapter.class.php @@ -20,6 +20,12 @@ class GDImageAdapter implements IImageAdapter { */ protected $color = null; + /** + * red, green, blue data of the active color + * @var array + */ + protected $colorData = array(); + /** * image height * @var integer @@ -44,6 +50,12 @@ class GDImageAdapter implements IImageAdapter { */ protected $width = 0; + /** + * value of the font parameter of gd functions + * @var integer + */ + const FONT = 3; + /** * @see \wcf\system\image\adapter\IImageAdapter::load() */ @@ -179,15 +191,81 @@ class GDImageAdapter implements IImageAdapter { /** * @see \wcf\system\image\adapter\IImageAdapter::drawText() */ - public function drawText($string, $x, $y) { + public function drawText($string, $x, $y, $opacity) { if (!StringUtil::isUTF8($string)) { - throw new SystemException("Only UTF-8 encoded text can be written onto images"); // GD is buggy with UTF-8 + // GD is buggy with UTF-8 + throw new SystemException("Only UTF-8 encoded text can be written onto images"); } // convert UTF-8 characters > 127 to their numeric representation, e.g. A -> A - $string = mb_encode_numericentity($string, array(0x0, 0xFFFF, 0, 0xFFF), 'UTF-8'); + // todo: $string = mb_encode_numericentity($string, array(0x0, 0xFFFF, 0, 0xFFF), 'UTF-8'); + + // set opacity + $color = imagecolorallocatealpha($this->image, $this->colorData['red'], $this->colorData['green'], $this->colorData['blue'], (1 - $opacity) * 127); - imageString($this->image, 3, $x, $y, $string, $this->color); + imageString($this->image, self::FONT, $x, $y, $string, $color); + } + + /** + * @see \wcf\system\image\adapter\IImageAdapter::drawTextRelative() + */ + public function drawTextRelative($text, $position, $margin, $opacity) { + // split text into multiple lines to add each line separately + $lines = explode('\n', StringUtil::unifyNewlines($text)); + + $characterWidth = imagefontwidth(self::FONT); + $lineHeight = imagefontheight(self::FONT); + $textHeight = $lineHeight * count($lines); + + foreach ($lines as $key => $line) { + $lineWidth = mb_strlen($line) * $characterWidth; + + // calculate x coordinate + $x = 0; + switch ($position) { + case 'topLeft': + case 'middleLeft': + case 'bottomLeft': + $x = $margin; + break; + + case 'topCenter': + case 'middleCenter': + case 'bottomCenter': + $x = floor(($this->getWidth() - $lineWidth) / 2); + break; + + case 'topRight': + case 'middleRight': + case 'bottomRight': + $x = $this->getWidth() - $lineWidth - $margin; + break; + } + + // calculate y coordinate + $y = 0; + switch ($position) { + case 'topLeft': + case 'topCenter': + case 'topRight': + $y = $margin + $key * $lineHeight; + break; + + case 'middleLeft': + case 'middleCenter': + case 'middleRight': + $y = floor(($this->getHeight() - $textHeight) / 2) + $key * $lineHeight; + break; + + case 'bottomLeft': + case 'bottomCenter': + case 'bottomRight': + $y = $this->getHeight() - $textHeight + $key * $lineHeight - $margin; + break; + } + + $this->drawText($line, $x, $y, $opacity); + } } /** @@ -195,6 +273,13 @@ class GDImageAdapter implements IImageAdapter { */ public function setColor($red, $green, $blue) { $this->color = imageColorAllocate($this->image, $red, $green, $blue); + + // save data of the color + $this->colorData = array( + 'red' => $red, + 'green' => $green, + 'blue' => $blue + ); } /** diff --git a/wcfsetup/install/files/lib/system/image/adapter/IImageAdapter.class.php b/wcfsetup/install/files/lib/system/image/adapter/IImageAdapter.class.php index aaa0670dcc..a5b19a6d0a 100644 --- a/wcfsetup/install/files/lib/system/image/adapter/IImageAdapter.class.php +++ b/wcfsetup/install/files/lib/system/image/adapter/IImageAdapter.class.php @@ -87,10 +87,23 @@ interface IImageAdapter { * @param string $string * @param integer $x * @param integer $y + * @param float $opacity + * * @see \wcf\system\image\adapter\IImageAdapter::getImage() * @see \wcf\system\image\adapter\IImageAdapter::setColor() */ - public function drawText($string, $x, $y); + public function drawText($string, $x, $y, $opacity); + + /** + * Draws (multiple lines of) text on the image at the given relative position + * with a certain margin to the image border. + * + * @param string $text + * @param string $position + * @param integer $margin in pixels + * @param float $opacity + */ + public function drawTextRelative($text, $position, $margin, $opacity); /** * Sets active color. diff --git a/wcfsetup/install/files/lib/system/image/adapter/ImageAdapter.class.php b/wcfsetup/install/files/lib/system/image/adapter/ImageAdapter.class.php index 0433dac0e2..3d8248cb95 100644 --- a/wcfsetup/install/files/lib/system/image/adapter/ImageAdapter.class.php +++ b/wcfsetup/install/files/lib/system/image/adapter/ImageAdapter.class.php @@ -128,12 +128,43 @@ class ImageAdapter implements IImageAdapter { /** * @see \wcf\system\image\adapter\IImageAdapter::drawText() */ - public function drawText($string, $x, $y) { + public function drawText($string, $x, $y, $opacity) { if (!$this->adapter->hasColor()) { throw new SystemException("Cannot draw text unless a color has been specified with setColor()."); } - $this->adapter->drawText($string, $x, $y); + // validate opacity + if ($opacity < 0 || $opacity > 1) { + throw new SystemException("Invalid opacity value given."); + } + + $this->adapter->drawText($string, $x, $y, $opacity); + } + + /** + * @see \wcf\system\image\adapter\IImageAdapter::drawTextRelative() + */ + public function drawTextRelative($text, $position, $margin, $opacity) { + if (!$this->adapter->hasColor()) { + throw new SystemException("Cannot draw text unless a color has been specified with setColor()."); + } + + // validate position + if (!in_array($position, $this->relativePositions)) { + throw new SystemException("Unknown relative position '".$position."'."); + } + + // validate margin + if ($margin < 0 || $margin >= $this->getHeight() / 2 || $margin >= $this->getWidth() / 2) { + throw new SystemException("Margin has to be positive and respect image dimensions."); + } + + // validate opacity + if ($opacity < 0 || $opacity > 1) { + throw new SystemException("Invalid opacity value given."); + } + + $this->adapter->drawTextRelative($text, $position, $margin, $opacity); } /** @@ -217,6 +248,11 @@ class ImageAdapter implements IImageAdapter { throw new SystemException("Image '".$file."' does not exist."); } + // validate opacity + if ($opacity < 0 || $opacity > 1) { + throw new SystemException("Invalid opacity value given."); + } + $this->adapter->overlayImage($file, $x, $y, $opacity); } @@ -239,6 +275,11 @@ class ImageAdapter implements IImageAdapter { throw new SystemException("Margin has to be positive and respect image dimensions."); } + // validate opacity + if ($opacity < 0 || $opacity > 1) { + throw new SystemException("Invalid opacity value given."); + } + $adapterClassName = get_class($this->adapter); $overlayImage = new $adapterClassName(); $overlayImage->loadFile($file); diff --git a/wcfsetup/install/files/lib/system/image/adapter/ImagickImageAdapter.class.php b/wcfsetup/install/files/lib/system/image/adapter/ImagickImageAdapter.class.php index 42b3eaacb8..5fa9005ad4 100644 --- a/wcfsetup/install/files/lib/system/image/adapter/ImagickImageAdapter.class.php +++ b/wcfsetup/install/files/lib/system/image/adapter/ImagickImageAdapter.class.php @@ -187,8 +187,9 @@ class ImagickImageAdapter implements IImageAdapter { /** * @see \wcf\system\image\adapter\IImageAdapter::drawText() */ - public function drawText($string, $x, $y) { + public function drawText($string, $x, $y, $opacity) { $draw = new \ImagickDraw(); + $draw->setStrokeOpacity($opacity); $draw->setFillColor($this->color); $draw->setTextAntialias(true); @@ -197,6 +198,62 @@ class ImagickImageAdapter implements IImageAdapter { $this->imagick->drawImage($draw); } + /** + * @see \wcf\system\image\adapter\IImageAdapter::drawTextRelative() + */ + public function drawTextRelative($text, $position, $margin, $opacity) { + $draw = new \ImagickDraw(); + $draw->setStrokeOpacity($opacity); + $metrics = $this->imagick->queryFontMetrics($draw, $string); + + // calculate x coordinate + $x = 0; + switch ($position) { + case 'topLeft': + case 'middleLeft': + case 'bottomLeft': + $x = $margin; + break; + + case 'topCenter': + case 'middleCenter': + case 'bottomCenter': + $x = floor(($this->getWidth() - $metrics['textWidth']) / 2); + break; + + case 'topRight': + case 'middleRight': + case 'bottomRight': + $x = $this->getWidth() - $metrics['textWidth'] - $margin; + break; + } + + // calculate y coordinate + $y = 0; + switch ($position) { + case 'topLeft': + case 'topCenter': + case 'topRight': + $y = $margin; + break; + + case 'middleLeft': + case 'middleCenter': + case 'middleRight': + $y = floor(($this->getHeight() - $metrics['textHeight']) / 2); + break; + + case 'bottomLeft': + case 'bottomCenter': + case 'bottomRight': + $y = $this->getHeight() - $metrics['textHeight'] - $margin; + break; + } + + // draw text + $this->drawText($string, $x, $y); + } + /** * @see \wcf\system\image\adapter\IImageAdapter::setColor() */