<?php
    
    //========================================================================================================================
    /**
     * ImageMagickビルダークラス
     *
     * LICENSE: This source file is subject to GNU GENERAL PUBLIC LICENSE Version 3
     * http://www.gnu.org/licenses/gpl-3.0.txt.
     *
     * @package    LabbitBox
     * @subpackage core
     * @copyright  2010 LabbitBox Development Team.
     * @license    GPL v3 http://www.gnu.org/licenses/gpl-3.0.txt
     * @author     neobaba <neobaba@labbitbox.org>
     * @version    v0.1
     * @since      2010/2/26
     * @link       http://labbitbox.org/
     * @see        http://labbitbox.org/
     */
    //========================================================================================================================
    class MagickBuilder {
        //イメージデータ
        private $_imagick       = null;
        private $_imagickDraw   = null;   
        private $_inFile        = '';
        private $_outFile       = '';
        private $_imageType     = '';
        private $_options       = array();
        
        //キャンバスサイズ
        private $_width         = 0;
        private $_height        = 0;
        
        //描画データ
        private $_shapeList     = array();
     
        //-----------------------------------------------------------------------------------------------------------------------------------------
        /**
         * コンストラクタ/デストラクタ
         * 
         * @param string    $inFile     入力ファイル名(拡張子必須：ImageMagickは拡張子でファイル形式を識別する)
         * @param string    $outFile    出力ファイル名(拡張子必須：ImageMagickは拡張子でファイル形式を識別する)
         * @param integer   $width      キャンバスサイズ(幅)
         * @param integer   $height     キャンバスサイズ(高)
         * @param string    $imageType  出力ファイル形式('png'/'gif')
         */
        //-----------------------------------------------------------------------------------------------------------------------------------------
        function __construct($inFile = '', $outFile = '', $width = 0, $height = 0, $options = array(), $imageType = 'png'){
            $this->_imagick         = new Imagick($inFile);
            //$this->_imagick->readImageBlob(file_get_contents($inFile));
            $this->_imagick->setImageFormat($imageType);            
            $this->_imagickDraw     = new ImagickDraw();

            $this->_inFile          = $inFile;
            $this->_outFile         = $outFile;
            $this->_width           = $width;
            $this->_height          = $height;
            $this->_imageType       = $imageType;
            $this->_options         = $options;
        }

        public function __destruct(){
        
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * レスポンスデータ作成
         *
         * @param boolean $aResizeFlag 拡大・縮小フラグ
         * @param boolean $aStrechFlag 縦横比無視フラグ($aResizeFlag == TRUEの時のみ有効) 
         * @return string  レスポンス文字列データ
         */  
        //-------------------------------------------------------------------------------------------------------------------
        public function build($aResizeFlag = TRUE, $aStrechFlag = TRUE){
            //zxc('draw start:'.date('Y/m/d H:i:s').' => ', 'magick.html');
            
            $this->_imagickDraw     = new ImagickDraw();
            if ($aResizeFlag == TRUE){
                $this->_imagick->resizeImage($this->_width, $this->_height, imagick::FILTER_UNDEFINED, 0);
            }

            foreach ($this->_shapeList as $_shape) {
                $_shape->draw($this->_imagick);
            }

            //透過設定＆書き出し
            if (array_key_exists('transparent', $this->_options)){
                $this->_imagick->paintTransparentImage($this->_options['transparent'], 1, 0);
            }
            $this->_imagick->writeImages($this->_outFile, true);    
 
            //zx('draw end:'.date('Y/m/d H:i:s'), 'magick.html');
        }     
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 画像データ切り取り
         *
         * @param boolean $aResizeFlag 拡大・縮小フラグ
         * @param boolean $aStrechFlag 縦横比無視フラグ($aResizeFlag == TRUEの時のみ有効) 
         * @return string  レスポンス文字列データ
         */  
        //-------------------------------------------------------------------------------------------------------------------
        public function crop($x, $y, $width, $height, $aOutFile = ''){
            $this->_imagick->cropImage($width, $height, $x, $y);
            $this->_imagick->setImagePage($width, $height, 0, 0);
            $wOutFile  = ($aOutFile != '' ? $aOutFile : $this->_outFile);
            $this->_imagick->writeImages($wOutFile, true);
        }     

        public function free(){
            $this->_imagick->destroy();           
        }

        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 描画シェイプ追加
         * 
         * @param object    $shape  シェイプオブジェクト
         */  
        //-------------------------------------------------------------------------------------------------------------------
        public function addShape($shape){
            $this->_shapeList[] = $shape;
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 四角形シェイプ追加
         * 
         * @param integer   $x              開始位置：横座標(ピクセル)
         * @param integer   $y              開始位置：縦座標(ピクセル)
         * @param integer   $width          横サイズ(ピクセル)
         * @param integer   $height         縦サイズ(ピクセル)
         * @param string    $strokeColor    線色指定文字列(色名 or #000000 のRGB形式)
         * @param integer   $strokeWidth    線幅(ピクセル：0の場合はデフォルトもしくは設定済み幅値)
         * @param string    $fillColor      塗りつぶし色指定文字列(色名 or #000000 のRGB形式)
         * @param array     $options        その他オプションリスト
         */  
        //-------------------------------------------------------------------------------------------------------------------
        public function addRectangle($x, $y, $width, $height, $strokeColor = 'black', $strokeWidth = 1, $fillColor = 'white', $options = array()){
            $this->addShape(new Rectangle($x, $y, $width, $height, $strokeColor, $strokeWidth, $fillColor, $options));
        }

        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 直線シェイプ
         * 
         * @param integer   $x              開始位置：横座標(ピクセル)
         * @param integer   $y              開始位置：縦座標(ピクセル)
         * @param integer   $distanceX      起点からのX軸方向距離(ピクセル)
         * @param integer   $distanceY      起点からのY軸方向距離(ピクセル)
         * @param string    $strokeColor    線色指定文字列(色名 or #000000 のRGB形式)
         * @param integer   $strokeWidth    線幅(ピクセル：0の場合はデフォルトもしくは設定済み幅値)
         * @param array     $options        その他オプションリスト
         */  
        //-------------------------------------------------------------------------------------------------------------------
        public function addLine($x, $y, $distanceX, $distanceY, $strokeColor = 'black', $strokeWidth = 1, $options = array()){
            $this->addShape(new Line($x, $y, $distanceX, $distanceY, $strokeColor, $strokeWidth, $options));
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * テキストシェイプ
         * 
         * @param integer   $x              開始位置：横座標(ピクセル)
         * @param integer   $y              開始位置：縦座標(ピクセル)
         * @param integer   $angle          軸傾斜角度
         * (@param integer   $angleY        Y軸傾斜角度)
         * @param string    $text           描画文字列
         * @param string    $pointSize      文字サイズ(ポイント)
         * @param string    $font           使用フォント(日本語TTFを使用する場合はフルパスで指定する 例:FONT_DIR.'/kochi-gothic-subst.ttf')
         * @param string    $strokeColor    線色指定文字列(色名 or #000000 のRGB形式)：nullの場合セットしない
         * @param integer   $strokewidth    線幅(ピクセル：0の場合はデフォルトもしくは設定済み幅値)：nullの場合セットしない
         * @param string    $fillColor      塗りつぶし色指定文字列(色名 or #000000 のRGB形式)
         * @param array     $options        その他オプションリスト
         */  
        //-------------------------------------------------------------------------------------------------------------------
        public function addText($x, $y, $angle, $angleY, $text, $pointSize = '', $font = '', $strokeColor = null, $strokewidth = null, $fillColor = 'black', $options = array()){
            $this->addShape(new Text($x, $y, $angle, $angleY, $text, $pointSize, $font, $strokeColor, $strokewidth, $fillColor, $options));
        }
                
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 折れ線シェイプ追加
         * 
         * @param string    $strokeColor    線色指定文字列(色名 or #000000 のRGB形式)
         * @param integer   $strokewidth    線幅(ピクセル：0の場合はデフォルトもしくは設定済み幅値)
         * @param string    $fillColor      塗りつぶし色指定文字列(色名 or #000000 のRGB形式)
         * @param array     $options        その他オプションリスト
         * @return object   シェイプオブジェクト
         */  
        //-------------------------------------------------------------------------------------------------------------------
        public function addPolyline($strokeColor = 'black', $strokeWidth = 1, $fillColor = 'white', $options = array()){
            $wShape     = new Polyline($strokeColor, $strokeWidth, $fillColor, $options);
            $this->addShape($wShape);
            return $wShape;
        }        
       
    }

    //========================================================================================================================
    /**
     * ImageMagickビルダー用シェイプ基本クラス
     *
     * LICENSE: This source file is subject to GNU GENERAL PUBLIC LICENSE Version 3
     * http://www.gnu.org/licenses/gpl-3.0.txt.
     *
     * @package    LabbitBox
     * @subpackage core
     * @copyright  2010 LabbitBox Development Team.
     * @license    GPL v3 http://www.gnu.org/licenses/gpl-3.0.txt
     * @author     neobaba <neobaba@labbitbox.org>
     * @version    v0.1
     * @since      2010/2/26
     * @link       http://labbitbox.org/
     * @see        http://labbitbox.org/
     */
    //========================================================================================================================
    class MagickShape{
        //プロパティ
        public $type;                   //シェイプタイプ(offset/rectangle/line/text)
        
        //クラス変数
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * シェイプ基本クラス
         * 
         * @param string    $type       シェイプタイプ
         */  
        //-------------------------------------------------------------------------------------------------------------------
        function __construct($type){
            $this->type     = $type;
        }
       
        protected function setStyle($aImagickDraw, $aStyleList){
            foreach($aStyleList as $_key => $_style){
                switch($_key){
                    case 'STROKE_COLOR':
                        $aImagickDraw->setStrokeColor($_style);
                        break;
                    case 'STROKE_WIDTH':
                        $aImagickDraw->setStrokeWidth($_style);
                        break;
                    case 'FILL_COLOR':
                        $aImagickDraw->setFillColor($_style);
                        break;
                    case 'FILL_OPACITY':
                        $aImagickDraw->setFillOpacity($_style);
                        break;
                    case 'STROKE_DASH':
                        $aImagickDraw->setStrokeDashArray($_style);
                        break;
                }
            }
        } 
    }
            
    //========================================================================================================================
    /**
     * ImageMagickビルダー用シェイプ:rectangleクラス
     *
     * LICENSE: This source file is subject to GNU GENERAL PUBLIC LICENSE Version 3
     * http://www.gnu.org/licenses/gpl-3.0.txt.
     *
     * @package    LabbitBox
     * @subpackage core
     * @copyright  2010 LabbitBox Development Team.
     * @license    GPL v3 http://www.gnu.org/licenses/gpl-3.0.txt
     * @author     neobaba <neobaba@labbitbox.org>
     * @version    v0.1
     * @since      2010/2/26
     * @link       http://labbitbox.org/
     * @see        http://labbitbox.org/
     */
    //========================================================================================================================
    class Rectangle extends MagickShape{
        private $_imagickDraw   = null;
        private $_x             = 0;
        private $_y             = 0;
        private $_width         = 0;
        private $_height        = 0;

        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 四角形シェイプ
         * 
         * @param integer   $x              開始位置：横座標(ピクセル)
         * @param integer   $y              開始位置：縦座標(ピクセル)
         * @param integer   $width          横サイズ(ピクセル)
         * @param integer   $height         縦サイズ(ピクセル)
         * @param string    $strokeColor    線色指定文字列(色名 or #000000 のRGB形式)
         * @param integer   $strokeWidth    線幅(ピクセル：0の場合はデフォルトもしくは設定済み幅値)
         * @param string    $fillColor      塗りつぶし色指定文字列(色名 or #000000 のRGB形式)
         * @param array     $options        その他オプションリスト
         */  
        //-------------------------------------------------------------------------------------------------------------------
        function __construct($x, $y, $width, $height, $strokeColor = 'black', $strokeWidth = 1, $fillColor = 'white', $options = array()){
            $this->_x               = $x;
            $this->_y               = $y;
            $this->_width           = $width;
            $this->_height          = $height;
            
            $this->_imagickDraw     = new ImagickDraw();
            $this->setStyle(
                $this->_imagickDraw,
                array(
                    'STROKE_COLOR'  => $strokeColor,
                    'STROKE_WIDTH'  => $strokeWidth,
                )
            );
            if ($fillColor != null) $this->_imagickDraw->setFillColor($fillColor);
           
            parent::__construct('RECTANGLE');    
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 四角形編集
         * 
         * @param Object    $aImagick   Imagickオブジェクト
         * @return string   drawパラメータ文字列
         */  
        //-------------------------------------------------------------------------------------------------------------------
        public function draw($aImagick){
            $this->_imagickDraw->rectangle($this->_x, $this->_y, $this->_x + $this->_width, $this->_y + $this->_height);
            $aImagick->drawImage($this->_imagickDraw);
        }
    }
    
    //========================================================================================================================
    /**
     * ImageMagickビルダー用シェイプ:lineクラス
     *
     * LICENSE: This source file is subject to GNU GENERAL PUBLIC LICENSE Version 3
     * http://www.gnu.org/licenses/gpl-3.0.txt.
     *
     * @package    LabbitBox
     * @subpackage core
     * @copyright  2010 LabbitBox Development Team.
     * @license    GPL v3 http://www.gnu.org/licenses/gpl-3.0.txt
     * @author     neobaba <neobaba@labbitbox.org>
     * @version    v0.1
     * @since      2010/2/26
     * @link       http://labbitbox.org/
     * @see        http://labbitbox.org/
     */
    //========================================================================================================================
    class Line extends MagickShape{
        private $_imagickDraw   = null;
        private $_sx            = 0;
        private $_sy            = 0;
        private $_ex            = 0;
        private $_ey            = 0;

        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 直線シェイプ
         * 
         * @param integer   $x              開始位置：横座標(ピクセル)
         * @param integer   $y              開始位置：縦座標(ピクセル)
         * @param integer   $distanceX      起点からのX軸方向距離(ピクセル)
         * @param integer   $distanceY      起点からのY軸方向距離(ピクセル)
         * @param string    $strokeColor    線色指定文字列(色名 or #000000 のRGB形式)
         * @param integer   $strokeWidth    線幅(ピクセル：0の場合はデフォルトもしくは設定済み幅値)
         * @param array     $options        その他オプションリスト
         */  
        //-------------------------------------------------------------------------------------------------------------------
        function __construct($x, $y, $distanceX, $distanceY, $strokeColor = 'black', $strokeWidth = 1, $options = array()){
            $this->_sx      = $x;
            $this->_sy      = $y;
            $this->_ex      = $x + $distanceX;
            $this->_ey      = $y + $distanceY;
         
            $this->_imagickDraw     = new ImagickDraw();
            $this->setStyle(
                $this->_imagickDraw,
                array(      
                    'STROKE_COLOR'  => $strokeColor,
                    'STROKE_WIDTH'  => $strokeWidth,
                )
            );
            
            parent::__construct('LINE');    
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 直線編集
         * 
         * @param Object    $aImagick   Imagickオブジェクト
         * @return string   drawパラメータ文字列
         */  
        //-------------------------------------------------------------------------------------------------------------------
        public function draw($aImagick){
            $this->_imagickDraw->line($this->_sx, $this->_sy, $this->_ex, $this->_ey);
            $aImagick->drawImage($this->_imagickDraw);
        }
    }
            
    //========================================================================================================================
    /**
     * ImageMagickビルダー用シェイプ:textクラス
     *
     * LICENSE: This source file is subject to GNU GENERAL PUBLIC LICENSE Version 3
     * http://www.gnu.org/licenses/gpl-3.0.txt.
     *
     * @package    LabbitBox
     * @subpackage core
     * @copyright  2010 LabbitBox Development Team.
     * @license    GPL v3 http://www.gnu.org/licenses/gpl-3.0.txt
     * @author     neobaba <neobaba@labbitbox.org>
     * @version    v0.1
     * @since      2010/2/26
     * @link       http://labbitbox.org/
     * @see        http://labbitbox.org/
     */
    //========================================================================================================================
    class Text extends MagickShape{
        private $_imagickDraw   = null;
        private $_x     = 0;
        private $_y     = 0;
        private $_angle = 0;
        private $_text  = '';

        //-------------------------------------------------------------------------------------------------------------------
        /**
         * テキストシェイプ
         * 
         * @param integer   $x              開始位置：横座標(ピクセル)
         * @param integer   $y              開始位置：縦座標(ピクセル)
         * @param integer   $angle          軸傾斜角度
         * (@param integer   $angleY         Y軸傾斜角度)
         * @param string    $text           描画文字列
         * @param string    $pointSize      文字サイズ(ポイント)
         * @param string    $font           使用フォント(日本語TTFを使用する場合はフルパスで指定する 例:FONT_DIR.'/kochi-gothic-subst.ttf')
         * @param string    $strokeColor    線色指定文字列(色名 or #000000 のRGB形式)：nullの場合セットしない
         * @param integer   $strokeWidth    線幅(ピクセル：0の場合はデフォルトもしくは設定済み幅値)：nullの場合セットしない
         * @param string    $fillColor      塗りつぶし色指定文字列(色名 or #000000 のRGB形式)
         * @param array     $options        その他オプションリスト
         */  
        //-------------------------------------------------------------------------------------------------------------------
        function __construct($x, $y, $angle, $angleY, $text, $pointSize = '', $font = '', $strokeColor = null, $strokeWidth = null, $fillColor = 'black', $options = array()){
            $this->_x       = $x;
            $this->_y       = $y;
            $this->_angle   = $angle;
            $this->_text    = $text;

            $this->_imagickDraw     = new ImagickDraw();
            $this->_imagickDraw->setFont($font);
            if ($strokeWidth != null) $this->_imagickDraw->setStrokeWidth($strokeWidth);
            $this->_imagickDraw->setFontSize($pointSize);
            if ($strokeColor != null) $this->_imagickDraw->setStrokeColor($strokeColor);
            $this->_imagickDraw->setFillColor($fillColor);
            $this->_imagickDraw->setStrokeAntialias(true);
            $this->_imagickDraw->setTextAntialias(true);

            parent::__construct('TEXT');    
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * テキスト編集
         * 
         * @param Object    $aImagick   Imagickオブジェクト
         * @return string   annotateパラメータ文字列
         */  
        //-------------------------------------------------------------------------------------------------------------------
        public function draw($aImagick){
            $aImagick->annotateImage($this->_imagickDraw, $this->_x, $this->_y, $this->_angle, $this->_text);
        }
    }
            
    //========================================================================================================================
    /**
     * ImageMagickビルダー用シェイプ:polylineクラス
     *
     * LICENSE: This source file is subject to GNU GENERAL PUBLIC LICENSE Version 3
     * http://www.gnu.org/licenses/gpl-3.0.txt.
     *
     * @package    LabbitBox
     * @subpackage core
     * @copyright  2010 LabbitBox Development Team.
     * @license    GPL v3 http://www.gnu.org/licenses/gpl-3.0.txt
     * @author     neobaba <neobaba@labbitbox.org>
     * @version    v0.1
     * @since      2010/2/26
     * @link       http://labbitbox.org/
     * @see        http://labbitbox.org/
     */
    //========================================================================================================================
    class Polyline extends MagickShape{
        private $_imagickDraw   = null;
        private $_xList         = array();
        private $_yList         = array();
        private $_styleList     = array();
        private $_baseStyle     = array();
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 折れ線シェイプ
         * 
         * @param string    $strokeColor    線色指定文字列(色名 or #000000 のRGB形式)
         * @param integer   $strokeWidth    線幅(ピクセル：0の場合はデフォルトもしくは設定済み幅値)
         * @param string    $fillColor      塗りつぶし色指定文字列(色名 or #000000 のRGB形式)
         * @param array     $options        その他オプションリスト
         */  
        //-------------------------------------------------------------------------------------------------------------------
        function __construct($strokeColor = 'black', $strokeWidth = 1, $fillColor = 'white', $options = array()){
            $this->_imagickDraw = new ImagickDraw();

            $this->_baseStyle   = array(
                'STROKE_COLOR'  => $strokeColor,
                'STROKE_WIDTH'  => $strokeWidth,
                'FILL_COLOR'    => $fillColor,
                'FILL_OPACITY'  => 0.0,
            );

            parent::__construct('POLYLINE');    
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 座標追加
         * 
         * @param integer   $x      X座標
         * @param integer   $y      Y座標
         */  
        //-------------------------------------------------------------------------------------------------------------------
        public function addPoint($x, $y, $aStyleList = array()){
            $this->_xList[]     = $x;                
            $this->_yList[]     = $y;
            $this->_styleList[] = $aStyleList;                
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * テキスト編集
         * 
         * @param Object    $aImagick   Imagickオブジェクト
         * @return string   drawパラメータ文字列
         */  
        //-------------------------------------------------------------------------------------------------------------------
        public function draw($aImagick){
            //ポイントが複数ない場合は処理なし
            if (count($this->_xList) < 2){
                return;
            }

            //ポリライン描画
            $wPolyline  = array();
            $this->setStyle($this->_imagickDraw, $this->_baseStyle);
            for ($i = 0; $i < count($this->_xList); $i++){
                $wPolyline[]    = array('x' => $this->_xList[$i], 'y' => $this->_yList[$i]);
                
                $wNextIdx   = $i + 1;
                if ($wNextIdx < (count($this->_xList))){// - 1)){
                    if (count($this->_styleList[$wNextIdx]) > 0){
                        if (count($wPolyline) > 1){
                            $this->_imagickDraw->polyline($wPolyline);
                            $aImagick->drawImage($this->_imagickDraw);
                            $this->_imagickDraw = new ImagickDraw();
                        }                        

                        //変更スタイルで描画
                        $wPolyline      = array();
                        $wPolyline[]    = array('x' => $this->_xList[$i], 'y' => $this->_yList[$i]);
                        $wPolyline[]    = array('x' => $this->_xList[$wNextIdx], 'y' => $this->_yList[$wNextIdx]);
                        $this->setStyle($this->_imagickDraw, $this->_baseStyle);
                        $this->setStyle($this->_imagickDraw, $this->_styleList[$wNextIdx]);
                        $this->_imagickDraw->polyline($wPolyline);
                        $aImagick->drawImage($this->_imagickDraw);
                        
                        //ポリラインリセット
                        $this->_imagickDraw = new ImagickDraw();
                        $wPolyline  = array();
                        $this->setStyle($this->_imagickDraw, $this->_baseStyle);
                        $this->setStyle($this->_imagickDraw, array('STROKE_DASH' => null));
                    }
                }
            }
            if (count($wPolyline) > 1){
                $this->_imagickDraw->polyline($wPolyline);
                $aImagick->drawImage($this->_imagickDraw);
            }
        }   
    }
    
?>
