Blame Identity/Models/Html/phpBB/3.0.4/includes/captcha/captcha_gd.php

d6e8d8
d6e8d8
/**
d6e8d8
*
d6e8d8
* @package VC
d6e8d8
* @version $Id: captcha_gd.php 8479 2008-03-29 00:22:48Z naderman $
d6e8d8
* @copyright (c) 2006 phpBB Group
d6e8d8
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
d6e8d8
*
d6e8d8
*/
d6e8d8
d6e8d8
/**
d6e8d8
* @ignore
d6e8d8
*/
d6e8d8
if (!defined('IN_PHPBB'))
d6e8d8
{
d6e8d8
	exit;
d6e8d8
}
d6e8d8
d6e8d8
/**
d6e8d8
* Original Author - Xore (Robert Hetzler)
d6e8d8
* With contributions from Neothermic
d6e8d8
*
d6e8d8
* @package VC
d6e8d8
*/
d6e8d8
class captcha
d6e8d8
{
d6e8d8
	var $width = 360;
d6e8d8
	var $height = 96;
d6e8d8
d6e8d8
	/**
d6e8d8
	* Create the image containing $code with a seed of $seed
d6e8d8
	*/
d6e8d8
	function execute($code, $seed)
d6e8d8
	{
d6e8d8
		global $config;
d6e8d8
		srand($seed);
d6e8d8
		mt_srand($seed);
d6e8d8
d6e8d8
		// Create image
d6e8d8
		$img = imagecreatetruecolor($this->width, $this->height);
d6e8d8
d6e8d8
		// Generate colours
d6e8d8
		$colour = new colour_manager($img, array(
d6e8d8
			'random'	=> true,
d6e8d8
			'min_value'	=> 60,
d6e8d8
		), 'hsv');
d6e8d8
d6e8d8
		$scheme = $colour->colour_scheme('background', false);
d6e8d8
		$scheme = $colour->mono_range($scheme, 10, false);
d6e8d8
		shuffle($scheme);
d6e8d8
d6e8d8
		$bg_colours = array_splice($scheme, mt_rand(6, 12));
d6e8d8
d6e8d8
		// Generate code characters
d6e8d8
		$characters = $sizes = $bounding_boxes = array();
d6e8d8
		$width_avail = $this->width - 15;
d6e8d8
		$code_len = strlen($code);
d6e8d8
d6e8d8
		$captcha_bitmaps = $this->captcha_bitmaps();
d6e8d8
		for ($i = 0; $i < $code_len; ++$i)
d6e8d8
		{
d6e8d8
			$characters[$i] = new char_cube3d($captcha_bitmaps, $code[$i]);
d6e8d8
d6e8d8
			list($min, $max) = $characters[$i]->range();
d6e8d8
			$sizes[$i] = mt_rand($min, $max);
d6e8d8
d6e8d8
			$box = $characters[$i]->dimensions($sizes[$i]);
d6e8d8
			$width_avail -= ($box[2] - $box[0]);
d6e8d8
			$bounding_boxes[$i] = $box;
d6e8d8
		}
d6e8d8
d6e8d8
		// Redistribute leftover x-space
d6e8d8
		$offset = array();
d6e8d8
		for ($i = 0; $i < $code_len; ++$i)
d6e8d8
		{
d6e8d8
			$denom = ($code_len - $i);
d6e8d8
			$denom = max(1.3, $denom);
d6e8d8
			$offset[$i] = mt_rand(0, (1.5 * $width_avail) / $denom);
d6e8d8
			$width_avail -= $offset[$i];
d6e8d8
		}
d6e8d8
d6e8d8
		if ($config['captcha_gd_x_grid'])
d6e8d8
		{
d6e8d8
			$grid = (int) $config['captcha_gd_x_grid'];
d6e8d8
			for ($y = 0; $y < $this->height; $y += mt_rand($grid - 2, $grid + 2))
d6e8d8
			{
d6e8d8
				$current_colour = $scheme[array_rand($scheme)];
d6e8d8
				imageline($img, mt_rand(0,4), mt_rand($y - 3, $y), mt_rand($this->width - 5, $this->width), mt_rand($y - 3, $y), $current_colour);
d6e8d8
			}
d6e8d8
		}
d6e8d8
d6e8d8
		if ($config['captcha_gd_y_grid'])
d6e8d8
		{
d6e8d8
			$grid = (int) $config['captcha_gd_y_grid'];
d6e8d8
			for ($x = 0; $x < $this->width; $x += mt_rand($grid - 2, $grid + 2))
d6e8d8
			{
d6e8d8
				$current_colour = $scheme[array_rand($scheme)];
d6e8d8
				imagedashedline($img, mt_rand($x -3, $x + 3), mt_rand(0, 4), mt_rand($x -3, $x + 3), mt_rand($this->height - 5, $this->height), $current_colour);
d6e8d8
			}
d6e8d8
		}
d6e8d8
d6e8d8
		$xoffset = 5;
d6e8d8
		for ($i = 0; $i < $code_len; ++$i)
d6e8d8
		{
d6e8d8
			$dimm = $bounding_boxes[$i];
d6e8d8
			$xoffset += ($offset[$i] - $dimm[0]);
d6e8d8
			$yoffset = mt_rand(-$dimm[1], $this->height - $dimm[3]);
d6e8d8
d6e8d8
			$characters[$i]->drawchar($sizes[$i], $xoffset, $yoffset, $img, $colour->get_resource('background'), $scheme);
d6e8d8
			$xoffset += $dimm[2];
d6e8d8
		}
d6e8d8
		
d6e8d8
		if ($config['captcha_gd_foreground_noise'])
d6e8d8
		{
d6e8d8
			$this->noise_line($img, 0, 0, $this->width, $this->height, $colour->get_resource('background'), $scheme, $bg_colours);
d6e8d8
		}
d6e8d8
d6e8d8
		// Send image
d6e8d8
		header('Content-Type: image/png');
d6e8d8
		header('Cache-control: no-cache, no-store');
d6e8d8
		imagepng($img);
d6e8d8
		imagedestroy($img);
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	* Noise line
d6e8d8
	*/
d6e8d8
	function noise_line($img, $min_x, $min_y, $max_x, $max_y, $bg, $font, $non_font)
d6e8d8
	{
d6e8d8
		imagesetthickness($img, 2);
d6e8d8
d6e8d8
		$x1 = $min_x;
d6e8d8
		$x2 = $max_x;
d6e8d8
		$y1 = $min_y;
d6e8d8
		$y2 = $min_y;
d6e8d8
d6e8d8
		do
d6e8d8
		{
d6e8d8
			$line = array_merge(
d6e8d8
				array_fill(0, mt_rand(30, 60), $non_font[array_rand($non_font)]),
d6e8d8
				array_fill(0, mt_rand(30, 60), $bg)
d6e8d8
			);
d6e8d8
d6e8d8
			imagesetstyle($img, $line);
d6e8d8
			imageline($img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
d6e8d8
d6e8d8
			$y1 += mt_rand(12, 35);
d6e8d8
			$y2 += mt_rand(12, 35);
d6e8d8
		}
d6e8d8
		while ($y1 < $max_y && $y2 < $max_y);
d6e8d8
d6e8d8
		$x1 = $min_x;
d6e8d8
		$x2 = $min_x;
d6e8d8
		$y1 = $min_y;
d6e8d8
		$y2 = $max_y;
d6e8d8
d6e8d8
		do
d6e8d8
		{
d6e8d8
			$line = array_merge(
d6e8d8
				array_fill(0, mt_rand(30, 60), $non_font[array_rand($non_font)]),
d6e8d8
				array_fill(0, mt_rand(30, 60), $bg)
d6e8d8
			);
d6e8d8
d6e8d8
			imagesetstyle($img, $line);
d6e8d8
			imageline($img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
d6e8d8
d6e8d8
			$x1 += mt_rand(20, 35);
d6e8d8
			$x2 += mt_rand(20, 35);
d6e8d8
		}
d6e8d8
		while ($x1 < $max_x && $x2 < $max_x);
d6e8d8
		imagesetthickness($img, 1);
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	* Return bitmaps
d6e8d8
	*/
d6e8d8
	function captcha_bitmaps()
d6e8d8
	{
d6e8d8
		return array(
d6e8d8
			'width'		=> 9,
d6e8d8
			'height'	=> 15,
d6e8d8
			'data'		=> array(
d6e8d8
d6e8d8
			'A' => array(
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,1,0,1,0,0,0),
d6e8d8
				array(0,0,0,1,0,1,0,0,0),
d6e8d8
				array(0,0,0,1,0,1,0,0,0),
d6e8d8
				array(0,0,1,0,0,0,1,0,0),
d6e8d8
				array(0,0,1,0,0,0,1,0,0),
d6e8d8
				array(0,0,1,0,0,0,1,0,0),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,1,1,1,1,1,1,1,0),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
			),
d6e8d8
			'B' => array(
d6e8d8
				array(1,1,1,1,1,1,1,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,1,0),
d6e8d8
				array(1,1,1,1,1,1,1,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,1,0),
d6e8d8
				array(1,1,1,1,1,1,1,0,0),
d6e8d8
			),
d6e8d8
			'C' => array(
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
			),
d6e8d8
			'D' => array(
d6e8d8
				array(1,1,1,1,1,1,1,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,1,0),
d6e8d8
				array(1,1,1,1,1,1,1,0,0),
d6e8d8
			),
d6e8d8
			'E' => array(
d6e8d8
				array(1,1,1,1,1,1,1,1,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,1,1,1,1,1,1,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,1,1,1,1,1,1,1,1),
d6e8d8
			),
d6e8d8
			'F' => array(
d6e8d8
				array(1,1,1,1,1,1,1,1,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,1,1,1,1,1,1,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
			),
d6e8d8
			'G' => array(
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,1,1,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
			),
d6e8d8
			'H' => array(
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,1,1,1,1,1,1,1,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
			),
d6e8d8
			'I' => array(
d6e8d8
				array(1,1,1,1,1,1,1,1,1),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(1,1,1,1,1,1,1,1,1),
d6e8d8
			),
d6e8d8
			'J' => array(
d6e8d8
				array(1,1,1,1,1,1,1,1,1),
d6e8d8
				array(0,0,0,0,0,1,0,0,0),
d6e8d8
				array(0,0,0,0,0,1,0,0,0),
d6e8d8
				array(0,0,0,0,0,1,0,0,0),
d6e8d8
				array(0,0,0,0,0,1,0,0,0),
d6e8d8
				array(0,0,0,0,0,1,0,0,0),
d6e8d8
				array(0,0,0,0,0,1,0,0,0),
d6e8d8
				array(0,0,0,0,0,1,0,0,0),
d6e8d8
				array(0,0,0,0,0,1,0,0,0),
d6e8d8
				array(0,0,0,0,0,1,0,0,0),
d6e8d8
				array(0,0,0,0,0,1,0,0,0),
d6e8d8
				array(1,0,0,0,0,1,0,0,0),
d6e8d8
				array(1,0,0,0,0,1,0,0,0),
d6e8d8
				array(0,1,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,1,1,0,0,0,0,0),
d6e8d8
			),
d6e8d8
			'K' => array(    // New 'K', supplied by NeoThermic
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,1,0,0),
d6e8d8
				array(1,0,0,0,0,1,0,0,0),
d6e8d8
				array(1,0,0,0,1,0,0,0,0),
d6e8d8
				array(1,0,0,1,0,0,0,0,0),
d6e8d8
				array(1,0,1,0,0,0,0,0,0),
d6e8d8
				array(1,1,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,1,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,1,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,1,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,1,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,1,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
			),
d6e8d8
			'L' => array(
d6e8d8
				array(0,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,1,1,1,1,1,1,1,1),
d6e8d8
			),
d6e8d8
			'M' => array(
d6e8d8
				array(1,1,0,0,0,0,0,1,1),
d6e8d8
				array(1,1,0,0,0,0,0,1,1),
d6e8d8
				array(1,0,1,0,0,0,1,0,1),
d6e8d8
				array(1,0,1,0,0,0,1,0,1),
d6e8d8
				array(1,0,1,0,0,0,1,0,1),
d6e8d8
				array(1,0,0,1,0,1,0,0,1),
d6e8d8
				array(1,0,0,1,0,1,0,0,1),
d6e8d8
				array(1,0,0,1,0,1,0,0,1),
d6e8d8
				array(1,0,0,0,1,0,0,0,1),
d6e8d8
				array(1,0,0,0,1,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
			),
d6e8d8
			'N' => array(
d6e8d8
				array(1,1,0,0,0,0,0,0,1),
d6e8d8
				array(1,1,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,1,0,0,0,0,0,1),
d6e8d8
				array(1,0,1,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,1,0,0,0,0,1),
d6e8d8
				array(1,0,0,1,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,1,0,0,0,1),
d6e8d8
				array(1,0,0,0,1,0,0,0,1),
d6e8d8
				array(1,0,0,0,1,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,1,0,0,1),
d6e8d8
				array(1,0,0,0,0,1,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,1,0,1),
d6e8d8
				array(1,0,0,0,0,0,1,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,1,1),
d6e8d8
				array(1,0,0,0,0,0,0,1,1),
d6e8d8
			),
d6e8d8
			'O' => array(
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
			),
d6e8d8
			'P' => array(
d6e8d8
				array(1,1,1,1,1,1,1,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,1,0),
d6e8d8
				array(1,1,1,1,1,1,1,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
			),
d6e8d8
			'Q' => array(
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,1,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,1,0,1),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,1,1,1,1,1,0,1),
d6e8d8
			),
d6e8d8
			'R' => array(
d6e8d8
				array(1,1,1,1,1,1,1,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,1,0),
d6e8d8
				array(1,1,1,1,1,1,1,0,0),
d6e8d8
				array(1,1,1,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,1,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,1,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,1,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,1,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
			),
d6e8d8
			'S' => array(
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(0,1,0,0,0,0,0,0,0),
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
				array(0,0,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
			),
d6e8d8
			'T' => array(
d6e8d8
				array(1,1,1,1,1,1,1,1,1),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
			),
d6e8d8
			'U' => array(
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
			),
d6e8d8
			'V' => array(
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,1,0,0,0,1,0,0),
d6e8d8
				array(0,0,1,0,0,0,1,0,0),
d6e8d8
				array(0,0,1,0,0,0,1,0,0),
d6e8d8
				array(0,0,1,0,0,0,1,0,0),
d6e8d8
				array(0,0,0,1,0,1,0,0,0),
d6e8d8
				array(0,0,0,1,0,1,0,0,0),
d6e8d8
				array(0,0,0,1,0,1,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
			),
d6e8d8
			'W' => array(    // New 'W', supplied by MHobbit
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,1,0,0,0,1),
d6e8d8
				array(1,0,0,0,1,0,0,0,1),
d6e8d8
				array(1,0,0,1,0,1,0,0,1),
d6e8d8
				array(1,0,0,1,0,1,0,0,1),
d6e8d8
				array(1,0,0,1,0,1,0,0,1),
d6e8d8
				array(1,0,1,0,0,0,1,0,1),
d6e8d8
				array(1,0,1,0,0,0,1,0,1),
d6e8d8
				array(1,0,1,0,0,0,1,0,1),
d6e8d8
				array(1,1,0,0,0,0,0,1,1),
d6e8d8
				array(1,1,0,0,0,0,0,1,1),
d6e8d8
			),
d6e8d8
			'X' => array(
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,1,0,0,0,1,0,0),
d6e8d8
				array(0,0,0,1,0,1,0,0,0),
d6e8d8
				array(0,0,0,1,0,1,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,1,0,1,0,0,0),
d6e8d8
				array(0,0,0,1,0,1,0,0,0),
d6e8d8
				array(0,0,1,0,0,0,1,0,0),
d6e8d8
				array(0,1,0,0,0,0,1,0,0),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
			),
d6e8d8
			'Y' => array(
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,1,0,0,0,1,0,0),
d6e8d8
				array(0,0,1,0,0,0,1,0,0),
d6e8d8
				array(0,0,0,1,0,1,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
			),
d6e8d8
			'Z' => array(    // New 'Z' supplied by Anon
d6e8d8
				array(1,1,1,1,1,1,1,1,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,0,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,0,0,0,0,1,0,0),
d6e8d8
				array(0,0,0,0,0,1,0,0,0),
d6e8d8
				array(0,0,0,0,0,1,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,1,0,0,0,0,0),
d6e8d8
				array(0,0,0,1,0,0,0,0,0),
d6e8d8
				array(0,0,1,0,0,0,0,0,0),
d6e8d8
				array(0,1,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,1,1,1,1,1,1,1,1),
d6e8d8
			),
d6e8d8
			'1' => array(
d6e8d8
				array(0,0,0,1,1,0,0,0,0),
d6e8d8
				array(0,0,1,0,1,0,0,0,0),
d6e8d8
				array(0,1,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,1,1,1,1,1,1,1,0),
d6e8d8
			),
d6e8d8
			'2' => array(    // New '2' supplied by Anon
d6e8d8
				array(0,0,0,1,1,1,0,0,0),
d6e8d8
				array(0,0,1,0,0,0,1,0,0),
d6e8d8
				array(0,1,0,0,0,0,1,1,0),
d6e8d8
				array(0,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,0,0,0,0,0,0,1,1),
d6e8d8
				array(0,0,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,0,0,0,0,1,0,0),
d6e8d8
				array(0,0,0,0,0,1,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,1,0,0,0,0,0),
d6e8d8
				array(0,0,1,0,0,0,0,0,0),
d6e8d8
				array(0,1,0,0,0,0,0,0,0),
d6e8d8
				array(1,1,1,1,1,1,1,1,1),
d6e8d8
				array(0,0,0,0,0,0,0,0,0),
d6e8d8
			),
d6e8d8
			'3' => array(
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,0,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,0,0,0,1,1,0,0),
d6e8d8
				array(0,0,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
			),
d6e8d8
			'4' => array(
d6e8d8
				array(0,0,0,0,0,0,1,1,0),
d6e8d8
				array(0,0,0,0,0,1,0,1,0),
d6e8d8
				array(0,0,0,0,1,0,0,1,0),
d6e8d8
				array(0,0,0,1,0,0,0,1,0),
d6e8d8
				array(0,0,1,0,0,0,0,1,0),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,1,0),
d6e8d8
				array(1,1,1,1,1,1,1,1,1),
d6e8d8
				array(0,0,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,0,0,0,0,0,1,0),
d6e8d8
			),
d6e8d8
			'5' => array(
d6e8d8
				array(1,1,1,1,1,1,1,1,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(0,1,0,0,0,0,0,0,0),
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
				array(0,0,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
			),
d6e8d8
			'6' => array(
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,1,1,1,1,0,0),
d6e8d8
				array(1,0,1,0,0,0,0,1,0),
d6e8d8
				array(1,1,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
			),
d6e8d8
			'7' => array(
d6e8d8
				array(1,1,1,1,1,1,1,1,1),
d6e8d8
				array(0,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,0,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,0,0,0,0,1,0,0),
d6e8d8
				array(0,0,0,0,0,1,0,0,0),
d6e8d8
				array(0,0,0,0,0,1,0,0,0),
d6e8d8
				array(0,0,0,0,1,0,0,0,0),
d6e8d8
				array(0,0,0,1,0,0,0,0,0),
d6e8d8
				array(0,0,0,1,0,0,0,0,0),
d6e8d8
				array(0,0,1,0,0,0,0,0,0),
d6e8d8
				array(0,1,0,0,0,0,0,0,0),
d6e8d8
				array(0,1,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,0),
d6e8d8
			),
d6e8d8
			'8' => array(
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
			),
d6e8d8
			'9' => array(
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,1,1),
d6e8d8
				array(0,1,0,0,0,0,1,0,1),
d6e8d8
				array(0,0,1,1,1,1,0,0,1),
d6e8d8
				array(0,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(1,0,0,0,0,0,0,0,1),
d6e8d8
				array(0,1,0,0,0,0,0,1,0),
d6e8d8
				array(0,0,1,1,1,1,1,0,0),
d6e8d8
			),
d6e8d8
			)
d6e8d8
		);
d6e8d8
	}
d6e8d8
}
d6e8d8
d6e8d8
/**
d6e8d8
* @package VC
d6e8d8
*/
d6e8d8
class char_cube3d
d6e8d8
{
d6e8d8
	var $bitmap;
d6e8d8
	var $bitmap_width;
d6e8d8
	var $bitmap_height;
d6e8d8
d6e8d8
	var $basis_matrix = array(array(1, 0, 0), array(0, 1, 0), array(0, 0, 1));
d6e8d8
	var $abs_x = array(1, 0);
d6e8d8
	var $abs_y = array(0, 1);
d6e8d8
	var $x = 0;
d6e8d8
	var $y = 1;
d6e8d8
	var $z = 2;
d6e8d8
	var $letter = '';
d6e8d8
d6e8d8
	/**
d6e8d8
	*/
d6e8d8
	function char_cube3d(&$bitmaps, $letter)
d6e8d8
	{
d6e8d8
		$this->bitmap			= $bitmaps['data'][$letter];
d6e8d8
		$this->bitmap_width		= $bitmaps['width'];
d6e8d8
		$this->bitmap_height	= $bitmaps['height'];
d6e8d8
d6e8d8
		$this->basis_matrix[0][0] = mt_rand(-600, 600);
d6e8d8
		$this->basis_matrix[0][1] = mt_rand(-600, 600);
d6e8d8
		$this->basis_matrix[0][2] = (mt_rand(0, 1) * 2000) - 1000;
d6e8d8
		$this->basis_matrix[1][0] = mt_rand(-1000, 1000);
d6e8d8
		$this->basis_matrix[1][1] = mt_rand(-1000, 1000);
d6e8d8
		$this->basis_matrix[1][2] = mt_rand(-1000, 1000);
d6e8d8
d6e8d8
		$this->normalize($this->basis_matrix[0]);
d6e8d8
		$this->normalize($this->basis_matrix[1]);
d6e8d8
		$this->basis_matrix[2] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[1]);
d6e8d8
		$this->normalize($this->basis_matrix[2]);
d6e8d8
d6e8d8
		// $this->basis_matrix[1] might not be (probably isn't) orthogonal to $basis_matrix[0]
d6e8d8
		$this->basis_matrix[1] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[2]);
d6e8d8
		$this->normalize($this->basis_matrix[1]);
d6e8d8
d6e8d8
		// Make sure our cube is facing into the canvas (assuming +z == in)
d6e8d8
		for ($i = 0; $i < 3; ++$i)
d6e8d8
		{
d6e8d8
			if ($this->basis_matrix[$i][2] < 0)
d6e8d8
			{
d6e8d8
				$this->basis_matrix[$i][0] *= -1;
d6e8d8
				$this->basis_matrix[$i][1] *= -1;
d6e8d8
				$this->basis_matrix[$i][2] *= -1;
d6e8d8
			}
d6e8d8
		}
d6e8d8
d6e8d8
		// Force our "z" basis vector to be the one with greatest absolute z value
d6e8d8
		$this->x = 0;
d6e8d8
		$this->y = 1;
d6e8d8
		$this->z = 2;
d6e8d8
d6e8d8
		// Swap "y" with "z"
d6e8d8
		if ($this->basis_matrix[1][2] > $this->basis_matrix[2][2])
d6e8d8
		{
d6e8d8
			$this->z = 1;
d6e8d8
			$this->y = 2;
d6e8d8
		}
d6e8d8
d6e8d8
		// Swap "x" with "z"
d6e8d8
		if ($this->basis_matrix[0][2] > $this->basis_matrix[$this->z][2])
d6e8d8
		{
d6e8d8
			$this->x = $this->z;
d6e8d8
			$this->z = 0;
d6e8d8
		}
d6e8d8
d6e8d8
		// Still need to determine which of $x,$y are which.
d6e8d8
		// wrong orientation if y's y-component is less than it's x-component
d6e8d8
		// likewise if x's x-component is less than it's y-component
d6e8d8
		// if they disagree, go with the one with the greater weight difference.
d6e8d8
		// rotate if positive
d6e8d8
		$weight = (abs($this->basis_matrix[$this->x][1]) - abs($this->basis_matrix[$this->x][0])) + (abs($this->basis_matrix[$this->y][0]) - abs($this->basis_matrix[$this->y][1]));
d6e8d8
d6e8d8
		// Swap "x" with "y"
d6e8d8
		if ($weight > 0)
d6e8d8
		{
d6e8d8
			list($this->x, $this->y) = array($this->y, $this->x);
d6e8d8
		}
d6e8d8
d6e8d8
		$this->abs_x = array($this->basis_matrix[$this->x][0], $this->basis_matrix[$this->x][1]);
d6e8d8
		$this->abs_y = array($this->basis_matrix[$this->y][0], $this->basis_matrix[$this->y][1]);
d6e8d8
d6e8d8
		if ($this->abs_x[0] < 0)
d6e8d8
		{
d6e8d8
			$this->abs_x[0] *= -1;
d6e8d8
			$this->abs_x[1] *= -1;
d6e8d8
		}
d6e8d8
d6e8d8
		if ($this->abs_y[1] > 0)
d6e8d8
		{
d6e8d8
			$this->abs_y[0] *= -1;
d6e8d8
			$this->abs_y[1] *= -1;
d6e8d8
		}
d6e8d8
d6e8d8
		$this->letter = $letter;
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	* Draw a character
d6e8d8
	*/
d6e8d8
	function drawchar($scale, $xoff, $yoff, $img, $background, $colours)
d6e8d8
	{
d6e8d8
		$width	= $this->bitmap_width;
d6e8d8
		$height	= $this->bitmap_height;
d6e8d8
		$bitmap	= $this->bitmap;
d6e8d8
d6e8d8
		$colour1 = $colours[array_rand($colours)];
d6e8d8
		$colour2 = $colours[array_rand($colours)];
d6e8d8
d6e8d8
		$swapx = ($this->basis_matrix[$this->x][0] > 0);
d6e8d8
		$swapy = ($this->basis_matrix[$this->y][1] < 0);
d6e8d8
d6e8d8
		for ($y = 0; $y < $height; ++$y)
d6e8d8
		{
d6e8d8
			for ($x = 0; $x < $width; ++$x)
d6e8d8
			{
d6e8d8
				$xp = ($swapx) ? ($width - $x - 1) : $x;
d6e8d8
				$yp = ($swapy) ? ($height - $y - 1) : $y;
d6e8d8
d6e8d8
				if ($bitmap[$height - $yp - 1][$xp])
d6e8d8
				{
d6e8d8
					$dx = $this->scale($this->abs_x, ($xp - ($swapx ? ($width / 2) : ($width / 2) - 1)) * $scale);
d6e8d8
					$dy = $this->scale($this->abs_y, ($yp - ($swapy ? ($height / 2) : ($height / 2) - 1)) * $scale);
d6e8d8
					$xo = $xoff + $dx[0] + $dy[0];
d6e8d8
					$yo = $yoff + $dx[1] + $dy[1];
d6e8d8
d6e8d8
					$origin = array(0, 0, 0);
d6e8d8
					$xvec = $this->scale($this->basis_matrix[$this->x], $scale);
d6e8d8
					$yvec = $this->scale($this->basis_matrix[$this->y], $scale);
d6e8d8
					$face_corner = $this->sum2($xvec, $yvec);
d6e8d8
d6e8d8
					$zvec = $this->scale($this->basis_matrix[$this->z], $scale);
d6e8d8
					$x_corner = $this->sum2($xvec, $zvec);
d6e8d8
					$y_corner = $this->sum2($yvec, $zvec);
d6e8d8
d6e8d8
					imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $xvec, $x_corner,$zvec), 4, $colour1);
d6e8d8
					imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $yvec, $y_corner,$zvec), 4, $colour2);
d6e8d8
d6e8d8
					$face = $this->gen_poly($xo, $yo, $origin, $xvec, $face_corner, $yvec);
d6e8d8
d6e8d8
					imagefilledpolygon($img, $face, 4, $background);
d6e8d8
					imagepolygon($img, $face, 4, $colour1);
d6e8d8
				}
d6e8d8
			}
d6e8d8
		}
d6e8d8
	}
d6e8d8
d6e8d8
	/*
d6e8d8
	* return a roughly acceptable range of sizes for rendering with this texttype
d6e8d8
	*/
d6e8d8
	function range()
d6e8d8
	{
d6e8d8
		return array(3, 4);
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	* Vector length
d6e8d8
	*/
d6e8d8
	function vectorlen($vector)
d6e8d8
	{
d6e8d8
		return sqrt(pow($vector[0], 2) + pow($vector[1], 2) + pow($vector[2], 2));
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	* Normalize
d6e8d8
	*/
d6e8d8
	function normalize(&$vector, $length = 1)
d6e8d8
	{
d6e8d8
		$length = (( $length < 1) ? 1 : $length);
d6e8d8
		$length /= $this->vectorlen($vector);
d6e8d8
		$vector[0] *= $length;
d6e8d8
		$vector[1] *= $length;
d6e8d8
		$vector[2] *= $length;
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	*/
d6e8d8
	function cross_product($vector1, $vector2)
d6e8d8
	{
d6e8d8
		$retval = array(0, 0, 0);
d6e8d8
		$retval[0] =  (($vector1[1] * $vector2[2]) - ($vector1[2] * $vector2[1]));
d6e8d8
		$retval[1] = -(($vector1[0] * $vector2[2]) - ($vector1[2] * $vector2[0]));
d6e8d8
		$retval[2] =  (($vector1[0] * $vector2[1]) - ($vector1[1] * $vector2[0]));
d6e8d8
d6e8d8
		return $retval;
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	*/
d6e8d8
	function sum($vector1, $vector2)
d6e8d8
	{
d6e8d8
		return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1], $vector1[2] + $vector2[2]);
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	*/
d6e8d8
	function sum2($vector1, $vector2)
d6e8d8
	{
d6e8d8
		return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1]);
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	*/
d6e8d8
	function scale($vector, $length)
d6e8d8
	{
d6e8d8
		if (sizeof($vector) == 2)
d6e8d8
		{
d6e8d8
			return array($vector[0] * $length, $vector[1] * $length);
d6e8d8
		}
d6e8d8
d6e8d8
		return array($vector[0] * $length, $vector[1] * $length, $vector[2] * $length);
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	*/
d6e8d8
	function gen_poly($xoff, $yoff, &$vec1, &$vec2, &$vec3, &$vec4)
d6e8d8
	{
d6e8d8
		$poly = array();
d6e8d8
		$poly[0] = $xoff + $vec1[0];
d6e8d8
		$poly[1] = $yoff + $vec1[1];
d6e8d8
		$poly[2] = $xoff + $vec2[0];
d6e8d8
		$poly[3] = $yoff + $vec2[1];
d6e8d8
		$poly[4] = $xoff + $vec3[0];
d6e8d8
		$poly[5] = $yoff + $vec3[1];
d6e8d8
		$poly[6] = $xoff + $vec4[0];
d6e8d8
		$poly[7] = $yoff + $vec4[1];
d6e8d8
d6e8d8
		return $poly;
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	* dimensions
d6e8d8
	*/
d6e8d8
	function dimensions($size)
d6e8d8
	{
d6e8d8
		$xn = $this->scale($this->basis_matrix[$this->x], -($this->bitmap_width / 2) * $size);
d6e8d8
		$xp = $this->scale($this->basis_matrix[$this->x], ($this->bitmap_width / 2) * $size);
d6e8d8
		$yn = $this->scale($this->basis_matrix[$this->y], -($this->bitmap_height / 2) * $size);
d6e8d8
		$yp = $this->scale($this->basis_matrix[$this->y], ($this->bitmap_height / 2) * $size);
d6e8d8
d6e8d8
		$p = array();
d6e8d8
		$p[0] = $this->sum2($xn, $yn);
d6e8d8
		$p[1] = $this->sum2($xp, $yn);
d6e8d8
		$p[2] = $this->sum2($xp, $yp);
d6e8d8
		$p[3] = $this->sum2($xn, $yp);
d6e8d8
d6e8d8
		$min_x = $max_x = $p[0][0];
d6e8d8
		$min_y = $max_y = $p[0][1];
d6e8d8
d6e8d8
		for ($i = 1; $i < 4; ++$i)
d6e8d8
		{
d6e8d8
			$min_x = ($min_x > $p[$i][0]) ? $p[$i][0] : $min_x;
d6e8d8
			$min_y = ($min_y > $p[$i][1]) ? $p[$i][1] : $min_y;
d6e8d8
			$max_x = ($max_x < $p[$i][0]) ? $p[$i][0] : $max_x;
d6e8d8
			$max_y = ($max_y < $p[$i][1]) ? $p[$i][1] : $max_y;
d6e8d8
		}
d6e8d8
d6e8d8
		return array($min_x, $min_y, $max_x, $max_y);
d6e8d8
	}
d6e8d8
}
d6e8d8
d6e8d8
/**
d6e8d8
* @package VC
d6e8d8
*/
d6e8d8
class colour_manager
d6e8d8
{
d6e8d8
	var $img;
d6e8d8
	var $mode;
d6e8d8
	var $colours;
d6e8d8
	var $named_colours;
d6e8d8
d6e8d8
	/**
d6e8d8
	* Create the colour manager, link it to the image resource
d6e8d8
	*/
d6e8d8
	function colour_manager($img, $background = false, $mode = 'ahsv')
d6e8d8
	{
d6e8d8
		$this->img = $img;
d6e8d8
		$this->mode = $mode;
d6e8d8
		$this->colours = array();
d6e8d8
		$this->named_colours = array();
d6e8d8
d6e8d8
		if ($background !== false)
d6e8d8
		{
d6e8d8
			$bg = $this->allocate_named('background', $background);
d6e8d8
			imagefill($this->img, 0, 0, $bg);
d6e8d8
		}
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	* Lookup a named colour resource
d6e8d8
	*/
d6e8d8
	function get_resource($named_colour)
d6e8d8
	{
d6e8d8
		if (isset($this->named_colours[$named_colour]))
d6e8d8
		{
d6e8d8
			return $this->named_colours[$named_colour];
d6e8d8
		}
d6e8d8
d6e8d8
		if (isset($this->named_rgb[$named_colour]))
d6e8d8
		{
d6e8d8
			return $this->allocate_named($named_colour, $this->named_rgb[$named_colour], 'rgb');
d6e8d8
		}
d6e8d8
d6e8d8
		return false;
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	* Assign a name to a colour resource
d6e8d8
	*/
d6e8d8
	function name_colour($name, $resource)
d6e8d8
	{
d6e8d8
		$this->named_colours[$name] = $resource;
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	* names and allocates a colour resource
d6e8d8
	*/
d6e8d8
	function allocate_named($name, $colour, $mode = false)
d6e8d8
	{
d6e8d8
		$resource = $this->allocate($colour, $mode);
d6e8d8
d6e8d8
		if ($resource !== false)
d6e8d8
		{
d6e8d8
			$this->name_colour($name, $resource);
d6e8d8
		}
d6e8d8
		return $resource;
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	* allocates a specified colour into the image
d6e8d8
	*/
d6e8d8
	function allocate($colour, $mode = false)
d6e8d8
	{
d6e8d8
		if ($mode === false)
d6e8d8
		{
d6e8d8
			$mode = $this->mode;
d6e8d8
		}
d6e8d8
		
d6e8d8
		if (!is_array($colour))
d6e8d8
		{
d6e8d8
			if (isset($this->named_rgb[$colour]))
d6e8d8
			{
d6e8d8
				return $this->allocate_named($colour, $this->named_rgb[$colour], 'rgb');
d6e8d8
			}
d6e8d8
d6e8d8
			if (!is_int($colour))
d6e8d8
			{
d6e8d8
				return false;
d6e8d8
			}
d6e8d8
d6e8d8
			$mode = 'rgb';
d6e8d8
			$colour = array(255 & ($colour >> 16), 255 & ($colour >>  8), 255 & $colour);
d6e8d8
		}
d6e8d8
d6e8d8
		if (isset($colour['mode']))
d6e8d8
		{
d6e8d8
			$mode = $colour['mode'];
d6e8d8
			unset($colour['mode']);
d6e8d8
		}
d6e8d8
d6e8d8
		if (isset($colour['random']))
d6e8d8
		{
d6e8d8
			unset($colour['random']);
d6e8d8
			// everything else is params
d6e8d8
			return $this->random_colour($colour, $mode);
d6e8d8
		}
d6e8d8
d6e8d8
		$rgb		= colour_manager::model_convert($colour, $mode, 'rgb');
d6e8d8
		$store		= ($this->mode == 'rgb') ? $rgb : colour_manager::model_convert($colour, $mode, $this->mode);
d6e8d8
		$resource	= imagecolorallocate($this->img, $rgb[0], $rgb[1], $rgb[2]);
d6e8d8
		$this->colours[$resource] = $store;
d6e8d8
d6e8d8
		return $resource;
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	* randomly generates a colour, with optional params
d6e8d8
	*/
d6e8d8
	function random_colour($params = array(), $mode = false)
d6e8d8
	{
d6e8d8
		if ($mode === false)
d6e8d8
		{
d6e8d8
			$mode = $this->mode;
d6e8d8
		}
d6e8d8
d6e8d8
		switch ($mode)
d6e8d8
		{
d6e8d8
			case 'rgb':
d6e8d8
				// @TODO random rgb generation. do we intend to do this, or is it just too tedious?
d6e8d8
			break;
d6e8d8
d6e8d8
			case 'ahsv':
d6e8d8
			case 'hsv':
d6e8d8
			default:
d6e8d8
d6e8d8
				$default_params = array(
d6e8d8
					'hue_bias'			=> false,	// degree / 'r'/'g'/'b'/'c'/'m'/'y'   /'o'
d6e8d8
					'hue_range'			=> false,	// if hue bias, then difference range +/- from bias
d6e8d8
					'min_saturation'	=> 30,		// 0 - 100
d6e8d8
					'max_saturation'	=> 80,		// 0 - 100
d6e8d8
					'min_value'			=> 30,		// 0 - 100
d6e8d8
					'max_value'			=> 80,		// 0 - 100
d6e8d8
				);
d6e8d8
d6e8d8
				$alt = ($mode == 'ahsv') ? true : false;
d6e8d8
				$params = array_merge($default_params, $params);
d6e8d8
d6e8d8
				$min_hue		= 0;
d6e8d8
				$max_hue		= 359;
d6e8d8
				$min_saturation	= max(0, $params['min_saturation']);
d6e8d8
				$max_saturation	= min(100, $params['max_saturation']);
d6e8d8
				$min_value		= max(0, $params['min_value']);
d6e8d8
				$max_value		= min(100, $params['max_value']);
d6e8d8
d6e8d8
				if ($params['hue_bias'] !== false)
d6e8d8
				{
d6e8d8
					if (is_numeric($params['hue_bias']))
d6e8d8
					{
d6e8d8
						$h = intval($params['hue_bias']) % 360;
d6e8d8
					}
d6e8d8
					else
d6e8d8
					{
d6e8d8
						switch ($params['hue_bias'])
d6e8d8
						{
d6e8d8
							case 'o':
d6e8d8
								$h = $alt ?  60 :  30;
d6e8d8
							break;
d6e8d8
d6e8d8
							case 'y':
d6e8d8
								$h = $alt ? 120 :  60;
d6e8d8
							break;
d6e8d8
d6e8d8
							case 'g':
d6e8d8
								$h = $alt ? 180 : 120;
d6e8d8
							break;
d6e8d8
d6e8d8
							case 'c':
d6e8d8
								$h = $alt ? 210 : 180;
d6e8d8
							break;
d6e8d8
d6e8d8
							case 'b':
d6e8d8
								$h = 240;
d6e8d8
							break;
d6e8d8
d6e8d8
							case 'm':
d6e8d8
								$h = 300;
d6e8d8
							break;
d6e8d8
d6e8d8
							case 'r':
d6e8d8
							default:
d6e8d8
								$h = 0;
d6e8d8
							break;
d6e8d8
						}
d6e8d8
					}
d6e8d8
d6e8d8
					$min_hue = $h + 360;
d6e8d8
					$max_hue = $h + 360;
d6e8d8
d6e8d8
					if ($params['hue_range'])
d6e8d8
					{
d6e8d8
						$min_hue -= min(180, $params['hue_range']);
d6e8d8
						$max_hue += min(180, $params['hue_range']);
d6e8d8
					}
d6e8d8
				}
d6e8d8
d6e8d8
				$h = mt_rand($min_hue, $max_hue);
d6e8d8
				$s = mt_rand($min_saturation, $max_saturation);
d6e8d8
				$v = mt_rand($min_value, $max_value);
d6e8d8
d6e8d8
				return $this->allocate(array($h, $s, $v), $mode);
d6e8d8
d6e8d8
			break;
d6e8d8
		}
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	*/
d6e8d8
	function colour_scheme($resource, $include_original = true)
d6e8d8
	{
d6e8d8
		$mode = 'hsv';
d6e8d8
d6e8d8
		if (($pre = $this->get_resource($resource)) !== false)
d6e8d8
		{
d6e8d8
			$resource = $pre;
d6e8d8
		}
d6e8d8
d6e8d8
		$colour = colour_manager::model_convert($this->colours[$resource], $this->mode, $mode);
d6e8d8
		$results = ($include_original) ? array($resource) : array();
d6e8d8
		$colour2 = $colour3 = $colour4 = $colour;
d6e8d8
		$colour2[0] += 150;
d6e8d8
		$colour3[0] += 180;
d6e8d8
		$colour4[0] += 210;
d6e8d8
d6e8d8
d6e8d8
		$results[] = $this->allocate($colour2, $mode);
d6e8d8
		$results[] = $this->allocate($colour3, $mode);
d6e8d8
		$results[] = $this->allocate($colour4, $mode);
d6e8d8
d6e8d8
		return $results;
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	*/
d6e8d8
	function mono_range($resource, $count = 5, $include_original = true)
d6e8d8
	{
d6e8d8
		if (is_array($resource))
d6e8d8
		{
d6e8d8
			$results = array();
d6e8d8
			for ($i = 0, $size = sizeof($resource); $i < $size; ++$i)
d6e8d8
			{
d6e8d8
				$results = array_merge($results, $this->mono_range($resource[$i], $count, $include_original));
d6e8d8
			}
d6e8d8
			return $results;
d6e8d8
		}
d6e8d8
d6e8d8
		$mode = (in_array($this->mode, array('hsv', 'ahsv'), true) ? $this->mode : 'ahsv');
d6e8d8
		if (($pre = $this->get_resource($resource)) !== false)
d6e8d8
		{
d6e8d8
			$resource = $pre;
d6e8d8
		}
d6e8d8
d6e8d8
		$colour = colour_manager::model_convert($this->colours[$resource], $this->mode, $mode);
d6e8d8
d6e8d8
		$results = array();
d6e8d8
		if ($include_original)
d6e8d8
		{
d6e8d8
			$results[] = $resource;
d6e8d8
			$count--;
d6e8d8
		}
d6e8d8
d6e8d8
		// This is a hard problem. I chicken out and try to maintain readability at the cost of less randomness.
d6e8d8
		
d6e8d8
		while ($count > 0)
d6e8d8
		{
d6e8d8
			$colour[1] = ($colour[1] + mt_rand(40,60)) % 99;
d6e8d8
			$colour[2] = ($colour[2] + mt_rand(40,60));
d6e8d8
			$results[] = $this->allocate($colour, $mode);
d6e8d8
			$count--;
d6e8d8
		}
d6e8d8
		return $results;
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	* Convert from one colour model to another
d6e8d8
	*/
d6e8d8
	function model_convert($colour, $from_model, $to_model)
d6e8d8
	{
d6e8d8
		if ($from_model == $to_model)
d6e8d8
		{
d6e8d8
			return $colour;
d6e8d8
		}
d6e8d8
d6e8d8
		switch ($to_model)
d6e8d8
		{
d6e8d8
			case 'hsv':
d6e8d8
d6e8d8
				switch ($from_model)
d6e8d8
				{
d6e8d8
					case 'ahsv':
d6e8d8
						return colour_manager::ah2h($colour);
d6e8d8
					break;
d6e8d8
d6e8d8
					case 'rgb':
d6e8d8
						return colour_manager::rgb2hsv($colour);
d6e8d8
					break;
d6e8d8
				}
d6e8d8
			break;
d6e8d8
d6e8d8
			case 'ahsv':
d6e8d8
d6e8d8
				switch ($from_model)
d6e8d8
				{
d6e8d8
					case 'hsv':
d6e8d8
						return colour_manager::h2ah($colour);
d6e8d8
					break;
d6e8d8
d6e8d8
					case 'rgb':
d6e8d8
						return colour_manager::h2ah(colour_manager::rgb2hsv($colour));
d6e8d8
					break;
d6e8d8
				}
d6e8d8
			break;
d6e8d8
d6e8d8
			case 'rgb':
d6e8d8
				switch ($from_model)
d6e8d8
				{
d6e8d8
					case 'hsv':
d6e8d8
						return colour_manager::hsv2rgb($colour);
d6e8d8
					break;
d6e8d8
d6e8d8
					case 'ahsv':
d6e8d8
						return colour_manager::hsv2rgb(colour_manager::ah2h($colour));
d6e8d8
					break;
d6e8d8
				}
d6e8d8
			break;
d6e8d8
		}
d6e8d8
		return false;
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	* Slightly altered from wikipedia's algorithm
d6e8d8
	*/
d6e8d8
	function hsv2rgb($hsv)
d6e8d8
	{
d6e8d8
		colour_manager::normalize_hue($hsv[0]);
d6e8d8
d6e8d8
		$h = $hsv[0];
d6e8d8
		$s = min(1, max(0, $hsv[1] / 100));
d6e8d8
		$v = min(1, max(0, $hsv[2] / 100));
d6e8d8
d6e8d8
		// calculate hue sector
d6e8d8
		$hi = floor($hsv[0] / 60);
d6e8d8
d6e8d8
		// calculate opposite colour
d6e8d8
		$p = $v * (1 - $s);
d6e8d8
d6e8d8
		// calculate distance between hex vertices
d6e8d8
		$f = ($h / 60) - $hi;
d6e8d8
d6e8d8
		// coming in or going out?
d6e8d8
		if (!($hi & 1))
d6e8d8
		{
d6e8d8
			$f = 1 - $f;
d6e8d8
		}
d6e8d8
d6e8d8
		// calculate adjacent colour
d6e8d8
		$q = $v * (1 - ($f * $s));
d6e8d8
d6e8d8
		switch ($hi)
d6e8d8
		{
d6e8d8
			case 0:
d6e8d8
				$rgb = array($v, $q, $p);
d6e8d8
			break;
d6e8d8
d6e8d8
			case 1:
d6e8d8
				$rgb = array($q, $v, $p);
d6e8d8
			break;
d6e8d8
d6e8d8
			case 2:
d6e8d8
				$rgb = array($p, $v, $q);
d6e8d8
			break;
d6e8d8
d6e8d8
			case 3:
d6e8d8
				$rgb = array($p, $q, $v);
d6e8d8
			break;
d6e8d8
d6e8d8
			case 4:
d6e8d8
				$rgb = array($q, $p, $v);
d6e8d8
			break;
d6e8d8
d6e8d8
			case 5:
d6e8d8
				$rgb = array($v, $p, $q);
d6e8d8
			break;
d6e8d8
d6e8d8
			default:
d6e8d8
				return array(0, 0, 0);
d6e8d8
			break;
d6e8d8
		}
d6e8d8
d6e8d8
		return array(255 * $rgb[0], 255 * $rgb[1], 255 * $rgb[2]);
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	* (more than) Slightly altered from wikipedia's algorithm
d6e8d8
	*/
d6e8d8
	function rgb2hsv($rgb)
d6e8d8
	{
d6e8d8
		$r = min(255, max(0, $rgb[0]));
d6e8d8
		$g = min(255, max(0, $rgb[1]));
d6e8d8
		$b = min(255, max(0, $rgb[2]));
d6e8d8
		$max = max($r, $g, $b);
d6e8d8
		$min = min($r, $g, $b);
d6e8d8
d6e8d8
		$v = $max / 255;
d6e8d8
		$s = (!$max) ? 0 : 1 - ($min / $max);
d6e8d8
d6e8d8
		// if max - min is 0, we want hue to be 0 anyway.
d6e8d8
		$h = $max - $min;
d6e8d8
d6e8d8
		if ($h)
d6e8d8
		{
d6e8d8
			switch ($max)
d6e8d8
			{
d6e8d8
				case $g:
d6e8d8
					$h = 120 + (60 * ($b - $r) / $h);
d6e8d8
				break;
d6e8d8
d6e8d8
				case $b:
d6e8d8
					$h = 240 + (60 * ($r - $g) / $h);
d6e8d8
				break;
d6e8d8
d6e8d8
				case $r:
d6e8d8
					$h = 360 + (60 * ($g - $b) / $h);
d6e8d8
				break;
d6e8d8
			}
d6e8d8
		}
d6e8d8
		colour_manager::normalize_hue($h);
d6e8d8
d6e8d8
		return array($h, $s * 100, $v * 100);
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	*/
d6e8d8
	function normalize_hue(&$hue)
d6e8d8
	{
d6e8d8
		$hue %= 360;
d6e8d8
d6e8d8
		if ($hue < 0)
d6e8d8
		{
d6e8d8
			$hue += 360;
d6e8d8
		}
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	* Alternate hue to hue
d6e8d8
	*/
d6e8d8
	function ah2h($ahue)
d6e8d8
	{
d6e8d8
		if (is_array($ahue))
d6e8d8
		{
d6e8d8
			$ahue[0] = colour_manager::ah2h($ahue[0]);
d6e8d8
			return $ahue;
d6e8d8
		}
d6e8d8
		colour_manager::normalize_hue($ahue);
d6e8d8
d6e8d8
		// blue through red is already ok
d6e8d8
		if ($ahue >= 240)
d6e8d8
		{
d6e8d8
			return $ahue;
d6e8d8
		}
d6e8d8
d6e8d8
		// ahue green is at 180
d6e8d8
		if ($ahue >= 180)
d6e8d8
		{
d6e8d8
			// return (240 - (2 * (240 - $ahue)));
d6e8d8
			return (2 * $ahue) - 240; // equivalent
d6e8d8
		}
d6e8d8
d6e8d8
		// ahue yellow is at 120   (RYB rather than RGB)
d6e8d8
		if ($ahue >= 120)
d6e8d8
		{
d6e8d8
			return $ahue - 60;
d6e8d8
		}
d6e8d8
d6e8d8
		return $ahue / 2;
d6e8d8
	}
d6e8d8
d6e8d8
	/**
d6e8d8
	* hue to Alternate hue
d6e8d8
	*/
d6e8d8
	function h2ah($hue)
d6e8d8
	{
d6e8d8
		if (is_array($hue))
d6e8d8
		{
d6e8d8
			$hue[0] = colour_manager::h2ah($hue[0]);
d6e8d8
			return $hue;
d6e8d8
		}
d6e8d8
		colour_manager::normalize_hue($hue);
d6e8d8
d6e8d8
		// blue through red is already ok
d6e8d8
		if ($hue >= 240)
d6e8d8
		{
d6e8d8
			return $hue;
d6e8d8
		}
d6e8d8
		else if ($hue <= 60)
d6e8d8
		{
d6e8d8
			return $hue * 2;
d6e8d8
		}
d6e8d8
		else if ($hue <= 120)
d6e8d8
		{
d6e8d8
			return $hue + 60;
d6e8d8
		}
d6e8d8
		else
d6e8d8
		{
d6e8d8
			return ($hue + 240) / 2;
d6e8d8
		}
d6e8d8
	}
d6e8d8
}
d6e8d8
d6e8d8
?>