*/
protected $color = null;
+ /**
+ * red, green, blue data of the active color
+ * @var array
+ */
+ protected $colorData = array();
+
/**
* image height
* @var integer
*/
protected $width = 0;
+ /**
+ * value of the font parameter of gd functions
+ * @var integer
+ */
+ const FONT = 3;
+
/**
* @see \wcf\system\image\adapter\IImageAdapter::load()
*/
/**
* @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);
+ }
}
/**
*/
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
+ );
}
/**
* @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.
/**
* @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);
}
/**
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);
}
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);
/**
* @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);
$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()
*/