Blame Extras/phpBB/3.0.4/includes/captcha/captcha_gd.php

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