<?php
//
//   CF ImageText 1.0
//   -------------------------------
//
//   Author:    codefuture.co.uk
//   Version:   1.0v
//   Date:      07 June 2011 @ 21:48:33
//
//   download the latest version from - http://codefuture.co.uk/projects/ImageText/
//
//   Copyright (c) 2011 codefuture.co.uk
//   This file is part of the CF ImageText 1.0.
//
//   CF ImageText 1.0 is free software: you can redistribute it and/or modify
//   it under the terms of the GNU General Public License as published by
//   the Free Software Foundation, either version 3 of the License, or
//   (at your option) any later version.
//
//   CF ImageText 1.0 is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU General Public License for more details.
//   You should have received a copy of the GNU General Public License
//   along with CF ImageText 1.0.  If not, see http://www.gnu.org/licenses/.
//
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

@include '../content/setting/img_key.php';

function Hex2Str($hex){
    $string='';
    for ($i=0; $i < strlen($hex)-1; $i+=2){
        $string .= chr(hexdec($hex[$i].$hex[$i+1]));
    }
    return $string;
}

if(isset($_GET['text'])){
	$authKey	= isset($_GET['a'])		? $_GET['a']:'';
	$text		= isset($_GET['text'])	? $_GET['text']:'';
	$fontSize	= isset($_GET['size'])	? (intval($_GET['size'])<5?null:intval($_GET['size'])):null;
	$fontName	= isset($_GET['font'])	? $_GET['font']:null;
	$fontColor	= isset($_GET['color'])	? $_GET['color']:null;
    $text=urldecode(Hex2Str($text));
	$timg = new imageText();
	$timg->imageSettings($text,$fontSize,$fontName,$fontColor);
	$timg->authSign($authKey);
	$timg->makeImage();
}


class imageText {

	var $set = array();
	var $imgSet = array();
	var $imgKey;

	function __construct() {
	// Settings
	global $userkey;
		$this->set['Path']			= realpath(dirname(__FILE__)); // set's the server path to the script folder
		$this->set['url']			= ''; // url to the script folder
		$this->set['cacheDir']		= '/cache/';				// directory for caching generated images should be writable 
		$this->set['imgQuality']	= 0;						// image save Quality 0-9 (0 is best, not 9)
		$this->set['fontDir']		= $this->set['Path'].'/fonts/';		// full path to font folder
		$this->set['fontName']		= '';						// preferred TTF font (it needs to be in the fonts folder)
		$this->set['fontSize']		= 30;						// preferred font size
		$this->set['fontColor']		= 666;						// preferred font color
		$this->set['userKey']		= $userkey;			// your user key it's best to make this a random string
	}


/*
 * imageSettings
 *
 * text -> text on image (str)
 * $fontSize -> font settings (arr)
 * $fontName -> dir\imageName.png (str)
 * $fontColor -> image save quality (int)
 */
	public function imageSettings($text,$fontSize=null,$fontName=null,$fontColor=null){
		$this->imgSet['txt'] = $text;
		$this->imgSet['fontSize']	= is_numeric($fontSize) ? (int)$fontSize:$fontSize;
		$this->imgSet['fontColor']	= $fontColor;
		$this->imgSet['fontName']	= $fontName;
	}


/*
 * basic sign checking: computing md5 sum of concatenation of secret key and parameters
 *
 * auth_sign -> user key (str)
 * var -> key var (arr) (order -> userKey, text, fontSize, fontColor, fontName)
 */
	public function authSign($authKey){
		$this->imgKey = md5($this->set['userKey'].implode("",$this->imgSet));
		if ($this->imgKey != $authKey){
		// auth error, provided sign is invalid 
			die('Auth failed');//.$authKey.' != '.$this->imgKey);
		}
	}


/*
 * Make the image
 *
 * return -> the type of info to send back (str)
 */
	public function makeImage($return = 'print'){
	
		$this->imgSet['fontSize']	= !is_null($this->imgSet['fontSize']) && is_numeric($this->imgSet['fontSize']) ? (int)$this->imgSet['fontSize']:$this->set['fontSize'];
		$this->imgSet['fontColor']	= !is_null($this->imgSet['fontColor'])	? $this->imgSet['fontColor'] : $this->set['fontColor'];
		$this->imgSet['fontName']	= !is_null($this->imgSet['fontName'])	? $this->imgSet['fontName']	 : $this->set['fontName'];

	// set image key for html out
		if($return != 'print'){
			$this->imgKey = md5($this->set['userKey'].implode("",$this->imgSet));
		}

	// if cached file exists output it and quit or return the cache file address
		$cacheImg = $this->loadCache($return);
		if(is_resource($cacheImg)) return $cacheImg;
		if($return == 'html' && is_array($cacheImg))return $cacheImg[0];

		$fontAddress	= $this->set['fontDir'].$this->imgSet['fontName'].'.ttf';
		$txtArray		= explode("|",$this->imgSet['txt']);
		$longStr 		= 0;
		$offy			= 3;
		$offx			= 3;

		foreach ($txtArray as $line){
			$lines[]=$line;
			$longStr = strlen($line)>strlen($longStr)?$line:$longStr;
		}

		$n = count($lines);
		$bbox = $this->imagettfbbox_t($this->imgSet['fontSize'], 0, $fontAddress, $longStr);

		$tww = abs($bbox[2] - $bbox[0]) * 1.01; //Calculates the width of the text box by subtracting the Upper Right "X" position with the Lower Left "X" position.
		$thh = abs($bbox[7] - $bbox[1]); //Calculates the height of the text box by adding the absolute value of the Upper Left "Y" position with the Lower Left "Y" position.

		$th	= -$bbox[7]-1;
		$sp	= ($n>1)?$th+((($thh*$n)-($n*$th))/($n)):0;

		$width	= $tww+($offx*2);
		$height	= $thh*$n+($offy*2);
		$image	= $this->transparentImage($width,$height);// creating image

		$fontColor = $this->html2rgb($this->imgSet['fontColor']);
		$tclr = imagecolorallocate($image, $fontColor[0], $fontColor[1], $fontColor[2]);

		$ynew = $this->Vert($height,$thh*$n,$th);

		foreach($lines as $tx){
			$bbox	= $this->imagettfbbox_t  ($this->imgSet['fontSize'], 0, $fontAddress, $tx);
			$tw		= $bbox[2]-$bbox[0];
			$xnew	= $this->Horiz($width,$tww,$tw);
			imagettftext($image, $this->imgSet['fontSize'], 0, $xnew, $ynew, $tclr, $fontAddress, $tx);// rendering text
			$ynew += $sp;
		}

	// save cache file 
		imagepng($image, $cacheImg,$this->set['imgQuality']); // outputing PNG image to file cache 

	// return image as resource
		if($return == 'resource'){
			return $image;
		}
	// output html image tag
		elseif($return == 'html'){
			return '<img src="'.$this->set['url'].$this->set['cacheDir'].$this->imgKey.'.png" alt="'.implode(" ",$lines).'" title="'.implode(" ",$lines).'" />';
		}
	// print image png
		else{
			$this->browserCache(time());
			header("Content-type: image/png");
			imagepng($image);
		}

	// destroy image
		imagedestroy($image);
	}


/*
 * checking for cached file:
 *
 * return -> the type of info to send back (str)
 */
	private function loadCache($return){
		$cacheFile = $this->set['Path'].$this->set['cacheDir'].$this->imgKey.'.png';
	//if cached file exists
		if (!file_exists($cacheFile))return $cacheFile;
	
	//if cached file exists output it and quit
		if($return == 'resource')	return $this->openImage($cacheFile);
		if($return == 'html')		return array('<img src="'.$this->set['url'].$this->set['cacheDir'].$this->imgKey.'.png'.'" alt="'.urlencode(str_replace("|"," ",$this->imgSet['txt'])).'" title="'.urlencode(str_replace("|"," ",$this->imgSet['txt'])).'" />');
	
		if(array_key_exists("HTTP_IF_MODIFIED_SINCE",$_SERVER)){
			$if_modified_since=strtotime(preg_replace('/;.*$/','',$_SERVER["HTTP_IF_MODIFIED_SINCE"]));
			if($if_modified_since >= filemtime($cacheFile)){
				header("HTTP/1.0 304 Not Modified");
				exit();
			}
		}
		$this->browserCache(filemtime($cacheFile));
		$filePieces	= pathinfo($cacheFile);
		header("Content-type: image/".($filePieces['extension']=='jpg'?'jpeg':$filePieces['extension']));
		readfile($cacheFile);
		exit();
	}


/*
 * Set's the browsers Cache 
 *
 * time -> the time when the file was last modified
 */
	private function browserCache($time){
		header('Last-Modified: '.gmdate('D, d M Y H:i:s', $time).' GMT', true, 200);
		header('Expires: '.gmdate('D, d M Y H:i:s', $time + 86400*365).' GMT', true, 200);
		header("Pragma: public");
		header("Cache-Control: maxage=".(86400*14));
	}


/*
 * openImage
 *
 * $src -> address of the image 
 * return image resource
 */
	private function openImage($src){
		switch( exif_imagetype($src)){
			case IMAGETYPE_PNG:
				$img = @imagecreatefrompng($src);
				break;
			case IMAGETYPE_GIF:
				$img = @imagecreatefromgif($src);
				break;
			case IMAGETYPE_JPEG:
				$img = @imagecreatefromjpeg($src);
				break;
			default:
				die('can\'t open image');
				break;
		}

		return $img;
	}


/*
 * Sets the horizontal position of the first character of a line of text.
 *
 * $width -> width of the image
 * $twidth -> width of the longest line of this group of lines of text
 * $lwidth -> width of this line of text.
 */
	private function Horiz($width,$twidth,$lwidth){
		$xnew=0;
		$just='left';
		$horz='center';
		if($just=="right")$xnew=$twidth-$lwidth-2;
		if($just=="center")$xnew=($twidth-$lwidth)/2;
		if($just=="left")$xnew=1;
		if($horz=="right")$xnew=$xnew+($width-$twidth);
		if($horz=="center")$xnew=$xnew+($width-$twidth)/2;
		return $xnew;
	}


/*
 * Sets the vertical position of the first character of a line of text.
 *
 * $height -> height of the image
 * $theight -> height of this group of lines of text
 * $lheight -> height of one line of text.
 */
	private function Vert($height,$theight,$lheight){
		$vert = 'center';
		if($vert=="center")$ynew=($height/2)-($theight/2)+$lheight;
		if($vert=="top")$ynew=$lheight;
		if($vert=="bottom")$ynew=$height-$theight+$lheight;
		return $ynew;
	}


/*
 * html2rgb recognizes HTML or CSS colors in format #(hex_red)(hex_green)(hex_blue),
 * where hex_red, hex_green and hex_blue are 1 or 2-digit hex-representations of red,
 * green or blue color components.
 *
 * color -> hex color (str)
 */
	private function html2rgb($color) {
		if (strlen($color) == 6) {
			list($strRed, $strGreen, $strBlue) = array( $color[0].$color[1],
														$color[2].$color[3],
														$color[4].$color[5]);
		} elseif (strlen($color) == 3) {
			list($strRed, $strGreen, $strBlue) = array( $color[0].$color[0],
														$color[1].$color[1],
														$color[2].$color[2]);
		} elseif (strlen($color) == 2) {
			list($strRed, $strGreen, $strBlue) = array( $color[0].$color[1],
														$color[0].$color[1],
														$color[0].$color[1]);
		} elseif (strlen($color) == 1) {
			list($strRed, $strGreen, $strBlue) = array( $color[0].$color[0],
														$color[0].$color[0],
														$color[0].$color[0]);
		}

		$strRed   = hexdec($strRed);
		$strGreen = hexdec($strGreen);
		$strBlue  = hexdec($strBlue);

		return array($strRed, $strGreen, $strBlue);
	}


/*
 * imagettfbbox_t a better function to find the coordinates of the text bounding box so I used it.
 * made by uquay K Calloway http://ruquay.com/sandbox/imagettf/ made 
 */
	private function imagettfbbox_t($size, $angle, $fontfile, $text){
		// compute size with a zero angle
		$coords = imagettfbbox($size, 0, $fontfile, $text);
		// convert angle to radians
		$a = deg2rad($angle);
		// compute some usefull values
		$ca = cos($a);
		$sa = sin($a);
		$ret = array();
		// perform transformations
		for($i = 0; $i < 7; $i += 2){
			$ret[$i] = round($coords[$i] * $ca + $coords[$i+1] * $sa);
			$ret[$i+1] = round($coords[$i+1] * $ca - $coords[$i] * $sa);
		}
		return $ret;
	}


/*
 * Checking for gd, Freetype support and
 * that your cache dir is really writable to PHP scripts
 *
 * dir -> cache dir (str)
 */
	private function checking($dir){
		if (!function_exists('gd_info')) die('No <a href="http://www.php.net/manual/en/ref.image.php">gd</a> support in PHP.');
		$gd = gd_info();
		if ($gd["FreeType Support"] == false) die('No FreeType support in gd</a>');

		$tf = $dir.md5(rand()).".test";
		$f = @fopen($tf, "w");
		if ($f == false)
			die("Fatal error! {$cache_dir} is not writable. Set 'chmod 777 {$cache_dir}' 
				   or something like this");
		fclose($f);
		unlink($tf);
	}

	private	function transparentImage($width,$height){
		$im = imagecreatetruecolor($width, $height);
		imagealphablending($im, false);
		$color = imagecolorallocatealpha($im, 0, 0, 0, 127);
		imagefill($im, 0, 0, $color);
		imagesavealpha($im, true);
		imagealphablending($im, true);
		return $im;
	}
}
