Verzeichnisstruktur phpBB-3.0.0


Veröffentlicht
12.12.2007

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

captcha_gd.php

Zuletzt modifiziert: 09.10.2024, 12:51 - Dateigröße: 36.85 KiB


0001  <?php
0002  /**
0003  *
0004  * @package VC
0005  * @version $Id$
0006  * @copyright (c) 2006 phpBB Group
0007  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
0008  *
0009  */
0010   
0011  /**
0012  * @ignore
0013  */
0014  if (!defined('IN_PHPBB'))
0015  {
0016      exit;
0017  }
0018   
0019  /**
0020  * Original Author - Xore (Robert Hetzler)
0021  * With contributions from Neothermic
0022  *
0023  * @package VC
0024  */
0025  class captcha
0026  {
0027      var $width = 360;
0028      var $height = 96;
0029   
0030      /**
0031      * Create the image containing $code with a seed of $seed
0032      */
0033      function execute($code, $seed)
0034      {
0035          global $config;
0036          srand($seed);
0037          mt_srand($seed);
0038   
0039          // Create image
0040          $img = imagecreatetruecolor($this->width, $this->height);
0041   
0042          // Generate colours
0043          $colour = new colour_manager($img, array(
0044              'random'    => true,
0045              'min_value'    => 60,
0046          ), 'hsv');
0047   
0048          $scheme = $colour->colour_scheme('background', false);
0049          $scheme = $colour->mono_range($scheme, 10, false);
0050          shuffle($scheme);
0051   
0052          $bg_colours = array_splice($scheme, mt_rand(6, 12));
0053   
0054          // Generate code characters
0055          $characters = $sizes = $bounding_boxes = array();
0056          $width_avail = $this->width - 15;
0057          $code_len = strlen($code);
0058   
0059          $captcha_bitmaps = $this->captcha_bitmaps();
0060          for ($i = 0; $i < $code_len; ++$i)
0061          {
0062              $characters[$i] = new char_cube3d($captcha_bitmaps, $code[$i]);
0063   
0064              list($min, $max) = $characters[$i]->range();
0065              $sizes[$i] = mt_rand($min, $max);
0066   
0067              $box = $characters[$i]->dimensions($sizes[$i]);
0068              $width_avail -= ($box[2] - $box[0]);
0069              $bounding_boxes[$i] = $box;
0070          }
0071   
0072          // Redistribute leftover x-space
0073          $offset = array();
0074          for ($i = 0; $i < $code_len; ++$i)
0075          {
0076              $denom = ($code_len - $i);
0077              $denom = max(1.3, $denom);
0078              $offset[$i] = mt_rand(0, (1.5 * $width_avail) / $denom);
0079              $width_avail -= $offset[$i];
0080          }
0081   
0082          if ($config['captcha_gd_x_grid'])
0083          {
0084              $grid = (int) $config['captcha_gd_x_grid'];
0085              for ($y = 0; $y < $this->height; $y += mt_rand($grid - 2, $grid + 2))
0086              {
0087                  $current_colour = $scheme[array_rand($scheme)];
0088                  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);
0089              }
0090          }
0091   
0092          if ($config['captcha_gd_y_grid'])
0093          {
0094              $grid = (int) $config['captcha_gd_y_grid'];
0095              for ($x = 0; $x < $this->width; $x += mt_rand($grid - 2, $grid + 2))
0096              {
0097                  $current_colour = $scheme[array_rand($scheme)];
0098                  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);
0099              }
0100          }
0101   
0102          $xoffset = 5;
0103          for ($i = 0; $i < $code_len; ++$i)
0104          {
0105              $dimm = $bounding_boxes[$i];
0106              $xoffset += ($offset[$i] - $dimm[0]);
0107              $yoffset = mt_rand(-$dimm[1], $this->height - $dimm[3]);
0108   
0109              $characters[$i]->drawchar($sizes[$i], $xoffset, $yoffset, $img, $colour->get_resource('background'), $scheme);
0110              $xoffset += $dimm[2];
0111          }
0112          
0113          if ($config['captcha_gd_foreground_noise'])
0114          {
0115              $this->noise_line($img, 0, 0, $this->width, $this->height, $colour->get_resource('background'), $scheme, $bg_colours);
0116          }
0117   
0118          // Send image
0119          header('Content-Type: image/png');
0120          header('Cache-control: no-cache, no-store');
0121          imagepng($img);
0122          imagedestroy($img);
0123      }
0124   
0125      /**
0126      * Noise line
0127      */
0128      function noise_line($img, $min_x, $min_y, $max_x, $max_y, $bg, $font, $non_font)
0129      {
0130          imagesetthickness($img, 2);
0131   
0132          $x1 = $min_x;
0133          $x2 = $max_x;
0134          $y1 = $min_y;
0135          $y2 = $min_y;
0136   
0137          do
0138          {
0139              $line = array_merge(
0140                  array_fill(0, mt_rand(30, 60), $non_font[array_rand($non_font)]),
0141                  array_fill(0, mt_rand(30, 60), $bg)
0142              );
0143   
0144              imagesetstyle($img, $line);
0145              imageline($img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
0146   
0147              $y1 += mt_rand(12, 35);
0148              $y2 += mt_rand(12, 35);
0149          }
0150          while ($y1 < $max_y && $y2 < $max_y);
0151   
0152          $x1 = $min_x;
0153          $x2 = $min_x;
0154          $y1 = $min_y;
0155          $y2 = $max_y;
0156   
0157          do
0158          {
0159              $line = array_merge(
0160                  array_fill(0, mt_rand(30, 60), $non_font[array_rand($non_font)]),
0161                  array_fill(0, mt_rand(30, 60), $bg)
0162              );
0163   
0164              imagesetstyle($img, $line);
0165              imageline($img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
0166   
0167              $x1 += mt_rand(20, 35);
0168              $x2 += mt_rand(20, 35);
0169          }
0170          while ($x1 < $max_x && $x2 < $max_x);
0171          imagesetthickness($img, 1);
0172      }
0173   
0174      /**
0175      * Return bitmaps
0176      */
0177      function captcha_bitmaps()
0178      {
0179          return array(
0180              'width'        => 9,
0181              'height'    => 15,
0182              'data'        => array(
0183   
0184              'A' => array(
0185                  array(0,0,0,0,1,0,0,0,0),
0186                  array(0,0,0,1,0,1,0,0,0),
0187                  array(0,0,0,1,0,1,0,0,0),
0188                  array(0,0,0,1,0,1,0,0,0),
0189                  array(0,0,1,0,0,0,1,0,0),
0190                  array(0,0,1,0,0,0,1,0,0),
0191                  array(0,0,1,0,0,0,1,0,0),
0192                  array(0,1,0,0,0,0,0,1,0),
0193                  array(0,1,0,0,0,0,0,1,0),
0194                  array(0,1,1,1,1,1,1,1,0),
0195                  array(0,1,0,0,0,0,0,1,0),
0196                  array(1,0,0,0,0,0,0,0,1),
0197                  array(1,0,0,0,0,0,0,0,1),
0198                  array(1,0,0,0,0,0,0,0,1),
0199                  array(1,0,0,0,0,0,0,0,1),
0200              ),
0201              'B' => array(
0202                  array(1,1,1,1,1,1,1,0,0),
0203                  array(1,0,0,0,0,0,0,1,0),
0204                  array(1,0,0,0,0,0,0,0,1),
0205                  array(1,0,0,0,0,0,0,0,1),
0206                  array(1,0,0,0,0,0,0,0,1),
0207                  array(1,0,0,0,0,0,0,0,1),
0208                  array(1,0,0,0,0,0,0,1,0),
0209                  array(1,1,1,1,1,1,1,0,0),
0210                  array(1,0,0,0,0,0,0,1,0),
0211                  array(1,0,0,0,0,0,0,0,1),
0212                  array(1,0,0,0,0,0,0,0,1),
0213                  array(1,0,0,0,0,0,0,0,1),
0214                  array(1,0,0,0,0,0,0,0,1),
0215                  array(1,0,0,0,0,0,0,1,0),
0216                  array(1,1,1,1,1,1,1,0,0),
0217              ),
0218              'C' => array(
0219                  array(0,0,1,1,1,1,1,0,0),
0220                  array(0,1,0,0,0,0,0,1,0),
0221                  array(1,0,0,0,0,0,0,0,1),
0222                  array(1,0,0,0,0,0,0,0,1),
0223                  array(1,0,0,0,0,0,0,0,0),
0224                  array(1,0,0,0,0,0,0,0,0),
0225                  array(1,0,0,0,0,0,0,0,0),
0226                  array(1,0,0,0,0,0,0,0,0),
0227                  array(1,0,0,0,0,0,0,0,0),
0228                  array(1,0,0,0,0,0,0,0,0),
0229                  array(1,0,0,0,0,0,0,0,0),
0230                  array(1,0,0,0,0,0,0,0,1),
0231                  array(1,0,0,0,0,0,0,0,1),
0232                  array(0,1,0,0,0,0,0,1,0),
0233                  array(0,0,1,1,1,1,1,0,0),
0234              ),
0235              'D' => array(
0236                  array(1,1,1,1,1,1,1,0,0),
0237                  array(1,0,0,0,0,0,0,1,0),
0238                  array(1,0,0,0,0,0,0,0,1),
0239                  array(1,0,0,0,0,0,0,0,1),
0240                  array(1,0,0,0,0,0,0,0,1),
0241                  array(1,0,0,0,0,0,0,0,1),
0242                  array(1,0,0,0,0,0,0,0,1),
0243                  array(1,0,0,0,0,0,0,0,1),
0244                  array(1,0,0,0,0,0,0,0,1),
0245                  array(1,0,0,0,0,0,0,0,1),
0246                  array(1,0,0,0,0,0,0,0,1),
0247                  array(1,0,0,0,0,0,0,0,1),
0248                  array(1,0,0,0,0,0,0,0,1),
0249                  array(1,0,0,0,0,0,0,1,0),
0250                  array(1,1,1,1,1,1,1,0,0),
0251              ),
0252              'E' => array(
0253                  array(1,1,1,1,1,1,1,1,1),
0254                  array(1,0,0,0,0,0,0,0,0),
0255                  array(1,0,0,0,0,0,0,0,0),
0256                  array(1,0,0,0,0,0,0,0,0),
0257                  array(1,0,0,0,0,0,0,0,0),
0258                  array(1,0,0,0,0,0,0,0,0),
0259                  array(1,0,0,0,0,0,0,0,0),
0260                  array(1,1,1,1,1,1,1,1,0),
0261                  array(1,0,0,0,0,0,0,0,0),
0262                  array(1,0,0,0,0,0,0,0,0),
0263                  array(1,0,0,0,0,0,0,0,0),
0264                  array(1,0,0,0,0,0,0,0,0),
0265                  array(1,0,0,0,0,0,0,0,0),
0266                  array(1,0,0,0,0,0,0,0,0),
0267                  array(1,1,1,1,1,1,1,1,1),
0268              ),
0269              'F' => array(
0270                  array(1,1,1,1,1,1,1,1,1),
0271                  array(1,0,0,0,0,0,0,0,0),
0272                  array(1,0,0,0,0,0,0,0,0),
0273                  array(1,0,0,0,0,0,0,0,0),
0274                  array(1,0,0,0,0,0,0,0,0),
0275                  array(1,0,0,0,0,0,0,0,0),
0276                  array(1,0,0,0,0,0,0,0,0),
0277                  array(1,1,1,1,1,1,1,0,0),
0278                  array(1,0,0,0,0,0,0,0,0),
0279                  array(1,0,0,0,0,0,0,0,0),
0280                  array(1,0,0,0,0,0,0,0,0),
0281                  array(1,0,0,0,0,0,0,0,0),
0282                  array(1,0,0,0,0,0,0,0,0),
0283                  array(1,0,0,0,0,0,0,0,0),
0284                  array(1,0,0,0,0,0,0,0,0),
0285              ),
0286              'G' => array(
0287                  array(0,0,1,1,1,1,1,0,0),
0288                  array(0,1,0,0,0,0,0,1,0),
0289                  array(1,0,0,0,0,0,0,0,1),
0290                  array(1,0,0,0,0,0,0,0,0),
0291                  array(1,0,0,0,0,0,0,0,0),
0292                  array(1,0,0,0,0,0,0,0,0),
0293                  array(1,0,0,0,0,0,0,0,0),
0294                  array(1,0,0,0,0,0,0,0,0),
0295                  array(1,0,0,0,0,0,1,1,1),
0296                  array(1,0,0,0,0,0,0,0,1),
0297                  array(1,0,0,0,0,0,0,0,1),
0298                  array(1,0,0,0,0,0,0,0,1),
0299                  array(1,0,0,0,0,0,0,0,1),
0300                  array(0,1,0,0,0,0,0,1,0),
0301                  array(0,0,1,1,1,1,1,0,0),
0302              ),
0303              'H' => array(
0304                  array(1,0,0,0,0,0,0,0,1),
0305                  array(1,0,0,0,0,0,0,0,1),
0306                  array(1,0,0,0,0,0,0,0,1),
0307                  array(1,0,0,0,0,0,0,0,1),
0308                  array(1,0,0,0,0,0,0,0,1),
0309                  array(1,0,0,0,0,0,0,0,1),
0310                  array(1,0,0,0,0,0,0,0,1),
0311                  array(1,1,1,1,1,1,1,1,1),
0312                  array(1,0,0,0,0,0,0,0,1),
0313                  array(1,0,0,0,0,0,0,0,1),
0314                  array(1,0,0,0,0,0,0,0,1),
0315                  array(1,0,0,0,0,0,0,0,1),
0316                  array(1,0,0,0,0,0,0,0,1),
0317                  array(1,0,0,0,0,0,0,0,1),
0318                  array(1,0,0,0,0,0,0,0,1),
0319              ),
0320              'I' => array(
0321                  array(1,1,1,1,1,1,1,1,1),
0322                  array(0,0,0,0,1,0,0,0,0),
0323                  array(0,0,0,0,1,0,0,0,0),
0324                  array(0,0,0,0,1,0,0,0,0),
0325                  array(0,0,0,0,1,0,0,0,0),
0326                  array(0,0,0,0,1,0,0,0,0),
0327                  array(0,0,0,0,1,0,0,0,0),
0328                  array(0,0,0,0,1,0,0,0,0),
0329                  array(0,0,0,0,1,0,0,0,0),
0330                  array(0,0,0,0,1,0,0,0,0),
0331                  array(0,0,0,0,1,0,0,0,0),
0332                  array(0,0,0,0,1,0,0,0,0),
0333                  array(0,0,0,0,1,0,0,0,0),
0334                  array(0,0,0,0,1,0,0,0,0),
0335                  array(1,1,1,1,1,1,1,1,1),
0336              ),
0337              'J' => array(
0338                  array(1,1,1,1,1,1,1,1,1),
0339                  array(0,0,0,0,0,1,0,0,0),
0340                  array(0,0,0,0,0,1,0,0,0),
0341                  array(0,0,0,0,0,1,0,0,0),
0342                  array(0,0,0,0,0,1,0,0,0),
0343                  array(0,0,0,0,0,1,0,0,0),
0344                  array(0,0,0,0,0,1,0,0,0),
0345                  array(0,0,0,0,0,1,0,0,0),
0346                  array(0,0,0,0,0,1,0,0,0),
0347                  array(0,0,0,0,0,1,0,0,0),
0348                  array(0,0,0,0,0,1,0,0,0),
0349                  array(1,0,0,0,0,1,0,0,0),
0350                  array(1,0,0,0,0,1,0,0,0),
0351                  array(0,1,0,0,1,0,0,0,0),
0352                  array(0,0,1,1,0,0,0,0,0),
0353              ),
0354              'K' => array(    // New 'K', supplied by NeoThermic
0355                  array(1,0,0,0,0,0,0,0,1),
0356                  array(1,0,0,0,0,0,0,1,0),
0357                  array(1,0,0,0,0,0,1,0,0),
0358                  array(1,0,0,0,0,1,0,0,0),
0359                  array(1,0,0,0,1,0,0,0,0),
0360                  array(1,0,0,1,0,0,0,0,0),
0361                  array(1,0,1,0,0,0,0,0,0),
0362                  array(1,1,0,0,0,0,0,0,0),
0363                  array(1,0,1,0,0,0,0,0,0),
0364                  array(1,0,0,1,0,0,0,0,0),
0365                  array(1,0,0,0,1,0,0,0,0),
0366                  array(1,0,0,0,0,1,0,0,0),
0367                  array(1,0,0,0,0,0,1,0,0),
0368                  array(1,0,0,0,0,0,0,1,0),
0369                  array(1,0,0,0,0,0,0,0,1),
0370              ),
0371              'L' => array(
0372                  array(0,0,0,0,0,0,0,0,0),
0373                  array(1,0,0,0,0,0,0,0,0),
0374                  array(1,0,0,0,0,0,0,0,0),
0375                  array(1,0,0,0,0,0,0,0,0),
0376                  array(1,0,0,0,0,0,0,0,0),
0377                  array(1,0,0,0,0,0,0,0,0),
0378                  array(1,0,0,0,0,0,0,0,0),
0379                  array(1,0,0,0,0,0,0,0,0),
0380                  array(1,0,0,0,0,0,0,0,0),
0381                  array(1,0,0,0,0,0,0,0,0),
0382                  array(1,0,0,0,0,0,0,0,0),
0383                  array(1,0,0,0,0,0,0,0,0),
0384                  array(1,0,0,0,0,0,0,0,0),
0385                  array(1,0,0,0,0,0,0,0,0),
0386                  array(1,1,1,1,1,1,1,1,1),
0387              ),
0388              'M' => array(
0389                  array(1,1,0,0,0,0,0,1,1),
0390                  array(1,1,0,0,0,0,0,1,1),
0391                  array(1,0,1,0,0,0,1,0,1),
0392                  array(1,0,1,0,0,0,1,0,1),
0393                  array(1,0,1,0,0,0,1,0,1),
0394                  array(1,0,0,1,0,1,0,0,1),
0395                  array(1,0,0,1,0,1,0,0,1),
0396                  array(1,0,0,1,0,1,0,0,1),
0397                  array(1,0,0,0,1,0,0,0,1),
0398                  array(1,0,0,0,1,0,0,0,1),
0399                  array(1,0,0,0,0,0,0,0,1),
0400                  array(1,0,0,0,0,0,0,0,1),
0401                  array(1,0,0,0,0,0,0,0,1),
0402                  array(1,0,0,0,0,0,0,0,1),
0403                  array(1,0,0,0,0,0,0,0,1),
0404              ),
0405              'N' => array(
0406                  array(1,1,0,0,0,0,0,0,1),
0407                  array(1,1,0,0,0,0,0,0,1),
0408                  array(1,0,1,0,0,0,0,0,1),
0409                  array(1,0,1,0,0,0,0,0,1),
0410                  array(1,0,0,1,0,0,0,0,1),
0411                  array(1,0,0,1,0,0,0,0,1),
0412                  array(1,0,0,0,1,0,0,0,1),
0413                  array(1,0,0,0,1,0,0,0,1),
0414                  array(1,0,0,0,1,0,0,0,1),
0415                  array(1,0,0,0,0,1,0,0,1),
0416                  array(1,0,0,0,0,1,0,0,1),
0417                  array(1,0,0,0,0,0,1,0,1),
0418                  array(1,0,0,0,0,0,1,0,1),
0419                  array(1,0,0,0,0,0,0,1,1),
0420                  array(1,0,0,0,0,0,0,1,1),
0421              ),
0422              'O' => array(
0423                  array(0,0,1,1,1,1,1,0,0),
0424                  array(0,1,0,0,0,0,0,1,0),
0425                  array(1,0,0,0,0,0,0,0,1),
0426                  array(1,0,0,0,0,0,0,0,1),
0427                  array(1,0,0,0,0,0,0,0,1),
0428                  array(1,0,0,0,0,0,0,0,1),
0429                  array(1,0,0,0,0,0,0,0,1),
0430                  array(1,0,0,0,0,0,0,0,1),
0431                  array(1,0,0,0,0,0,0,0,1),
0432                  array(1,0,0,0,0,0,0,0,1),
0433                  array(1,0,0,0,0,0,0,0,1),
0434                  array(1,0,0,0,0,0,0,0,1),
0435                  array(1,0,0,0,0,0,0,0,1),
0436                  array(0,1,0,0,0,0,0,1,0),
0437                  array(0,0,1,1,1,1,1,0,0),
0438              ),
0439              'P' => array(
0440                  array(1,1,1,1,1,1,1,0,0),
0441                  array(1,0,0,0,0,0,0,1,0),
0442                  array(1,0,0,0,0,0,0,0,1),
0443                  array(1,0,0,0,0,0,0,0,1),
0444                  array(1,0,0,0,0,0,0,0,1),
0445                  array(1,0,0,0,0,0,0,0,1),
0446                  array(1,0,0,0,0,0,0,1,0),
0447                  array(1,1,1,1,1,1,1,0,0),
0448                  array(1,0,0,0,0,0,0,0,0),
0449                  array(1,0,0,0,0,0,0,0,0),
0450                  array(1,0,0,0,0,0,0,0,0),
0451                  array(1,0,0,0,0,0,0,0,0),
0452                  array(1,0,0,0,0,0,0,0,0),
0453                  array(1,0,0,0,0,0,0,0,0),
0454                  array(1,0,0,0,0,0,0,0,0),
0455              ),
0456              'Q' => array(
0457                  array(0,0,1,1,1,1,1,0,0),
0458                  array(0,1,0,0,0,0,0,1,0),
0459                  array(1,0,0,0,0,0,0,0,1),
0460                  array(1,0,0,0,0,0,0,0,1),
0461                  array(1,0,0,0,0,0,0,0,1),
0462                  array(1,0,0,0,0,0,0,0,1),
0463                  array(1,0,0,0,0,0,0,0,1),
0464                  array(1,0,0,0,0,0,0,0,1),
0465                  array(1,0,0,0,0,0,0,0,1),
0466                  array(1,0,0,0,0,0,0,0,1),
0467                  array(1,0,0,0,0,0,0,0,1),
0468                  array(1,0,0,0,0,1,0,0,1),
0469                  array(1,0,0,0,0,0,1,0,1),
0470                  array(0,1,0,0,0,0,0,1,0),
0471                  array(0,0,1,1,1,1,1,0,1),
0472              ),
0473              'R' => array(
0474                  array(1,1,1,1,1,1,1,0,0),
0475                  array(1,0,0,0,0,0,0,1,0),
0476                  array(1,0,0,0,0,0,0,0,1),
0477                  array(1,0,0,0,0,0,0,0,1),
0478                  array(1,0,0,0,0,0,0,0,1),
0479                  array(1,0,0,0,0,0,0,0,1),
0480                  array(1,0,0,0,0,0,0,1,0),
0481                  array(1,1,1,1,1,1,1,0,0),
0482                  array(1,1,1,0,0,0,0,0,0),
0483                  array(1,0,0,1,0,0,0,0,0),
0484                  array(1,0,0,0,1,0,0,0,0),
0485                  array(1,0,0,0,0,1,0,0,0),
0486                  array(1,0,0,0,0,0,1,0,0),
0487                  array(1,0,0,0,0,0,0,1,0),
0488                  array(1,0,0,0,0,0,0,0,1),
0489              ),
0490              'S' => array(
0491                  array(0,0,1,1,1,1,1,0,0),
0492                  array(0,1,0,0,0,0,0,1,0),
0493                  array(1,0,0,0,0,0,0,0,1),
0494                  array(1,0,0,0,0,0,0,0,0),
0495                  array(1,0,0,0,0,0,0,0,0),
0496                  array(1,0,0,0,0,0,0,0,0),
0497                  array(0,1,0,0,0,0,0,0,0),
0498                  array(0,0,1,1,1,1,1,0,0),
0499                  array(0,0,0,0,0,0,0,1,0),
0500                  array(0,0,0,0,0,0,0,0,1),
0501                  array(0,0,0,0,0,0,0,0,1),
0502                  array(0,0,0,0,0,0,0,0,1),
0503                  array(1,0,0,0,0,0,0,0,1),
0504                  array(0,1,0,0,0,0,0,1,0),
0505                  array(0,0,1,1,1,1,1,0,0),
0506              ),
0507              'T' => array(
0508                  array(1,1,1,1,1,1,1,1,1),
0509                  array(0,0,0,0,1,0,0,0,0),
0510                  array(0,0,0,0,1,0,0,0,0),
0511                  array(0,0,0,0,1,0,0,0,0),
0512                  array(0,0,0,0,1,0,0,0,0),
0513                  array(0,0,0,0,1,0,0,0,0),
0514                  array(0,0,0,0,1,0,0,0,0),
0515                  array(0,0,0,0,1,0,0,0,0),
0516                  array(0,0,0,0,1,0,0,0,0),
0517                  array(0,0,0,0,1,0,0,0,0),
0518                  array(0,0,0,0,1,0,0,0,0),
0519                  array(0,0,0,0,1,0,0,0,0),
0520                  array(0,0,0,0,1,0,0,0,0),
0521                  array(0,0,0,0,1,0,0,0,0),
0522                  array(0,0,0,0,1,0,0,0,0),
0523              ),
0524              'U' => array(
0525                  array(1,0,0,0,0,0,0,0,1),
0526                  array(1,0,0,0,0,0,0,0,1),
0527                  array(1,0,0,0,0,0,0,0,1),
0528                  array(1,0,0,0,0,0,0,0,1),
0529                  array(1,0,0,0,0,0,0,0,1),
0530                  array(1,0,0,0,0,0,0,0,1),
0531                  array(1,0,0,0,0,0,0,0,1),
0532                  array(1,0,0,0,0,0,0,0,1),
0533                  array(1,0,0,0,0,0,0,0,1),
0534                  array(1,0,0,0,0,0,0,0,1),
0535                  array(1,0,0,0,0,0,0,0,1),
0536                  array(1,0,0,0,0,0,0,0,1),
0537                  array(1,0,0,0,0,0,0,0,1),
0538                  array(0,1,0,0,0,0,0,1,0),
0539                  array(0,0,1,1,1,1,1,0,0),
0540              ),
0541              'V' => array(
0542                  array(1,0,0,0,0,0,0,0,1),
0543                  array(1,0,0,0,0,0,0,0,1),
0544                  array(1,0,0,0,0,0,0,0,1),
0545                  array(0,1,0,0,0,0,0,1,0),
0546                  array(0,1,0,0,0,0,0,1,0),
0547                  array(0,1,0,0,0,0,0,1,0),
0548                  array(0,0,1,0,0,0,1,0,0),
0549                  array(0,0,1,0,0,0,1,0,0),
0550                  array(0,0,1,0,0,0,1,0,0),
0551                  array(0,0,1,0,0,0,1,0,0),
0552                  array(0,0,0,1,0,1,0,0,0),
0553                  array(0,0,0,1,0,1,0,0,0),
0554                  array(0,0,0,1,0,1,0,0,0),
0555                  array(0,0,0,0,1,0,0,0,0),
0556                  array(0,0,0,0,1,0,0,0,0),
0557              ),
0558              'W' => array(    // New 'W', supplied by MHobbit
0559                  array(1,0,0,0,0,0,0,0,1),
0560                  array(1,0,0,0,0,0,0,0,1),
0561                  array(1,0,0,0,0,0,0,0,1),
0562                  array(1,0,0,0,0,0,0,0,1),
0563                  array(1,0,0,0,0,0,0,0,1),
0564                  array(1,0,0,0,1,0,0,0,1),
0565                  array(1,0,0,0,1,0,0,0,1),
0566                  array(1,0,0,1,0,1,0,0,1),
0567                  array(1,0,0,1,0,1,0,0,1),
0568                  array(1,0,0,1,0,1,0,0,1),
0569                  array(1,0,1,0,0,0,1,0,1),
0570                  array(1,0,1,0,0,0,1,0,1),
0571                  array(1,0,1,0,0,0,1,0,1),
0572                  array(1,1,0,0,0,0,0,1,1),
0573                  array(1,1,0,0,0,0,0,1,1),
0574              ),
0575              'X' => array(
0576                  array(1,0,0,0,0,0,0,0,1),
0577                  array(1,0,0,0,0,0,0,0,1),
0578                  array(0,1,0,0,0,0,0,1,0),
0579                  array(0,1,0,0,0,0,0,1,0),
0580                  array(0,0,1,0,0,0,1,0,0),
0581                  array(0,0,0,1,0,1,0,0,0),
0582                  array(0,0,0,1,0,1,0,0,0),
0583                  array(0,0,0,0,1,0,0,0,0),
0584                  array(0,0,0,1,0,1,0,0,0),
0585                  array(0,0,0,1,0,1,0,0,0),
0586                  array(0,0,1,0,0,0,1,0,0),
0587                  array(0,1,0,0,0,0,1,0,0),
0588                  array(0,1,0,0,0,0,0,1,0),
0589                  array(1,0,0,0,0,0,0,0,1),
0590                  array(1,0,0,0,0,0,0,0,1),
0591              ),
0592              'Y' => array(
0593                  array(1,0,0,0,0,0,0,0,1),
0594                  array(1,0,0,0,0,0,0,0,1),
0595                  array(0,1,0,0,0,0,0,1,0),
0596                  array(0,1,0,0,0,0,0,1,0),
0597                  array(0,0,1,0,0,0,1,0,0),
0598                  array(0,0,1,0,0,0,1,0,0),
0599                  array(0,0,0,1,0,1,0,0,0),
0600                  array(0,0,0,0,1,0,0,0,0),
0601                  array(0,0,0,0,1,0,0,0,0),
0602                  array(0,0,0,0,1,0,0,0,0),
0603                  array(0,0,0,0,1,0,0,0,0),
0604                  array(0,0,0,0,1,0,0,0,0),
0605                  array(0,0,0,0,1,0,0,0,0),
0606                  array(0,0,0,0,1,0,0,0,0),
0607                  array(0,0,0,0,1,0,0,0,0),
0608              ),
0609              'Z' => array(    // New 'Z' supplied by Anon
0610                  array(1,1,1,1,1,1,1,1,1),
0611                  array(1,0,0,0,0,0,0,0,1),
0612                  array(0,0,0,0,0,0,0,0,1),
0613                  array(0,0,0,0,0,0,0,1,0),
0614                  array(0,0,0,0,0,0,1,0,0),
0615                  array(0,0,0,0,0,1,0,0,0),
0616                  array(0,0,0,0,0,1,0,0,0),
0617                  array(0,0,0,0,1,0,0,0,0),
0618                  array(0,0,0,1,0,0,0,0,0),
0619                  array(0,0,0,1,0,0,0,0,0),
0620                  array(0,0,1,0,0,0,0,0,0),
0621                  array(0,1,0,0,0,0,0,0,0),
0622                  array(1,0,0,0,0,0,0,0,0),
0623                  array(1,0,0,0,0,0,0,0,1),
0624                  array(1,1,1,1,1,1,1,1,1),
0625              ),
0626              '1' => array(
0627                  array(0,0,0,1,1,0,0,0,0),
0628                  array(0,0,1,0,1,0,0,0,0),
0629                  array(0,1,0,0,1,0,0,0,0),
0630                  array(0,0,0,0,1,0,0,0,0),
0631                  array(0,0,0,0,1,0,0,0,0),
0632                  array(0,0,0,0,1,0,0,0,0),
0633                  array(0,0,0,0,1,0,0,0,0),
0634                  array(0,0,0,0,1,0,0,0,0),
0635                  array(0,0,0,0,1,0,0,0,0),
0636                  array(0,0,0,0,1,0,0,0,0),
0637                  array(0,0,0,0,1,0,0,0,0),
0638                  array(0,0,0,0,1,0,0,0,0),
0639                  array(0,0,0,0,1,0,0,0,0),
0640                  array(0,0,0,0,1,0,0,0,0),
0641                  array(0,1,1,1,1,1,1,1,0),
0642              ),
0643              '2' => array(    // New '2' supplied by Anon
0644                  array(0,0,0,1,1,1,0,0,0),
0645                  array(0,0,1,0,0,0,1,0,0),
0646                  array(0,1,0,0,0,0,1,1,0),
0647                  array(0,0,0,0,0,0,0,0,1),
0648                  array(0,0,0,0,0,0,0,0,1),
0649                  array(0,0,0,0,0,0,0,1,1),
0650                  array(0,0,0,0,0,0,0,1,0),
0651                  array(0,0,0,0,0,0,1,0,0),
0652                  array(0,0,0,0,0,1,0,0,0),
0653                  array(0,0,0,0,1,0,0,0,0),
0654                  array(0,0,0,1,0,0,0,0,0),
0655                  array(0,0,1,0,0,0,0,0,0),
0656                  array(0,1,0,0,0,0,0,0,0),
0657                  array(1,1,1,1,1,1,1,1,1),
0658                  array(0,0,0,0,0,0,0,0,0),
0659              ),
0660              '3' => array(
0661                  array(0,0,1,1,1,1,1,0,0),
0662                  array(0,1,0,0,0,0,0,1,0),
0663                  array(1,0,0,0,0,0,0,0,1),
0664                  array(0,0,0,0,0,0,0,0,1),
0665                  array(0,0,0,0,0,0,0,0,1),
0666                  array(0,0,0,0,0,0,0,0,1),
0667                  array(0,0,0,0,0,0,0,1,0),
0668                  array(0,0,0,0,0,1,1,0,0),
0669                  array(0,0,0,0,0,0,0,1,0),
0670                  array(0,0,0,0,0,0,0,0,1),
0671                  array(0,0,0,0,0,0,0,0,1),
0672                  array(0,0,0,0,0,0,0,0,1),
0673                  array(1,0,0,0,0,0,0,0,1),
0674                  array(0,1,0,0,0,0,0,1,0),
0675                  array(0,0,1,1,1,1,1,0,0),
0676              ),
0677              '4' => array(
0678                  array(0,0,0,0,0,0,1,1,0),
0679                  array(0,0,0,0,0,1,0,1,0),
0680                  array(0,0,0,0,1,0,0,1,0),
0681                  array(0,0,0,1,0,0,0,1,0),
0682                  array(0,0,1,0,0,0,0,1,0),
0683                  array(0,1,0,0,0,0,0,1,0),
0684                  array(1,0,0,0,0,0,0,1,0),
0685                  array(1,0,0,0,0,0,0,1,0),
0686                  array(1,1,1,1,1,1,1,1,1),
0687                  array(0,0,0,0,0,0,0,1,0),
0688                  array(0,0,0,0,0,0,0,1,0),
0689                  array(0,0,0,0,0,0,0,1,0),
0690                  array(0,0,0,0,0,0,0,1,0),
0691                  array(0,0,0,0,0,0,0,1,0),
0692                  array(0,0,0,0,0,0,0,1,0),
0693              ),
0694              '5' => array(
0695                  array(1,1,1,1,1,1,1,1,1),
0696                  array(1,0,0,0,0,0,0,0,0),
0697                  array(1,0,0,0,0,0,0,0,0),
0698                  array(1,0,0,0,0,0,0,0,0),
0699                  array(1,0,0,0,0,0,0,0,0),
0700                  array(0,1,0,0,0,0,0,0,0),
0701                  array(0,0,1,1,1,1,1,0,0),
0702                  array(0,0,0,0,0,0,0,1,0),
0703                  array(0,0,0,0,0,0,0,0,1),
0704                  array(0,0,0,0,0,0,0,0,1),
0705                  array(0,0,0,0,0,0,0,0,1),
0706                  array(0,0,0,0,0,0,0,0,1),
0707                  array(1,0,0,0,0,0,0,0,1),
0708                  array(0,1,0,0,0,0,0,1,0),
0709                  array(0,0,1,1,1,1,1,0,0),
0710              ),
0711              '6' => array(
0712                  array(0,0,1,1,1,1,1,0,0),
0713                  array(0,1,0,0,0,0,0,1,0),
0714                  array(1,0,0,0,0,0,0,0,1),
0715                  array(1,0,0,0,0,0,0,0,1),
0716                  array(1,0,0,0,0,0,0,0,0),
0717                  array(1,0,0,0,0,0,0,0,0),
0718                  array(1,0,0,1,1,1,1,0,0),
0719                  array(1,0,1,0,0,0,0,1,0),
0720                  array(1,1,0,0,0,0,0,0,1),
0721                  array(1,0,0,0,0,0,0,0,1),
0722                  array(1,0,0,0,0,0,0,0,1),
0723                  array(1,0,0,0,0,0,0,0,1),
0724                  array(1,0,0,0,0,0,0,0,1),
0725                  array(0,1,0,0,0,0,0,1,0),
0726                  array(0,0,1,1,1,1,1,0,0),
0727              ),
0728              '7' => array(
0729                  array(1,1,1,1,1,1,1,1,1),
0730                  array(0,0,0,0,0,0,0,0,1),
0731                  array(0,0,0,0,0,0,0,1,0),
0732                  array(0,0,0,0,0,0,0,1,0),
0733                  array(0,0,0,0,0,0,1,0,0),
0734                  array(0,0,0,0,0,1,0,0,0),
0735                  array(0,0,0,0,0,1,0,0,0),
0736                  array(0,0,0,0,1,0,0,0,0),
0737                  array(0,0,0,1,0,0,0,0,0),
0738                  array(0,0,0,1,0,0,0,0,0),
0739                  array(0,0,1,0,0,0,0,0,0),
0740                  array(0,1,0,0,0,0,0,0,0),
0741                  array(0,1,0,0,0,0,0,0,0),
0742                  array(1,0,0,0,0,0,0,0,0),
0743                  array(1,0,0,0,0,0,0,0,0),
0744              ),
0745              '8' => array(
0746                  array(0,0,1,1,1,1,1,0,0),
0747                  array(0,1,0,0,0,0,0,1,0),
0748                  array(1,0,0,0,0,0,0,0,1),
0749                  array(1,0,0,0,0,0,0,0,1),
0750                  array(1,0,0,0,0,0,0,0,1),
0751                  array(1,0,0,0,0,0,0,0,1),
0752                  array(0,1,0,0,0,0,0,1,0),
0753                  array(0,0,1,1,1,1,1,0,0),
0754                  array(0,1,0,0,0,0,0,1,0),
0755                  array(1,0,0,0,0,0,0,0,1),
0756                  array(1,0,0,0,0,0,0,0,1),
0757                  array(1,0,0,0,0,0,0,0,1),
0758                  array(1,0,0,0,0,0,0,0,1),
0759                  array(0,1,0,0,0,0,0,1,0),
0760                  array(0,0,1,1,1,1,1,0,0),
0761              ),
0762              '9' => array(
0763                  array(0,0,1,1,1,1,1,0,0),
0764                  array(0,1,0,0,0,0,0,1,0),
0765                  array(1,0,0,0,0,0,0,0,1),
0766                  array(1,0,0,0,0,0,0,0,1),
0767                  array(1,0,0,0,0,0,0,0,1),
0768                  array(1,0,0,0,0,0,0,0,1),
0769                  array(1,0,0,0,0,0,0,1,1),
0770                  array(0,1,0,0,0,0,1,0,1),
0771                  array(0,0,1,1,1,1,0,0,1),
0772                  array(0,0,0,0,0,0,0,0,1),
0773                  array(0,0,0,0,0,0,0,0,1),
0774                  array(1,0,0,0,0,0,0,0,1),
0775                  array(1,0,0,0,0,0,0,0,1),
0776                  array(0,1,0,0,0,0,0,1,0),
0777                  array(0,0,1,1,1,1,1,0,0),
0778              ),
0779              )
0780          );
0781      }
0782  }
0783   
0784  /**
0785  * @package VC
0786  */
0787  class char_cube3d
0788  {
0789      var $bitmap;
0790      var $bitmap_width;
0791      var $bitmap_height;
0792   
0793      var $basis_matrix = array(array(1, 0, 0), array(0, 1, 0), array(0, 0, 1));
0794      var $abs_x = array(1, 0);
0795      var $abs_y = array(0, 1);
0796      var $x = 0;
0797      var $y = 1;
0798      var $z = 2;
0799      var $letter = '';
0800   
0801      /**
0802      */
0803      function char_cube3d(&$bitmaps, $letter)
0804      {
0805          $this->bitmap            = $bitmaps['data'][$letter];
0806          $this->bitmap_width        = $bitmaps['width'];
0807          $this->bitmap_height    = $bitmaps['height'];
0808   
0809          $this->basis_matrix[0][0] = mt_rand(-600, 600);
0810          $this->basis_matrix[0][1] = mt_rand(-600, 600);
0811          $this->basis_matrix[0][2] = (mt_rand(0, 1) * 2000) - 1000;
0812          $this->basis_matrix[1][0] = mt_rand(-1000, 1000);
0813          $this->basis_matrix[1][1] = mt_rand(-1000, 1000);
0814          $this->basis_matrix[1][2] = mt_rand(-1000, 1000);
0815   
0816          $this->normalize($this->basis_matrix[0]);
0817          $this->normalize($this->basis_matrix[1]);
0818          $this->basis_matrix[2] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[1]);
0819          $this->normalize($this->basis_matrix[2]);
0820   
0821          // $this->basis_matrix[1] might not be (probably isn't) orthogonal to $basis_matrix[0]
0822          $this->basis_matrix[1] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[2]);
0823          $this->normalize($this->basis_matrix[1]);
0824   
0825          // Make sure our cube is facing into the canvas (assuming +z == in)
0826          for ($i = 0; $i < 3; ++$i)
0827          {
0828              if ($this->basis_matrix[$i][2] < 0)
0829              {
0830                  $this->basis_matrix[$i][0] *= -1;
0831                  $this->basis_matrix[$i][1] *= -1;
0832                  $this->basis_matrix[$i][2] *= -1;
0833              }
0834          }
0835   
0836          // Force our "z" basis vector to be the one with greatest absolute z value
0837          $this->x = 0;
0838          $this->y = 1;
0839          $this->z = 2;
0840   
0841          // Swap "y" with "z"
0842          if ($this->basis_matrix[1][2] > $this->basis_matrix[2][2])
0843          {
0844              $this->z = 1;
0845              $this->y = 2;
0846          }
0847   
0848          // Swap "x" with "z"
0849          if ($this->basis_matrix[0][2] > $this->basis_matrix[$this->z][2])
0850          {
0851              $this->x = $this->z;
0852              $this->z = 0;
0853          }
0854   
0855          // Still need to determine which of $x,$y are which.
0856          // wrong orientation if y's y-component is less than it's x-component
0857          // likewise if x's x-component is less than it's y-component
0858          // if they disagree, go with the one with the greater weight difference.
0859          // rotate if positive
0860          $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]));
0861   
0862          // Swap "x" with "y"
0863          if ($weight > 0)
0864          {
0865              list($this->x, $this->y) = array($this->y, $this->x);
0866          }
0867   
0868          $this->abs_x = array($this->basis_matrix[$this->x][0], $this->basis_matrix[$this->x][1]);
0869          $this->abs_y = array($this->basis_matrix[$this->y][0], $this->basis_matrix[$this->y][1]);
0870   
0871          if ($this->abs_x[0] < 0)
0872          {
0873              $this->abs_x[0] *= -1;
0874              $this->abs_x[1] *= -1;
0875          }
0876   
0877          if ($this->abs_y[1] > 0)
0878          {
0879              $this->abs_y[0] *= -1;
0880              $this->abs_y[1] *= -1;
0881          }
0882   
0883          $this->letter = $letter;
0884      }
0885   
0886      /**
0887      * Draw a character
0888      */
0889      function drawchar($scale, $xoff, $yoff, $img, $background, $colours)
0890      {
0891          $width    = $this->bitmap_width;
0892          $height    = $this->bitmap_height;
0893          $bitmap    = $this->bitmap;
0894   
0895          $colour1 = $colours[array_rand($colours)];
0896          $colour2 = $colours[array_rand($colours)];
0897   
0898          $swapx = ($this->basis_matrix[$this->x][0] > 0);
0899          $swapy = ($this->basis_matrix[$this->y][1] < 0);
0900   
0901          for ($y = 0; $y < $height; ++$y)
0902          {
0903              for ($x = 0; $x < $width; ++$x)
0904              {
0905                  $xp = ($swapx) ? ($width - $x - 1) : $x;
0906                  $yp = ($swapy) ? ($height - $y - 1) : $y;
0907   
0908                  if ($bitmap[$height - $yp - 1][$xp])
0909                  {
0910                      $dx = $this->scale($this->abs_x, ($xp - ($swapx ? ($width / 2) : ($width / 2) - 1)) * $scale);
0911                      $dy = $this->scale($this->abs_y, ($yp - ($swapy ? ($height / 2) : ($height / 2) - 1)) * $scale);
0912                      $xo = $xoff + $dx[0] + $dy[0];
0913                      $yo = $yoff + $dx[1] + $dy[1];
0914   
0915                      $origin = array(0, 0, 0);
0916                      $xvec = $this->scale($this->basis_matrix[$this->x], $scale);
0917                      $yvec = $this->scale($this->basis_matrix[$this->y], $scale);
0918                      $face_corner = $this->sum2($xvec, $yvec);
0919   
0920                      $zvec = $this->scale($this->basis_matrix[$this->z], $scale);
0921                      $x_corner = $this->sum2($xvec, $zvec);
0922                      $y_corner = $this->sum2($yvec, $zvec);
0923   
0924                      imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $xvec, $x_corner,$zvec), 4, $colour1);
0925                      imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $yvec, $y_corner,$zvec), 4, $colour2);
0926   
0927                      $face = $this->gen_poly($xo, $yo, $origin, $xvec, $face_corner, $yvec);
0928   
0929                      imagefilledpolygon($img, $face, 4, $background);
0930                      imagepolygon($img, $face, 4, $colour1);
0931                  }
0932              }
0933          }
0934      }
0935   
0936      /*
0937      * return a roughly acceptable range of sizes for rendering with this texttype
0938      */
0939      function range()
0940      {
0941          return array(3, 4);
0942      }
0943   
0944      /**
0945      * Vector length
0946      */
0947      function vectorlen($vector)
0948      {
0949          return sqrt(pow($vector[0], 2) + pow($vector[1], 2) + pow($vector[2], 2));
0950      }
0951   
0952      /**
0953      * Normalize
0954      */
0955      function normalize(&$vector, $length = 1)
0956      {
0957          $length = (( $length < 1) ? 1 : $length);
0958          $length /= $this->vectorlen($vector);
0959          $vector[0] *= $length;
0960          $vector[1] *= $length;
0961          $vector[2] *= $length;
0962      }
0963   
0964      /**
0965      */
0966      function cross_product($vector1, $vector2)
0967      {
0968          $retval = array(0, 0, 0);
0969          $retval[0] =  (($vector1[1] * $vector2[2]) - ($vector1[2] * $vector2[1]));
0970          $retval[1] = -(($vector1[0] * $vector2[2]) - ($vector1[2] * $vector2[0]));
0971          $retval[2] =  (($vector1[0] * $vector2[1]) - ($vector1[1] * $vector2[0]));
0972   
0973          return $retval;
0974      }
0975   
0976      /**
0977      */
0978      function sum($vector1, $vector2)
0979      {
0980          return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1], $vector1[2] + $vector2[2]);
0981      }
0982   
0983      /**
0984      */
0985      function sum2($vector1, $vector2)
0986      {
0987          return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1]);
0988      }
0989   
0990      /**
0991      */
0992      function scale($vector, $length)
0993      {
0994          if (sizeof($vector) == 2)
0995          {
0996              return array($vector[0] * $length, $vector[1] * $length);
0997          }
0998   
0999          return array($vector[0] * $length, $vector[1] * $length, $vector[2] * $length);
1000      }
1001   
1002      /**
1003      */
1004      function gen_poly($xoff, $yoff, &$vec1, &$vec2, &$vec3, &$vec4)
1005      {
1006          $poly = array();
1007          $poly[0] = $xoff + $vec1[0];
1008          $poly[1] = $yoff + $vec1[1];
1009          $poly[2] = $xoff + $vec2[0];
1010          $poly[3] = $yoff + $vec2[1];
1011          $poly[4] = $xoff + $vec3[0];
1012          $poly[5] = $yoff + $vec3[1];
1013          $poly[6] = $xoff + $vec4[0];
1014          $poly[7] = $yoff + $vec4[1];
1015   
1016          return $poly;
1017      }
1018   
1019      /**
1020      * dimensions
1021      */
1022      function dimensions($size)
1023      {
1024          $xn = $this->scale($this->basis_matrix[$this->x], -($this->bitmap_width / 2) * $size);
1025          $xp = $this->scale($this->basis_matrix[$this->x], ($this->bitmap_width / 2) * $size);
1026          $yn = $this->scale($this->basis_matrix[$this->y], -($this->bitmap_height / 2) * $size);
1027          $yp = $this->scale($this->basis_matrix[$this->y], ($this->bitmap_height / 2) * $size);
1028   
1029          $p = array();
1030          $p[0] = $this->sum2($xn, $yn);
1031          $p[1] = $this->sum2($xp, $yn);
1032          $p[2] = $this->sum2($xp, $yp);
1033          $p[3] = $this->sum2($xn, $yp);
1034   
1035          $min_x = $max_x = $p[0][0];
1036          $min_y = $max_y = $p[0][1];
1037   
1038          for ($i = 1; $i < 4; ++$i)
1039          {
1040              $min_x = ($min_x > $p[$i][0]) ? $p[$i][0] : $min_x;
1041              $min_y = ($min_y > $p[$i][1]) ? $p[$i][1] : $min_y;
1042              $max_x = ($max_x < $p[$i][0]) ? $p[$i][0] : $max_x;
1043              $max_y = ($max_y < $p[$i][1]) ? $p[$i][1] : $max_y;
1044          }
1045   
1046          return array($min_x, $min_y, $max_x, $max_y);
1047      }
1048  }
1049   
1050  /**
1051  * @package VC
1052  */
1053  class colour_manager
1054  {
1055      var $img;
1056      var $mode;
1057      var $colours;
1058      var $named_colours;
1059   
1060      /**
1061      * Create the colour manager, link it to the image resource
1062      */
1063      function colour_manager($img, $background = false, $mode = 'ahsv')
1064      {
1065          $this->img = $img;
1066          $this->mode = $mode;
1067          $this->colours = array();
1068          $this->named_colours = array();
1069   
1070          if ($background !== false)
1071          {
1072              $bg = $this->allocate_named('background', $background);
1073              imagefill($this->img, 0, 0, $bg);
1074          }
1075      }
1076   
1077      /**
1078      * Lookup a named colour resource
1079      */
1080      function get_resource($named_colour)
1081      {
1082          if (isset($this->named_colours[$named_colour]))
1083          {
1084              return $this->named_colours[$named_colour];
1085          }
1086   
1087          if (isset($this->named_rgb[$named_colour]))
1088          {
1089              return $this->allocate_named($named_colour, $this->named_rgb[$named_colour], 'rgb');
1090          }
1091   
1092          return false;
1093      }
1094   
1095      /**
1096      * Assign a name to a colour resource
1097      */
1098      function name_colour($name, $resource)
1099      {
1100          $this->named_colours[$name] = $resource;
1101      }
1102   
1103      /**
1104      * names and allocates a colour resource
1105      */
1106      function allocate_named($name, $colour, $mode = false)
1107      {
1108          $resource = $this->allocate($colour, $mode);
1109   
1110          if ($resource !== false)
1111          {
1112              $this->name_colour($name, $resource);
1113          }
1114          return $resource;
1115      }
1116   
1117      /**
1118      * allocates a specified colour into the image
1119      */
1120      function allocate($colour, $mode = false)
1121      {
1122          if ($mode === false)
1123          {
1124              $mode = $this->mode;
1125          }
1126          
1127          if (!is_array($colour))
1128          {
1129              if (isset($this->named_rgb[$colour]))
1130              {
1131                  return $this->allocate_named($colour, $this->named_rgb[$colour], 'rgb');
1132              }
1133   
1134              if (!is_int($colour))
1135              {
1136                  return false;
1137              }
1138   
1139              $mode = 'rgb';
1140              $colour = array(255 & ($colour >> 16), 255 & ($colour >>  8), 255 & $colour);
1141          }
1142   
1143          if (isset($colour['mode']))
1144          {
1145              $mode = $colour['mode'];
1146              unset($colour['mode']);
1147          }
1148   
1149          if (isset($colour['random']))
1150          {
1151              unset($colour['random']);
1152              // everything else is params
1153              return $this->random_colour($colour, $mode);
1154          }
1155   
1156          $rgb        = colour_manager::model_convert($colour, $mode, 'rgb');
1157          $store        = ($this->mode == 'rgb') ? $rgb : colour_manager::model_convert($colour, $mode, $this->mode);
1158          $resource    = imagecolorallocate($this->img, $rgb[0], $rgb[1], $rgb[2]);
1159          $this->colours[$resource] = $store;
1160   
1161          return $resource;
1162      }
1163   
1164      /**
1165      * randomly generates a colour, with optional params
1166      */
1167      function random_colour($params = array(), $mode = false)
1168      {
1169          if ($mode === false)
1170          {
1171              $mode = $this->mode;
1172          }
1173   
1174          switch ($mode)
1175          {
1176              case 'rgb':
1177                  // @TODO random rgb generation. do we intend to do this, or is it just too tedious?
1178              break;
1179   
1180              case 'ahsv':
1181              case 'hsv':
1182              default:
1183   
1184                  $default_params = array(
1185                      'hue_bias'            => false,    // degree / 'r'/'g'/'b'/'c'/'m'/'y'   /'o'
1186                      'hue_range'            => false,    // if hue bias, then difference range +/- from bias
1187                      'min_saturation'    => 30,        // 0 - 100
1188                      'max_saturation'    => 80,        // 0 - 100
1189                      'min_value'            => 30,        // 0 - 100
1190                      'max_value'            => 80,        // 0 - 100
1191                  );
1192   
1193                  $alt = ($mode == 'ahsv') ? true : false;
1194                  $params = array_merge($default_params, $params);
1195   
1196                  $min_hue        = 0;
1197                  $max_hue        = 359;
1198                  $min_saturation    = max(0, $params['min_saturation']);
1199                  $max_saturation    = min(100, $params['max_saturation']);
1200                  $min_value        = max(0, $params['min_value']);
1201                  $max_value        = min(100, $params['max_value']);
1202   
1203                  if ($params['hue_bias'] !== false)
1204                  {
1205                      if (is_numeric($params['hue_bias']))
1206                      {
1207                          $h = intval($params['hue_bias']) % 360;
1208                      }
1209                      else
1210                      {
1211                          switch ($params['hue_bias'])
1212                          {
1213                              case 'o':
1214                                  $h = $alt ?  60 :  30;
1215                              break;
1216   
1217                              case 'y':
1218                                  $h = $alt ? 120 :  60;
1219                              break;
1220   
1221                              case 'g':
1222                                  $h = $alt ? 180 : 120;
1223                              break;
1224   
1225                              case 'c':
1226                                  $h = $alt ? 210 : 180;
1227                              break;
1228   
1229                              case 'b':
1230                                  $h = 240;
1231                              break;
1232   
1233                              case 'm':
1234                                  $h = 300;
1235                              break;
1236   
1237                              case 'r':
1238                              default:
1239                                  $h = 0;
1240                              break;
1241                          }
1242                      }
1243   
1244                      $min_hue = $h + 360;
1245                      $max_hue = $h + 360;
1246   
1247                      if ($params['hue_range'])
1248                      {
1249                          $min_hue -= min(180, $params['hue_range']);
1250                          $max_hue += min(180, $params['hue_range']);
1251                      }
1252                  }
1253   
1254                  $h = mt_rand($min_hue, $max_hue);
1255                  $s = mt_rand($min_saturation, $max_saturation);
1256                  $v = mt_rand($min_value, $max_value);
1257   
1258                  return $this->allocate(array($h, $s, $v), $mode);
1259   
1260              break;
1261          }
1262      }
1263   
1264      /**
1265      */
1266      function colour_scheme($resource, $include_original = true)
1267      {
1268          $mode = 'hsv';
1269   
1270          if (($pre = $this->get_resource($resource)) !== false)
1271          {
1272              $resource = $pre;
1273          }
1274   
1275          $colour = colour_manager::model_convert($this->colours[$resource], $this->mode, $mode);
1276          $results = ($include_original) ? array($resource) : array();
1277          $colour2 = $colour3 = $colour4 = $colour;
1278          $colour2[0] += 150;
1279          $colour3[0] += 180;
1280          $colour4[0] += 210;
1281   
1282   
1283          $results[] = $this->allocate($colour2, $mode);
1284          $results[] = $this->allocate($colour3, $mode);
1285          $results[] = $this->allocate($colour4, $mode);
1286   
1287          return $results;
1288      }
1289   
1290      /**
1291      */
1292      function mono_range($resource, $count = 5, $include_original = true)
1293      {
1294          if (is_array($resource))
1295          {
1296              $results = array();
1297              for ($i = 0, $size = sizeof($resource); $i < $size; ++$i)
1298              {
1299                  $results = array_merge($results, $this->mono_range($resource[$i], $count, $include_original));
1300              }
1301              return $results;
1302          }
1303   
1304          $mode = (in_array($this->mode, array('hsv', 'ahsv'), true) ? $this->mode : 'ahsv');
1305          if (($pre = $this->get_resource($resource)) !== false)
1306          {
1307              $resource = $pre;
1308          }
1309   
1310          $colour = colour_manager::model_convert($this->colours[$resource], $this->mode, $mode);
1311   
1312          $results = array();
1313          if ($include_original)
1314          {
1315              $results[] = $resource;
1316              $count--;
1317          }
1318   
1319          // This is a hard problem. I chicken out and try to maintain readability at the cost of less randomness.
1320          
1321          while ($count > 0)
1322          {
1323              $colour[1] = ($colour[1] + mt_rand(40,60)) % 99;
1324              $colour[2] = ($colour[2] + mt_rand(40,60));
1325              $results[] = $this->allocate($colour, $mode);
1326              $count--;
1327          }
1328          return $results;
1329      }
1330   
1331      /**
1332      * Convert from one colour model to another
1333      */
1334      function model_convert($colour, $from_model, $to_model)
1335      {
1336          if ($from_model == $to_model)
1337          {
1338              return $colour;
1339          }
1340   
1341          switch ($to_model)
1342          {
1343              case 'hsv':
1344   
1345                  switch ($from_model)
1346                  {
1347                      case 'ahsv':
1348                          return colour_manager::ah2h($colour);
1349                      break;
1350   
1351                      case 'rgb':
1352                          return colour_manager::rgb2hsv($colour);
1353                      break;
1354                  }
1355              break;
1356   
1357              case 'ahsv':
1358   
1359                  switch ($from_model)
1360                  {
1361                      case 'hsv':
1362                          return colour_manager::h2ah($colour);
1363                      break;
1364   
1365                      case 'rgb':
1366                          return colour_manager::h2ah(colour_manager::rgb2hsv($colour));
1367                      break;
1368                  }
1369              break;
1370   
1371              case 'rgb':
1372                  switch ($from_model)
1373                  {
1374                      case 'hsv':
1375                          return colour_manager::hsv2rgb($colour);
1376                      break;
1377   
1378                      case 'ahsv':
1379                          return colour_manager::hsv2rgb(colour_manager::ah2h($colour));
1380                      break;
1381                  }
1382              break;
1383          }
1384          return false;
1385      }
1386   
1387      /**
1388      * Slightly altered from wikipedia's algorithm
1389      */
1390      function hsv2rgb($hsv)
1391      {
1392          colour_manager::normalize_hue($hsv[0]);
1393   
1394          $h = $hsv[0];
1395          $s = min(1, max(0, $hsv[1] / 100));
1396          $v = min(1, max(0, $hsv[2] / 100));
1397   
1398          // calculate hue sector
1399          $hi = floor($hsv[0] / 60);
1400   
1401          // calculate opposite colour
1402          $p = $v * (1 - $s);
1403   
1404          // calculate distance between hex vertices
1405          $f = ($h / 60) - $hi;
1406   
1407          // coming in or going out?
1408          if (!($hi & 1))
1409          {
1410              $f = 1 - $f;
1411          }
1412   
1413          // calculate adjacent colour
1414          $q = $v * (1 - ($f * $s));
1415   
1416          switch ($hi)
1417          {
1418              case 0:
1419                  $rgb = array($v, $q, $p);
1420              break;
1421   
1422              case 1:
1423                  $rgb = array($q, $v, $p);
1424              break;
1425   
1426              case 2:
1427                  $rgb = array($p, $v, $q);
1428              break;
1429   
1430              case 3:
1431                  $rgb = array($p, $q, $v);
1432              break;
1433   
1434              case 4:
1435                  $rgb = array($q, $p, $v);
1436              break;
1437   
1438              case 5:
1439                  $rgb = array($v, $p, $q);
1440              break;
1441   
1442              default:
1443                  return array(0, 0, 0);
1444              break;
1445          }
1446   
1447          return array(255 * $rgb[0], 255 * $rgb[1], 255 * $rgb[2]);
1448      }
1449   
1450      /**
1451      * (more than) Slightly altered from wikipedia's algorithm
1452      */
1453      function rgb2hsv($rgb)
1454      {
1455          $r = min(255, max(0, $rgb[0]));
1456          $g = min(255, max(0, $rgb[1]));
1457          $b = min(255, max(0, $rgb[2]));
1458          $max = max($r, $g, $b);
1459          $min = min($r, $g, $b);
1460   
1461          $v = $max / 255;
1462          $s = (!$max) ? 0 : 1 - ($min / $max);
1463   
1464          // if max - min is 0, we want hue to be 0 anyway.
1465          $h = $max - $min;
1466   
1467          if ($h)
1468          {
1469              switch ($max)
1470              {
1471                  case $g:
1472                      $h = 120 + (60 * ($b - $r) / $h);
1473                  break;
1474   
1475                  case $b:
1476                      $h = 240 + (60 * ($r - $g) / $h);
1477                  break;
1478   
1479                  case $r:
1480                      $h = 360 + (60 * ($g - $b) / $h);
1481                  break;
1482              }
1483          }
1484          colour_manager::normalize_hue($h);
1485   
1486          return array($h, $s * 100, $v * 100);
1487      }
1488   
1489      /**
1490      */
1491      function normalize_hue(&$hue)
1492      {
1493          $hue %= 360;
1494   
1495          if ($hue < 0)
1496          {
1497              $hue += 360;
1498          }
1499      }
1500   
1501      /**
1502      * Alternate hue to hue
1503      */
1504      function ah2h($ahue)
1505      {
1506          if (is_array($ahue))
1507          {
1508              $ahue[0] = colour_manager::ah2h($ahue[0]);
1509              return $ahue;
1510          }
1511          colour_manager::normalize_hue($ahue);
1512   
1513          // blue through red is already ok
1514          if ($ahue >= 240)
1515          {
1516              return $ahue;
1517          }
1518   
1519          // ahue green is at 180
1520          if ($ahue >= 180)
1521          {
1522              // return (240 - (2 * (240 - $ahue)));
1523              return (2 * $ahue) - 240; // equivalent
1524          }
1525   
1526          // ahue yellow is at 120   (RYB rather than RGB)
1527          if ($ahue >= 120)
1528          {
1529              return $ahue - 60;
1530          }
1531   
1532          return $ahue / 2;
1533      }
1534   
1535      /**
1536      * hue to Alternate hue
1537      */
1538      function h2ah($hue)
1539      {
1540          if (is_array($hue))
1541          {
1542              $hue[0] = colour_manager::h2ah($hue[0]);
1543              return $hue;
1544          }
1545          colour_manager::normalize_hue($hue);
1546   
1547          // blue through red is already ok
1548          if ($hue >= 240)
1549          {
1550              return $hue;
1551          }
1552          else if ($hue <= 60)
1553          {
1554              return $hue * 2;
1555          }
1556          else if ($hue <= 120)
1557          {
1558              return $hue + 60;
1559          }
1560          else
1561          {
1562              return ($hue + 240) / 2;
1563          }
1564      }
1565  }
1566   
1567  ?>