<?php
/**
 * Copyright 2007-2017 Horde LLC (http://www.horde.org/)
 *
 * See the enclosed file LICENSE for license information (LGPL). If you
 * did not receive this file, see http://www.horde.org/licenses/lgpl21.
 *
 * @author    Michael J. Rubinsky <mrubinsk@horde.org>
 * @category  Horde
 * @license   http://www.horde.org/licenses/lgpl21 LGPL-2.1
 * @package   Image
 */

/**
 * Image effect for adding a drop shadow.
 *
 * @author    Michael J. Rubinsky <mrubinsk@horde.org>
 * @category  Horde
 * @copyright 2007-2017 Horde LLC
 * @license   http://www.horde.org/licenses/lgpl21 LGPL-2.1
 * @package   Image
 */
class Horde_Image_Effect_Imagick_DropShadow extends Horde_Image_Effect
{
    /**
     * Valid parameters:
     *
     * @TODO
     *
     * @var array
     */
    protected $_params = array(
        'distance' => 5, // This is used as the x and y offset
        'width' => 2,    // ignored
        'hexcolor' => '000000', // ignored
        'angle' => 215,         // ignored
        'fade' => 3, // Sigma value
        'padding' => 0,
        'background' => 'none'
    );

    /**
     * Applies the effect.
     */
    public function apply()
    {
        // There is what *I* call a bug in the magickwand interface of Im that
        // Imagick is compiled against. The X and Y parameters are ignored, and
        // the distance of the shadow is determined *solely* by the sigma value
        // which makes it pretty much impossible to have Imagick shadows look
        // identical to Im shadows...
        try {
            $shadow = $this->_image->cloneImagickObject();
            $shadow->setImageBackgroundColor(new ImagickPixel('black'));
            $shadow->shadowImage(
                80,
                $this->_params['fade'],
                $this->_params['distance'],
                $this->_params['distance']
            );

            // If we explicitly request a background color, we need to compose
            // an image of the background color with the shadow since the
            // shadow is always generated with transparent background.
            if ($this->_params['background'] != 'none') {
                $size = $shadow->getImageGeometry();
                $new = new Imagick();
                $new->newImage($size['width'], $size['height'], new ImagickPixel($this->_params['background']));
                $new->setImageFormat($this->_image->getType());
                $new->compositeImage($shadow, Imagick::COMPOSITE_OVER, 0, 0);
                $shadow->clear();
                $shadow->addImage($new);
                $new->destroy();
            }

            $shadow->compositeImage(
                $this->_image->imagick, Imagick::COMPOSITE_OVER, 0, 0
            );

            if ($this->_params['padding']) {
                $shadow->borderImage(
                    $this->_params['background'],
                    $this->_params['padding'],
                    $this->_params['padding']
                );
            }
            $this->_image->imagick->clear();
            $this->_image->imagick->addImage($shadow);
        } catch (ImagickPixelException $e) {
            throw new Horde_Image_Exception($e);
        } catch (ImagickException $e) {
            throw new Horde_Image_Exception($e);
        }
        $shadow->destroy();

        $this->_image->clearGeometry();
    }
}
