--- /dev/null
+<?php
+
+namespace Cubist\Util\Graphics;
+
+class Color
+{
+
+ protected $_red = 1;
+ protected $_green = 1;
+ protected $_blue = 1;
+ protected $_alpha = 1;
+
+ const NORM = 255;
+
+ function __construct($input = null)
+ {
+ if (!is_null($input)) {
+ $input = trim($input);
+ if (is_string($input)) {
+ $this->_parseString($input);
+ }
+ }
+ }
+
+ /**
+ * @return self
+ */
+ public function copy()
+ {
+ $res = new self();
+ $res->setAlpha($this->getAlpha());
+ $res->setRed($this->getRed());
+ $res->setGreen($this->getGreen());
+ $res->setBlue($this->getBlue());
+ return $res;
+ }
+
+ public function getRed()
+ {
+ return $this->_red;
+ }
+
+ public function setRed($red)
+ {
+ $this->_red = $red;
+ return $this;
+ }
+
+ public function getGreen()
+ {
+ return $this->_green;
+ }
+
+ public function setGreen($green)
+ {
+ $this->_green = $green;
+ return $this;
+ }
+
+ public function getBlue()
+ {
+ return $this->_blue;
+ }
+
+ public function setBlue($blue)
+ {
+ $this->_blue = $blue;
+ return $this;
+ }
+
+ public function getAlpha()
+ {
+ return $this->_alpha;
+ }
+
+ public function setAlpha($alpha)
+ {
+ $this->_alpha = $alpha;
+ return $this;
+ }
+
+ protected function _parseString($input)
+ {
+ $input = ltrim($input, '#');
+ $c = array('alpha' => 'ff', 'red' => 'ff', 'green' => 'ff', 'blue' => 'ff');
+ if ($input === 'transparent') {
+ $this->_alpha=0;
+ } else if (preg_match('/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9.]+)\s*)?\)/', $input, $matches)) {
+ $this->_red = (int)$matches[1] / self::NORM;
+ $this->_green = (int)$matches[2] / self::NORM;
+ $this->_blue = (int)$matches[3] / self::NORM;
+ if (isset($matches[5])) {
+ $this->_alpha = $matches[5];
+ }
+ } else {
+ if (strlen($input) == 6) {
+ $s = 0;
+ } elseif (strlen($input) >= 8) {
+ $s = 2;
+ $c['alpha'] = substr($input, 0, 2);
+ }
+ $c['red'] = substr($input, $s + 0, 2);
+ $c['green'] = substr($input, $s + 2, 2);
+ $c['blue'] = substr($input, $s + 4, 2);
+ $this->_processComposantes($c);
+ }
+
+ }
+
+ protected function _processComposantes($c)
+ {
+ // Normalize all values between 0 & 1
+ foreach ($c as $k => $v) {
+ if (is_string($v)) {
+ $r = hexdec($v) / self::NORM;
+ } elseif (is_numeric($v)) {
+ if ($v > 1) {
+ $r = $v / self::NORM;
+ } else {
+ $r = $v;
+ }
+ }
+ $this->{'_' . $k} = $r;
+ }
+ }
+
+ public function toCSS()
+ {
+ if ($this->_alpha == 0) {
+ return 'transparent';
+ } elseif ($this->_alpha == 1) {
+ return '#' . $this->toHexRVB();
+ }
+ return 'rgba(' . self::_to255($this->_red) . ',' . self::_to255($this->_green) . ',' . self::_to255($this->_blue) . ',' . $this->_alpha . ')';
+ }
+
+ public function toHexRVB()
+ {
+ return $this->toHexComposante('red') . $this->toHexComposante('green') . $this->toHexComposante('blue');
+ }
+
+ /**
+ *
+ * @param self $color
+ * @return self
+ */
+ public function multiply($color, $factor = 1)
+ {
+ $res = $this->copy();
+
+ $res->setRed($res->getRed() * self::_reduceMultiplyEffect($color->getRed(), $factor));
+ $res->setGreen($res->getGreen() * self::_reduceMultiplyEffect($color->getGreen(), $factor));
+ $res->setBlue($res->getBlue() * self::_reduceMultiplyEffect($color->getBlue(), $factor));
+ return $res;
+ }
+
+ protected static function _reduceMultiplyEffect($color, $factor = 1)
+ {
+ if ($factor == 1) {
+ return $color;
+ }
+ $diff = 1 - $color;
+ $diff *= $factor;
+
+ return 1 - $diff;
+ }
+
+ public function toHexComposante($c)
+ {
+ $res = dechex(self::_to255($this->{'_' . $c}));
+ if (strlen($res) == 2) {
+ return $res;
+ } elseif (strlen($res) == 0) {
+ return '00';
+ } elseif (strlen($res) == 1) {
+ return '0' . $res;
+ }
+ }
+
+ public function toArray()
+ {
+ return array(
+ 'hexrvb' => $this->toHexRVB(),
+ 'red' => $this->_red,
+ 'green' => $this->_green,
+ 'blue' => $this->_blue,
+ 'alpha' => $this->_alpha,
+ 'css' => $this->toCSS()
+ );
+ }
+
+ public static function colorToCSS($color, $forceAlpha = null)
+ {
+ $color = new self($color);
+ if (!is_null($forceAlpha)) {
+ $color->setAlpha($forceAlpha);
+ }
+ return $color->toCSS();
+ }
+
+ protected static function _to255($c)
+ {
+ return round($c * self::NORM);
+ }
+
+}