Merge branch 'MDL-35155-27' of git://github.com/danpoltawski/moodle into MOODLE_27_STABLE
[moodle.git] / lib / lessphp / Tree / Color.php
blobc0433a700f366fc78a150a3f410b9920f6827957
1 <?php
3 /**
4 * Color
6 * @package Less
7 * @subpackage tree
8 */
9 class Less_Tree_Color extends Less_Tree{
10 public $rgb;
11 public $alpha;
12 public $isTransparentKeyword;
13 public $type = 'Color';
15 public function __construct($rgb, $a = 1, $isTransparentKeyword = null ){
17 if( $isTransparentKeyword ){
18 $this->rgb = $rgb;
19 $this->alpha = $a;
20 $this->isTransparentKeyword = true;
21 return;
24 $this->rgb = array();
25 if( is_array($rgb) ){
26 $this->rgb = $rgb;
27 }else if( strlen($rgb) == 6 ){
28 foreach(str_split($rgb, 2) as $c){
29 $this->rgb[] = hexdec($c);
31 }else{
32 foreach(str_split($rgb, 1) as $c){
33 $this->rgb[] = hexdec($c.$c);
36 $this->alpha = is_numeric($a) ? $a : 1;
39 public function compile(){
40 return $this;
43 public function luma(){
44 $r = $this->rgb[0] / 255;
45 $g = $this->rgb[1] / 255;
46 $b = $this->rgb[2] / 255;
48 $r = ($r <= 0.03928) ? $r / 12.92 : pow((($r + 0.055) / 1.055), 2.4);
49 $g = ($g <= 0.03928) ? $g / 12.92 : pow((($g + 0.055) / 1.055), 2.4);
50 $b = ($b <= 0.03928) ? $b / 12.92 : pow((($b + 0.055) / 1.055), 2.4);
52 return 0.2126 * $r + 0.7152 * $g + 0.0722 * $b;
55 /**
56 * @see Less_Tree::genCSS
58 public function genCSS( $output ){
59 $output->add( $this->toCSS() );
62 public function toCSS( $doNotCompress = false ){
63 $compress = Less_Parser::$options['compress'] && !$doNotCompress;
64 $alpha = Less_Functions::fround( $this->alpha );
68 // If we have some transparency, the only way to represent it
69 // is via `rgba`. Otherwise, we use the hex representation,
70 // which has better compatibility with older browsers.
71 // Values are capped between `0` and `255`, rounded and zero-padded.
73 if( $alpha < 1 ){
74 if( $alpha === 0 && isset($this->isTransparentKeyword) && $this->isTransparentKeyword ){
75 return 'transparent';
78 $values = array();
79 foreach($this->rgb as $c){
80 $values[] = Less_Functions::clamp( round($c), 255);
82 $values[] = $alpha;
84 $glue = ($compress ? ',' : ', ');
85 return "rgba(" . implode($glue, $values) . ")";
86 }else{
88 $color = $this->toRGB();
90 if( $compress ){
92 // Convert color to short format
93 if( $color[1] === $color[2] && $color[3] === $color[4] && $color[5] === $color[6]) {
94 $color = '#'.$color[1] . $color[3] . $color[5];
98 return $color;
103 // Operations have to be done per-channel, if not,
104 // channels will spill onto each other. Once we have
105 // our result, in the form of an integer triplet,
106 // we create a new Color node to hold the result.
110 * @param string $op
112 public function operate( $op, $other) {
113 $rgb = array();
114 $alpha = $this->alpha * (1 - $other->alpha) + $other->alpha;
115 for ($c = 0; $c < 3; $c++) {
116 $rgb[$c] = Less_Functions::operate( $op, $this->rgb[$c], $other->rgb[$c]);
118 return new Less_Tree_Color($rgb, $alpha);
121 public function toRGB(){
122 return $this->toHex($this->rgb);
125 public function toHSL(){
126 $r = $this->rgb[0] / 255;
127 $g = $this->rgb[1] / 255;
128 $b = $this->rgb[2] / 255;
129 $a = $this->alpha;
131 $max = max($r, $g, $b);
132 $min = min($r, $g, $b);
133 $l = ($max + $min) / 2;
134 $d = $max - $min;
136 $h = $s = 0;
137 if( $max !== $min ){
138 $s = $l > 0.5 ? $d / (2 - $max - $min) : $d / ($max + $min);
140 switch ($max) {
141 case $r: $h = ($g - $b) / $d + ($g < $b ? 6 : 0); break;
142 case $g: $h = ($b - $r) / $d + 2; break;
143 case $b: $h = ($r - $g) / $d + 4; break;
145 $h /= 6;
147 return array('h' => $h * 360, 's' => $s, 'l' => $l, 'a' => $a );
150 //Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
151 function toHSV() {
152 $r = $this->rgb[0] / 255;
153 $g = $this->rgb[1] / 255;
154 $b = $this->rgb[2] / 255;
155 $a = $this->alpha;
157 $max = max($r, $g, $b);
158 $min = min($r, $g, $b);
160 $v = $max;
162 $d = $max - $min;
163 if ($max === 0) {
164 $s = 0;
165 } else {
166 $s = $d / $max;
169 $h = 0;
170 if( $max !== $min ){
171 switch($max){
172 case $r: $h = ($g - $b) / $d + ($g < $b ? 6 : 0); break;
173 case $g: $h = ($b - $r) / $d + 2; break;
174 case $b: $h = ($r - $g) / $d + 4; break;
176 $h /= 6;
178 return array('h'=> $h * 360, 's'=> $s, 'v'=> $v, 'a' => $a );
181 public function toARGB(){
182 $argb = array_merge( (array) Less_Parser::round($this->alpha * 255), $this->rgb);
183 return $this->toHex( $argb );
186 public function compare($x){
188 if( !property_exists( $x, 'rgb' ) ){
189 return -1;
193 return ($x->rgb[0] === $this->rgb[0] &&
194 $x->rgb[1] === $this->rgb[1] &&
195 $x->rgb[2] === $this->rgb[2] &&
196 $x->alpha === $this->alpha) ? 0 : -1;
199 function toHex( $v ){
201 $ret = '#';
202 foreach($v as $c){
203 $c = Less_Functions::clamp( Less_Parser::round($c), 255);
204 if( $c < 16 ){
205 $ret .= '0';
207 $ret .= dechex($c);
210 return $ret;
215 * @param string $keyword
217 public static function fromKeyword( $keyword ){
218 $keyword = strtolower($keyword);
220 if( Less_Colors::hasOwnProperty($keyword) ){
221 // detect named color
222 return new Less_Tree_Color(substr(Less_Colors::color($keyword), 1));
225 if( $keyword === 'transparent' ){
226 return new Less_Tree_Color( array(0, 0, 0), 0, true);